area/
/*


 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
 *                                                                         *
 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
 *  Chastain, Michael Quan, and Mitchell Tse.                              *
 *                                                                         *
 *  In order to use any part of this Merc Diku Mud, you must comply with   *
 *  both the original Diku license in 'license.doc' as well the Merc       *
 *  license in 'license.txt'.  In particular, you may not remove either of *
 *  these copyright notices.                                               *
 *                                                                         *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 ***************************************************************************/

#if defined(macintosh)
#include<types.h>
#else
#include <sys/types.h>
#endif
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"


char *	const	where_name	[] =
{
    "[Light         ] ",
    "[On Finger     ] ",
    "[On Finger     ] ",
    "[Around Neck   ] ",
    "[Around Neck   ] ",
    "[On Body       ] ",
    "[On Head       ] ",
    "[On Legs       ] ",
    "[On Feet       ] ",
    "[On Hands      ] ",
    "[On Arms       ] ",
    "[Off Hand      ] ",
    "[Around Body   ] ",
    "[Around Waist  ] ",
    "[Around Wrist  ] ",
    "[Around Wrist  ] ",
    "[Right Hand    ] ",
    "[Left Hand     ] ",
    "[Third Hand    ] ",
    "[Fourth Hand   ] ",
    "[On Face       ] ",
    "[Left Scabbard ] ",
    "[Right Scabbard] ",
};

const char * exitname [6] =
{
	"north",
	"east",
	"south",
	"west",
	"up",
	"down"
};

const char * exitname2 [6] =
{
	"to the north",
	"to the east",
	"to the south",
	"to the west",
	"above you",
	"below you"
};


/*
 * Local functions.
 */
char *	format_obj_to_char	args( ( OBJ_DATA *obj, CHAR_DATA *ch,
				    bool fShort ) );
void	show_char_to_char_0	args( ( CHAR_DATA *victim, CHAR_DATA *ch ) );
void	show_char_to_char_1	args( ( CHAR_DATA *victim, CHAR_DATA *ch ) );
void	show_char_to_char	args( ( CHAR_DATA *list, CHAR_DATA *ch ) );
bool	check_blind		args( ( CHAR_DATA *ch ) );

void	evil_eye		args( ( CHAR_DATA *victim, CHAR_DATA *ch ) );
void 	check_left_arm		args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
void 	check_right_arm		args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
void 	check_left_leg		args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
void 	check_right_leg		args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );

void	obj_score		args( ( CHAR_DATA *ch, OBJ_DATA *obj ) );


char *format_obj_to_char( OBJ_DATA *obj, CHAR_DATA *ch, bool fShort )
{
    static char buf[MAX_STRING_LENGTH];

    buf[0] = '\0';
    if ( IS_SET(obj->quest, QUEST_ARTIFACT)) strcat(buf, "#7(Artifact)#n "
);
    else if ( IS_SET(obj->quest, QUEST_RELIC)) strcat(buf,"#3(#7Relic#3)#n " );
    else if ( obj->points < 750 && obj->points != 0) strcat(buf,"#3(Legendary)#n " );
    else if ( obj->points < 1250 && obj->points != 0 ) strcat(buf,
"#7(#2Mythical#7)#n " );
    else if ( obj->points < 3000 && obj->points !=0) strcat(buf,
"#6(#3Priceless#6)#n " );	
    if ( IS_OBJ_STAT(obj, ITEM_INVIS)     )   strcat( buf, "#6(Invis)#n "
);
    if ( IS_AFFECTED(ch, AFF_DETECT_EVIL)
         && !IS_OBJ_STAT(obj, ITEM_ANTI_GOOD)
         && IS_OBJ_STAT(obj, ITEM_ANTI_EVIL)   )   strcat( buf, "#4(Blue Aura)#n "  );
    else if ( IS_AFFECTED(ch, AFF_DETECT_EVIL)
         && IS_OBJ_STAT(obj, ITEM_ANTI_GOOD)
         && !IS_OBJ_STAT(obj, ITEM_ANTI_EVIL)   )   strcat( buf, "#1(Red Aura)#n "  );
    else if ( IS_AFFECTED(ch, AFF_DETECT_EVIL)
         && IS_OBJ_STAT(obj, ITEM_ANTI_GOOD)
         && !IS_OBJ_STAT(obj, ITEM_ANTI_NEUTRAL)
         && IS_OBJ_STAT(obj, ITEM_ANTI_EVIL)   )   strcat( buf, "#3(Yellow Aura)#n "  );
    if ( IS_AFFECTED(ch, AFF_DETECT_MAGIC)
         && IS_OBJ_STAT(obj, ITEM_MAGIC)  )   strcat( buf, "#4(Magical)#n 
" );
        if (IS_SET(obj->spectype, SITEM_COPPER))  strcat(buf,"(Copper) ");
    if (IS_SET(obj->spectype, SITEM_IRON))  strcat(buf,"(Iron) ");
    if (IS_SET(obj->spectype, SITEM_STEEL))  strcat(buf,"(Steel) ");
    if (IS_SET(obj->spectype, SITEM_ADAMANTITE))  strcat(buf,"(Adamantite) ");
    if (IS_SET(obj->spectype, SITEM_HILT))  strcat(buf,"(Hilted) ");
    if (IS_SET(obj->spectype, SITEM_GEMSTONE)) strcat(buf,"(Gemstoned) ");
    if (obj->value[0] == 18000 && obj->item_type == ITEM_WEAPON)
       strcat(buf,"(Sharpened) ");    
    if ( IS_OBJ_STAT(obj, ITEM_SHADOWPLANE) &&
	 obj->in_room != NULL &&
	!IS_AFFECTED(ch,AFF_SHADOWPLANE) )    strcat( buf,
"#0(Shadowplane)#n " );
    if (!IS_OBJ_STAT(obj, ITEM_SHADOWPLANE) &&
	 obj->in_room != NULL &&
	 IS_AFFECTED(ch,AFF_SHADOWPLANE) )    strcat( buf, "#7(Normal plane)#n " );

    if ( fShort )
    {
	if ( obj->short_descr != NULL )
	    strcat( buf, obj->short_descr );
	if ( obj->condition < 100) strcat(buf, " #1(Damaged)#n");
    }
    else
    {
	if ( obj->description != NULL )
	    strcat( buf, obj->description );
    }

    return buf;
}

int char_damroll(CHAR_DATA *ch)
{
    int value = 0;

    value += ch->damroll;

	if (lost_kpower(ch)) value -=50;

    if (!IS_NPC(ch) && ch->generation <= 0)
       ch->generation = 4;

    if (!IS_NPC(ch)) 
    {
        value += str_app[get_curr_str(ch)].todam;
        value += ch->xdamroll;
    }

    /* Vampire Rage */
    if (IS_CLASS(ch, CLASS_VAMPIRE) && ch->rage > 0)
	  value += ch->rage;

	if (IS_CLASS(ch, CLASS_NINJA) && ch->rage > 0)
	value += ch->rage;

    /* Werewolf Rage */
    if (IS_SET(ch->special,SPC_WOLFMAN) && ch->rage > 99)
	  value += ch->rage;


        if (IS_CLASS( ch,CLASS_DEMON) && ch->pcdata->stats[DEMON_POWER] > 0)
	value += (( ch->pcdata->stats[DEMON_POWER]) * ch->pcdata->stats[DEMON_POWER]);
	else if (IS_SET(ch->special,SPC_CHAMPION) && ch->pcdata->stats[DEMON_POWER] > 0)
	value += (( ch->pcdata->stats[DEMON_POWER]) * ch->pcdata->stats[DEMON_POWER]);

	if (!IS_NPC(ch))
	if (IS_CLASS(ch, CLASS_NINJA) && ch->pcdata->powers[NPOWER_CHIKYU] >= 6
	&& ch->pcdata->powers[HARA_KIRI] > 0)
	value += 50;

    if (IS_CLASS(ch, CLASS_HIGHLANDER) && (get_eq_char(ch, WEAR_WIELD) != NULL))
    {
	int wpn = ch->wpn[1];
	  if (wpn >= 1000)
		value += 500;
	  else
		value += wpn/2;
    }
    return value;
}

int char_hitroll(CHAR_DATA *ch)
{
    int value = 0;

    value += ch->hitroll;

	if (lost_kpower(ch)) value -= 50;

    /* Stop boars having 239034 dam and hit for some reason */
    if (!IS_NPC(ch))
        value += str_app[get_curr_str(ch)].tohit;

    /* Vampire Rage */
    if (IS_CLASS(ch, CLASS_VAMPIRE) && ch->rage > 0)
	  value += ch->rage;

	if (IS_CLASS(ch, CLASS_NINJA) && ch->rage > 0)
	value += ch->rage;

	if (!IS_NPC(ch))
	if (IS_CLASS(ch, CLASS_NINJA) && ch->pcdata->powers[NPOWER_CHIKYU] >= 6
	&& ch->pcdata->powers[HARA_KIRI] > 0)
	value += 100;

    /* Werewolf Rage */
    if (IS_SET(ch->special,SPC_WOLFMAN) && ch->rage > 99)
	  value += ch->rage;

    if (IS_CLASS( ch,CLASS_DEMON) && ch->pcdata->stats[DEMON_POWER] > 0)
       value += (( ch->pcdata->stats[DEMON_POWER]) * ch->pcdata->stats[DEMON_POWER]);
        else if (IS_SET(ch->special,SPC_CHAMPION) && ch->pcdata->stats[DEMON_POWER] > 0)
        value += (( ch->pcdata->stats[DEMON_POWER]) * ch->pcdata->stats[DEMON_POWER]);

    /* Highlander */
    if (IS_CLASS(ch, CLASS_HIGHLANDER) && (get_eq_char(ch, WEAR_WIELD) != NULL))
    {
	int wpn = ch->wpn[1];
	  if (wpn >= 1000)
		value += 500;
	  else
		value += wpn/2;
    }

    return value;
}

int char_ac(CHAR_DATA *ch)
{
    int value = 0;

    value = GET_AC(ch);

	if (lost_kpower(ch)) value += 100;

    if (IS_AWAKE(ch))
   	value += dex_app[get_curr_dex(ch)].defensive;

    /* Highlander */
    if (IS_CLASS(ch, CLASS_HIGHLANDER) && (get_eq_char(ch, WEAR_WIELD) != NULL))
    {
	int wpn = ch->wpn[1];
	    value -= wpn;
    }

    return value;
}



/*
 * Show a list to a character.
 * Can coalesce duplicated items.
 */
void show_list_to_char( OBJ_DATA *list, CHAR_DATA *ch, bool fShort, bool fShowNothing )
{
    char buf[MAX_STRING_LENGTH];
    char **prgpstrShow;
    int *prgnShow;
    char *pstrShow;
    OBJ_DATA *obj;
    int nShow;
    int iShow;
    int count;
    bool fCombine;

    if ( ch->desc == NULL )
	return;

    /*
     * Alloc space for output lines.
     */
    count = 0;
    for ( obj = list; obj != NULL; obj = obj->next_content )
	count++;
    prgpstrShow	= alloc_mem( count * sizeof(char *) );
    prgnShow    = alloc_mem( count * sizeof(int)    );
    nShow	= 0;

    /*
     * Format the list of objects.
     */
    for ( obj = list; obj != NULL; obj = obj->next_content )
    { 
	if (!IS_NPC(ch) && ch->pcdata->chobj != NULL && obj->chobj != NULL && obj->chobj == ch)
	    continue;
	if ( obj->wear_loc == WEAR_NONE && can_see_obj( ch, obj ) )
	{
	    pstrShow = format_obj_to_char( obj, ch, fShort );
	    fCombine = FALSE;

	    if ( IS_NPC(ch) || IS_SET(ch->act, PLR_COMBINE) )
	    {
		/*
		 * Look for duplicates, case sensitive.
		 * Matches tend to be near end so run loop backwords.
		 */
		for ( iShow = nShow - 1; iShow >= 0; iShow-- )
		{
		    if ( !strcmp( prgpstrShow[iShow], pstrShow ) )
		    {
			prgnShow[iShow]++;
			fCombine = TRUE;
			break;
		    }
		}
	    }

	    /*
	     * Couldn't combine, or didn't want to.
	     */
	    if ( !fCombine )
	    {
		prgpstrShow [nShow] = str_dup( pstrShow );
		prgnShow    [nShow] = 1;
		nShow++;
	    }
	}
    }

    /*
     * Output the formatted list.
     */
    for ( iShow = 0; iShow < nShow; iShow++ )
    {
	if ( IS_NPC(ch) || IS_SET(ch->act, PLR_COMBINE) )
	{
	    if ( prgnShow[iShow] != 1 )
	    {
		sprintf( buf, "(%2d) ", prgnShow[iShow] );
		send_to_char( buf, ch );
	    }
	    else
	    {
		send_to_char( "     ", ch );
	    }
	}
	send_to_char( prgpstrShow[iShow], ch );
	send_to_char( "\n\r", ch );
	free_string( prgpstrShow[iShow] );
    }

    if ( fShowNothing && nShow == 0 )
    {
	if ( IS_NPC(ch) || IS_SET(ch->act, PLR_COMBINE) )
	    send_to_char( "     ", ch );
	send_to_char( "Nothing.\n\r", ch );
    }

    /*
     * Clean up.
     */
    free_mem( prgpstrShow, count * sizeof(char *) );
    free_mem( prgnShow,    count * sizeof(int)    );

    return;
}



void show_char_to_char_0( CHAR_DATA *victim, CHAR_DATA *ch )
{
    char buf[MAX_STRING_LENGTH];
    char buf2[MAX_STRING_LENGTH];
    char buf3[MAX_STRING_LENGTH];
    char buf4[MAX_STRING_LENGTH];
    char buf6[MAX_STRING_LENGTH];
    char buf7[MAX_STRING_LENGTH];
    char mount2[MAX_STRING_LENGTH];
    CHAR_DATA *mount;

    buf[0] = '\0';
    buf2[0] = '\0';
    buf3[0] = '\0';
    buf6[0] = '\0';


    if (!IS_NPC(victim) && victim->pcdata->chobj != NULL )
	return;

    if ((mount = victim->mount) != NULL && IS_SET(victim->mounted, IS_MOUNT))
	return;

    if ( !IS_NPC(victim) && IS_SET(victim->flag2, VAMP_OBJMASK) )
    {
	sprintf(buf, "     %s\n\r",victim->objdesc);
	stc(buf,ch);
	return;
    }

     if (victim->cur_form != 0)
    {
    buf[0] = '\0';
   
    if ( IS_HEAD(victim, LOST_HEAD) && IS_AFFECTED(victim, AFF_POLYMORPH))
	strcat( buf, "     " );
 else {
	if (!IS_NPC(victim) && victim->desc==NULL ) strcat( buf,"(Link-Dead) ");
    	if ( IS_AFFECTED(victim, AFF_INVISIBLE)   ) strcat( buf, "(Invis) "   );
    	if ( IS_AFFECTED(victim, AFF_HIDE)        ) strcat( buf, "(Hide) " );
    	if ( IS_AFFECTED(victim, AFF_CHARM)       ) strcat( buf, "(Charmed) " );
    	if ( IS_AFFECTED(victim, AFF_PASS_DOOR)  || 
           IS_AFFECTED(victim, AFF_ETHEREAL)    ) strcat( buf, "(Translucent) ");
    	if ( IS_AFFECTED(victim, AFF_FAERIE_FIRE) ) strcat( buf, "(Pink Aura) "  );
    	if ( IS_EVIL(victim)
    	&&   IS_AFFECTED(ch, AFF_DETECT_EVIL)     ) strcat( buf, "(Red Aura) "   );
    	if ( IS_AFFECTED(victim, AFF_SANCTUARY)   ) strcat( buf, "(White Aura) " );
      }
    if ( IS_AFFECTED(ch, AFF_SHADOWPLANE) 
     && !IS_AFFECTED(victim, AFF_SHADOWPLANE))    strcat( buf, "(Normal Plane) ");
    else if ( !IS_AFFECTED(ch, AFF_SHADOWPLANE) 
        && IS_AFFECTED(victim, AFF_SHADOWPLANE))  strcat( buf, "(Shadowplane) "     );
    
    if (ch->class > 0)
    {
       if (IS_CLASS(victim, CLASS_VAMPIRE))
                strcat(buf, "(Vampire) ");
       if (IS_CLASS(victim, CLASS_WEREWOLF))
		strcat(buf, "(Werewolf) ");
       if (IS_CLASS(victim, CLASS_MONK))
	        strcat(buf, "(Monk) ");
       if (IS_CLASS(victim, CLASS_DEMON))
	        strcat(buf, "(Daemon) ");
       if (IS_CLASS(victim, CLASS_DROW))
	        strcat(buf, "(Drow)" );
       if (IS_CLASS(victim, CLASS_MAGE))
                strcat(buf, "(Warlock) ");
       if (IS_CLASS(victim, CLASS_DEMON) && IS_CLASS(ch, CLASS_DEMON))
       {
                strcat(buf, "(" );
		strcat(buf, victim->pcdata->switchname );
	        strcat(buf, ") " );
       }
       if (IS_VAMPAFF(ch, VAM_DISGUISED) && IS_CLASS(ch, CLASS_VAMPIRE))
       {
                strcat(buf, "(" );
		strcat(buf, victim->pcdata->switchname );
	        strcat(buf, ") " );
       }
       if (ch->class == victim->class && victim->cur_form != get_normal_form(victim) && !IS_CLASS(victim, CLASS_DEMON))
       {
		strcat(buf, "(" );
		strcat(buf, victim->pcdata->switchname );
 	        strcat(buf, ") " );
       }
    }

/*
    if (victim->cur_form == FRM_MIST && victim->position == POS_STANDING)
    	strcat(buf, "A flowing white mist is here, swirling around the room.");
    else if (victim->cur_form == FRM_MIST)
	strcat(buf, "A flowing white mist");
    else if (victim->cur_form == FRM_WOLF && victim->position == POS_STANDING)
    	strcat(buf, "A ferocious dire wolf is here snarling at you.");
    else if (victim->cur_form == FRM_WOLF)
	strcat(buf, "A ferocious dire wolf");
    else if (victim->cur_form == FRM_BAT && victim->position == POS_STANDING)
    	strcat(buf, "A vampire bat is flying around here.");
    else if (victim->cur_form == FRM_BAT)
	strcat(buf, "A vampire bat");
    else if (victim->cur_form == FRM_DOLPHIN && victim->position == POS_STANDING)
    	strcat(buf, "A beautiful dolphin is swimming around here.");
    else if (victim->cur_form == FRM_DOLPHIN)
	strcat(buf, "A beautiful dolphin");
    else if (victim->cur_form == FRM_FLAME && victim->position == POS_STANDING)
    	strcat(buf, "A roaring pillar of flame stands in the centre of the room.");
    else if (victim->cur_form == FRM_FLAME)
	strcat(buf, "A roaring pillar of flame");
    else if (victim->cur_form == FRM_SPIDER && victim->position == POS_STANDING)
    	strcat(buf, "A hairy little spider is creeping along here.");
    else if (victim->cur_form == FRM_SPIDER)
	strcat(buf, "A hairy little spider");
    else if (victim->cur_form == FRM_LIGHT && victim->position == POS_STANDING)
    	strcat(buf, "A ball of glowing light hangs in mid-air here.");
    else if (victim->cur_form == FRM_LIGHT)
	strcat(buf, "A ball of glowing light");
    else if (victim->cur_form == FRM_COCKROACH && victim->position == POS_STANDING)
    	strcat(buf, "A nasty little cockroach is here, waiting to be squished.");
    else if (victim->cur_form == FRM_COCKROACH)
	strcat(buf, "A nasty little cockroach");
    else if (victim->cur_form == FRM_RABBIT && victim->position == POS_STANDING)
    	strcat(buf, "A cute little bunny rabbit is sitting here.");
    else if (victim->cur_form == FRM_RABBIT)
	strcat(buf, "A cute little bunny rabbit");
    else if (victim->cur_form == FRM_BLOB && victim->position == POS_STANDING)
    	strcat(buf, "A slimy green blob is oozing in a corner.");
    else if (victim->cur_form == FRM_BLOB)
	strcat(buf, "A slimy green blob");
    else if (victim->cur_form == FRM_FROG && victim->position == POS_STANDING)
    	strcat(buf, "A slimy little frog is sitting on the floor.");
    else if (victim->cur_form == FRM_FROG)
	strcat(buf, "A slimy little frog");
    else if (victim->cur_form == FRM_WHIRLWIND && victim->position == POS_STANDING)
    	strcat(buf, "A roaring whirlwind is sweeping you around the room.");
    else if (victim->cur_form == FRM_WHIRLWIND)
	strcat(buf, "A roaring whirlwind");
    else if (victim->cur_form == FRM_CRIMSON && victim->position == POS_STANDING)
    	strcat(buf, "An eerie pinkish mist hangs suspended in the air.");
    else if (victim->cur_form == FRM_CRIMSON)
	strcat(buf, "An eerie pinkish mist");
    else if (victim->cur_form == FRM_HAWK && victim->position == POS_STANDING)
    	strcat(buf, "A hawk flies gracefully overhead.");
    else if (victim->cur_form == FRM_HAWK)
	strcat(buf, "A hawk");
*/
    if (victim->cur_form != 0)
    {
	if (victim->position == POS_STANDING)
	{
	    char buf2[MAX_STRING_LENGTH];
	    form_in_room_desc(victim, buf2);
	    strcat(buf, buf2);
	}
	else
	{
	    if (is_vowel(form_data[victim->cur_form].lookname[0]))
	        strcat(buf, "An ");
	    else strcat(buf, "A ");
	    strcat(buf, form_data[victim->cur_form].lookname);
	}
    }
    
    switch ( victim->position )
    {
    case POS_DEAD:     strcat( buf, " is lying dead on the floor." ); break;
    case POS_MORTAL:   strcat( buf, " is lying here, mortally wounded." ); break;
    case POS_INCAP:    strcat( buf, " is lying here incapacitated." ); break;
    case POS_STUNNED:  strcat( buf, " is lying here stunned." ); break;
    case POS_SLEEPING: strcat(buf," is sleeping here."); break;
    case POS_RESTING:  strcat( buf, " is resting here." ); break;
    case POS_SITTING:  strcat(buf, " is sitting here."); break;
    case POS_FIGHTING:
	strcat( buf, " is here, fighting " );
	if ( victim->fighting == NULL )
	    strcat( buf, "thin air??" );
	else if ( victim->fighting == ch )
	    strcat( buf, "YOU!" );
	else if ( victim->in_room == victim->fighting->in_room )
	{
	    strcat( buf, PERS( victim->fighting, ch ) );
	    strcat( buf, "." );
	}
	else
	    strcat( buf, "someone who left??" );
	break;
    }

    strcat( buf, "\n\r" );
    buf[0] = UPPER(buf[0]);
    send_to_char( buf, ch );
    return;
    }	


    if ( IS_HEAD(victim, LOST_HEAD) && IS_AFFECTED(victim, AFF_POLYMORPH))
	strcat( buf, "     " );
    else {
	if (!IS_NPC(victim) && victim->desc==NULL ) strcat( buf,"(Link-Dead) ");
    	if ( IS_AFFECTED(victim, AFF_INVISIBLE)   ) strcat( buf, "(Invis) "   );
    	if ( IS_AFFECTED(victim, AFF_HIDE)        ) strcat( buf, "(Hide) "    );
    	if ( IS_AFFECTED(victim, AFF_CHARM)       ) strcat( buf, "(Charmed) " );
    	if ( IS_AFFECTED(victim, AFF_PASS_DOOR)  ||
         IS_AFFECTED(victim, AFF_ETHEREAL)    )
	 strcat( buf, "(Translucent) ");
    	if ( IS_AFFECTED(victim, AFF_FAERIE_FIRE) ) strcat( buf, "(Pink Aura) "  );
    	if ( IS_EVIL(victim)
    	&&   IS_AFFECTED(ch, AFF_DETECT_EVIL)     ) strcat( buf, "(Red Aura) "   );
    	if ( IS_AFFECTED(victim, AFF_SANCTUARY)   ) strcat( buf, "(White Aura) " );
    }
    if ( IS_AFFECTED(ch, AFF_SHADOWPLANE) && !IS_AFFECTED(victim, AFF_SHADOWPLANE))
	strcat( buf, "(Normal plane) "     );
    else if ( !IS_AFFECTED(ch, AFF_SHADOWPLANE) && IS_AFFECTED(victim, AFF_SHADOWPLANE))
	strcat( buf, "(Shadowplane) "     );
    /* Vampires and werewolves can recognise each other - KaVir */
    else if ( !IS_NPC(victim) && !IS_NPC(ch) && IS_CLASS(victim,CLASS_WEREWOLF)
	&& IS_HERO(victim) && IS_HERO(ch) &&
	(IS_CLASS(ch, CLASS_VAMPIRE) || IS_CLASS(ch, CLASS_WEREWOLF)
	|| IS_CLASS(ch, CLASS_HIGHLANDER) || IS_CLASS( ch, CLASS_DEMON)
        || IS_SET(ch->special, SPC_CHAMPION) ||IS_CLASS(ch, CLASS_DROW)))
	strcat( buf, "(Werewolf) " );
    else if ( !IS_NPC(victim) && !IS_NPC(ch) && IS_CLASS( victim,CLASS_DEMON)
	&& IS_HERO(victim) && IS_HERO(ch) && IS_SET(victim->special, SPC_DEMON_LORD) 
	&& (IS_CLASS(ch, CLASS_VAMPIRE) || IS_CLASS(ch, CLASS_WEREWOLF)
	|| IS_CLASS(ch, CLASS_HIGHLANDER) || IS_CLASS(ch, CLASS_DEMON)
        || IS_SET(ch->special, SPC_CHAMPION) ||IS_CLASS(ch, CLASS_DROW)))
	strcat( buf, "(Demon Lord) " );
    else if ( !IS_NPC(victim) && !IS_NPC(ch) && IS_SET(victim->special,SPC_CHAMPION)
	&& IS_HERO(victim) && IS_HERO(ch) &&
	(IS_CLASS(ch, CLASS_VAMPIRE) || IS_CLASS(ch, CLASS_WEREWOLF)
	|| IS_CLASS(ch, CLASS_HIGHLANDER) || IS_CLASS( ch, CLASS_DEMON)
        || IS_SET(ch->special, SPC_CHAMPION) ||IS_CLASS(ch, CLASS_DROW)))
    {
	    strcat( buf, "(Demon) " );
    }
    else if ( !IS_NPC(victim) && !IS_NPC(ch) && IS_CLASS(victim, CLASS_HIGHLANDER)
	&& IS_HERO(victim) && IS_HERO(ch) &&
	(IS_CLASS(ch, CLASS_VAMPIRE) || IS_CLASS(ch, CLASS_WEREWOLF)
	|| IS_CLASS(ch, CLASS_HIGHLANDER) || IS_CLASS(ch, CLASS_DEMON)
        || IS_SET(ch->special, SPC_CHAMPION) ||IS_CLASS(ch, CLASS_DROW)))
	strcat( buf, "(Highlander) " );
    else if ( !IS_NPC(victim) && !IS_NPC(ch) && IS_CLASS(victim, CLASS_MAGE)
	&& IS_HERO(victim) && IS_HERO(ch) &&
	(IS_CLASS(ch, CLASS_VAMPIRE) || IS_CLASS(ch, CLASS_WEREWOLF)
	|| IS_CLASS(ch, CLASS_HIGHLANDER) || IS_CLASS( ch, CLASS_DEMON)
        || IS_SET(ch->special, SPC_CHAMPION) ||IS_CLASS(ch, CLASS_DROW)))
    {
	if (victim->level == LEVEL_APPRENTICE)    strcat( buf,"(Apprentice) " );
	else if (victim->level == LEVEL_MAGE)     strcat( buf,"(Mage) " );
	else if (victim->level == LEVEL_ARCHMAGE) strcat( buf,"(Archmage) " );
    }
    else if ( !IS_NPC(victim) && !IS_NPC(ch) && IS_CLASS(victim, CLASS_DROW) 
	&& IS_HERO(victim) && IS_HERO(ch) &&
	(IS_CLASS(ch, CLASS_VAMPIRE) || IS_CLASS(ch, CLASS_WEREWOLF)
	|| IS_CLASS(ch, CLASS_HIGHLANDER) || IS_CLASS(ch, CLASS_DEMON)
	|| IS_SET(ch->special, SPC_CHAMPION) ||IS_CLASS(ch, CLASS_MONK)))
		strcat(buf, "(Drow) ");
    if ( !IS_NPC(ch) && IS_VAMPAFF(ch,VAM_AUSPEX) && 
	 !IS_NPC(victim) && IS_CLASS(victim, CLASS_VAMPIRE) &&
	  IS_VAMPAFF(victim, VAM_DISGUISED) )
    {
	strcat( buf, "(");
	strcat( buf, victim->name);
	strcat( buf, ") ");
    }
if (victim->embracing!= NULL)
{
sprintf(buf7,"\n\r...%s is holding %s in a stern embrace!",victim->name,victim->embracing->name);
}
else if (victim->embraced!=NULL)
{
sprintf(buf7,"\n\r...%s is being embraced by %s!",victim->name,victim->embraced->name);
}
    if ( IS_EXTRA(victim, EXTRA_ROT))
     {
        if (IS_NPC(victim)) 
          sprintf(buf6,"\n\r...%s is coated with a layer of rotten skin!",victim->short_descr);
        else if (!IS_NPC(victim) && IS_AFFECTED(victim,AFF_POLYMORPH))
           sprintf(buf6,"\n\r...%s is coated with a layer of rotten skin!",victim->morph);
        else 
           sprintf(buf6,"\n\r...%s is coated with a layer of rotten skin!",victim->name);
       }
    if ( IS_AFFECTED(victim, AFF_FLAMING) ) 
    {
	if (IS_NPC(victim))
	    sprintf( buf2, "\n\r...%s is engulfed in blazing flames!", victim->short_descr );
	else if (!IS_NPC(victim) && IS_AFFECTED(victim,AFF_POLYMORPH))
	    sprintf( buf2, "\n\r...%s is engulfed in blazing flames!", victim->morph );
	else
	    sprintf( buf2, "\n\r...%s is engulfed in blazing flames!", victim->name );
    }

    if ( !IS_NPC(victim) && IS_HEAD(victim, LOST_HEAD) && IS_AFFECTED(victim, AFF_POLYMORPH)) 
    {
	if (IS_EXTRA(victim,GAGGED) && IS_EXTRA(victim,BLINDFOLDED))
	    sprintf( buf3, "...%s is gagged and blindfolded, kinky!", victim->morph );
	else if (IS_EXTRA(victim,GAGGED))
	    sprintf( buf3, "...%s is gagged!", victim->morph );
	else if (IS_EXTRA(victim,BLINDFOLDED))
	    sprintf( buf3, "...%s is blindfolded!", victim->morph );
    }

    if ( IS_HEAD(victim, LOST_HEAD) && IS_AFFECTED(victim, AFF_POLYMORPH))
    {
	strcat( buf, victim->morph );
	strcat( buf, " is lying here." );
    	strcat( buf, buf2 );
    	strcat( buf, buf3 );
    	strcat( buf, buf6 );
        strcat(buf,buf7);   
     strcat( buf, "\n\r" );
    	buf[5] = UPPER(buf[5]);
    	send_to_char( buf, ch );
	return;
    }
    
    if ( IS_EXTRA(victim, TIED_UP) ) 
    {
	if (IS_NPC(victim))
	    sprintf( buf3, "\n\r...%s is tied up", victim->short_descr );
	else if (!IS_NPC(victim) && IS_AFFECTED(victim,AFF_POLYMORPH))
	    sprintf( buf3, "\n\r...%s is tied up", victim->morph );
	else
	    sprintf( buf3, "\n\r...%s is tied up", victim->name );
	if (IS_EXTRA(victim,GAGGED) && IS_EXTRA(victim,BLINDFOLDED))
	    strcat( buf3, ", gagged and blindfolded!" );
	else if (IS_EXTRA(victim,GAGGED))
	    strcat( buf3, " and gagged!" );
	else if (IS_EXTRA(victim,BLINDFOLDED))
	    strcat( buf3, " and blindfolded!" );
	else
	    strcat( buf3, "!" );
    }

    if ( IS_AFFECTED(victim, AFF_WEBBED) ) 
    {
	if (IS_NPC(victim))
	    sprintf( buf4, "\n\r...%s is coated in a sticky web.", victim->short_descr );
	else if (!IS_NPC(victim) && IS_AFFECTED(victim,AFF_POLYMORPH))
	    sprintf( buf4, "\n\r...%s is coated in a sticky web.", victim->morph );
	else
	    sprintf( buf4, "\n\r...%s is coated in a sticky web.", victim->name );
	strcat( buf3, buf4 );
    }
        if ( IS_AFFECTED(victim, AFF_TENDRILS) ) 
    {
	if (IS_NPC(victim))
sprintf( buf4, "\n\r...%s is entrapped by tendrils of darkness.",
victim->short_descr );
	else if (!IS_NPC(victim) && IS_AFFECTED(victim,AFF_POLYMORPH))
sprintf( buf4, "\n\r...%s is entrapped by tendrils of darkness.",
victim->morph );
	else
sprintf( buf4, "\n\r...%s is entrapped by tendrils of darkness.",
victim->name );
	strcat( buf3, buf4 );
    }

    if ( !IS_NPC(victim) && IS_AFFECTED(victim, AFF_POLYMORPH) )
	strcat( buf, victim->morph );
    else if ( victim->position == POS_STANDING && victim->long_descr[0] != '\0' && (mount = victim->mount) == NULL )
    {
	strcat( buf, victim->long_descr );
	send_to_char( buf, ch );
	if ( IS_NPC(ch) || !IS_SET(ch->act, PLR_BRIEF) )
	{
	    if ( IS_ITEMAFF(victim, ITEMA_SHOCKSHIELD) ) 
		act( "...$N is surrounded by a crackling shield of lightning.", ch,NULL,victim,TO_CHAR );
	    if ( IS_ITEMAFF(victim, ITEMA_FIRESHIELD) ) 
		act( "...$N is surrounded by a burning shield of fire.", ch,NULL,victim,TO_CHAR );
	    if ( IS_ITEMAFF(victim, ITEMA_ICESHIELD) ) 
		act( "...$N is surrounded by a shimmering shield of ice.", ch,NULL,victim,TO_CHAR );
	    if ( IS_ITEMAFF(victim, ITEMA_ACIDSHIELD) ) 
		act( "...$N is surrounded by a bubbling shield of acid.", ch,NULL,victim,TO_CHAR );
	    if ( IS_ITEMAFF(victim, ITEMA_CHAOSSHIELD) ) 
		act( "...$N is surrounded by a swirling shield of chaos.", ch,NULL,victim,TO_CHAR );
	    if ( IS_ITEMAFF(victim, ITEMA_REFLECT) ) 
		act( "...$N is surrounded by a flickering shield of darkness.", ch,NULL,victim,TO_CHAR );
	}
	return;
    }
    else
    	strcat( buf, PERS( victim, ch ) );

    if ((mount = victim->mount) != NULL && victim->mounted == IS_RIDING)
    {
	if (IS_NPC(mount))
	    sprintf( mount2, " is here riding %s", mount->short_descr );
	else
	    sprintf( mount2, " is here riding %s", mount->name );
	strcat( buf, mount2 );
	if (victim->position == POS_FIGHTING)
	{
	    strcat( buf, ", fighting " );
	    if ( victim->fighting == NULL )
	        strcat( buf, "thin air??" );
	    else if ( victim->fighting == ch )
	    strcat( buf, "YOU!" );
	    else if ( victim->in_room == victim->fighting->in_room )
	    {
	        strcat( buf, PERS( victim->fighting, ch ) );
	        strcat( buf, "." );
	    }
	    else
	        strcat( buf, "somone who left??" );
	}
	else strcat( buf, "." );
    }
    else if ( victim->position == POS_STANDING && IS_AFFECTED(victim, AFF_FLYING) )
	strcat( buf, " is hovering here" );
    else if ( victim->position == POS_STANDING && (!IS_NPC(victim) && (IS_VAMPAFF(victim, VAM_FLYING))) )
	strcat( buf, " is hovering here" );
    else if (victim->position == POS_STANDING && (!IS_NPC(victim) &&
IS_CLASS(victim, CLASS_DROW) && IS_SET(victim->pcdata->powers[1], DPOWER_LEVITATION)))
	strcat(buf, " is hovering here" );
    else
    {
    	switch ( victim->position )
    	{
    	case POS_DEAD:     strcat( buf, " is DEAD!!" );              break;
        case POS_MORTAL:   strcat( buf, " is mortally wounded." );   break; 
    	case POS_INCAP:    strcat( buf, " is incapacitated." );      break;
    	case POS_STUNNED:  strcat( buf, " is lying here stunned." ); break;
    	case POS_SLEEPING: strcat( buf, " is sleeping here." );      break;
    	case POS_RESTING:  strcat( buf, " is resting here." );       break;
    	case POS_MEDITATING: strcat( buf, " is meditating here." );  break;
    	case POS_SITTING:  strcat( buf, " is sitting here." );       break;
    	case POS_STANDING:
	    if      (!IS_NPC(victim) && victim->stance[0] == STANCE_NORMAL)
		strcat( buf, " is here, crouched in a fighting stance." );
	    else if (!IS_NPC(victim) && victim->stance[0] == STANCE_VIPER)
		strcat( buf, " is here, crouched in a viper fighting stance." );
	    else if (!IS_NPC(victim) && victim->stance[0] == STANCE_CRANE)
		strcat( buf, " is here, crouched in a crane fighting stance." );
	    else if (!IS_NPC(victim) && victim->stance[0] == STANCE_CRAB)
		strcat( buf, " is here, crouched in a crab fighting stance." );
	    else if (!IS_NPC(victim) && victim->stance[0] == STANCE_MONGOOSE)
		strcat( buf, " is here, crouched in a mongoose fighting stance." );
	    else if (!IS_NPC(victim) && victim->stance[0] == STANCE_BULL)
		strcat( buf, " is here, crouched in a bull fighting stance." );
	    else if (!IS_NPC(victim) && victim->stance[0] == STANCE_MANTIS)
		strcat( buf, " is here, crouched in a mantis fighting stance." );
	    else if (!IS_NPC(victim) && victim->stance[0] == STANCE_DRAGON)
		strcat( buf, " is here, crouched in a dragon fighting stance." );
	    else if (!IS_NPC(victim) && victim->stance[0] == STANCE_TIGER)
		strcat( buf, " is here, crouched in a tiger fighting stance." );
	    else if (!IS_NPC(victim) && victim->stance[0] == STANCE_MONKEY)
		strcat( buf, " is here, crouched in a monkey fighting stance." );
	    else if (!IS_NPC(victim) && victim->stance[0] == STANCE_SWALLOW)
		strcat( buf, " is here, crouched in a swallow fighting stance." );
            else if (!IS_NPC(victim) && victim->stance[0] == STANCE_KOZUDO)
                strcat( buf, " is here, shifted in the kozudo fighting stance." );
	    else
		strcat( buf, " is here." );
	    break;
    	case POS_FIGHTING:
	    strcat( buf, " is here, fighting " );
	    if ( victim->fighting == NULL )
	        strcat( buf, "thin air??" );
	    else if ( victim->fighting == ch )
	    strcat( buf, "YOU!" );
	    else if ( victim->in_room == victim->fighting->in_room )
	    {
	        strcat( buf, PERS( victim->fighting, ch ) );
	        strcat( buf, "." );
	    }
	    else
	        strcat( buf, "somone who left??" );
	    break;
	}
    }

    strcat( buf, buf2 );
    strcat( buf, buf3 );
    strcat( buf, "\n\r" );
    buf[0] = UPPER(buf[0]);
    send_to_char( buf, ch );

    if ( !IS_NPC(ch) && IS_SET(ch->act, PLR_BRIEF) ) return;

    if ( IS_ITEMAFF(victim, ITEMA_SHOCKSHIELD) ) 
	act( "...$N is surrounded by a crackling shield of lightning.", ch,NULL,victim,TO_CHAR );
    if ( IS_ITEMAFF(victim, ITEMA_FIRESHIELD) ) 
	act( "...$N is surrounded by a burning shield of fire.", ch,NULL,victim,TO_CHAR );
    if ( IS_ITEMAFF(victim, ITEMA_ICESHIELD) ) 
	act( "...$N is surrounded by a shimmering shield of ice.", ch,NULL,victim,TO_CHAR );
    if ( IS_ITEMAFF(victim, ITEMA_ACIDSHIELD) ) 
	act( "...$N is surrounded by a bubbling shield of acid.", ch,NULL,victim,TO_CHAR );
    if ( IS_ITEMAFF(victim, ITEMA_CHAOSSHIELD) ) 
	act( "...$N is surrounded by a swirling shield of chaos.", ch,NULL,victim,TO_CHAR );
    if ( IS_ITEMAFF(victim, ITEMA_REFLECT) ) 
	act( "...$N is surrounded by a flickering shield of darkness.", ch,NULL,victim,TO_CHAR );
    return;
}



void evil_eye( CHAR_DATA *victim, CHAR_DATA *ch )
{
    char buf [MAX_STRING_LENGTH];
    int tabletype;

    if (IS_NPC(victim)) return;
    if (victim == ch) return;
    if (ch->level < 3 || victim->level < 3) return;
    if (victim->power[DISC_DAEM_DISC] < 2) return;
    if (victim->power[DISC_DAEM_DISC] < dice(1, 10)) return;
    if (!str_suffix(victim->poweraction,"gi") ||
	!str_suffix(victim->poweraction,"qui"))
	return;
    if (is_safe(ch, victim) ) return;
    if (victim->powertype != NULL && strlen(victim->powertype) > 1)
    {
	sprintf(buf,"\n\r%s\n\r",victim->powertype);
	send_to_char(buf,ch);
    }
    if (IS_SET(victim->spectype,EYE_SELFACTION) && victim->poweraction != NULL)
	interpret(victim,victim->poweraction);
    if (IS_SET(victim->spectype,EYE_ACTION) && victim->poweraction != NULL)
	interpret(ch,victim->poweraction);
    if (IS_SET(victim->spectype,EYE_SPELL) && victim->specpower > 0)
    {
	tabletype = skill_table[victim->specpower].target;
	(*skill_table[victim->specpower].spell_fun) (victim->specpower,victim->spl[tabletype],victim,ch);
    }
    return;
}


void show_char_to_char_1( CHAR_DATA *victim, CHAR_DATA *ch )
{
    char buf[MAX_STRING_LENGTH];
    OBJ_DATA *obj;
    int iWear;
    int percent;
    bool found;

    if ( can_see( victim, ch ) )
    {
	act( "$n looks at you.", ch, NULL, victim, TO_VICT    );
	act( "$n looks at $N.",  ch, NULL, victim, TO_NOTVICT );
    }

    if (!IS_NPC(ch) && IS_HEAD(victim,LOST_HEAD))
    {
	act( "$N is lying here.", ch, NULL, victim, TO_CHAR );
	return;
    }
    if ( victim->description[0] != '\0' )
    {
	send_to_char( victim->description, ch );
    }
    else
    {
	act( "You see nothing special about $M.", ch, NULL, victim, TO_CHAR );
    }

    if ( victim->max_hit > 0 )
	percent = ( 100 * victim->hit ) / victim->max_hit;
    else
	percent = -1;

    strcpy( buf, PERS(victim, ch) );

         if ( percent >= 100 ) strcat( buf, " is in perfect health.\n\r"  );
    else if ( percent >=  90 ) strcat( buf, " is slightly scratched.\n\r" );
    else if ( percent >=  80 ) strcat( buf, " has a few bruises.\n\r"     );
    else if ( percent >=  70 ) strcat( buf, " has some cuts.\n\r"         );
    else if ( percent >=  60 ) strcat( buf, " has several wounds.\n\r"    );
    else if ( percent >=  50 ) strcat( buf, " has many nasty wounds.\n\r" );
    else if ( percent >=  40 ) strcat( buf, " is bleeding freely.\n\r"    );
    else if ( percent >=  30 ) strcat( buf, " is covered in blood.\n\r"   );
    else if ( percent >=  20 ) strcat( buf, " is leaking guts.\n\r"       );
    else if ( percent >=  10 ) strcat( buf, " is almost dead.\n\r"        );
    else                       strcat( buf, " is DYING.\n\r"              );

    buf[0] = UPPER(buf[0]);
    send_to_char( buf, ch );
 
    if (!IS_NPC( victim ))
    {
    	if (IS_AFFECTED(victim, AFF_INFRARED) || IS_VAMPAFF(victim, VAM_NIGHTSIGHT)) act("$N's eyes are glowing bright red.",ch,NULL,victim,TO_CHAR);
    	if (IS_AFFECTED(victim, AFF_FLYING)) act("$N is hovering in the air.",ch,NULL,victim,TO_CHAR);
	if (!IS_NPC(victim) && IS_CLASS(victim, CLASS_DROW) &&
IS_SET(victim->pcdata->powers[1], DPOWER_LEVITATION))
	act("$N is hovering in the air.", ch,NULL,victim,TO_CHAR);
	if (!IS_NPC(victim) && IS_CLASS(victim, CLASS_DROW) &&
IS_SET(victim->pcdata->powers[1], DPOWER_ARMS))
	act("$N has 6 extra spidery arms protruding from $S body.",ch,NULL,victim,TO_CHAR);
    	if (IS_VAMPAFF(victim, VAM_FANGS)) act("$N has a pair of long, pointed fangs.",ch,NULL,victim,TO_CHAR);
    	if (!IS_NPC(victim) && IS_CLASS(victim, CLASS_VAMPIRE) && IS_VAMPAFF(victim, VAM_CLAWS))
		act("$N has razor sharp claws protruding from under $S finger nails.",ch,NULL,victim,TO_CHAR);
	else if (IS_CLASS(victim, CLASS_NINJA) && IS_VAMPAFF(victim, VAM_CLAWS))
	act("$N has IronClaws protruding from $S wrists.",ch,NULL,victim,TO_CHAR);
    	else if (!IS_NPC(victim) && IS_VAMPAFF(victim, VAM_CLAWS))
		act("$N has razor sharp talons extending from $S fingers.",ch,NULL,victim,TO_CHAR);
    	if (!IS_NPC(victim))
    	{
	if (!IS_CLASS(ch, CLASS_VAMPIRE) && IS_SET(ch->newbits, NEW_SKIN))
act("$N has scales all over $S body.",ch,NULL,victim,TO_CHAR);
		if (IS_VAMPAFF(victim, VAM_HORNS)) act("$N has a pair of pointed horns extending from $S head.",ch,NULL,victim,TO_CHAR);
		if (IS_VAMPAFF(victim, VAM_WINGS))
		{
	    		if (IS_DEMAFF(victim, DEM_UNFOLDED))
				act("$N has a pair of batlike wings spread out from behind $S back.",ch,NULL,victim,TO_CHAR);
    		else
 		act("$N has a pair of batlike wings folded behind $S back.",ch,NULL,victim,TO_CHAR);
		}
	if (IS_VAMPAFF(victim, VAM_HEAD))
	 {
	   act("$N's head resembles that of a fierce lion.",ch,NULL,victim,TO_CHAR);
	 }
   if (IS_VAMPAFF(victim, VAM_TAIL))
	act("$N has a sharp tail extending from $S spine.",ch,NULL,victim,TO_CHAR); 
   if (IS_VAMPAFF(victim, VAM_EXOSKELETON))
	act("$N's skin is covered by a hard exoskeleton.",ch,NULL,victim,TO_CHAR);
 
  	}
    }
    found = FALSE;
    for ( iWear = 0; iWear < MAX_WEAR; iWear++ )
    {
	if ( ( obj = get_eq_char( victim, iWear ) ) != NULL
	&&   can_see_obj( ch, obj ) )
	{
	    if ( !found )
	    {
		send_to_char( "\n\r", ch );
		act( "$N is using:", ch, NULL, victim, TO_CHAR );
		found = TRUE;
	    }
	    send_to_char( where_name[iWear], ch );
	    if (IS_NPC(ch) || ch->pcdata->chobj == NULL || ch->pcdata->chobj != obj)
	    {
	    	send_to_char( format_obj_to_char( obj, ch, TRUE ), ch );
	    	send_to_char( "\n\r", ch );
	    }
	    else
		send_to_char( "you\n\r", ch);
	}
    }

    if ( victim != ch
    &&   !IS_NPC(ch)
    &&   !IS_HEAD(victim, LOST_HEAD)
    &&   number_percent( ) < ch->pcdata->learned[gsn_peek] )
    {
	send_to_char( "\n\rYou peek at the inventory:\n\r", ch );
	show_list_to_char( victim->carrying, ch, TRUE, TRUE );
    }

    return;
}



void show_char_to_char( CHAR_DATA *list, CHAR_DATA *ch )
{
    CHAR_DATA *rch;

    for ( rch = list; rch != NULL; rch = rch->next_in_room )
    {
	if ( rch == ch )
	    continue;

	if ( IS_IMMORTAL(ch) || IS_IMMORTAL(rch) )
	{
	    if ( !IS_NPC(rch)
	    &&   IS_SET(rch->act, PLR_WIZINVIS)
	    &&   get_trust( ch ) < get_trust( rch ) )
		continue;
	}
	else
	{
	    if ( !IS_NPC(rch)
	    && ( IS_SET(rch->act, PLR_WIZINVIS)
	    ||   IS_ITEMAFF(rch, ITEMA_VANISH) )
	    &&   !IS_SET(ch->act, PLR_HOLYLIGHT)
	    &&   !IS_ITEMAFF(ch, ITEMA_VISION) )
		continue;
	}

	if ( !IS_NPC(rch) && IS_HEAD(rch,LOST_HEAD))
	    continue;

	if ( !IS_NPC(rch) && IS_EXTRA(rch,EXTRA_OSWITCH))
	    continue;

	if ( can_see( ch, rch ) )
	    show_char_to_char_0( rch, ch );
	else if ( room_is_dark( ch->in_room )
	&&      ( IS_AFFECTED(rch, AFF_INFRARED)||(!IS_NPC(rch)&&IS_VAMPAFF(rch, VAM_NIGHTSIGHT))))
	{
	    send_to_char( "You see glowing red eyes watching YOU!\n\r", ch );
	}
    }

    return;
} 



bool check_blind( CHAR_DATA *ch )
{

    if ( IS_EXTRA(ch, BLINDFOLDED) )
    {
        send_to_char( "You can't see a thing through the blindfold!\n\r", ch );
        return FALSE;
    }     

    if ( !IS_NPC(ch) && IS_SET(ch->act, PLR_HOLYLIGHT) )
	return TRUE;

    if ( IS_ITEMAFF(ch, ITEMA_VISION) )
	return TRUE;

    if ( IS_HEAD(ch, LOST_EYE_L) && IS_HEAD(ch, LOST_EYE_R) )
    {
	send_to_char( "You have no eyes!\n\r", ch );
	return FALSE;
    }

    if ( IS_AFFECTED(ch, AFF_BLIND) && !IS_AFFECTED(ch, AFF_SHADOWSIGHT))
    {
	send_to_char( "You can't see a thing!\n\r", ch );
	return FALSE;
    }

    return TRUE;
}



void do_look( CHAR_DATA *ch, char *argument )
{
    char buf  [MAX_STRING_LENGTH];
    char arg1 [MAX_INPUT_LENGTH];
    char arg2 [MAX_INPUT_LENGTH];
    EXIT_DATA *pexit;
    CHAR_DATA *victim;
    CHAR_DATA *vch;
    CHAR_DATA *vch_next;
    CHAR_DATA *wizard;
    OBJ_DATA *obj;
    OBJ_DATA *portal;
    OBJ_DATA *portal_next;
    ROOM_INDEX_DATA *pRoomIndex;
    ROOM_INDEX_DATA *location;
    char *pdesc;
    int door;
    bool found;

    if ( ch->desc == NULL && (wizard = ch->wizard) == NULL) return;

    if (ch->in_room == NULL) return;

    if ( ch->position < POS_SLEEPING )
    {
	send_to_char( "You can't see anything but stars!\n\r", ch );
	return;
    }

    if ( ch->position == POS_SLEEPING )
    {
	send_to_char( "You can't see anything, you're sleeping!\n\r", ch );
	return;
    }

    if ( IS_SET(ch->flag2,AFF_TOTALBLIND))
    {
    send_to_char("You can't see anything because you're blinded!\n\r",ch);
    return;
    }

    if ( !check_blind( ch ) )
	return;

    if ( !IS_NPC(ch) && IS_SET(ch->in_room->room_flags, ROOM_TOTAL_DARKNESS) &&
	!IS_ITEMAFF(ch, ITEMA_VISION) && !IS_IMMORTAL(ch) &&
!(IS_CLASS(ch, CLASS_DROW)))
    {
	send_to_char( "It is pitch black ... \n\r", ch );
	return;
    }

    if ( !IS_NPC(ch)
    &&   !IS_SET(ch->act, PLR_HOLYLIGHT)
    &&   !IS_ITEMAFF(ch, ITEMA_VISION)
    &&   !IS_VAMPAFF(ch, VAM_NIGHTSIGHT)
    &&   !IS_AFFECTED(ch, AFF_SHADOWPLANE)
    &&   !(ch->in_room != NULL && ch->in_room->vnum == ROOM_VNUM_IN_OBJECT
    &&   !IS_NPC(ch) && ch->pcdata->chobj != NULL
    &&   ch->pcdata->chobj->in_obj != NULL)
    &&   room_is_dark( ch->in_room ) )
    {
	send_to_char( "It is pitch black ... \n\r", ch );
	show_char_to_char( ch->in_room->people, ch );
	return;
    }

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if ( arg1[0] == '\0' || !str_cmp( arg1, "auto" ) )
    {
	/* 'look' or 'look auto' */
	if (ch->in_room != NULL && ch->in_room->vnum == ROOM_VNUM_IN_OBJECT
	&& !IS_NPC(ch) && ch->pcdata->chobj != NULL && ch->pcdata->chobj->in_obj != NULL)
	    act( "$p",ch,ch->pcdata->chobj->in_obj,NULL,TO_CHAR);
    	else if ( IS_AFFECTED(ch, AFF_SHADOWPLANE) )
	    send_to_char( "The shadow plane\n\r", ch );
	else
	{
	    sprintf(buf, "%s\n\r", ch->in_room->name);
	    send_to_char( buf, ch );
	}

	if ( !IS_NPC(ch) && IS_SET(ch->act, PLR_AUTOEXIT) )
	    do_exits( ch, "auto" );

	if (ch->in_room != NULL && ch->in_room->vnum == ROOM_VNUM_IN_OBJECT
	&& !IS_NPC(ch) && ch->pcdata->chobj != NULL && ch->pcdata->chobj->in_obj != NULL)
	{
	    act( "You are inside $p.",ch,ch->pcdata->chobj->in_obj,NULL,TO_CHAR);
	    show_list_to_char( ch->pcdata->chobj->in_obj->contains, ch, FALSE, FALSE );
	}
	else if ( (arg1[0] == '\0' || !str_cmp( arg1, "auto" ) ) && IS_AFFECTED(ch, AFF_SHADOWPLANE) )
	    send_to_char( "You are standing in complete darkness.\n\r", ch );
	else if ( ( !IS_NPC(ch) && !IS_SET(ch->act, PLR_BRIEF) ) &&
		( arg1[0] == '\0' || !str_cmp( arg1, "auto" ) ) )
	{
	    send_to_char( ch->in_room->description, ch );
	    if (ch->in_room->blood == 1000)
		sprintf(buf,"You notice that the room is completely drenched in blood.\n\r");
	    else if (ch->in_room->blood > 750)
		sprintf(buf,"You notice that there is a very large amount of blood around the room.\n\r");
	    else if (ch->in_room->blood > 500)
		sprintf(buf,"You notice that there is a large quantity of blood around the room.\n\r");
	    else if (ch->in_room->blood > 250)
		sprintf(buf,"You notice a fair amount of blood on the floor.\n\r");
	    else if (ch->in_room->blood > 100)
		sprintf(buf,"You notice several blood stains on the floor.\n\r");
	    else if (ch->in_room->blood > 50)
		sprintf(buf,"You notice a few blood stains on the floor.\n\r");
	    else if (ch->in_room->blood > 25)
		sprintf(buf,"You notice a couple of blood stains on the floor.\n\r");
	    else if (ch->in_room->blood > 0)
		sprintf(buf,"You notice a few drops of blood on the floor.\n\r");
	    else sprintf(buf,"You notice nothing special in the room.\n\r");
	    ADD_COLOUR(ch, buf, L_RED);
	    if (ch->in_room->blood > 0) send_to_char(buf,ch);
	}
            if (IS_SET(ch->in_room->room_flags, ROOM_FLAMING))
            send_to_char("..This room is engulfed in flames!\n\r",ch);

	show_list_to_char( ch->in_room->contents, ch, FALSE, FALSE );

        for (door=0 ; door < 6 ; door++)
	{	
	    if (ch->in_room == NULL) continue;
	    if (ch->in_room->exit[door] == NULL) continue;

	    if (IS_SET(ch->in_room->exit[door]->exit_info, EX_ICE_WALL))
	    {
		sprintf(buf, "     You see a glacier of ice %s.\n\r", exitname2[door]);
	        send_to_char(buf, ch);
	    }
	    else if (IS_SET(ch->in_room->exit[door]->exit_info,EX_CALTROP_WALL))
	    {
		sprintf(buf, "     You see a wall of caltrops %s.\n\r", exitname2[door]);
	        send_to_char(buf, ch);
	    }
	    else if (IS_SET(ch->in_room->exit[door]->exit_info,EX_FIRE_WALL))
	    {
		sprintf(buf, "     You see a blazing wall of fire %s.\n\r", exitname2[door]);
	        send_to_char(buf, ch);
	    }
	    else if (IS_SET(ch->in_room->exit[door]->exit_info,EX_SWORD_WALL))
	    {
		sprintf(buf, "     You see a spinning wall of swords %s.\n\r", exitname2[door]);
	        send_to_char(buf, ch);
	    }
	    else if (IS_SET(ch->in_room->exit[door]->exit_info,EX_MUSHROOM_WALL))
	    {
		sprintf(buf, "     You see a vibrating mound of mushrooms %s.\n\r", exitname2[door]);
	        send_to_char(buf, ch);
	    }
	    else if (IS_SET(ch->in_room->exit[door]->exit_info,EX_PRISMATIC_WALL)) 	    
	    {
		sprintf(buf, "     You see a shimmering wall of many colours %s.\n\r", exitname2[door]);
	        send_to_char(buf, ch);
	    }
	    else if (IS_SET(ch->in_room->exit[door]->exit_info, EX_IRON_WALL))
	    {
		sprintf(buf, "    You see a solid wall of iron %s.\n\r", exitname2[door]);
	        send_to_char(buf, ch);
	    }
	    else if (IS_SET(ch->in_room->exit[door]->exit_info, EX_ASH_WALL))
	    {
		sprintf(buf, "    You see a deadly wall of ash %s.\n\r", exitname2[door]);
	        send_to_char(buf, ch);
	    }
	}
	show_char_to_char( ch->in_room->people,   ch );
	return;
    }

    if ( !str_cmp( arg1, "i" ) || !str_cmp( arg1, "in" ) )
    {
	/* 'look in' */
	if ( arg2[0] == '\0' )
	{
	    send_to_char( "Look in what?\n\r", ch );
	    return;
	}

	if ( ( obj = get_obj_here( ch, arg2 ) ) == NULL )
	{
	    send_to_char( "You do not see that here.\n\r", ch );
	    return;
	}

	switch ( obj->item_type )
	{
	default:
	    send_to_char( "That is not a container.\n\r", ch );
	    break;

	case ITEM_PORTAL:
	    pRoomIndex = get_room_index(obj->value[0]);
	    location = ch->in_room;
	    if ( pRoomIndex == NULL )
	    {
		send_to_char( "It doesn't seem to lead anywhere.\n\r", ch );
		return;
	    }
	    if (obj->value[2] == 1 || obj->value[2] == 3)
	    {
		send_to_char( "It seems to be closed.\n\r", ch );
		return;
	    }
	    char_from_room(ch);
	    char_to_room(ch,pRoomIndex);

	    found = FALSE;
	    for ( portal = ch->in_room->contents; portal != NULL; portal = portal_next )
	    {
		portal_next = portal->next_content;
		if ( ( obj->value[0] == portal->value[3]  )
		    && (obj->value[3] == portal->value[0]) )
		{
		    found = TRUE;
		    if (IS_AFFECTED(ch, AFF_SHADOWPLANE) &&
			!IS_SET(portal->extra_flags, ITEM_SHADOWPLANE) )
		    {
			REMOVE_BIT(ch->affected_by, AFF_SHADOWPLANE);
	    		do_look(ch,"auto");
			SET_BIT(ch->affected_by, AFF_SHADOWPLANE);
			break;
		    }
		    else if (!IS_AFFECTED(ch, AFF_SHADOWPLANE) &&
			IS_SET(portal->extra_flags, ITEM_SHADOWPLANE) )
		    {
			SET_BIT(ch->affected_by, AFF_SHADOWPLANE);
	    		do_look(ch,"auto");
			REMOVE_BIT(ch->affected_by, AFF_SHADOWPLANE);
			break;
		    }
		    else
		    {
	    		do_look(ch,"auto");
			break;
		    }
	    	}
	    }
	    char_from_room(ch);
	    char_to_room(ch,location);
	    break;

	case ITEM_DRINK_CON:
	    if ( obj->value[1] <= 0 )
	    {
		send_to_char( "It is empty.\n\r", ch );
		break;
	    }

	    if (obj->value[1] < obj->value[0] / 5)
	    	sprintf( buf, "There is a little %s liquid left in it.\n\r",liq_table[obj->value[2]].liq_color);
	    else if (obj->value[1] < obj->value[0] / 4)
	    	sprintf( buf, "It contains a small about of %s liquid.\n\r",liq_table[obj->value[2]].liq_color);
	    else if (obj->value[1] < obj->value[0] / 3)
	    	sprintf( buf, "It's about a third full of %s liquid.\n\r",liq_table[obj->value[2]].liq_color);
	    else if (obj->value[1] < obj->value[0] / 2)
	    	sprintf( buf, "It's about half full of %s liquid.\n\r",liq_table[obj->value[2]].liq_color);
	    else if (obj->value[1] < obj->value[0])
	    	sprintf( buf, "It is almost full of %s liquid.\n\r",liq_table[obj->value[2]].liq_color);
	    else if (obj->value[1] == obj->value[0])
	    	sprintf( buf, "It's completely full of %s liquid.\n\r",liq_table[obj->value[2]].liq_color);
	    else
	    	sprintf( buf, "Somehow it is MORE than full of %s liquid.\n\r",liq_table[obj->value[2]].liq_color);
	    send_to_char( buf, ch );
	    break;

	case ITEM_CONTAINER:
	case ITEM_CORPSE_NPC:
	case ITEM_CORPSE_PC:
	    if ( IS_SET(obj->value[1], CONT_CLOSED) )
	    {
		send_to_char( "It is closed.\n\r", ch );
		break;
	    }

	    act( "$p contains:", ch, obj, NULL, TO_CHAR );
	    show_list_to_char( obj->contains, ch, TRUE, TRUE );
	    break;
	}
	return;
    }

    if ( ( victim = get_char_room( ch, arg1 ) ) != NULL )
    {
	show_char_to_char_1( victim, ch );
	evil_eye(victim,ch);
	return;
    }

    for ( vch = char_list; vch != NULL; vch = vch_next )
    {
	vch_next	= vch->next;
	if ( vch->in_room == NULL )
	    continue;
	if ( vch->in_room == ch->in_room )
	{
	    if (!IS_NPC(vch) && !str_cmp(arg1,vch->morph))
	    {
		show_char_to_char_1( vch, ch );
		evil_eye(vch,ch);
		return;
	    }
	    continue;
	}
    }

    if (!IS_NPC(ch) && ch->pcdata->chobj != NULL && ch->pcdata->chobj->in_obj != NULL)
    {
	obj = get_obj_in_obj(ch,arg1);
	if (obj != NULL)
	{
	    send_to_char( obj->description, ch );
	    send_to_char( "\n\r", ch );
	    return;
	}
    }

    for ( obj = ch->carrying; obj != NULL; obj = obj->next_content )
    {
	if (!IS_NPC(ch) && ch->pcdata->chobj != NULL && obj->chobj != NULL && obj->chobj == ch)
	    continue;
	if ( can_see_obj( ch, obj ) )
	{
	    pdesc = get_extra_descr( arg1, obj->extra_descr );
	    if ( pdesc != NULL )
	    {
		send_to_char( pdesc, ch );
		return;
	    }

	    pdesc = get_extra_descr( arg1, obj->pIndexData->extra_descr );
	    if ( pdesc != NULL )
	    {
		send_to_char( pdesc, ch );
		return;
	    }
	}

	if ( is_name( arg1, obj->name ) )
	{
	    send_to_char( obj->description, ch );
	    send_to_char( "\n\r", ch );
	    return;
	}
    }

    for ( obj = ch->in_room->contents; obj != NULL; obj = obj->next_content )
    {
	if (!IS_NPC(ch) && ch->pcdata->chobj != NULL && obj->chobj != NULL && obj->chobj == ch)
	    continue;
	if ( can_see_obj( ch, obj ) )
	{
	    pdesc = get_extra_descr( arg1, obj->extra_descr );
	    if ( pdesc != NULL )
	    {
		send_to_char( pdesc, ch );
		return;
	    }

	    pdesc = get_extra_descr( arg1, obj->pIndexData->extra_descr );
	    if ( pdesc != NULL )
	    {
		send_to_char( pdesc, ch );
		return;
	    }
	}

	if ( is_name( arg1, obj->name ) )
	{
	    send_to_char( obj->description, ch );
	    send_to_char( "\n\r", ch );
	    return;
	}
    }

    pdesc = get_extra_descr( arg1, ch->in_room->extra_descr );
    if ( pdesc != NULL )
    {
	send_to_char( pdesc, ch );
	return;
    }

         if ( !str_cmp( arg1, "n" ) || !str_cmp( arg1, "north" ) ) door = 0;
    else if ( !str_cmp( arg1, "e" ) || !str_cmp( arg1, "east"  ) ) door = 1;
    else if ( !str_cmp( arg1, "s" ) || !str_cmp( arg1, "south" ) ) door = 2;
    else if ( !str_cmp( arg1, "w" ) || !str_cmp( arg1, "west"  ) ) door = 3;
    else if ( !str_cmp( arg1, "u" ) || !str_cmp( arg1, "up"    ) ) door = 4;
    else if ( !str_cmp( arg1, "d" ) || !str_cmp( arg1, "down"  ) ) door = 5;
    else
    {
	send_to_char( "You do not see that here.\n\r", ch );
	return;
    }

    /* 'look direction' */
    if ( ( pexit = ch->in_room->exit[door] ) == NULL )
    {
	send_to_char( "Nothing special there.\n\r", ch );
	return;
    }
/*
    if ( pexit->description != NULL && pexit->description[0] != '\0' )
	send_to_char( pexit->description, ch );
    else
	send_to_char( "Nothing special there.\n\r", ch );
*/

    if ( pexit->keyword    != NULL
    &&   pexit->keyword[0] != '\0'
    &&   pexit->keyword[0] != ' ' )
    {
	if ( IS_SET(pexit->exit_info, EX_CLOSED) )
	{
	    act( "The $d is closed.", ch, NULL, pexit->keyword, TO_CHAR );
	}
	else if ( IS_SET(pexit->exit_info, EX_ISDOOR) )
	{
	    act( "The $d is open.",   ch, NULL, pexit->keyword, TO_CHAR );
	    if ((pexit = ch->in_room->exit[door]) == NULL) return;
	    if ((pRoomIndex = pexit->to_room) == NULL) return;
	    location = ch->in_room;
	    char_from_room(ch);
	    char_to_room(ch,pRoomIndex);
	    do_look(ch,"auto");
	    char_from_room(ch);
	    char_to_room(ch,location);
	}
	else
	{
	    if ((pexit = ch->in_room->exit[door]) == NULL) return;
	    if ((pRoomIndex = pexit->to_room) == NULL) return;
	    location = ch->in_room;
	    char_from_room(ch);
	    char_to_room(ch,pRoomIndex);
	    do_look(ch,"auto");
	    char_from_room(ch);
	    char_to_room(ch,location);
	}
    }
    else
    {
	if ((pexit = ch->in_room->exit[door]) == NULL) return;
	if ((pRoomIndex = pexit->to_room) == NULL) return;
	location = ch->in_room;
	char_from_room(ch);
	char_to_room(ch,pRoomIndex);
	do_look(ch,"auto");
	char_from_room(ch);
	char_to_room(ch,location);
    }

    return;
}



void do_examine( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char( "Examine what?\n\r", ch );
	return;
    }

    do_look( ch, arg );

    if ( ( obj = get_obj_here( ch, arg ) ) != NULL )
    {
	     if (obj->condition >= 100) 
	    sprintf( buf, "You notice that %s is in perfect condition.\n\r",obj->short_descr );
	else if (obj->condition >= 75 )
	    sprintf( buf, "You notice that %s is in good condition.\n\r",obj->short_descr );
	else if (obj->condition >= 50 )
	    sprintf( buf, "You notice that %s is in average condition.\n\r",obj->short_descr );
	else if (obj->condition >= 25 )
	    sprintf( buf, "You notice that %s is in poor condition.\n\r",obj->short_descr );
	else
	    sprintf( buf, "You notice that %s is in awful condition.\n\r",obj->short_descr );
	send_to_char(buf,ch);
	switch ( obj->item_type )
	{
	default:
	    break;

	case ITEM_DRINK_CON:
	case ITEM_CONTAINER:
	case ITEM_CORPSE_NPC:
	case ITEM_CORPSE_PC:
	    send_to_char( "When you look inside, you see:\n\r", ch );
	    sprintf( buf, "in %s", arg );
	    do_look( ch, buf );
	}
    }

    return;
}



/*
 * Thanks to Zrin for auto-exit part.
 */
void do_exits( CHAR_DATA *ch, char *argument )
{
    extern char * const dir_name[];
    char buf[MAX_STRING_LENGTH];
    EXIT_DATA *pexit;
    bool found;
    bool fAuto;
    int door;

    buf[0] = '\0';
    fAuto  = !str_cmp( argument, "auto" );

    if ( !check_blind( ch ) )
	return;

    strcpy( buf, fAuto ? "[Exits:" : "Obvious exits:\n\r" );

    found = FALSE;
    for ( door = 0; door <= 5; door++ )
    {
	if ( ( pexit = ch->in_room->exit[door] ) != NULL
	&&   pexit->to_room != NULL
	&&   !IS_SET(pexit->exit_info, EX_CLOSED) )
	{
	    found = TRUE;
	    if ( fAuto )
	    {
		strcat( buf, " " );
		strcat( buf, dir_name[door] );
	    }
	    else
	    {
		sprintf( buf + strlen(buf), "%-5s - %s\n\r",
		    capitalize( dir_name[door] ),
		    room_is_dark( pexit->to_room )
			?  "Too dark to tell"
			: pexit->to_room->name
		    );
	    }
	}
    }

    if ( !found )
	strcat( buf, fAuto ? " none" : "None.\n\r" );

    if ( fAuto )
	strcat( buf, "]\n\r" );

    send_to_char( buf, ch );
    return;
}



const char * transformation_message[2][12] =
{
{
"\n\rYour body shudders and convulses as your form transforms. Arms and legs grow out of
your slimy torso, your skin turns a sickly veined green.\n\r" ,
"\n\rYour demonic form is reduced to a pool of pulsating jelly, the fires of hell
heat and char your semi-liquid form until you stiffen.  Limbs grow and
spiny talons extend from your arms and back.\n\r" ,
"\n\rYou start the transformation.  Your gargoylish apperance is changed as you grow
another two feet in height.  Scales, dripping with acid, begin to cover your skin.\n\r" ,
"\n\rThe fires of hell surround you once more.  Sharp claws start to grow from
your hands, and you grow a viscious barbed tail.  Small flames play over your
burnt and blackened skin.\n\r" ,
"\n\rYour next form is that of a sickly, gaunt skeleton.  Your leathery flesh
held tight over a demonic frame.  A huge tail, with a poisonous barb on the end
protrudes out of the base of your spine.\n\r" ,
"\n\rAs you transform, you grow another four feet in height. This time, wicked
barbs cover your entire body.  You find you have the ability to wield weapons, and use armor.\n\r" ,
"\n\rWhat?  What is happening, with the transformation into an Erinyes, your
form is no longer repulsive and demonic, but you are now a beautiful
mortal, with long auburn hair and huge white wings growing out of your
back.  You can see the world again with your mortal eyes, but the 
passions of a demon will always stay.\n\r",
"\n\rYour skin melts and you transform once more, but this time you become a gruesome
pug nosed, vile dwarf-like creature with large leathery wings and a mouth
filled of razor sharp teeth, an Amnizu.\n\r" ,
"\n\rThe intense heat of the fires of Baator surround you. Your skin is
wrenched apart and you transform into a grotesque 9-foot tall monstrosity
with huge wings, a snaking, prehensile tail, and a long barbed
whip.  A true demon, a Cornugon.\n\r",
"\n\rThe power of Baator now fills your very soul.  You grow again
as the chill winds of Caina tear the flesh from your bones.  You look to see what
you have become, you look alien, with a twelve foot long icy insect-like
body, your head bulging with multi-faceted eyes and you have
a long tail covered with razor-sharp spikes.\n\r",
"\n\rAaargh!  You are cast into the pit of flame. The fires, more intense
than ever before sear and scar your flesh as it bubbles and boils.
You have become the most terrible demon, the Pit Fiend, a huge bat winged 
humanoid, twelve feet tall, with large fangs that drip with a vile green liquid
and a hulking red scaly body that bursts into flame when you are angered or
excited.\n\r",
"\n\rYour fiery skin blackens as you are infused with the embodiment of
ultimate evil.  You are the most powerful demon, the lord of all.  You
are everything, nothing can oppose you.  Twenty foot tall, your torso
drips with the vile acid of the Abyss.  A ravenous hunger is gnawing at your
bones.  Welcome to Immortality..."
	},
	{
"Your first transformation is quite remarkable, you grow to over seven feet tall,
and your skin starts to dull and lose all signs of vitality.  Your teeth begin to
extend.  The world starts to look different, you have left mortality behind.\n\r",
"You start to grow, the base of your spine slowly extends into a short stump of
a tail.  The metamorphosis is tearing you apart.  Your skin begin to harden, and
your hands twist into claws.\n\r",
"Once again the painful metamorphosis strikes.  Your bones rend through your
scaled flesh as jagged spines shoot through your back.  You feel as if you are
being wrenched apart.  You are now over ten feet tall, and your skin is covered
with thick green scales.\n\r",
"You transform once again.  This time a small pair of wings burst through your
back.  Your hands and feet have become viscious claws, and your nose has extended
into a snout.  Long jagged teeth begin to grow in your mouth, and your tail now
reaches the floor.\n\r",
"You fall to the floor in agony.  Clutching your chest as the transformation
strikes.  You grow to over fifteen feet in length, towering above all the
mortals that you have left behind.  Impenetrable scales now cover your body, 
and smoke issues from your nostrils when you breathe.\n\r",
"You grow to over twenty feet in length, your tail and claws grow at an alarming
rate.  Your wings are now so powerful that you can fly.  Nobody can oppose you
now.  Suddenly it hits you, a hunger so intense that you cannot ignore it.
You must feed.\n\r",
"",
"",
"",
"",
"You have reached the pinnacle of power for a dragon.  As your body undergoes
the by now familiar transformation you grow to over fifty feet tall, with
incredibly sharp claws and fangs, a powerful tail and a fiery breath weapon.
Nobody can oppose you now.  You are the lord of the realm.\n\r",
""
	}
};


void do_promote (CHAR_DATA *ch, char *argument)
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    bool override = FALSE;

    if (IS_NPC(ch)) return;

    argument = one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char( "Who do you wish to promote?\n\r", ch );
	return;
    }

    if (argument[0] != 0 && !str_prefix(argument, "override") && IS_CREATOR(ch))
    {
	stc("Manual override granted.\n\r", ch);
	override = TRUE;
    }

    if (!IS_CLASS(ch, CLASS_DEMON) && !override) {
	send_to_char("Only demons can promote.\n\r", ch );
	return;}

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if (IS_NPC(victim))
    {
	send_to_char("You cannot promote a NPC.\n\r", ch);
	return;
    }

/*
    if ((IS_CLASS(ch, CLASS_DEMON)
	&& ch->generation == 10
	&& IS_CLASS(victim, CLASS_DEMON)
	&& victim->generation > 4))
    {
	send_to_char("Cornugons may only promote demons of Barbazu rank and lower.\n\r", ch);
	return;
    }

    if (IS_CLASS(victim, CLASS_DEMON)
	&& victim->generation == 10
	&& victim->power[DISC_DAEM_GELU] < 10)
    {
	send_to_char("Only a demon with level 10 Geluge may become a Gelugon.\n\r", ch);
	return;
    }
*/

    if ((IS_CLASS(victim, CLASS_DEMON)
	&& victim->pcdata->souls < souls_needed(victim) ) && !override)
    {
	send_to_char("They have not collected enough souls to be promoted.\n\r", ch);
	return;
    }

    if (!IS_CLASS(victim, CLASS_DEMON))
    {
	send_to_char("Only demons can be promoted in this fashion.\n\r", ch);
	return;
    }

/*
    if ( victim == ch )
    {
	send_to_char("You must be promoted by another.\n\r",ch);
	return;
    }
*/

    if ( ch->class != victim->class && ch->level < 12)
    {
	send_to_char("You can't promote someone of a different race.\n\r",ch);
	return;
    }

/*
    if ( victim->generation >= ch->generation)
    {
	send_to_char("You can't promote someone of an equal or higher rank.\n\r",ch);
	return;
    }
*/

    send_to_char("You have been chosen for promotion.\n\r",victim);

    if ( victim->generation == 13)
    {
	send_to_char("But you cannot transform any further.\n\r",victim);
	send_to_char("They are already maximum generation.\n\r",ch);
	return;
    }

    set_form(victim, get_normal_form(victim) + 1);
    victim->generation+=1;
    look_name(victim);

/*
    sprintf(buf, "%s has been promoted by %s.", victim->pcdata->switchname,
ch->pcdata->switchname);
    do_info(ch,buf);
*/

    /* DEMON GENERATIONS....  HAVE FUN */
    
    if (IS_CLASS(ch, CLASS_DEMON)
	&& victim->generation == 11)
    {
	  victim->size = SIZE_HUGE;
	  victim->proper_size = SIZE_HUGE;
    }

    if (IS_CLASS(victim, CLASS_DEMON)
	&& victim->generation > 7 )
    {
	ch->pcdata->perm_str += 1;
    }

    victim->hit += 100;
    victim->max_hit += 100;
    victim->xhitroll += 10;
    victim->xdamroll += 10;

    send_to_char(transformation_message[0][victim->generation-2],victim);
    act("$N has been successfully promoted to the next rank.", ch, NULL, victim, TO_CHAR);
}



void do_weaplist( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    if (IS_NPC(ch)) return;
 
 
send_to_char(

"------------------------------------------------------------------------------\n\r",ch);
send_to_char(
 "                    Weapon, Stance, and Spell Skill           \n\r",ch);
send_to_char(

"------------------------------------------------------------------------------\n\r",ch);
send_to_char(
 "                            Weapon\n\r",ch);
sprintf( buf,
"Unarm:%-4d Slice:%-4d Stab:%-4d Slash:%-4d Whip:%-4d Claw:%-4d Blast:%-4d\n\r",
ch->wpn[0],ch->wpn[1],ch->wpn[2],ch->wpn[3],ch->wpn[4],ch->wpn[5],ch->wpn[6]);
send_to_char(buf,ch);
sprintf( buf,
"Pound  :%-4d Crush  :%-4d Grep   :%-4d Bite    :%-4d Pierce:%-4d Suck   :%-4d\n\r",
ch->wpn[7],ch->wpn[8],ch->wpn[9],ch->wpn[10],ch->wpn[11],ch->wpn[12]);
send_to_char(buf,ch);
send_to_char(

"------------------------------------------------------------------------------\n\r",ch);
send_to_char(
 "                            Stances\n\r",ch);
sprintf( buf,
"Viper : %-4d Crane: %-4d Crab  : %-4d Mongoose: %-4d Bull: %-4d Mantis: %-4d\n\r",
ch->stance[1],ch->stance[2],ch->stance[3],ch->stance[4],ch->stance[5],ch->stance[6]);
send_to_char(buf,ch);
sprintf( buf,
"Dragon: %-4d Tiger: %-4d Monkey: %-4d Swallow : %-4d Kozudo: %-4d\n\r",
ch->stance[7],ch->stance[8],ch->stance[9],ch->stance[10],ch->stance[11]);
send_to_char(buf,ch);
send_to_char(

"------------------------------------------------------------------------------\n\r",ch);
send_to_char(
 "                            Magic\n\r",ch);
sprintf( buf,
"Purple: %-4d  Red: %-4d  Blue: %-4d  Green: %-4d  Yellow: %-4d\n\r",ch->spl[0],ch->spl[1],ch->spl[2],ch->spl[3],ch->spl[4]);
send_to_char(buf,ch);
send_to_char(

"------------------------------------------------------------------------------\n\r",ch);
 
 
return;
}

 
void do_far( CHAR_DATA *ch, char *argument )
{
   CHAR_DATA *victim;
   ROOM_INDEX_DATA *chroom;
   ROOM_INDEX_DATA *victimroom;
   char arg1[MAX_STRING_LENGTH];

   argument = one_argument (argument, arg1);

    if ( IS_NPC(ch) )
	return;

	if (arg1[0] == '\0')
	{
	   send_to_char("Who do you wish to use farcommand on?\n\r",ch);
	   return;
	}
/*  
        if (arg2[0] == '\0')
	{
	   send_to_char("What do you wish to do to them?\n\r",ch);
	   return;
	}

	if (arg3[0] == '\0')
	{
	   send_to_char("Possess or command who?\n\r",ch);
	   return;
	}
*/
  	if (!IS_CLASS(ch, CLASS_VAMPIRE))
  	{
  	send_to_char("Huh?\n\r", ch);
  	return;
  	}
  	
  	if ( IS_CLASS(ch, CLASS_VAMPIRE) && ch->power[DISC_VAMP_PRES] < 9 )
  	{
  	send_to_char("You need level 9 Presence to use this power.\n\r", ch);
	return;
	}

      if ( ( victim = get_char_world( ch, arg1 ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }
 
     if ( !IS_NPC(victim) )
	{
	   send_to_char("Their mind is too strong!\n\r",ch);
	   return;
	}
    if ( victim->level > 250)
    {
    send_to_char("They are too big!\n\r",ch);
    return;
    } 
  
    chroom = ch->in_room;
    victimroom = victim->in_room;
    char_from_room(ch);
    char_to_room(ch,victimroom);
    ch->pcdata->familiar = victim;
    victim->wizard = ch;
    send_to_char("You possess their body.\n\r",ch);
    WAIT_STATE(ch, 50);
    char_from_room(ch);
    char_to_room(ch,chroom);  	
    
    return;
}

void do_stat( CHAR_DATA *ch, char *argument )
{
    char buf   [MAX_STRING_LENGTH];
    char lin   [MAX_STRING_LENGTH];
    char age   [MAX_STRING_LENGTH];
    int blood;
    int bloodpool;

    if (ch->generation <= 0)
	ch->generation = 4;

    {
    if (IS_SET(ch->newbits, NEW_TIDE))
    bloodpool = (3000 / ch->generation);
    else bloodpool = (2000 / ch->generation);
    }

    blood = ch->pcdata->condition[COND_THIRST];
    if (IS_NPC(ch)) return;
    if (!IS_CLASS(ch, CLASS_VAMPIRE)) return;
    if (ch->pcdata->rank == AGE_ANCILLA)         sprintf( age, "Ancilla");
    else if (ch->pcdata->rank == AGE_CHILDE)     sprintf( age, "Childe");
    else if (ch->pcdata->rank == AGE_NEONATE)    sprintf( age, "Neonate");
    else if (ch->pcdata->rank == AGE_ELDER)      sprintf( age, "Elder");
    else if (ch->pcdata->rank == AGE_METHUSELAH) sprintf( age, "Methuselah");
    sprintf( lin,
"---------------------------------------------------------------------------\n\r");
    send_to_char( lin,ch);
    send_to_char(
"                              Vampire Status\n\r",ch);
send_to_char(lin,ch);
sprintf(buf,
"Generation:%d  Bloodpool:%d  Age:%s  Blood:%d\n\r",
ch->generation,bloodpool,age,blood);
send_to_char(buf,ch);
send_to_char(lin,ch);
send_to_char(
"                              Disciplines\n\r",ch);
send_to_char(lin,ch);
sprintf(buf,
"Animalism:    [%d]             Celerity:   [%d]             Fortitude: [%d]\n\r",
ch->power[DISC_VAMP_ANIM],ch->power[DISC_VAMP_CELE],
ch->power[DISC_VAMP_FORT]);
send_to_char(buf,ch);
sprintf(buf,
"Obtenebration:[%d]             Presence:   [%d]             Quietus:   [%d]\n\r",
ch->power[DISC_VAMP_OBTE],ch->power[DISC_VAMP_PRES],
ch->power[DISC_VAMP_QUIE]);
send_to_char(buf,ch);
sprintf(buf,
"Thaumaturgy:  [%d]             Auspex:     [%d]             Dominate:  [%d]\n\r",
ch->power[DISC_VAMP_THAU],ch->power[DISC_VAMP_AUSP],
ch->power[DISC_VAMP_DOMI]);
send_to_char(buf,ch);
sprintf(buf,
"Obfuscate:    [%d]             Potence:    [%d]             Protean:   [%d]\n\r",
ch->power[DISC_VAMP_OBFU],ch->power[DISC_VAMP_POTE],
ch->power[DISC_VAMP_PROT]);
send_to_char(buf,ch);
sprintf(buf,
"Serpentis:    [%d]             Vicissitude:[%d]             Daimoinon: [%d]\n\r",
ch->power[DISC_VAMP_SERP],ch->power[DISC_VAMP_VICI],
ch->power[DISC_VAMP_DAIM]);
send_to_char(buf,ch);
sprintf(buf,			 
"Chimerstry:   [%d]             Obeah:      [%d]             Melpominee:[%d]\n\r",
ch->power[DISC_VAMP_CHIM], ch->power[DISC_VAMP_OBEA], ch->power[DISC_VAMP_MELP]);
send_to_char(buf,ch);
sprintf(buf,
"Necromancy:   [%d]                                         Thanatosis:[%d]\n\r",
ch->power[DISC_VAMP_NECR], ch->power[DISC_VAMP_THAN] );
stc(buf,ch);
send_to_char(lin,ch);
 
return;
}

void do_racestats( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    
    banner_to_char("S T A T I S T I C S",ch);
    
    if (ch->class == 0)
       sprintf(buf,"You have yet to be transformed.");
    else if (ch->class == CLASS_DEMON)
       sprintf(buf,"You have been transformed into a Demon.");
    else if (ch->class == CLASS_VAMPIRE)
       sprintf(buf,"You have been transformed into a Vampire.");
    else if (ch->class == CLASS_WEREWOLF)
       sprintf(buf,"You have been transformed into a Werewolf.");
    else if (ch->class == CLASS_MAGE)
       sprintf(buf,"You have been trained in the ways of Magic.");
    else if (ch->class == CLASS_DROW)
       sprintf(buf,"You have become a legion of Lloth's Army.");
    else if (ch->class == CLASS_MONK)
       sprintf(buf,"You have been guided by the ways of the Almighty.");
    else
       sprintf(buf,"You have been transformed.");

    cent_to_char( buf, ch );

    if (ch->class == CLASS_VAMPIRE)
    {
	sprintf(buf, "You are of generation %d.", ch->generation);
	cent_to_char(buf, ch);
    }

    if (ch->class == 0)
    {
	sprintf(buf, "You are %d%% of the way to being powerful enough for transformation,",
		ch->explevel * 100 / 20);
	cent_to_char(buf, ch);
	if (ch->max_hit < 1500 && ch->max_move >= 1500)
	    sprintf(buf, "and you need %d more hit points.", 1500 - ch->max_hit);
	else if (ch->max_hit < 1500 && ch->max_move < 1500)
	    sprintf(buf, "and you need %d more hit points and %d more vitality.",
		1500 - ch->max_hit, 1500 - ch->max_move);
	else if (ch->max_move < 1500)
	    sprintf(buf, "and you need %d more vitality.", 1500 - ch->max_move);
	else sprintf(buf, "and you have the required hit points and vitality.");
	cent_to_char(buf, ch);
    }

    if (ch->cur_form != 0)
    {
	sprintf(buf, "You are currently in the form of a %s.",
	    form_data[ch->cur_form].lookname);
	cent_to_char(buf, ch);
    }

    ch->size = get_size(ch);

    if (ch->size == SIZE_TINY)
	cent_to_char("You are of tiny size.", ch);
    else if (ch->size == SIZE_SMALL)
	cent_to_char("You are of small size.", ch);
    else if (ch->size == SIZE_MEDIUM)
	cent_to_char("You are of medium size.", ch);
    else if (ch->size == SIZE_LARGE)
	cent_to_char("You are of large size.", ch);
    else if (ch->size == SIZE_HUGE)
	cent_to_char("You are of huge size.", ch);
    else if (ch->size == SIZE_GIANT)
	cent_to_char("You are absolutely gigantic.", ch);
    else
	cent_to_char("You are of medium size.", ch);

    if (IS_SET(ch->act, PLR_WIZINVIS) && IS_IMMORTAL(ch))
    {
	sprintf( buf, "You are invisible.");
	cent_to_char(buf,ch);
    }

    divide5_to_char(ch);

    if (IS_SET(ch->newbits, THIRD_HAND) && !IS_SET(ch->newbits, FOURTH_HAND))
	  cent_to_char("You have grown an extra arm.",ch);
    if (!IS_SET(ch->newbits, THIRD_HAND) && IS_SET(ch->newbits, FOURTH_HAND))
        cent_to_char("You have grown an extra arm.",ch);
    if (IS_SET(ch->newbits, THIRD_HAND) && IS_SET(ch->newbits, FOURTH_HAND))
        cent_to_char("You have grown two extra arms.",ch);

    if (ch->class == CLASS_VAMPIRE
	&& ch->pcdata->stats[COND_THIRST] < 20)
    	cent_to_char("You are dangerously low on blood.", ch);

    if (!IS_NPC(ch) && str_cmp(ch->name, ch->pcdata->switchname)
	&& !IS_BASE_FORM(ch))
    {
	sprintf(buf,"You are currently masked as %s.", ch->name);
	cent_to_char(buf, ch);
    }

    if (ch->class == CLASS_DEMON
	&& !IS_NPC(ch)
	&& ch->generation != 13)
    {
	sprintf(buf,"You have collected %d souls, and need %d more for promotion."
		, ch->pcdata->souls, souls_needed(ch) - ch->pcdata->souls);
	cent_to_char(buf, ch);
    }
   
    if (ch->class == 0)
    {
	if (IS_NEWFLAG(ch,AFF_ALLOW_VAMP))
		cent_to_char("You may be bitten by vampires.",ch);
	if (IS_NEWFLAG(ch,AFF_ALLOW_WERE))
		cent_to_char("You may be cursed with lycanthropy.",ch);
	if (IS_NEWFLAG(ch,AFF_ALLOW_ELAD))
		cent_to_char("You may join the eladrin.",ch);
	if (IS_NEWFLAG(ch,AFF_ALLOW_DEMON))
		cent_to_char("You are willing to sell your soul to Baator.",ch);
	if (IS_NEWFLAG(ch,AFF_ALLOW_WARLOCK))
		cent_to_char("You are ready to study to become a Warlock.",ch);
    }

   divide5_to_char(ch);

    if (!IS_NPC(ch) )
    {
	  sprintf(buf,"Your maximum damage is currently %d.",ch->damcap[0]);
        cent_to_char(buf, ch);
	sprintf(buf, "You have killed %d enemy mobs, and been killed by %d.", ch->mkill, ch->mdeath);
	cent_to_char(buf, ch);
    }

    if (ch->power[DISC_DAEM_GELU] > 1 && ch->played/18000 > 0)
    {
	sprintf(buf,"Your icy strength is improving your damage by %d.", ch->played/18000);
	cent_to_char(buf, ch);
    }

   if (IS_VAMPAFF(ch, VAM_FANGS)
	|| IS_VAMPAFF(ch, VAM_CLAWS)
	|| IS_VAMPAFF(ch, VAM_WINGS)
	|| IS_VAMPAFF(ch, VAM_HORNS)
	|| IS_VAMPAFF(ch, VAM_TAIL))
   {
	bool comma = FALSE;
	strcpy(buf, "You have extra ");
	if (IS_VAMPAFF(ch, VAM_FANGS))
	{
	    comma = TRUE;
	    strcat(buf, "bite");
        }
	if (IS_VAMPAFF(ch, VAM_CLAWS))
	{
	    if (comma)
	    {
		if (!IS_VAMPAFF(ch, VAM_WINGS) && IS_VAMPAFF(ch,VAM_TAIL))
		    strcat(buf, " and ");
		else strcat(buf, ", ");
	    }
	    comma = TRUE;
	    strcat(buf, "claw");
        }
	if (IS_VAMPAFF(ch, VAM_WINGS))
	{
	    if (comma)
	    {
		if (!IS_VAMPAFF(ch, VAM_TAIL))
		    strcat(buf, " and ");
		else strcat(buf,", ");
	    }
	    comma = TRUE;
	    strcat(buf,"wing");
        }
	if (IS_VAMPAFF(ch, VAM_HORNS))
	{
	    if (comma)
	    {
		if (!IS_VAMPAFF(ch, VAM_TAIL))
		    strcat(buf, " and ");
		else strcat(buf,", ");
	    }
	    comma = TRUE;
	    strcat(buf,"horn");
        }
	if (IS_VAMPAFF(ch, VAM_TAIL))
	{
	    if (comma) strcat(buf," and ");
	    strcat(buf,"tail");
        }

	strcat(buf," attacks.");
	cent_to_char(buf,ch);
    }

    divide4_to_char(ch);
}

/**** ALLOW COMMANDS ****/

void do_vampallow(CHAR_DATA *ch, char *argument)
{
    if (IS_NPC(ch)) return;

    if (IS_NEWFLAG(ch,AFF_ALLOW_VAMP))
    {
	send_to_char("You refuse your body to the kindred.\n\r",ch);
	REMOVE_BIT(ch->flag2,AFF_ALLOW_VAMP);
	return;
    }
    else
    {
	send_to_char("You give your body to the kindred.\n\r",ch);
	SET_BIT(ch->flag2,AFF_ALLOW_VAMP);
	return;
    }
}

void do_wereallow(CHAR_DATA *ch, char *argument)
{
    if (IS_NPC(ch)) return;

    if (IS_NEWFLAG(ch,AFF_ALLOW_WERE))
    {
	send_to_char("You are now immune to lycanthropy.\n\r",ch);
	REMOVE_BIT(ch->flag2,AFF_ALLOW_WERE);
	return;
    }
    else
    {
	send_to_char("You gift your body to the lupines.\n\r",ch);
	SET_BIT(ch->flag2,AFF_ALLOW_WERE);
	return;
    }
}

void do_eladallow(CHAR_DATA *ch, char *argument)
{
    if (IS_NPC(ch)) return;

    if (IS_NEWFLAG(ch,AFF_ALLOW_ELAD))
    {
	send_to_char("You reject the ways of the faerie folk.\n\r",ch);
	REMOVE_BIT(ch->flag2,AFF_ALLOW_ELAD);
	return;
    }
    else
    {
	send_to_char("You pledge your life to nature.\n\r",ch);
	SET_BIT(ch->flag2,AFF_ALLOW_ELAD);
	return;
    }
}

void do_demonallow(CHAR_DATA *ch, char *argument)
{
    if (IS_NPC(ch)) return;

    if (IS_NEWFLAG(ch,AFF_ALLOW_DEMON))
    {
	send_to_char("You snatch your soul back from eternal damnation.\n\r",ch);
	REMOVE_BIT(ch->flag2,AFF_ALLOW_DEMON);
	return;
    }
    else
    {
	send_to_char("You sell your soul to darkness.\n\r",ch);
	SET_BIT(ch->flag2,AFF_ALLOW_DEMON);
	return;
    }
}

void do_warlockallow(CHAR_DATA *ch, char *argument)
{
    if (IS_NPC(ch)) return;

    if (IS_NEWFLAG(ch,AFF_ALLOW_WARLOCK))
    {
	send_to_char("You reject the paths of magic.\n\r",ch);
	REMOVE_BIT(ch->flag2,AFF_ALLOW_WARLOCK);
	return;
    }
    else
    {
	send_to_char("You prepare yourself for a life of studying.\n\r",ch);
	SET_BIT(ch->flag2,AFF_ALLOW_WARLOCK);
	return;
    }
}

void do_score( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    char ss1[MAX_STRING_LENGTH];
    char ss2[MAX_STRING_LENGTH];
    AFFECT_DATA *paf;
    int a_c = char_ac(ch);

	if (IS_NPC(ch)) return;

    if (!IS_NPC(ch) && (IS_EXTRA(ch,EXTRA_OSWITCH) || IS_HEAD(ch,LOST_HEAD)))
	{obj_score(ch,ch->pcdata->chobj);return;}
    sprintf( buf,
	"You are %s%s.  You have been playing for %d hours.\n\r",
	ch->pcdata->switchname,
	IS_NPC(ch) ? "" : ch->pcdata->title,
	(get_age(ch) - 17) * 2 );
    send_to_char( buf, ch );
    if (!IS_NPC(ch)) birth_date(ch, TRUE);
    if (!IS_NPC(ch) && IS_EXTRA(ch, EXTRA_PREGNANT)) birth_date(ch, FALSE);

    if ( get_trust( ch ) != ch->level )
    {
	sprintf( buf, "You are trusted at level %d.\n\r",
	    get_trust( ch ) );
	send_to_char( buf, ch );
    }

    sprintf( buf,
	"You have %d/%d hit, %d/%d mana, %d/%d movement, %d primal energy.\n\r",
	ch->hit,  ch->max_hit,
	ch->mana, ch->max_mana,
	ch->move, ch->max_move,
	ch->practice );
    send_to_char( buf, ch );

    sprintf( buf,
	"You are carrying %d/%d items with weight %d/%d kg.\n\r",
	ch->carry_number, can_carry_n(ch),
	ch->carry_weight, can_carry_w(ch) );
    send_to_char( buf, ch );

    sprintf( buf,
	"Str: %d  Int: %d  Wis: %d  Dex: %d  Con: %d.\n\r",
	get_curr_str(ch),
	get_curr_int(ch),
	get_curr_wis(ch),
	get_curr_dex(ch),
	get_curr_con(ch) );
    send_to_char( buf, ch );

    sprintf( buf,
	"You have scored %d exp, and have %d gold coins.\n\r",
	ch->exp,  ch->gold );
    send_to_char( buf, ch );

    if (!IS_NPC(ch) && (IS_CLASS( ch, CLASS_DEMON) || IS_SET(ch->special,SPC_CHAMPION)))
    {
	sprintf( buf,
	"You have %d out of %d points of demonic power stored.\n\r",
	ch->pcdata->stats[DEMON_CURRENT],  ch->pcdata->stats[DEMON_TOTAL] );
	send_to_char( buf, ch );
    }
    if (!IS_NPC(ch) && IS_CLASS(ch, CLASS_DEMON) && ch->generation < 13)
    {
	sprintf( buf,
	"You have obtained %d souls and require %d more for a promotion.\n\r",
	ch->pcdata->souls, souls_needed(ch));
	stc(buf, ch);
    }

    if (!IS_NPC(ch) && IS_CLASS(ch, CLASS_CYBORG))
    {
	sprintf(buf,"You have %d cyborg energy points.\n\r",ch->pcdata->stats[CYBORG_POWER]);
	send_to_char(buf,ch);
    }

    if (!IS_NPC(ch) && IS_CLASS(ch, CLASS_DROW)) {
	sprintf( buf, "You have %d drow power points!.\n\r",
	ch->pcdata->stats[DROW_POWER] );
	send_to_char( buf, ch );
	sprintf( buf, "You have %d points of magic resistance.\n\r",
	ch->pcdata->stats[DROW_MAGIC] );
	send_to_char( buf, ch ); 
	if (weather_info.sunlight == SUN_DARK) 
	send_to_char("You feel strong in the night.\n\r", ch );}

    sprintf( buf,
	"Autoexit: %s.  Autoloot: %s.  Autosac: %s.\n\r",
	(!IS_NPC(ch) && IS_SET(ch->act, PLR_AUTOEXIT)) ? "yes" : "no",
	(!IS_NPC(ch) && IS_SET(ch->act, PLR_AUTOLOOT)) ? "yes" : "no",
	(!IS_NPC(ch) && IS_SET(ch->act, PLR_AUTOSAC) ) ? "yes" : "no" );
    send_to_char( buf, ch );
    
    sprintf( buf, "Wimpy set to %d hit points.", ch->wimpy );
    if ( !IS_NPC(ch) && IS_EXTRA(ch, EXTRA_DONE) )
	strcat(buf,"  You've done the dead.\n\r");
    else strcat(buf,"\n\r");
    send_to_char( buf, ch );


    if(!IS_NPC(ch))
    {
       sprintf(buf,"[Arena Stats] Wins: %d  losses: %d\n\r",
       ch->pcdata->awins, ch->pcdata->alosses );
       send_to_char( buf, ch);
       if(ch->challenger != NULL)
       {
          sprintf(buf,"[Arena] You have been challenged by %s.\n\r",
          ch->challenger->name);
          send_to_char( buf, ch);
       }
       if(ch->challenged != NULL)
       {
          sprintf(buf,"[Arena] You have challenged %s.\n\r",
          ch->challenged->name);
          send_to_char( buf, ch);
       }
       if(ch->gladiator != NULL)
       {
          sprintf(buf,"[Arena bet] You have a %d gold bet on %s\n\r",
          ch->pcdata->plr_wager, ch->gladiator->name);
          send_to_char( buf, ch);
       }
    }

    if ( !IS_NPC(ch) && IS_CLASS(ch, CLASS_MONK) )
    {
      sprintf(buf,"Your block counter is currently: %d\n\r",ch->monkblock);
      stc(buf,ch);
      sprintf(buf,"Your current level of chi:       %d\n\r",ch->chi[CURRENT]);
      stc(buf,ch);
      sprintf(buf,"Your maximum level of chi:       %d\n\r",ch->chi[MAXIMUM]);
      stc(buf,ch);
      sprintf(buf,"Your current focus points:       %d\n\r",ch->focus[CURRENT]);
      stc(buf,ch);
      sprintf(buf,"Your maximum focus points:       %d\n\r",ch->focus[MAXIMUM]);
      stc(buf,ch);
    }

    if ( !IS_NPC(ch) && ch->pcdata->condition[COND_DRUNK]   > 10 )
	send_to_char( "You are drunk.\n\r",   ch );
    if ( !IS_NPC(ch) && ch->pcdata->condition[COND_THIRST] ==  0 )
	send_to_char( "You are thirsty.\n\r", ch );
    if ( !IS_NPC(ch) && ch->pcdata->condition[COND_FULL]   ==  0 )
	send_to_char( "You are hungry.\n\r",  ch );
    if ( !IS_NPC(ch) && ch->pcdata->stage[0] >= 100 )
	send_to_char( "You are feeling extremely horny.\n\r",  ch );
    else if ( !IS_NPC(ch) && ch->pcdata->stage[0] >= 50 )
	send_to_char( "You are feeling pretty randy.\n\r",  ch );
    else if ( !IS_NPC(ch) && ch->pcdata->stage[0] >= 1 )
	send_to_char( "You are feeling rather kinky.\n\r",  ch );

    if ( !IS_NPC(ch) && ch->pcdata->stage[1] > 0 && ch->position == POS_STANDING )
    {
	send_to_char( "You are having sexual intercourse.\n\r",  ch );
	if (!IS_NPC(ch) && (ch->pcdata->stage[2] + 25) >= ch->pcdata->stage[1])
	    send_to_char( "You are on the verge of having an orgasm.\n\r",  ch );
    }
    else switch ( ch->position )
    {
    case POS_DEAD:     
	send_to_char( "You are DEAD!!\n\r",		ch );
	break;
    case POS_MORTAL:
	send_to_char( "You are mortally wounded.\n\r",	ch );
	break;
    case POS_INCAP:
	send_to_char( "You are incapacitated.\n\r",	ch );
	break;
    case POS_STUNNED:
	send_to_char( "You are stunned.\n\r",		ch );
	break;
    case POS_SLEEPING:
	send_to_char( "You are sleeping.\n\r",		ch );
	break;
    case POS_RESTING:
	send_to_char( "You are resting.\n\r",		ch );
	break;
    case POS_MEDITATING:
	send_to_char( "You are meditating.\n\r",	ch );
	break;
    case POS_SITTING:
	send_to_char( "You are sitting.\n\r",		ch );
	break;
    case POS_STANDING:
	send_to_char( "You are standing.\n\r",		ch );
	break;
    case POS_FIGHTING:
	send_to_char( "You are fighting.\n\r",		ch );
	break;
    }

    if ( ch->level >= 0 )
    {
	sprintf( buf, "AC: %d.  ", a_c );
	send_to_char( buf, ch );
    }

    send_to_char( "You are ", ch );
         if ( a_c >=  101 ) send_to_char( "naked!\n\r", ch );
    else if ( a_c >=   80 ) send_to_char( "barely clothed.\n\r",   ch );
    else if ( a_c >=   60 ) send_to_char( "wearing clothes.\n\r",  ch );
    else if ( a_c >=   40 ) send_to_char( "slightly armored.\n\r", ch );
    else if ( a_c >=   20 ) send_to_char( "somewhat armored.\n\r", ch );
    else if ( a_c >=    0 ) send_to_char( "armored.\n\r",          ch );
    else if ( a_c >=  -50 ) send_to_char( "well armored.\n\r",     ch );
    else if ( a_c >= -100 ) send_to_char( "strongly armored.\n\r", ch );
    else if ( a_c >= -250 ) send_to_char( "heavily armored.\n\r",  ch );
    else if ( a_c >= -500 ) send_to_char( "superbly armored.\n\r", ch );
    else if ( a_c >= -749 ) send_to_char( "divinely armored.\n\r", ch );
    else                    send_to_char( "ultimately armored!\n\r",ch );

    sprintf( buf, "Hitroll: %d.  Damroll: %d.  Damcap: %d. ",
char_hitroll(ch), char_damroll(ch), ch->damcap[0] );
    send_to_char( buf, ch );
    

    if ( !IS_NPC(ch) && IS_CLASS(ch,CLASS_VAMPIRE) )
    {
	sprintf( buf, "Blood: %d.\n\r", ch->pcdata->condition[COND_THIRST] );
	send_to_char( buf, ch );

/*	sprintf( buf, "Beast: %d.  ", ch->beast );
	send_to_char( buf, ch );
	if      (ch->beast <  0 ) send_to_char("You are a cheat!\n\r",ch);
	else if (ch->beast == 0 ) send_to_char("You have attained Golconda!\n\r",ch);
	else if (ch->beast <= 5 ) send_to_char("You have almost reached Golconda!\n\r",ch);
	else if (ch->beast <= 10) send_to_char("You are nearing Golconda!\n\r",ch);
	else if (ch->beast <= 15) send_to_char("You have great control over your beast.\n\r",ch);
	else if (ch->beast <= 20) send_to_char("Your beast has little influence over your actions.\n\r",ch);
	else if (ch->beast <= 30) send_to_char("You are in control of your beast.\n\r",ch);
	else if (ch->beast <= 40) send_to_char("You are able to hold back the beast.\n\r",ch);
	else if (ch->beast <= 60) send_to_char("You are constantly struggling for control of your beast.\n\r",ch);
	else if (ch->beast <= 75) send_to_char("Your beast has great control over your actions.\n\r",ch);
	else if (ch->beast <= 90) send_to_char("The power of the beast overwhelms you.\n\r",ch);
	else if (ch->beast <= 99) send_to_char("You have almost lost your battle with the beast!\n\r",ch);
	else                      send_to_char("The beast has taken over!\n\r",ch);
*/
    }
    else if (ch->level >= 0)
	send_to_char( "\n\r", ch );

    if ( ch->level >= 0 )
    {
	sprintf( buf, "Alignment: %d.  ", ch->alignment );
	send_to_char( buf, ch );
    }

    send_to_char( "You are ", ch );
         if ( ch->alignment >  900 ) send_to_char( "angelic.\n\r", ch );
    else if ( ch->alignment >  700 ) send_to_char( "saintly.\n\r", ch );
    else if ( ch->alignment >  350 ) send_to_char( "good.\n\r",    ch );
    else if ( ch->alignment >  100 ) send_to_char( "kind.\n\r",    ch );
    else if ( ch->alignment > -100 ) send_to_char( "neutral.\n\r", ch );
    else if ( ch->alignment > -350 ) send_to_char( "mean.\n\r",    ch );
    else if ( ch->alignment > -700 ) send_to_char( "evil.\n\r",    ch );
    else if ( ch->alignment > -900 ) send_to_char( "demonic.\n\r", ch );
    else                             send_to_char( "satanic.\n\r", ch );
    
    if ( !IS_NPC(ch) && ch->level >= 0 )
    {
	sprintf( buf, "Status: %d.  ", ch->race );
	send_to_char( buf, ch );
    }


    if (!IS_NPC(ch)) send_to_char( "You are ", ch );

         if (!IS_NPC(ch) && ch->level == 1 ) send_to_char( "a Mortal.\n\r", ch);
    else if (!IS_NPC(ch) && ch->level == 2 ) send_to_char( "a Mortal.\n\r", ch);
    else if (!IS_NPC(ch) && ch->level == 7 ) send_to_char( "a Builder.\n\r", ch);
    else if (!IS_NPC(ch) && ch->level == 8 ) send_to_char( "a Quest Maker.\n\r", ch);
    else if (!IS_NPC(ch) && ch->level == 9 ) send_to_char( "an Enforcer.\n\r", ch);
    else if (!IS_NPC(ch) && ch->level == 10) send_to_char( "a Judge.\n\r", ch);
    else if (!IS_NPC(ch) && ch->level == 11) send_to_char( "a High Judge.\n\r", ch);
    else if (!IS_NPC(ch) && ch->level == 12) send_to_char( "an Implementor.\n\r", ch);
    else if (!IS_NPC(ch) && ch->race <= 0 ) send_to_char( "an Avatar.\n\r",ch);
    else if (!IS_NPC(ch) && ch->race <= 4 ) send_to_char( "Immortal.\n\r", ch);
    else if (!IS_NPC(ch) && ch->race <= 9 ) send_to_char( "Godling.\n\r", ch);
    else if (!IS_NPC(ch) && ch->race <= 14) send_to_char( "Demigod.\n\r",ch);
    else if (!IS_NPC(ch) && ch->race <= 19) send_to_char( "Lesser God.\n\r", ch);
    else if (!IS_NPC(ch) && ch->race <= 24) send_to_char( "Greater God.\n\r", ch);
    else if (!IS_NPC(ch) && ch->race >= 25) send_to_char( "Supreme God.\n\r", ch);
    else if (!IS_NPC(ch)) send_to_char( "a Bugged Character!\n\r", ch);

    if ( !IS_NPC(ch) )
    {
	if      (ch->pkill  == 0) sprintf(ss1,"no players");
	else if (ch->pkill  == 1) sprintf(ss1,"%d player",ch->pkill);
	else                      sprintf(ss1,"%d players",ch->pkill);
	if      (ch->pdeath == 0) sprintf(ss2,"no players");
	else if (ch->pdeath == 1) sprintf(ss2,"%d player",ch->pdeath);
	else                      sprintf(ss2,"%d players",ch->pdeath);
	sprintf( buf, "You have killed %s and have been killed by %s.\n\r", ss1, ss2 );
	send_to_char( buf, ch );
	if      (ch->mkill  == 0) sprintf(ss1,"no mobs");
	else if (ch->mkill  == 1) sprintf(ss1,"%d mob",ch->mkill);
	else                      sprintf(ss1,"%d mobs",ch->mkill);
	if      (ch->mdeath == 0) sprintf(ss2,"no mobs");
	else if (ch->mdeath == 1) sprintf(ss2,"%d mob",ch->mdeath);
	else                      sprintf(ss2,"%d mobs",ch->mdeath);
	sprintf( buf, "You have killed %s and have been killed by %s.\n\r", ss1, ss2 );
	send_to_char( buf, ch );
    }

    if ( !IS_NPC(ch) && ch->pcdata->quest > 0)
    {
	if (ch->pcdata->quest == 1)
	    sprintf( buf, "You have a single quest point.\n\r" );
	else
	    sprintf( buf, "You have %d quest points.\n\r", ch->pcdata->quest );
	send_to_char( buf, ch );
    }

    if (IS_AFFECTED(ch,AFF_HIDE)) send_to_char( "You are keeping yourself hidden from those around you.\n\r", ch );

    if ( !IS_NPC(ch) )
    {
	if ( IS_CLASS(ch,CLASS_WEREWOLF) && ch->siltol > 0)
	{
	    sprintf(buf,"You have attained %d points of silver tolerance.\n\r",ch->siltol);
	    send_to_char( buf, ch );
	}
	if ( IS_CLASS(ch,CLASS_VAMPIRE) && ch->rage > 0)
	{
	    sprintf(buf,"The beast is in control of your actions:  Affects Hitroll and Damroll by +%d.\n\r",ch->rage);
	    send_to_char( buf, ch );
	}
	if ( IS_CLASS(ch, CLASS_WEREWOLF) && IS_SET(ch->special,SPC_WOLFMAN) && ch->rage > 0)
	{
	    sprintf(buf,"You are raging:  Affects Hitroll and Damroll by +%d.\n\r",ch->rage);
	    send_to_char( buf, ch );
	}
	if (IS_CLASS(ch, CLASS_NINJA) && ch->rage > 0) {
	sprintf(buf,"Your michi gives you an extra %d hitroll and damroll.\n\r", ch->rage);
	send_to_char(buf,ch);
	}
	if (IS_CLASS(ch, CLASS_NINJA) && ch->pcdata->powers[NPOWER_CHIKYU] >= 6
	&& ch->pcdata->powers[HARA_KIRI] > 0) {
	sprintf(buf,"You receive the power of HaraKiri for %d more ticks.\n\r",ch->pcdata->powers[HARA_KIRI]);
	send_to_char(buf,ch);
	}

        if ( !IS_CLASS(ch, CLASS_WEREWOLF) && !IS_CLASS(ch, CLASS_VAMPIRE) &&
ch->rage > 0 && !IS_CLASS(ch, CLASS_NINJA))
	{
	   sprintf(buf,"You are in a mad frenzy, adding %d Hitroll and Damroll.\n\r",ch->rage);
	   stc(buf, ch);
	}

	else if ( IS_CLASS( ch, CLASS_DEMON) && ch->pcdata->stats[DEMON_POWER] > 0)
	{
	    sprintf(buf,"You are wearing demonic armour:  Affects Hitroll and Damroll by +%d.\n\r",
		((ch->pcdata->stats[DEMON_POWER]) *ch->pcdata->stats[DEMON_POWER]));
	    send_to_char( buf, ch );
	}
/*
	if ( IS_CLASS( ch, CLASS_DEMON) && ch->pcdata->stats[DEMON_POWER] > 0)
	{
	sprintf(buf,"You are wearing demonic armour:  Affects Hitroll and Damroll by +%d.\n\r", (ch->pcdata->stats[DEMON_POWER] * ch->pcdata->stats[DEMON_POWER]));
	stc(buf, ch);
	}

	else if ( IS_SET(ch->special,SPC_CHAMPION) && ch->pcdata->stats[DEMON_POWER] > 0)
	{
	sprintf(buf,"You are wearing demonic armour:  Affects Hitroll and Damroll by +%d.\n\r", (ch->pcdata->stats[DEMON_POWER] * ch->pcdata->stats[DEMON_POWER]));
	stc(buf, ch);
	}
*/
    }	
	if (ch->fight_timer > 0) {
	sprintf(buf,"You have %d rounds left on your fight timer.\n\r", ch->fight_timer);
	send_to_char(buf,ch);
	}
	
	
    if ( ch->affected != NULL )
    {
	send_to_char( "You are affected by:\n\r", ch );
	for ( paf = ch->affected; paf != NULL; paf = paf->next )
	{
	    sprintf( buf, "Spell: '%s'", skill_table[paf->type].name );
	    send_to_char( buf, ch );

	    if ( ch->level >= 0 )
	    {
		sprintf( buf,
		    " modifies %s by %d for %d hours with bits %s.\n\r",
		    affect_loc_name( paf->location ),
		    paf->modifier,
		    paf->duration,
		    affect_bit_name( paf->bitvector ) );
		send_to_char( buf, ch );
	    }
	}
    }

    return;
}



char *	const	day_name	[] =
{
    "the Moon", "the Bull", "Deception", "Thunder", "Freedom",
    "the Great Gods", "the Sun"
};

char *	const	month_name	[] =
{
    "Winter", "the Winter Wolf", "the Frost Giant", "the Old Forces",
    "the Grand Struggle", "the Spring", "Nature", "Futility", "the Dragon",
    "the Sun", "the Heat", "the Battle", "the Dark Shades", "the Shadows",
    "the Long Shadows", "the Ancient Darkness", "the Great Evil"
};

void do_time( CHAR_DATA *ch, char *argument )
{
    extern char str_boot_time[];
    char buf[MAX_STRING_LENGTH];
    char *suf;
    int day;

    day     = time_info.day + 1;

         if ( day > 4 && day <  20 ) suf = "th";
    else if ( day % 10 ==  1       ) suf = "st";
    else if ( day % 10 ==  2       ) suf = "nd";
    else if ( day % 10 ==  3       ) suf = "rd";
    else                             suf = "th";

    sprintf( buf,
	"It is %d o'clock %s, Day of %s, %d%s the Month of %s.\n\rLords of war started up at %s\rThe system time is %s\r",

	(time_info.hour % 12 == 0) ? 12 : time_info.hour % 12,
	time_info.hour >= 12 ? "pm" : "am",
	day_name[day % 7],
	day, suf,
	month_name[time_info.month],
	str_boot_time,
	(char *) ctime( &current_time )
	);

    send_to_char( buf, ch );
    return;
}


void do_weather( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];

    static char * const sky_look[4] =
    {
	"cloudless",
	"cloudy",
	"rainy",
	"lit by flashes of lightning"
    };

    if ( !IS_OUTSIDE(ch) )
    {
	send_to_char( "You can't see the weather indoors.\n\r", ch );
	return;
    }

    sprintf( buf, "The sky is %s and %s.\n\r",
	sky_look[weather_info.sky],
	weather_info.change >= 0
	? "a warm southerly breeze blows"
	: "a cold northern gust blows"
	);
    send_to_char( buf, ch );
    return;
}




void do_wyrm( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];

        if ( IS_NPC(ch) )
        return;

        if (!IS_SET(ch->extra,EXTRA_BSD))
        {
        send_to_char( "You are now a Black Spiral Dancer.\n\r", ch );
        sprintf(buf,"%s is now a Black Spiral Dancer!",ch->name);
        ADD_COLOUR(ch,buf,L_GREEN); 
	do_info(ch,buf);
        REMOVE_BIT(ch->extra,EXTRA_BSD);
        return;
        }

        else if (!IS_SET(ch->extra,EXTRA_BSD))
        {
        send_to_char( "You are now a Black Spiral Dancer.\n\r", ch );
        sprintf(buf,"%s is now a Black Spiral Dancer!",ch->name);
        ADD_COLOUR(ch,buf,L_GREEN);
        do_info(ch,buf);
        SET_BIT(ch->extra,EXTRA_BSD);
        return;
        }

else
return;

}





/*
 * New 'who' command originally by Alander of Rivers of Mud.
 */
void do_who( CHAR_DATA *ch, char *argument )
{
    char cls[MAX_STRING_LENGTH];
    char buf[MAX_STRING_LENGTH];
    char buf2[MAX_STRING_LENGTH];
    char buf3[MAX_STRING_LENGTH];
    char buf4[MAX_STRING_LENGTH];
    char buf5[MAX_STRING_LENGTH];
    char buf6[MAX_STRING_LENGTH];
    char buf7[MAX_STRING_LENGTH];
    char buf8[MAX_STRING_LENGTH];
    char buf9[MAX_STRING_LENGTH];
    char buf10[MAX_STRING_LENGTH];
    char buf11[MAX_STRING_LENGTH];
    char buf12[MAX_STRING_LENGTH];
    char buf13[MAX_STRING_LENGTH];
    char buf14[MAX_STRING_LENGTH];
    char buf15[MAX_STRING_LENGTH];
    char buf16[MAX_STRING_LENGTH];
    char buf17[MAX_STRING_LENGTH];
    char buf18[MAX_STRING_LENGTH];
    char buf19[MAX_STRING_LENGTH];
    char buf20[MAX_STRING_LENGTH];
    char kav[MAX_STRING_LENGTH];
    char king[MAX_STRING_LENGTH];
    char openb[5];
    char closeb[5];
    char *mage_col;
    DESCRIPTOR_DATA *d;
    CHAR_DATA *wch;
    int iLevelLower;
    int iLevelUpper;
    int nNumber;
    int nMatch;
    bool fClassRestrict;
    bool fImmortalOnly;
    bool immortal = FALSE,avatar = FALSE,mortal = FALSE, main = FALSE; 
    bool imm = FALSE,ava = FALSE, mor = FALSE;
    bool a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16;

    if (IS_NPC(ch)) return;

    /*
     * Set default arguments.
     */
    iLevelLower    = 0;
    iLevelUpper    = MAX_LEVEL;
    fClassRestrict = FALSE;
    fImmortalOnly  = FALSE;

    /*
     * Parse arguments.
     */
    nNumber = 0;
    for ( ;; )
    {
	char arg[MAX_STRING_LENGTH];

	argument = one_argument( argument, arg );
	if ( arg[0] == '\0' )
	    break;

	if ( is_number( arg ) )
	{
	    send_to_char("Enter 'Avatar' for level 3's, or 'God' for level 4's and 5's.\n\r",ch);
	    return;
	}
	else
	{
	    /*
	     * Look for classes to turn on.
	     */
	    arg[3]    = '\0';
	    if (   !str_cmp( arg, "imm" ) || !str_cmp( arg, "immortal" )
		|| !str_cmp( arg, "ava" ) || !str_cmp( arg, "avatar"   ) )
	    {
		fClassRestrict = TRUE;
	    }
	    else if ( !str_cmp( arg, "god" ) || !str_cmp( arg, "imp" ) )
	    {
		fImmortalOnly = TRUE;
	    }
	    else
	    {
		send_to_char("Enter 'Avatar' for level 3's, or 'God' for level 4's and 5's.\n\r",ch);
		return;
	    }
	}
    }

    /*
     * Now show matching chars.
     */
    nMatch = 0;
    buf[0] = '\0';
    buf3[0] = '\0';
    buf4[0] = '\0';
    buf5[0] = '\0';
    buf6[0] = '\0';
    buf7[0] = '\0';
    buf8[0] = '\0';
    buf9[0] = '\0';
    buf10[0] = '\0';
    buf11[0] = '\0';
    buf12[0] = '\0';
    buf13[0] = '\0';
    buf14[0] = '\0';
    buf15[0] = '\0';
    buf16[0] = '\0';
    buf17[0] = '\0';
    buf18[0] = '\0';
    buf19[0] = '\0';
    buf20[0] = '\0';
 
    for ( d = descriptor_list; d != NULL; d = d->next )
    {
//	CHAR_DATA *wch;
	char const *class;

	/*
	 * Check for match against restrictions.
	 * Don't use trust as that exposes trusted mortals.
	 */

	if ( (d->connected != CON_PLAYING && d->connected != CON_EDITING) 
	   || (!can_see( ch, d->character ) && (!IS_SET(ch->act, PLR_WATCHER)) )  )
	    continue;

	wch   = ( d->original != NULL ) ? d->original : d->character;
	if ( wch->level < iLevelLower
	||   wch->level > iLevelUpper
	|| ( fImmortalOnly  && wch->level <  LEVEL_IMMORTAL )
	|| ( fClassRestrict && wch->level != LEVEL_HERO     ) )
	    continue;

	nMatch++;

	/*
	 * Figure out what to print for class.
	 */
	class = " ";

        if ((IS_HEAD(wch,LOST_HEAD) || IS_EXTRA(wch,EXTRA_OSWITCH)) && wch->pcdata->chobj != NULL)
	{
	    if (wch->pcdata->chobj->pIndexData->vnum == 12)
	    	class = "#7A Head#n           ";
	    else if (wch->pcdata->chobj->pIndexData->vnum == 30005)
	    	class = "#0A Brain#n         ";
	    else
	    	class = "#1An Object#n       ";
	} else
	switch ( wch->level )
	{
	default: break;
	case MAX_LEVEL -  0:
		     if ( IS_EXTRA(wch, EXTRA_AFK) )
			class = "#1       AFK#n      ";
	        else if (wch->prefix != NULL)
			class = wch->prefix;
else if (!str_cmp(wch->pcdata->switchname,"Zaphonite")) class = "#2Lord of War#n     ";
else if (!str_cmp(wch->pcdata->switchname,"Lobo"))      class = "#4Psycho Imp#n      ";
	        else class = "Implementor     "; break;  
	case MAX_LEVEL -  1: 
if (!str_cmp(wch->pcdata->switchname,"Dracos")) class =      "#7Help File Lord#n  ";
                else class = "High Judge      "; break;
	case MAX_LEVEL -  2: class = "Judge           "; break;
	case MAX_LEVEL -  3: class = "Enforcer        "; break;
	case MAX_LEVEL -  4: class = "Questmaker      "; break;
	case MAX_LEVEL -  5: class = "Builder         "; break;
	case MAX_LEVEL -  6:
	case MAX_LEVEL -  7:
	case MAX_LEVEL -  8:
	case MAX_LEVEL -  9:
	             if (wch->prefix != NULL) class = wch->prefix;
		else if (wch->race <= 0 ) class = "#1Peasant#n         ";
		else if (wch->race <= 3 ) class = "#2Squire#n          ";
		else if (wch->race <= 6 ) class = "#3Apprentice#n      ";
		else if (wch->race <= 9 ) class = "#4Scout#n           ";
		else if (wch->race <= 12) class = "#5Soldier#n         ";
		else if (wch->race <= 15) class = "#6Lieutenant#n      ";
	        else if (wch->race <= 18) class = "#7Captain#n         ";
		else if (wch->race <= 21) class = "#0Guard#n           ";
		else if (wch->race <= 24) class = "#1Knight#n          ";
		else if (wch->race <= 27) class = "#3Ranger#n          ";
		else if (wch->race <= 30) class = "#5Hunter#n          ";
		else if (wch->race <= 33) class = "#7Assassin#n        ";
		else if (wch->race <= 36) class = "#4L#1o#5rd#n            ";
		else if (wch->race <= 39) class = "#1Baron#n           ";
		else if (wch->race <= 42) class = "#5Duke#n            ";
		else if (wch->race <= 45) class = "#0Prince#n          ";
		else if (wch->race <= 50) class = "#6K#0i#7n#2g#n            ";
		break;

	case MAX_LEVEL - 10: class = "Mortal          "; break;
	case MAX_LEVEL - 11: class = "Newbie          "; break;
	case MAX_LEVEL - 12: class = "#7Undefined#n       "; break;
	}
	/*
	 * Format it up.
	 */
	if ( IS_CLASS(wch, CLASS_VAMPIRE))
	{ strcpy( openb, "<<" ); strcpy( closeb, ">>" ); }
	else if ( IS_CLASS(wch, CLASS_WEREWOLF))
	{ strcpy( openb, "(" ); strcpy( closeb, ")" ); }
	else if ( IS_CLASS(wch,CLASS_MAGE))
	{ strcpy( openb, "{" ); strcpy( closeb, "}" ); }
	else if ( IS_CLASS(wch, CLASS_HIGHLANDER))
	{ strcpy( openb, "-=" ); strcpy( closeb, "=-" ); }
	else if ( IS_CLASS(wch, CLASS_DROW))
	{ strcpy( openb, ".o0"); strcpy(closeb, "0o." ); }
        else if ( IS_CLASS(wch, CLASS_NINJA))
        { strcpy( openb, "***"); strcpy(closeb, "***" ); }
	else if (IS_CLASS(wch, CLASS_MONK))
	{ strcpy(openb, ".x["); strcpy(closeb, "]x."); }
	else if (IS_CLASS(wch, CLASS_CYBORG))
	{ strcpy(openb, "<^>"); strcpy(closeb, "<^>"); }
	else
	{ strcpy( openb, "[" ); strcpy( closeb, "]" ); }
	if ( ch->class > 0 || IS_IMMORTAL( ch ))
	  {
           
	    if ( IS_CLASS(wch, CLASS_DEMON))
	        sprintf( kav, " %sDemon%s",openb,closeb);
	    else if ( IS_CLASS(wch, CLASS_MONK) && wch->generation <= 1)
	        sprintf( kav, " %sMaster Monk%s", openb, closeb);
	    else if ( IS_CLASS(wch, CLASS_VAMPIRE) && wch->generation == 1 )
	    	sprintf( kav, " %sMaster Vampire%s", openb, closeb );
	    else if (IS_CLASS(wch, CLASS_WEREWOLF) && wch->generation == 1 )
	    	sprintf( kav, " %sMaster Werewolf%s", openb, closeb );
	    else if (IS_CLASS(wch, CLASS_DROW) && wch->generation == 1 )
		sprintf( kav, " %sLloth's Avatar%s", openb, closeb );
	    else if (IS_CLASS(wch, CLASS_CYBORG) && wch->generation == 1)
		sprintf( kav, " %sCollective Mind%d", openb, closeb );
	    else if ( IS_CLASS(wch, CLASS_VAMPIRE))
	    {
		bool get_age = FALSE;

		get_age = TRUE;

		if (get_age)
		{
		    if (wch->generation == 2)
			sprintf( kav, " %sVampire Antediluvian%s", openb, closeb );
			else if (IS_EXTRA(wch, SPC_INCONNU))
	/*	if ( IS_EXTRA(wch, EXTRA_AFK) )*/
		sprintf( kav, " %sInconnu Vampire%s", openb, closeb );
			
		else switch ( wch->pcdata->rank )
		    {
		    default:
			sprintf( kav, " %sVampire Childe%s", openb,
closeb );
			break;
		    case AGE_NEONATE:
			sprintf( kav, " %sVampire Neonate%s", openb,
closeb );
			break;
		    case AGE_ANCILLA:
			sprintf( kav, " %sVampire Ancilla%s", openb,
closeb );
			break;
		    case AGE_ELDER:
			sprintf( kav, " %sVampire Elder%s", openb,
closeb );
			break;
		    case AGE_METHUSELAH:
			sprintf( kav, " %sVampire Methuselah%s",
openb, closeb );
			break;
		    }
		}
	    }

	    else if ( IS_CLASS(wch, CLASS_WEREWOLF))
	    {
		if (!IS_SET(ch->extra,EXTRA_BSD))
                   sprintf( kav, " %sBlack Spiral Dancer%s", openb, closeb );
	    	if (wch->generation == 2)
	    	    sprintf( kav, " %sChieftain%s", openb, closeb );
	    	else
	    	    sprintf( kav, " %sWerewolf%s", openb, closeb );
	    }

	else if (IS_CLASS(wch, CLASS_CYBORG))
	    {
		if (wch->generation == 2)
		sprintf(kav,"%sMinor Collective Leader%s",openb,closeb);
		else
		sprintf(kav,"%sCyborg%s",openb,closeb);
	    }
	    
	else if ( IS_CLASS(wch, CLASS_MONK))
	    {
		if (wch->generation == 2)
		        sprintf(kav," %sAbbot%s", openb, closeb);
		else if (wch->generation > 2)
			sprintf(kav," %sMonk%s", openb, closeb);
	    }
	    else if ( IS_CLASS(wch, CLASS_DROW)) {
		if (wch->generation == 2)
			sprintf(kav," %sDrow Matron%s", openb,closeb );
		else if (IS_SET(wch->special, SPC_DROW_WAR))
			sprintf(kav, " %sDrow Warrior%s", openb, closeb );
		else if (IS_SET(wch->special, SPC_DROW_CLE))
			sprintf(kav, " %sDrow Cleric%s", openb, closeb );
		else if (IS_SET(wch->special, SPC_DROW_MAG))
			sprintf(kav, " %sDrow Mage%s", openb, closeb );
		else sprintf(kav, " %sDrow%s", openb, closeb);
		}
	    else if ( IS_CLASS(wch, CLASS_MAGE) )
	    {
            sprintf( kav, "%sMage%s", openb,closeb);
/*		mage_col = str_dup(wch->clan);
		     if (wch->level == LEVEL_APPRENTICE)
		    sprintf( kav, " %s%s Apprentice%s", openb, mage_col, closeb );
		else if (wch->level == LEVEL_MAGE)
		    sprintf( kav, " %s%s Mage%s", openb, mage_col, closeb );
		else if (wch->level == LEVEL_ARCHMAGE)
		    sprintf( kav, " %s%s Archmage%s", openb, mage_col,
closeb);*/
	    }
	    else if ( IS_CLASS(wch, CLASS_HIGHLANDER) )
	    {
		if (wch->generation == 1)
		sprintf(kav, " %sHighlander%s",openb,closeb);
		else if (wch->generation == 2)
		sprintf(kav," %sHighlander%s",openb,closeb);
		else if (wch->generation == 3)
		sprintf(kav," %sHighlander%s",openb,closeb);
		else
		sprintf( kav, " %sHighlander%s", openb, closeb);
	    }
            else if ( IS_CLASS(wch, CLASS_NINJA) )
                sprintf( kav, " %sNinja%s", openb, closeb);
	    else
	      sprintf( kav, " None" );
	}

	else
	    sprintf( kav, " %sNone%s" ,openb,closeb);


            if (IS_CLASS(wch,CLASS_VAMPIRE))
sprintf(cls,"Vampire");
      else  if (IS_CLASS(wch,CLASS_WEREWOLF))
sprintf(cls,"Werewolf");
      else  if (IS_CLASS(wch,CLASS_DEMON)) 	sprintf(cls,"Demon");
      else  if (IS_CLASS(wch,CLASS_DROW)) 	sprintf(cls,"Drow");
      else  if (IS_CLASS(wch,CLASS_MAGE)) 	sprintf(cls,"Mage");
      else 					sprintf(cls,"None");

      sprintf( king, "%s", king_table[wch->pcdata->kingdom].who_name);
      if ( IS_SET(wch->special, SPC_PRINCE) )
        sprintf( king, "Prince of %s", king_table[wch->pcdata->kingdom].who_name);
      else if ( !strcmp(wch->pcdata->switchname,
king_table[wch->pcdata->kingdom].leader_name) )
        sprintf( king, "Leader of %s", king_table[wch->pcdata->kingdom].who_name );
      else if ( !strcmp(wch->pcdata->switchname, "Zelucifur"))
        sprintf( king, "Jester of %s",king_table[wch->pcdata->kingdom].who_name);
	if ( wch->level > 6 )
        {
	sprintf( buf3 + strlen(buf3), "%-16s %-28s%-12s %s\n\r",
	    class,
	    kav,
	    wch->pcdata->switchname,
	    king);
	  imm = TRUE;
	}    
 
	else if ( wch->level >= 3 && wch->level <= 6 )
        {
          if ( wch->race >= 43 )
          {
            sprintf( buf4 + strlen(buf4), "%-16s %-28s%-12s %s\n\r",
              class,
              kav,
              wch->pcdata->switchname,
              king);
		a16 = TRUE;
          }
          else if ( wch->race >= 40 && wch->race <= 42 )
          {
            sprintf( buf6 + strlen(buf6), "%-16s %-28s%-12s %s\n\r",
              class,
              kav,
              wch->pcdata->switchname,
              king);
		a15 = TRUE;
          }
          else if ( wch->race >= 37 && wch->race <= 39 )
          {
            sprintf( buf7 + strlen(buf7), "%-16s %-28s%-12s %s\n\r",
              class,
              kav,
              wch->pcdata->switchname,
              king);
		a14 = TRUE;
          }
          else if ( wch->race >= 34 && wch->race <= 36 )
          {
            sprintf( buf8 + strlen(buf8), "%-16s %-28s%-12s %s\n\r",
              class,
              kav,
              wch->pcdata->switchname,
              king);
		a13 = TRUE;
          }
          else if ( wch->race >= 31 && wch->race <= 33 )
          {
            sprintf( buf9 + strlen(buf9), "%-16s %-28s%-12s %s\n\r",
              class,
              kav,
              wch->pcdata->switchname,
              king);
		a12 = TRUE;
          }
          else if ( wch->race >= 28 && wch->race <= 30 )
          {
            sprintf( buf10 + strlen(buf10), "%-16s %-28s%-12s %s\n\r",
              class,
              kav,
              wch->pcdata->switchname,
              king);
		a11 = TRUE;
          }
          else if ( wch->race >= 25 && wch->race <= 27 )
          {
            sprintf( buf11 + strlen(buf11), "%-16s %-28s%-12s %s\n\r",
              class,
              kav,
              wch->pcdata->switchname,
              king);
		a10 = TRUE;
          }
          else if ( wch->race >= 22 && wch->race <= 24 )
          {
            sprintf( buf12 + strlen(buf12), "%-16s %-28s%-12s %s\n\r",
              class,
              kav,
              wch->pcdata->switchname,
              king);
		a9 = TRUE;
          }
          else if ( wch->race >= 19 && wch->race <= 21 )
          {
            sprintf( buf13 + strlen(buf13), "%-16s %-28s%-12s %s\n\r",
              class,
              kav,
              wch->pcdata->switchname,
              king);
		a8 = TRUE;
          }
          else if ( wch->race >= 16 && wch->race <= 18 )
          {
            sprintf( buf14 + strlen(buf14), "%-16s %-28s%-12s %s\n\r",
              class,
              kav,
              wch->pcdata->switchname,
              king);
		a7 = TRUE;
          }
          else if ( wch->race >= 13 && wch->race <= 15 )
          {
            sprintf( buf15 + strlen(buf15), "%-16s %-28s%-12s %s\n\r",
              class,
              kav,
              wch->pcdata->switchname,
              king);
		a6 = TRUE;
          }
          else if ( wch->race >= 10 && wch->race <= 12 )
          {
            sprintf( buf16 + strlen(buf16), "%-16s %-28s%-12s %s\n\r",
              class,
              kav,
              wch->pcdata->switchname,
              king);
		a5 = TRUE;
          }
          else if ( wch->race >= 7 && wch->race <= 9 )
          {
            sprintf( buf17 + strlen(buf17), "%-16s %-28s%-12s %s\n\r",
              class,
              kav,
              wch->pcdata->switchname,
              king);
	    a4 = TRUE;
          }
          else if ( wch->race >= 4 && wch->race <= 6 )
          {
            sprintf( buf18 + strlen(buf18), "%-16s %-28s%-12s %s\n\r",
              class,
              kav,
              wch->pcdata->switchname,
              king);
	    a3 = TRUE;
          }
          else if ( wch->race >= 1 && wch->race <= 3 )
          {
            sprintf( buf19 + strlen(buf19), "%-16s %-28s%-12s %s\n\r",
              class,
              kav,
              wch->pcdata->switchname,
              king);
	    a2 = TRUE;
          }
          else if ( wch->race == 0 )
          {
            sprintf( buf20 + strlen(buf20), "%-16s %-28s%-12s %s\n\r",
              class,
              kav,
              wch->pcdata->switchname,
              king);
            a1 = TRUE;
          }
	  ava = TRUE;
        }

        else if ( wch->level < 3 )
        {
        sprintf( buf5 + strlen(buf5), "%-16s %-28s%-12s %s\n\r",
            class,
            kav,
            wch->pcdata->switchname,
            king);
          mor = TRUE;
        }

   if ( !main )
   {
      sprintf(buf2,"#1Lords #3of #1War#n"); 
      banner_to_char(buf2,ch);      
      main = TRUE;
   }
     
  }  

    if ( imm )
    {
      if ( !immortal )
      { stc("\n\r",ch);banner2_to_char("#1Gods#n",ch); immortal = TRUE; }
      stc(buf3,ch);
    }

    if ( ava )
    {
      if ( immortal ) stc("\n\r",ch);
      if ( !avatar )
      { banner2_to_char("#3Avatar#n",ch); avatar = TRUE; }
      if ( a16 ) stc(buf4, ch);
      if ( a15 ) stc(buf6, ch);
      if ( a14 ) stc(buf7, ch);
      if ( a13 ) stc(buf8, ch);
      if ( a12 ) stc(buf9, ch);
      if ( a11 ) stc(buf10,ch);
      if ( a10 ) stc(buf11,ch);
      if ( a9  ) stc(buf12,ch);
      if ( a8  ) stc(buf13,ch);
      if ( a7  ) stc(buf14,ch);
      if ( a6  ) stc(buf15,ch);
      if ( a5  ) stc(buf16,ch);
      if ( a4  ) stc(buf17,ch);
      if ( a3  ) stc(buf18,ch);
      if ( a2  ) stc(buf19,ch);
      if ( a1  ) stc(buf20,ch);
    }
 
    if ( mor )
    {
      if ( avatar ) stc("\n\r",ch);
      if ( immortal && !avatar ) stc("\n\r",ch);
      if ( !mortal )
      { banner2_to_char("#4Newbies#n",ch); mortal = TRUE; }
      stc(buf5,ch);
    }

     
    stc("\n\r",ch);
    sprintf(buf2," Total Players: %d ",nMatch);
    banner_to_char(buf2,ch);
    return;
 
}



void do_inventory( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;
    OBJ_DATA *portal;
    OBJ_DATA *portal_next;
    ROOM_INDEX_DATA *pRoomIndex;
    ROOM_INDEX_DATA *location;
    bool found;

    if (!IS_NPC(ch) && IS_HEAD(ch,LOST_HEAD))
        {send_to_char( "You are not a container.\n\r", ch ); return;}
    else if (!IS_NPC(ch) && IS_EXTRA(ch,EXTRA_OSWITCH))
    {
        if ( !IS_NPC(ch) && (obj = ch->pcdata->chobj) == NULL)
	    {send_to_char( "You are not a container.\n\r", ch ); return;}
	switch ( obj->item_type )
	{
	default:
	    send_to_char( "You are not a container.\n\r", ch );
	    break;

	case ITEM_PORTAL:
	    pRoomIndex = get_room_index(obj->value[0]);
	    location = ch->in_room;
	    if ( pRoomIndex == NULL )
	    {
		send_to_char( "You don't seem to lead anywhere.\n\r", ch );
		return;
	    }
	    char_from_room(ch);
	    char_to_room(ch,pRoomIndex);

	    found = FALSE;
	    for ( portal = ch->in_room->contents; portal != NULL; portal = portal_next )
	    {
		portal_next = portal->next_content;
		if ( ( obj->value[0] == portal->value[3]  )
		    && (obj->value[3] == portal->value[0]) )
		{
		    found = TRUE;
		    if (IS_AFFECTED(ch, AFF_SHADOWPLANE) &&
			!IS_SET(portal->extra_flags, ITEM_SHADOWPLANE) )
		    {
			REMOVE_BIT(ch->affected_by, AFF_SHADOWPLANE);
	    		do_look(ch,"auto");
			SET_BIT(ch->affected_by, AFF_SHADOWPLANE);
			break;
		    }
		    else if (!IS_AFFECTED(ch, AFF_SHADOWPLANE) &&
			IS_SET(portal->extra_flags, ITEM_SHADOWPLANE) )
		    {
			SET_BIT(ch->affected_by, AFF_SHADOWPLANE);
	    		do_look(ch,"auto");
			REMOVE_BIT(ch->affected_by, AFF_SHADOWPLANE);
			break;
		    }
		    else
		    {
	    		do_look(ch,"auto");
			break;
		    }
	    	}
	    }
	    char_from_room(ch);
	    char_to_room(ch,location);
	    break;

	case ITEM_DRINK_CON:
	    if ( obj->value[1] <= 0 )
	    {
		send_to_char( "You are empty.\n\r", ch );
		break;
	    }
	    if (obj->value[1] < obj->value[0] / 5)
	    	sprintf( buf, "There is a little %s liquid left in you.\n\r",liq_table[obj->value[2]].liq_color);
	    else if (obj->value[1] < obj->value[0] / 4)
	    	sprintf( buf, "You contain a small about of %s liquid.\n\r",liq_table[obj->value[2]].liq_color);
	    else if (obj->value[1] < obj->value[0] / 3)
	    	sprintf( buf, "You're about a third full of %s liquid.\n\r",liq_table[obj->value[2]].liq_color);
	    else if (obj->value[1] < obj->value[0] / 2)
	    	sprintf( buf, "You're about half full of %s liquid.\n\r",liq_table[obj->value[2]].liq_color);
	    else if (obj->value[1] < obj->value[0])
	    	sprintf( buf, "You are almost full of %s liquid.\n\r",liq_table[obj->value[2]].liq_color);
	    else if (obj->value[1] == obj->value[0])
	    	sprintf( buf, "You're completely full of %s liquid.\n\r",liq_table[obj->value[2]].liq_color);
	    else
	    	sprintf( buf, "Somehow you are MORE than full of %s liquid.\n\r",liq_table[obj->value[2]].liq_color);
	    send_to_char( buf, ch );
	    break;

	case ITEM_CONTAINER:
	case ITEM_CORPSE_NPC:
	case ITEM_CORPSE_PC:
	    act( "$p contain:", ch, obj, NULL, TO_CHAR );
	    show_list_to_char( obj->contains, ch, TRUE, TRUE );
	    break;
	}
	return;
    }
    send_to_char( "You are carrying:\n\r", ch );
    show_list_to_char( ch->carrying, ch, TRUE, TRUE );
    return;
}



void do_equipment( CHAR_DATA *ch, char *argument )
{
    OBJ_DATA *obj;
    int iWear;
    bool found;

    send_to_char( "You are using:\n\r", ch );
    found = FALSE;
    for ( iWear = 0; iWear < MAX_WEAR; iWear++ )
    {
	if ( ( obj = get_eq_char( ch, iWear ) ) == NULL )
	    continue;

	send_to_char( where_name[iWear], ch );
	if ( can_see_obj( ch, obj ) )
	{
	    send_to_char( format_obj_to_char( obj, ch, TRUE ), ch );
	    send_to_char( "\n\r", ch );
	}
	else
	{
	    send_to_char( "something.\n\r", ch );
	}
	found = TRUE;
    }

    if ( !found )
	send_to_char( "Nothing.\n\r", ch );

    return;
}



void do_compare( CHAR_DATA *ch, char *argument )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    OBJ_DATA *obj1;
    OBJ_DATA *obj2;
    int value1;
    int value2;
    char *msg;

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );
    if ( arg1[0] == '\0' )
    {
	send_to_char( "Compare what to what?\n\r", ch );
	return;
    }

    if ( ( obj1 = get_obj_carry( ch, arg1 ) ) == NULL )
    {
	send_to_char( "You do not have that item.\n\r", ch );
	return;
    }

    if ( arg2[0] == '\0' )
    {
	for ( obj2 = ch->carrying; obj2 != NULL; obj2 = obj2->next_content )
	{
	    if ( obj2->wear_loc != WEAR_NONE
	    &&   can_see_obj( ch, obj2 )
	    &&   obj1->item_type == obj2->item_type
	    && ( obj1->wear_flags & obj2->wear_flags & ~ITEM_TAKE) != 0 )
		break;
	}

	if ( obj2 == NULL )
	{
	    send_to_char( "You aren't wearing anything comparable.\n\r", ch );
	    return;
	}
    }
    else
    {
	if ( ( obj2 = get_obj_carry( ch, arg2 ) ) == NULL )
	{
	    send_to_char( "You do not have that item.\n\r", ch );
	    return;
	}
    }
	    
    msg		= NULL;
    value1	= 0;
    value2	= 0;

    if ( obj1 == obj2 )
    {
	msg = "You compare $p to itself.  It looks about the same.";
    }
    else if ( obj1->item_type != obj2->item_type )
    {
	msg = "You can't compare $p and $P.";
    }
    else
    {
	switch ( obj1->item_type )
	{
	default:
	    msg = "You can't compare $p and $P.";
	    break;

	case ITEM_ARMOR:
	    value1 = obj1->value[0];
	    value2 = obj2->value[0];
	    break;

	case ITEM_WEAPON:
	    value1 = obj1->value[1] + obj1->value[2];
	    value2 = obj2->value[1] + obj2->value[2];
	    break;
	}
    }

    if ( msg == NULL )
    {
	     if ( value1 == value2 ) msg = "$p and $P look about the same.";
	else if ( value1  > value2 ) msg = "$p looks better than $P.";
	else                         msg = "$p looks worse than $P.";
    }

    act( msg, ch, obj1, obj2, TO_CHAR );
    return;
}



void do_credits( CHAR_DATA *ch, char *argument )
{
    do_help( ch, "diku" );
    return;
}



void do_wizlist( CHAR_DATA *ch, char *argument )
{
    do_help( ch, "wizlist" );
    return;
}



void do_where( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    DESCRIPTOR_DATA *d;
    bool found;

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char( "Players near you:\n\r", ch );
	found = FALSE;
	for ( d = descriptor_list; d != NULL; d = d->next )
	{
	    if ( ( d->connected == CON_PLAYING
	    ||   d->connected == CON_EDITING)
	    && ( victim = d->character ) != NULL
	    &&   !IS_NPC(victim)
	    &&   victim->in_room != NULL
	    &&   victim->in_room->area == ch->in_room->area
	    &&   victim->pcdata->chobj == NULL
	    &&   can_see( ch, victim ) )
	    {
		found = TRUE;
		sprintf( buf, "%-28s %s\n\r",
		    victim->name, victim->in_room->name );
		send_to_char( buf, ch );
	    }
	}
	if ( !found )
	    send_to_char( "None\n\r", ch );
    }
    else
    {
	found = FALSE;
	for ( victim = char_list; victim != NULL; victim = victim->next )
	{
	    if ( victim->in_room != NULL
	    &&   victim->in_room->area == ch->in_room->area
	    &&   !IS_AFFECTED(victim, AFF_HIDE)
	    &&   !IS_AFFECTED(victim, AFF_SNEAK)
	    &&   can_see( ch, victim )
	    &&   is_name( arg, victim->name ) )
	    {
		found = TRUE;
		sprintf( buf, "%-28s %s\n\r",
		    PERS(victim, ch), victim->in_room->name );
		send_to_char( buf, ch );
		break;
	    }
	}
	if ( !found )
	    act( "You didn't find any $T.", ch, NULL, arg, TO_CHAR );
    }

    return;
}




void do_consider( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    char *msg;
    int diff;
    int overall;
    int con_hit;
    int con_dam;
    int con_ac;
    int con_hp;

    one_argument( argument, arg );
    overall = 0;

    if ( arg[0] == '\0' )
    {
	send_to_char( "Consider killing whom?\n\r", ch );
	return;
    }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They're not here.\n\r", ch );
	return;
    }

    act( "You examine $N closely, looking for $S weaknesses.", ch, NULL, victim, TO_CHAR );
    act( "$n examine $N closely, looking for $S weaknesses.", ch, NULL, victim, TO_NOTVICT );
    act( "$n examines you closely, looking for your weaknesses.", ch, NULL, victim, TO_VICT );

    if (!IS_NPC(victim)) do_skill(ch,victim->name);

    if (!IS_NPC(victim) && IS_CLASS(victim, CLASS_VAMPIRE) && 
	IS_EXTRA(victim, EXTRA_FAKE_CON))
    {
	con_hit = victim->pcdata->fake_hit;
	con_dam = victim->pcdata->fake_dam;
	con_ac = victim->pcdata->fake_ac;
	con_hp = victim->pcdata->fake_hp;
    }
    else
    {
	con_hit = char_hitroll(victim);
	con_dam = char_damroll(victim);
	con_ac = char_ac(victim);
	con_hp = victim->hit;
    }
    if (con_hp < 1) con_hp = 1;

    diff = victim->level - ch->level + con_hit - char_hitroll(ch);
         if ( diff <= -35 ) {msg = "You are FAR more skilled than $M."; overall = overall + 3;}
    else if ( diff <= -15 ) {msg = "$E is not as skilled as you are."; overall = overall + 2;}
    else if ( diff <=  -5 ) {msg = "$E doesn't seem quite as skilled as you."; overall = overall + 1;}
    else if ( diff <=   5 ) {msg = "You are about as skilled as $M.";}
    else if ( diff <=  15 ) {msg = "$E is slightly more skilled than you are."; overall = overall - 1;}
    else if ( diff <=  35 ) {msg = "$E seems more skilled than you are."; overall = overall -2;}
    else                    {msg = "$E is FAR more skilled than you."; overall = overall - 3;}
    act( msg, ch, NULL, victim, TO_CHAR );

    diff = victim->level - ch->level + con_dam - char_damroll(ch);
         if ( diff <= -35 ) {msg = "You are FAR more powerful than $M."; overall = overall + 3;}
    else if ( diff <= -15 ) {msg = "$E is not as powerful as you are."; overall = overall + 2;}
    else if ( diff <=  -5 ) {msg = "$E doesn't seem quite as powerful as you."; overall = overall + 1;}
    else if ( diff <=   5 ) {msg = "You are about as powerful as $M.";}
    else if ( diff <=  15 ) {msg = "$E is slightly more powerful than you are."; overall = overall - 1;}
    else if ( diff <=  35 ) {msg = "$E seems more powerful than you are."; overall = overall -2;}
    else                    {msg = "$E is FAR more powerful than you."; overall = overall - 3;}
    act( msg, ch, NULL, victim, TO_CHAR );

    diff = ch->hit * 100 / con_hp;
         if ( diff <=  10 ) {msg = "$E is currently FAR healthier than you are."; overall = overall - 3;}
    else if ( diff <=  50 ) {msg = "$E is currently much healthier than you are."; overall = overall - 2;}
    else if ( diff <=  75 ) {msg = "$E is currently slightly healthier than you are."; overall = overall - 1;}
    else if ( diff <= 125 ) {msg = "$E is currently about as healthy as you are.";}
    else if ( diff <= 200 ) {msg = "You are currently slightly healthier than $M."; overall = overall + 1;}
    else if ( diff <= 500 ) {msg = "You are currently much healthier than $M."; overall = overall + 2;}
    else                    {msg = "You are currently FAR healthier than $M."; overall = overall + 3;}
    act( msg, ch, NULL, victim, TO_CHAR );

    diff = con_ac - char_ac(ch);
         if ( diff <= -100) {msg = "$E is FAR better armoured than you."; overall = overall - 3;}
    else if ( diff <= -50 ) {msg = "$E looks much better armoured than you."; overall = overall - 2;}
    else if ( diff <= -25 ) {msg = "$E looks better armoured than you."; overall = overall - 1;}
    else if ( diff <=  25 ) {msg = "$E seems about as well armoured as you.";}
    else if ( diff <=  50 ) {msg = "You are better armoured than $M."; overall = overall + 1;}
    else if ( diff <=  100) {msg = "You are much better armoured than $M."; overall = overall + 2;}
    else                    {msg = "You are FAR better armoured than $M."; overall = overall + 3;}
    act( msg, ch, NULL, victim, TO_CHAR );

    diff = overall;
         if ( diff <= -11 ) msg = "Conclusion: $E would kill you in seconds.";
    else if ( diff <=  -7 ) msg = "Conclusion: You would need a lot of luck to beat $M.";
    else if ( diff <=  -3 ) msg = "Conclusion: You would need some luck to beat $N.";
    else if ( diff <=   2 ) msg = "Conclusion: It would be a very close fight.";
    else if ( diff <=   6 ) msg = "Conclusion: You shouldn't have a lot of trouble defeating $M.";
    else if ( diff <=  10 ) msg = "Conclusion: $N is no match for you.  You can easily beat $M.";
    else                    msg = "Conclusion: $E wouldn't last more than a few seconds against you.";
    act( msg, ch, NULL, victim, TO_CHAR );

    return;
}


void set_prefix( CHAR_DATA *ch, char *title )
{
    char buf[MAX_STRING_LENGTH];

    if ( IS_NPC(ch) )
    {
	bug( "Set_title: NPC.", 0 );
	return;
    }

    if ( isalpha(title[0]) || isdigit(title[0]) )
    {
	buf[0] = ' ';
	strcpy( buf+1, title );
    }
    else
    {
	strcpy( buf, title );
    }

    free_string( ch->prefix );
    ch->prefix = str_dup( buf );
    return;
}



void do_prefix( CHAR_DATA *ch, char *argument )
{
 
    char buf[MAX_STRING_LENGTH];

    if ( IS_NPC(ch) )
	return;

    if ( argument[0] == '\0' )
    {
	send_to_char( "Change your prefix to what?\n\r", ch );
	return;
    }

    if ( strlen(argument) > 13 )
	argument[13] = '\0';

    smash_tilde( argument );
    sprintf(buf,"#n");
    strcpy(buf,argument);
    set_prefix( ch, argument );
    send_to_char( "Prefix Set.\n\r", ch );
}

void set_title( CHAR_DATA *ch, char *title )
{
    char buf[MAX_STRING_LENGTH];

    if ( IS_NPC(ch) )
    {
	bug( "Set_title: NPC.", 0 );
	return;
    }

    if ( isalpha(title[0]) || isdigit(title[0]) )
    {
	buf[0] = ' ';
	strcpy( buf+1, title );
    }
    else
    {
	strcpy( buf, title );
    }

    free_string( ch->pcdata->title );
    ch->pcdata->title = str_dup( buf );
    return;
}



void do_title( CHAR_DATA *ch, char *argument )
{
 
    char buf[MAX_STRING_LENGTH];

    if ( IS_NPC(ch) )
	return;

    if ( argument[0] == '\0' )
    {
	send_to_char( "Change your title to what?\n\r", ch );
	return;
    }

    if ( strlen(argument) > 17 )
	argument[17] = '\0';

    smash_tilde( argument );
    sprintf(buf,"#n");
    strcpy(buf,argument);
    set_title( ch, argument );
    send_to_char( "Ok.\n\r", ch );
}

void do_afk( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];

	if ( IS_NPC(ch) )
	return;

        if (IS_SET(ch->extra, EXTRA_AFK))
	{
	free_string( ch->pcdata->title);
	ch->pcdata->title = str_dup( ch->short_descr );
	free_string( ch->short_descr );
	ch->short_descr = NULL;
	send_to_char( "You are no longer AFK.\n\r", ch );
	sprintf(buf,"%s is no longer AFK!",ch->pcdata->switchname);
        ADD_COLOUR(ch,buf,L_RED);
	do_info(ch,buf);
	REMOVE_BIT(ch->extra,EXTRA_AFK);
        return;
	}
	
	else if (!IS_SET(ch->extra,EXTRA_AFK))
	{
	free_string( ch->short_descr );
	ch->short_descr = str_dup( ch->pcdata->title );
	free_string( ch->pcdata->title );
	ch->pcdata->title = str_dup("#n(#1AFK#n)");
	send_to_char( "You are now AFK.\n\r", ch );
	sprintf(buf,"%s is now AFK!",ch->pcdata->switchname);
	ADD_COLOUR(ch,buf,L_RED);
	do_info(ch,buf);
	SET_BIT(ch->extra,EXTRA_AFK);
	WAIT_STATE(ch, 25);
        return;
	}

else
return;

}

void do_email( CHAR_DATA *ch, char *argument )
{
    if ( IS_NPC(ch) )
	return;

    if ( argument[0] == '\0' )
    {
	send_to_char( "What do you wish to set your email address to?\n\r", ch );
	return;
    }

    if ( strlen(argument) > 50 )
	argument[50] = '\0';

    smash_tilde( argument );
    free_string( ch->pcdata->email );
    ch->pcdata->email = str_dup( argument );
    send_to_char( "Ok.\n\r", ch );
}



void do_description( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];

    if ( argument[0] != '\0' )
    {
	buf[0] = '\0';
	smash_tilde( argument );
	if ( argument[0] == '+' )
	{
	    if ( ch->description != NULL )
		strcat( buf, ch->description );
	    argument++;
	    while ( isspace(*argument) )
		argument++;
	}

	if ( strlen(buf) + strlen(argument) >= MAX_STRING_LENGTH - 2 )
	{
	    send_to_char( "Description too long.\n\r", ch );
	    return;
	}

	strcat( buf, argument );
	strcat( buf, "\n\r" );
	free_string( ch->description );
	ch->description = str_dup( buf );
    }

    send_to_char( "Your description is:\n\r", ch );
    send_to_char( ch->description ? ch->description : "(None).\n\r", ch );
    return;
}



void do_report( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *vch;
    CHAR_DATA *vch_next;
    char buf[MAX_STRING_LENGTH];
    char hit_str[MAX_INPUT_LENGTH];
    char mana_str[MAX_INPUT_LENGTH];
    char move_str[MAX_INPUT_LENGTH];
    char mhit_str[MAX_INPUT_LENGTH];
    char mmana_str[MAX_INPUT_LENGTH];
    char mmove_str[MAX_INPUT_LENGTH];
    char exp_str[MAX_INPUT_LENGTH];
    sprintf(hit_str, "%d", ch->hit);
    COL_SCALE(hit_str, ch, ch->hit, ch->max_hit);
    sprintf(mana_str, "%d", ch->mana);
    COL_SCALE(mana_str, ch, ch->mana, ch->max_mana);
    sprintf(move_str, "%d", ch->move);
    COL_SCALE(move_str, ch, ch->move, ch->max_move);
    sprintf(exp_str, "%d", ch->exp);
    COL_SCALE(exp_str, ch, ch->exp, 1000);
    sprintf(mhit_str, "%d", ch->max_hit);
    ADD_COLOUR(ch, mhit_str, L_CYAN);
    sprintf(mmana_str, "%d", ch->max_mana);
    ADD_COLOUR(ch, mmana_str, L_CYAN);
    sprintf(mmove_str, "%d", ch->max_move);
    ADD_COLOUR(ch, mmove_str, L_CYAN);
    sprintf( buf,
	"You report: %s/%s hp %s/%s mana %s/%s mv %s xp.\n\r",
	hit_str,  mhit_str,
	mana_str, mmana_str,
	move_str, mmove_str,
	exp_str   );

    send_to_char( buf, ch );

    for ( vch = char_list; vch != NULL; vch = vch_next )
    {
	vch_next	= vch->next;
	if ( vch == NULL ) continue;
	if ( vch == ch ) continue;
	if ( vch->in_room == NULL ) continue;
	if ( vch->in_room != ch->in_room ) continue;
    	sprintf(hit_str, "%d", ch->hit);
    	COL_SCALE(hit_str, vch, ch->hit, ch->max_hit);
    	sprintf(mana_str, "%d", ch->mana);
    	COL_SCALE(mana_str, vch, ch->mana, ch->max_mana);
    	sprintf(move_str, "%d", ch->move);
    	COL_SCALE(move_str, vch, ch->move, ch->max_move);
    	sprintf(exp_str, "%d", ch->exp);
    	COL_SCALE(exp_str, vch, ch->exp, 1000);
    	sprintf(mhit_str, "%d", ch->max_hit);
    	ADD_COLOUR(vch, mhit_str, L_CYAN);
    	sprintf(mmana_str, "%d", ch->max_mana);
    	ADD_COLOUR(vch, mmana_str, L_CYAN);
    	sprintf(mmove_str, "%d", ch->max_move);
    	ADD_COLOUR(vch, mmove_str, L_CYAN);
    	if (!IS_NPC(ch) && IS_AFFECTED(ch,AFF_POLYMORPH))
    	    sprintf( buf, "%s reports: %s/%s hp %s/%s mana %s/%s mv %s xp.\n\r",
	    ch->morph,
	    hit_str,  mhit_str,
	    mana_str, mmana_str,
	    move_str, mmove_str,
	    exp_str   );
        else
    	    sprintf( buf, "%s reports: %s/%s hp %s/%s mana %s/%s mv %s xp.\n\r",
	    IS_NPC(ch) ? capitalize(ch->short_descr) : ch->name,
	    hit_str,  mhit_str,
	    mana_str, mmana_str,
	    move_str, mmove_str,
	    exp_str   );
	buf[0] = UPPER(buf[0]);
    	send_to_char( buf, vch );
    }
    return;
}



void do_practice( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    int sn;

    if ( IS_NPC(ch) )
	return;

    if ( argument[0] == '\0' )
    {
	int col;

	col    = 0;
	for ( sn = 0; sn < MAX_SKILL; sn++ )
	{
	    if ( skill_table[sn].name == NULL )
		break;
	    if ( ch->level < skill_table[sn].skill_level )
		continue;
	    sprintf( buf, "%18s %3d%%  ",
		skill_table[sn].name, ch->pcdata->learned[sn] );
	    send_to_char( buf, ch );
	    if ( ++col % 3 == 0 )
		send_to_char( "\n\r", ch );
	}

	if ( col % 3 != 0 )
	    send_to_char( "\n\r", ch );

	sprintf( buf, "You have %d exp left.\n\r", ch->exp );
	send_to_char( buf, ch );
    }
    else
    {
	if ( !IS_AWAKE(ch) )
	{
	    send_to_char( "In your dreams, or what?\n\r", ch );
	    return;
	}

	if ( ch->exp <= 0 )
	{
	    send_to_char( "You have no exp left.\n\r", ch );
	    return;
	}

	if ( ( sn = skill_lookup( argument ) ) < 0
	|| ( !IS_NPC(ch)
	&&   ch->level < skill_table[sn].skill_level ) )
	{
	    send_to_char( "You can't practice that.\n\r", ch );
	    return;
	}

	
	if ( ch->pcdata->learned[sn] >= SKILL_ADEPT )
	{
	    sprintf( buf, "You are already an adept of %s.\n\r",
	         skill_table[sn].name );
	    send_to_char( buf, ch );
	}
	else if ( ch->pcdata->learned[sn] > 0 &&
		ch->exp < 5000 )
	{
	    sprintf( buf, "You need 5000 exp to increase %s any more.\n\r",
		(skill_table[sn].name));
	    send_to_char( buf, ch );
	}
	else if ( ch->pcdata->learned[sn] == 0 && ch->exp < 5000 )
	{
	    sprintf( buf, "You need 5000 exp to increase %s.\n\r",
		skill_table[sn].name );
	    send_to_char( buf, ch );
	}
	else
	{
	    if (ch->pcdata->learned[sn] == 0)
	    {
	    	ch->exp -= 5000;
	    	ch->pcdata->learned[sn] +=100;
	    }
	    else
	    {
	    	ch->exp -= (ch->pcdata->learned[sn]/2);
	    	ch->pcdata->learned[sn] += int_app[get_curr_int(ch)].learn;
	    }
	    if ( ch->pcdata->learned[sn] < SKILL_ADEPT )
	    {
		act( "You practice $T.",
		    ch, NULL, skill_table[sn].name, TO_CHAR );
	    }
	    else
	    {
		ch->pcdata->learned[sn] = SKILL_ADEPT;
		act( "You are now an adept of $T.",
		    ch, NULL, skill_table[sn].name, TO_CHAR );
	    }
	}
    }
    return;
}



/*
 * 'Wimpy' originally by Dionysos.
 */
void do_wimpy( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    int wimpy;

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
	wimpy = ch->max_hit / 5;
    else
	wimpy = atoi( arg );

    if ( wimpy < 0 )
    {
	send_to_char( "Your courage exceeds your wisdom.\n\r", ch );
	return;
    }

    if ( wimpy > ch->max_hit )
    {
	send_to_char( "Such cowardice ill becomes you.\n\r", ch );
	return;
    }

    ch->wimpy	= wimpy;
    sprintf( buf, "Wimpy set to %d hit points.\n\r", wimpy );
    send_to_char( buf, ch );
    return;
}



void do_password( CHAR_DATA *ch, char *argument )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    char *pArg;
    char *pwdnew;
    char *p;
    char cEnd;

    if ( IS_NPC(ch) )
	return;

    /*
     * Can't use one_argument here because it smashes case.
     * So we just steal all its code.  Bleagh.
     */
    pArg = arg1;
    while ( isspace(*argument) )
	argument++;

    cEnd = ' ';
    if ( *argument == '\'' || *argument == '"' )
	cEnd = *argument++;

    while ( *argument != '\0' )
    {
	if ( *argument == cEnd )
	{
	    argument++;
	    break;
	}
	*pArg++ = *argument++;
    }
    *pArg = '\0';

    pArg = arg2;
    while ( isspace(*argument) )
	argument++;

    cEnd = ' ';
    if ( *argument == '\'' || *argument == '"' )
	cEnd = *argument++;

    while ( *argument != '\0' )
    {
	if ( *argument == cEnd )
	{
	    argument++;
	    break;
	}
	*pArg++ = *argument++;
    }
    *pArg = '\0';

    if ( arg1[0] == '\0' || arg2[0] == '\0' )
    {
	send_to_char( "Syntax: password <old> <new>.\n\r", ch );
	return;
    }

    if ( strcmp( arg1, ch->pcdata->pwd ) &&
         strcmp( crypt( arg1, ch->pcdata->pwd ), ch->pcdata->pwd ) )
    {
	WAIT_STATE( ch, 40 );
	send_to_char( "Wrong password.  Wait 10 seconds.\n\r", ch );
	return;
    }

    if ( strlen(arg2) < 5 )
    {
	send_to_char(
	    "New password must be at least five characters long.\n\r", ch );
	return;
    }

    /*
     * No tilde allowed because of player file format.
     */
    pwdnew = crypt( arg2, ch->pcdata->switchname );
    for ( p = pwdnew; *p != '\0'; p++ )
    {
	if ( *p == '~' )
	{
	    send_to_char(
		"New password not acceptable, try again.\n\r", ch );
	    return;
	}
    }

    free_string( ch->pcdata->pwd );
    ch->pcdata->pwd = str_dup( pwdnew );
    if (!IS_EXTRA(ch,EXTRA_NEWPASS)) SET_BIT(ch->extra,EXTRA_NEWPASS);
    save_char_obj( ch );
    if (ch->desc != NULL && ch->desc->connected == CON_PLAYING )
	send_to_char( "Ok.\n\r", ch );
    return;
}



void do_socials( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    int iSocial;
    int col;

    col = 0;

    for ( iSocial = 0; social_table[iSocial].name[0] != '\0'; iSocial++ )
    {
	sprintf( buf, "%-12s", social_table[iSocial].name );
	send_to_char( buf, ch );
	if ( ++col % 6 == 0 )
	    send_to_char( "\n\r", ch );
    }
 
    if ( col % 6 != 0 )
	send_to_char( "\n\r", ch );

    return;
}



void do_xsocials( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    int iSocial;
    int col;

    col = 0;

    for ( iSocial = 0; xsocial_table[iSocial].name[0] != '\0'; iSocial++ )
    {
	sprintf( buf, "%-12s", xsocial_table[iSocial].name );
	send_to_char( buf, ch );
	if ( ++col % 6 == 0 )
	    send_to_char( "\n\r", ch );
    }
 
    if ( col % 6 != 0 )
	send_to_char( "\n\r", ch );

    return;
}



void do_spells( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    int sn;
    int col;

    col = 0;
    for ( sn = 0; sn < MAX_SKILL && skill_table[sn].name != NULL; sn++ )
    {
	sprintf( buf, "%-12s", skill_table[sn].name );
	send_to_char( buf, ch );
	if ( ++col % 6 == 0 )
	    send_to_char( "\n\r", ch );
    }

    if ( col % 6 != 0 )
	send_to_char( "\n\r", ch );
    return;
}



/*
 * Contributed by Alander.
 */
void do_commands( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    int cmd;
    int col;
 
    col = 0;
    for ( cmd = 0; cmd_table[cmd].name[0] != '\0'; cmd++ )
    {
        if ( cmd_table[cmd].level == 0
        &&   cmd_table[cmd].level <= get_trust( ch ) )
	{
	    sprintf( buf, "%-12s", cmd_table[cmd].name );
	    send_to_char( buf, ch );
	    if ( ++col % 6 == 0 )
		send_to_char( "\n\r", ch );
	}
    }
 
    if ( col % 6 != 0 )
	send_to_char( "\n\r", ch );
    return;
}



void do_channels( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];

    one_argument( argument, arg );

    if (IS_NPC(ch)) return;
    if ( arg[0] == '\0' )
    {
	if ( !IS_NPC(ch) && IS_SET(ch->act, PLR_SILENCE) )
	{
	    send_to_char( "You are silenced.\n\r", ch );
	    return;
	}

	send_to_char( "Channels:", ch );

/*	send_to_char( !IS_SET(ch->deaf, CHANNEL_AUCTION)
	    ? " +AUCTION"
	    : " -auction",
	    ch );
*/
	send_to_char( !IS_SET(ch->deaf, CHANNEL_CHAT)
	    ? " +CHAT"
	    : " -chat",
	    ch );

#if 0
	send_to_char( !IS_SET(ch->deaf, CHANNEL_HACKER)
	    ? " +HACKER"
	    : " -hacker",
	    ch );
#endif

	if ( IS_IMMORTAL(ch) )
	{
	    send_to_char( !IS_SET(ch->deaf, CHANNEL_IMMTALK)
		? " +IMMTALK"
		: " -immtalk",
		ch );
	}

	send_to_char( !IS_SET(ch->deaf, CHANNEL_MUSIC)
	    ? " +MUSIC"
	    : " -music",
	    ch );

	send_to_char( !IS_SET(ch->deaf, CHANNEL_QUESTION)
	    ? " +QUESTION"
	    : " -question",
	    ch );

	send_to_char( !IS_SET(ch->deaf, CHANNEL_SHOUT)
	    ? " +SHOUT"
	    : " -shout",
	    ch );

	send_to_char( !IS_SET(ch->deaf, CHANNEL_HOWL)
	    ? " +HOWL"
	    : " -howl",
	    ch );

	if (IS_IMMORTAL(ch))
	{
	    send_to_char( !IS_SET(ch->deaf, CHANNEL_LOG)
		? " +LOG"
		: " -log",
		ch );
	}

        if (IS_CLASS( ch, CLASS_MAGE) || IS_IMMORTAL(ch))
        {
            send_to_char( !IS_SET(ch->deaf, CHANNEL_MAGETALK)
                ? " +MAGE"
                : " -mage",
                ch );
        }

        if (IS_CLASS( ch, CLASS_MONK) || IS_IMMORTAL(ch))
        {
            send_to_char( !IS_SET(ch->deaf, CHANNEL_MONK)
                ? " +MONK"
                : " -monk",
                ch );
        }

	if (IS_CLASS(ch, CLASS_DEMON) || IS_IMMORTAL(ch))
	{
	    send_to_char( !IS_SET(ch->deaf, CHANNEL_PRAY)
		? " +PRAY"
		: " -pray",
		ch );
	}

	send_to_char( !IS_SET(ch->deaf, CHANNEL_INFO)
	    ? " +INFO"
	    : " -info",
	    ch );

	if (IS_CLASS(ch, CLASS_VAMPIRE) || IS_IMMORTAL(ch))
	{
	    send_to_char( !IS_SET(ch->deaf, CHANNEL_VAMPTALK)
		? " +VAMP"
		: " -vamp",
		ch );
	}

	if (IS_CLASS(ch, CLASS_HIGHLANDER) || IS_IMMORTAL(ch)) {
		send_to_char( !IS_SET(ch->deaf, CHANNEL_HIGHTALK)
			? " +HIGH"
			: " -high",
			ch ); }

	send_to_char( !IS_SET(ch->deaf, CHANNEL_TELL)
	    ? " +TELL"
	    : " -tell",
	    ch );

	send_to_char( ".\n\r", ch );
    }
    else
    {
	bool fClear;
	int bit;

	     if ( arg[0] == '+' ) fClear = TRUE;
	else if ( arg[0] == '-' ) fClear = FALSE;
	else
	{
	    send_to_char( "Channels -channel or +channel?\n\r", ch );
	    return;
	}

/*	     if ( !str_cmp( arg+1, "auction"  ) ) bit = CHANNEL_AUCTION;*/
        if ( !str_cmp( arg+1, "chat"     ) ) bit = CHANNEL_CHAT;
#if 0
	else if ( !str_cmp( arg+1, "hacker"   ) ) bit = CHANNEL_HACKER;
#endif
	else if ( !str_cmp( arg+1, "immtalk"  ) ) bit = CHANNEL_IMMTALK;
	else if ( !str_cmp( arg+1, "music"    ) ) bit = CHANNEL_MUSIC;
	else if ( !str_cmp( arg+1, "question" ) ) bit = CHANNEL_QUESTION;
	else if ( !str_cmp( arg+1, "shout"    ) ) bit = CHANNEL_SHOUT;
	else if ( !str_cmp( arg+1, "yell"     ) ) bit = CHANNEL_YELL;
	else if ( !str_cmp( arg+1, "howl"     ) ) bit = CHANNEL_HOWL;
	else if (IS_IMMORTAL(ch) && !str_cmp( arg+1, "log") ) bit = CHANNEL_LOG;
        else if ( !str_cmp( arg+1, "monk"     ) ) bit = CHANNEL_MONK;          
        else if ( !str_cmp( arg+1, "mage"     ) ) bit = CHANNEL_MAGETALK;
	else if ((IS_SET(ch->special, SPC_CHAMPION) || (IS_IMMORTAL(ch))) && !str_cmp( arg+1, "pray") ) 
	    bit = CHANNEL_PRAY;
	else if ( !str_cmp( arg+1, "info"     ) ) bit = CHANNEL_INFO;
	else if ( !str_cmp( arg+1, "vamp"     ) ) bit = CHANNEL_VAMPTALK;
	else if ( !str_cmp( arg+1, "tell"     ) ) bit = CHANNEL_TELL;
	else
	{
	    send_to_char( "Set or clear which channel?\n\r", ch );
	    return;
	}

	if ( fClear )
	    REMOVE_BIT (ch->deaf, bit);
	else
	    SET_BIT    (ch->deaf, bit);

	send_to_char( "Ok.\n\r", ch );
    }

    return;
}



/*
 * Contributed by Grodyn.
 */
void do_config( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];

    if ( IS_NPC(ch) )
	return;

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
        send_to_char( "[ Keyword  ] Option\n\r", ch );

	send_to_char(  IS_SET(ch->act, PLR_ANSI)
            ? "[+ANSI     ] You have ansi colour on.\n\r"
	    : "[-ansi     ] You have ansi colour off.\n\r"
	    , ch );

	send_to_char(  IS_SET(ch->act, PLR_AUTOEXIT)
            ? "[+AUTOEXIT ] You automatically see exits.\n\r"
	    : "[-autoexit ] You don't automatically see exits.\n\r"
	    , ch );

	send_to_char(  IS_SET(ch->act, PLR_AUTOLOOT)
	    ? "[+AUTOLOOT ] You automatically loot corpses.\n\r"
	    : "[-autoloot ] You don't automatically loot corpses.\n\r"
	    , ch );

	send_to_char(  IS_SET(ch->act, PLR_AUTOSAC)
	    ? "[+AUTOSAC  ] You automatically sacrifice corpses.\n\r"
	    : "[-autosac  ] You don't automatically sacrifice corpses.\n\r"
	    , ch );

	send_to_char(  IS_SET(ch->act, PLR_BLANK)
	    ? "[+BLANK    ] You have a blank line before your prompt.\n\r"
	    : "[-blank    ] You have no blank line before your prompt.\n\r"
	    , ch );

	send_to_char(  IS_SET(ch->act, PLR_BRIEF)
	    ? "[+BRIEF    ] You see brief descriptions.\n\r"
	    : "[-brief    ] You see long descriptions.\n\r"
	    , ch );
         
	send_to_char(  IS_SET(ch->act, PLR_COMBINE)
	    ? "[+COMBINE  ] You see object lists in combined format.\n\r"
	    : "[-combine  ] You see object lists in single format.\n\r"
	    , ch );

	send_to_char(  IS_SET(ch->act, PLR_PROMPT)
	    ? "[+PROMPT   ] You have a prompt.\n\r"
	    : "[-prompt   ] You don't have a prompt.\n\r"
	    , ch );

	send_to_char(  IS_SET(ch->act, PLR_TELNET_GA)
	    ? "[+TELNETGA ] You receive a telnet GA sequence.\n\r"
	    : "[-telnetga ] You don't receive a telnet GA sequence.\n\r"
	    , ch );

	send_to_char(  IS_SET(ch->act, PLR_SILENCE)
	    ? "[+SILENCE  ] You are silenced.\n\r"
	    : ""
	    , ch );

	send_to_char( !IS_SET(ch->act, PLR_NO_TELL)
	    ? ""
	    : "[-tell     ] You can't use 'tell'.\n\r"
	    , ch );
    }
    else
    {
	bool fSet;
	int bit;

	     if ( arg[0] == '+' ) fSet = TRUE;
	else if ( arg[0] == '-' ) fSet = FALSE;
	else
	{
	    send_to_char( "Config -option or +option?\n\r", ch );
	    return;
	}

             if ( !str_cmp( arg+1, "ansi"     ) ) bit = PLR_ANSI;
        else if ( !str_cmp( arg+1, "autoexit" ) ) bit = PLR_AUTOEXIT;
	else if ( !str_cmp( arg+1, "autoloot" ) ) bit = PLR_AUTOLOOT;
	else if ( !str_cmp( arg+1, "autosac"  ) ) bit = PLR_AUTOSAC;
	else if ( !str_cmp( arg+1, "blank"    ) ) bit = PLR_BLANK;
	else if ( !str_cmp( arg+1, "brief"    ) ) bit = PLR_BRIEF;
	else if ( !str_cmp( arg+1, "combine"  ) ) bit = PLR_COMBINE;
        else if ( !str_cmp( arg+1, "prompt"   ) ) bit = PLR_PROMPT;
	else if ( !str_cmp( arg+1, "telnetga" ) ) bit = PLR_TELNET_GA;
	else
	{
	    send_to_char( "Config which option?\n\r", ch );
	    return;
	}

	if ( fSet )
	    SET_BIT    (ch->act, bit);
	else
	    REMOVE_BIT (ch->act, bit);

	send_to_char( "Ok.\n\r", ch );
    }

    return;
}

void do_ansi( CHAR_DATA *ch, char *argument )
{
    if ( IS_NPC(ch) ) return;
    if (IS_SET(ch->act, PLR_ANSI)) do_config(ch,"-ansi");
    else do_config(ch,"+ansi");
    return;
}

void do_autoexit( CHAR_DATA *ch, char *argument )
{
    if ( IS_NPC(ch) ) return;
    if (IS_SET(ch->act, PLR_AUTOEXIT)) do_config(ch,"-autoexit");
    else do_config(ch,"+autoexit");
    return;
}

void do_autoloot( CHAR_DATA *ch, char *argument )
{
    if ( IS_NPC(ch) ) return;
    if (IS_SET(ch->act, PLR_AUTOLOOT)) do_config(ch,"-autoloot");
    else do_config(ch,"+autoloot");
    return;
}

void do_autosac( CHAR_DATA *ch, char *argument )
{
    if ( IS_NPC(ch) ) return;
    if (IS_SET(ch->act, PLR_AUTOSAC)) do_config(ch,"-autosac");
    else do_config(ch,"+autosac");
    return;
}

void do_blank( CHAR_DATA *ch, char *argument )
{
    if ( IS_NPC(ch) ) return;
    if (IS_SET(ch->act, PLR_BLANK)) do_config(ch,"-blank");
    else do_config(ch,"+blank");
    return;
}

void do_brief( CHAR_DATA *ch, char *argument )
{
    if ( IS_NPC(ch) ) return;
    if (IS_SET(ch->act, PLR_BRIEF)) do_config(ch,"-brief");
    else do_config(ch,"+brief");
    return;
}

void do_diagnose( CHAR_DATA *ch, char *argument )
{
    char buf  [MAX_STRING_LENGTH];
    char arg  [MAX_INPUT_LENGTH];
    int teeth = 0;
    int ribs = 0;
    CHAR_DATA *victim;

    argument = one_argument( argument, arg );

    if (arg == '\0')
    {
	send_to_char("Who do you wish to diagnose?\n\r",ch);
	return;
    }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char("Nobody here by that name.\n\r",ch);
	return;
    }
    act("$n examines $N carefully, diagnosing $S injuries.",ch,NULL,victim,TO_NOTVICT);
    act("$n examines you carefully, diagnosing your injuries.",ch,NULL,victim,TO_VICT);
    act("Your diagnoses of $N reveals the following...",ch,NULL,victim,TO_CHAR);
    send_to_char("----------------------------------------------------------------------------\n\r",ch);
    if ( ( victim->loc_hp[0] + victim->loc_hp[1] + victim->loc_hp[2] + 
	   victim->loc_hp[3] + victim->loc_hp[4] + victim->loc_hp[5] +
	   victim->loc_hp[6] ) == 0 )
    {
	act("$N has no apparent injuries.",ch,NULL,victim,TO_CHAR);
	send_to_char("----------------------------------------------------------------------------\n\r",ch);
	return;
    }
    /* Check head */
    if (IS_HEAD(victim,LOST_EYE_L) && IS_HEAD(victim,LOST_EYE_R))
	act("$N has lost both of $S eyes.",ch,NULL,victim,TO_CHAR);
    else if (IS_HEAD(victim,LOST_EYE_L))
	act("$N has lost $S left eye.",ch,NULL,victim,TO_CHAR);
    else if (IS_HEAD(victim,LOST_EYE_R))
	act("$N has lost $S right eye.",ch,NULL,victim,TO_CHAR);
    if (IS_HEAD(victim,LOST_EAR_L) && IS_HEAD(victim,LOST_EAR_R))
	act("$N has lost both of $S ears.",ch,NULL,victim,TO_CHAR);
    else if (IS_HEAD(victim,LOST_EAR_L))
	act("$N has lost $S left ear.",ch,NULL,victim,TO_CHAR);
    else if (IS_HEAD(victim,LOST_EAR_R))
	act("$N has lost $S right ear.",ch,NULL,victim,TO_CHAR);
    if (IS_HEAD(victim,LOST_NOSE))
	act("$N has lost $S nose.",ch,NULL,victim,TO_CHAR);
    else if (IS_HEAD(victim,BROKEN_NOSE))
	act("$N has got a broken nose.",ch,NULL,victim,TO_CHAR);
    if (IS_HEAD(victim,BROKEN_JAW))
	act("$N has got a broken jaw.",ch,NULL,victim,TO_CHAR);
    if (IS_HEAD(victim,LOST_HEAD))
    {
	act("$N has had $S head cut off.",ch,NULL,victim,TO_CHAR);
	if (IS_BLEEDING(victim,BLEEDING_HEAD))
	    act("...Blood is spurting from the stump of $S neck.",ch,NULL,victim,TO_CHAR);
    }
    else
    {
	if (IS_BODY(victim,BROKEN_NECK))
	    act("$N has got a broken neck.",ch,NULL,victim,TO_CHAR);
	if (IS_BODY(victim,CUT_THROAT))
	{
	    act("$N has had $S throat cut open.",ch,NULL,victim,TO_CHAR);
	    if (IS_BLEEDING(victim,BLEEDING_THROAT))
		act("...Blood is pouring from the wound.",ch,NULL,victim,TO_CHAR);
	}
    }
    if (IS_HEAD(victim,BROKEN_SKULL))
	act("$N has got a broken skull.",ch,NULL,victim,TO_CHAR);
    if (IS_HEAD(victim,LOST_TOOTH_1 )) teeth += 1;
    if (IS_HEAD(victim,LOST_TOOTH_2 )) teeth += 2;
    if (IS_HEAD(victim,LOST_TOOTH_4 )) teeth += 4;
    if (IS_HEAD(victim,LOST_TOOTH_8 )) teeth += 8;
    if (IS_HEAD(victim,LOST_TOOTH_16)) teeth += 16;
    if (teeth > 0)
    {
	sprintf(buf,"$N has had %d teeth knocked out.",teeth);
	act(buf,ch,NULL,victim,TO_CHAR);
    }
    if (IS_HEAD(victim,LOST_TONGUE))
	act("$N has had $S tongue ripped out.",ch,NULL,victim,TO_CHAR);
    if (IS_HEAD(victim,LOST_HEAD))
    {
    	send_to_char("----------------------------------------------------------------------------\n\r",ch);
    	return;
    }
    /* Check body */
    if (IS_BODY(victim,BROKEN_RIBS_1 )) ribs += 1;
    if (IS_BODY(victim,BROKEN_RIBS_2 )) ribs += 2;
    if (IS_BODY(victim,BROKEN_RIBS_4 )) ribs += 4;
    if (IS_BODY(victim,BROKEN_RIBS_8 )) ribs += 8;
    if (IS_BODY(victim,BROKEN_RIBS_16)) ribs += 16;
    if (ribs > 0)
    {
	sprintf(buf,"$N has got %d broken ribs.",ribs);
	act(buf,ch,NULL,victim,TO_CHAR);
    }
    if (IS_BODY(victim,BROKEN_SPINE))
	act("$N has got a broken spine.",ch,NULL,victim,TO_CHAR);
    /* Check arms */
    check_left_arm(ch,victim);
    check_right_arm(ch,victim);
    check_left_leg(ch,victim);
    check_right_leg(ch,victim);
    send_to_char("----------------------------------------------------------------------------\n\r",ch);
    return;
}

void check_left_arm( CHAR_DATA *ch, CHAR_DATA *victim )
{
    char buf    [MAX_STRING_LENGTH];
    char finger [10];
    int fingers = 0;

    if (IS_ARM_L(victim,LOST_ARM) && IS_ARM_R(victim,LOST_ARM))
    {
	act("$N has lost both of $S arms.",ch,NULL,victim,TO_CHAR);
	if (IS_BLEEDING(victim,BLEEDING_ARM_L) && IS_BLEEDING(victim,BLEEDING_ARM_R))
	    act("...Blood is spurting from both stumps.",ch,NULL,victim,TO_CHAR);
	else if (IS_BLEEDING(victim,BLEEDING_ARM_L))
	    act("...Blood is spurting from the left stump.",ch,NULL,victim,TO_CHAR);
	else if (IS_BLEEDING(victim,BLEEDING_ARM_R))
	    act("...Blood is spurting from the right stump.",ch,NULL,victim,TO_CHAR);
	return;
    }
    if (IS_ARM_L(victim,LOST_ARM))
    {
	act("$N has lost $S left arm.",ch,NULL,victim,TO_CHAR);
	if (IS_BLEEDING(victim,BLEEDING_ARM_L))
	    act("...Blood is spurting from the stump.",ch,NULL,victim,TO_CHAR);
	return;
    }
    if (IS_ARM_L(victim,BROKEN_ARM) && IS_ARM_R(victim,BROKEN_ARM))
	act("$N arms are both broken.",ch,NULL,victim,TO_CHAR);
    else if (IS_ARM_L(victim,BROKEN_ARM))
	act("$N's left arm is broken.",ch,NULL,victim,TO_CHAR);
    if (IS_ARM_L(victim,LOST_HAND) && IS_ARM_R(victim,LOST_HAND) &&
	!IS_ARM_R(victim,LOST_ARM))
    {
	act("$N has lost both of $S hands.",ch,NULL,victim,TO_CHAR);
	if (IS_BLEEDING(victim,BLEEDING_HAND_L) && IS_BLEEDING(victim,BLEEDING_HAND_R))
	    act("...Blood is spurting from both stumps.",ch,NULL,victim,TO_CHAR);
	else if (IS_BLEEDING(victim,BLEEDING_HAND_L))
	    act("...Blood is spurting from the left stump.",ch,NULL,victim,TO_CHAR);
	else if (IS_BLEEDING(victim,BLEEDING_HAND_R))
	    act("...Blood is spurting from the right stump.",ch,NULL,victim,TO_CHAR);
	return;
    }
    if (IS_ARM_L(victim,LOST_HAND))
    {
	act("$N has lost $S left hand.",ch,NULL,victim,TO_CHAR);
	if (IS_BLEEDING(victim,BLEEDING_HAND_L))
	    act("...Blood is spurting from the stump.",ch,NULL,victim,TO_CHAR);
	return;
    }
    if (IS_ARM_L(victim,LOST_FINGER_I)) fingers += 1;
    if (IS_ARM_L(victim,LOST_FINGER_M)) fingers += 1;
    if (IS_ARM_L(victim,LOST_FINGER_R)) fingers += 1;
    if (IS_ARM_L(victim,LOST_FINGER_L)) fingers += 1;
    if (fingers == 1) sprintf(finger,"finger");
    else sprintf(finger,"fingers");
    if (fingers > 0 && IS_ARM_L(victim,LOST_THUMB))
    {
	sprintf(buf,"$N has lost %d %s and $S thumb from $S left hand.",fingers,finger);
	act(buf,ch,NULL,victim,TO_CHAR);
    }
    else if (fingers > 0)
    {
	sprintf(buf,"$N has lost %d %s from $S left hand.",fingers,finger);
	act(buf,ch,NULL,victim,TO_CHAR);
    }
    else if (IS_ARM_L(victim,LOST_THUMB))
    {
	sprintf(buf,"$N has lost the thumb from $S left hand.");
	act(buf,ch,NULL,victim,TO_CHAR);
    }
    fingers = 0;
    if (IS_ARM_L(victim,BROKEN_FINGER_I) && !IS_ARM_L(victim,LOST_FINGER_I)) fingers += 1;
    if (IS_ARM_L(victim,BROKEN_FINGER_M) && !IS_ARM_L(victim,LOST_FINGER_M)) fingers += 1;
    if (IS_ARM_L(victim,BROKEN_FINGER_R) && !IS_ARM_L(victim,LOST_FINGER_R)) fingers += 1;
    if (IS_ARM_L(victim,BROKEN_FINGER_L) && !IS_ARM_L(victim,LOST_FINGER_L)) fingers += 1;
    if (fingers == 1) sprintf(finger,"finger");
    else sprintf(finger,"fingers");
    if (fingers > 0 && IS_ARM_L(victim,BROKEN_THUMB) && !IS_ARM_L(victim,LOST_THUMB))
    {
	sprintf(buf,"$N has broken %d %s and $S thumb on $S left hand.",fingers,finger);
	act(buf,ch,NULL,victim,TO_CHAR);
    }
    else if (fingers > 0)
    {
	sprintf(buf,"$N has broken %d %s on $S left hand.",fingers,finger);
	act(buf,ch,NULL,victim,TO_CHAR);
    }
    else if (IS_ARM_L(victim,BROKEN_THUMB) && !IS_ARM_L(victim,LOST_THUMB))
    {
	sprintf(buf,"$N has broken the thumb on $S left hand.");
	act(buf,ch,NULL,victim,TO_CHAR);
    }
    return;
}

void check_right_arm( CHAR_DATA *ch, CHAR_DATA *victim )
{
    char buf    [MAX_STRING_LENGTH];
    char finger [10];
    int fingers = 0;

    if (IS_ARM_L(victim,LOST_ARM) && IS_ARM_R(victim,LOST_ARM))
	return;
    if (IS_ARM_R(victim,LOST_ARM))
    {
	act("$N has lost $S right arm.",ch,NULL,victim,TO_CHAR);
	if (IS_BLEEDING(victim,BLEEDING_ARM_R))
	    act("...Blood is spurting from the stump.",ch,NULL,victim,TO_CHAR);
	return;
    }
    if (!IS_ARM_L(victim,BROKEN_ARM) && IS_ARM_R(victim,BROKEN_ARM))
	act("$N's right arm is broken.",ch,NULL,victim,TO_CHAR);
    else if (IS_ARM_L(victim,LOST_ARM) && IS_ARM_R(victim,BROKEN_ARM))
	act("$N's right arm is broken.",ch,NULL,victim,TO_CHAR);
    if (IS_ARM_L(victim,LOST_HAND) && IS_ARM_R(victim,LOST_HAND))
	return;
    if (IS_ARM_R(victim,LOST_HAND))
    {
	act("$N has lost $S right hand.",ch,NULL,victim,TO_CHAR);
	if (IS_BLEEDING(victim,BLEEDING_HAND_R))
	    act("...Blood is spurting from the stump.",ch,NULL,victim,TO_CHAR);
	return;
    }
    if (IS_ARM_R(victim,LOST_FINGER_I)) fingers += 1;
    if (IS_ARM_R(victim,LOST_FINGER_M)) fingers += 1;
    if (IS_ARM_R(victim,LOST_FINGER_R)) fingers += 1;
    if (IS_ARM_R(victim,LOST_FINGER_L)) fingers += 1;
    if (fingers == 1) sprintf(finger,"finger");
    else sprintf(finger,"fingers");
    if (fingers > 0 && IS_ARM_R(victim,LOST_THUMB))
    {
	sprintf(buf,"$N has lost %d %s and $S thumb from $S right hand.",fingers,finger);
	act(buf,ch,NULL,victim,TO_CHAR);
    }
    else if (fingers > 0)
    {
	sprintf(buf,"$N has lost %d %s from $S right hand.",fingers,finger);
	act(buf,ch,NULL,victim,TO_CHAR);
    }
    else if (IS_ARM_R(victim,LOST_THUMB))
    {
	sprintf(buf,"$N has lost the thumb from $S right hand.");
	act(buf,ch,NULL,victim,TO_CHAR);
    }
    fingers = 0;
    if (IS_ARM_R(victim,BROKEN_FINGER_I) && !IS_ARM_R(victim,LOST_FINGER_I)) fingers += 1;
    if (IS_ARM_R(victim,BROKEN_FINGER_M) && !IS_ARM_R(victim,LOST_FINGER_M)) fingers += 1;
    if (IS_ARM_R(victim,BROKEN_FINGER_R) && !IS_ARM_R(victim,LOST_FINGER_R)) fingers += 1;
    if (IS_ARM_R(victim,BROKEN_FINGER_L) && !IS_ARM_R(victim,LOST_FINGER_L)) fingers += 1;
    if (fingers == 1) sprintf(finger,"finger");
    else sprintf(finger,"fingers");
    if (fingers > 0 && IS_ARM_R(victim,BROKEN_THUMB) && !IS_ARM_R(victim,LOST_THUMB))
    {
	sprintf(buf,"$N has broken %d %s and $S thumb on $S right hand.",fingers,finger);
	act(buf,ch,NULL,victim,TO_CHAR);
    }
    else if (fingers > 0)
    {
	sprintf(buf,"$N has broken %d %s on $S right hand.",fingers,finger);
	act(buf,ch,NULL,victim,TO_CHAR);
    }
    else if (IS_ARM_R(victim,BROKEN_THUMB) && !IS_ARM_R(victim,LOST_THUMB))
    {
	sprintf(buf,"$N has broken the thumb on $S right hand.");
	act(buf,ch,NULL,victim,TO_CHAR);
    }
    return;
}

void check_left_leg( CHAR_DATA *ch, CHAR_DATA *victim )
{
    char buf    [MAX_STRING_LENGTH];
    char toe [10];
    int toes = 0;

    if (IS_LEG_L(victim,LOST_LEG) && IS_LEG_R(victim,LOST_LEG))
    {
	act("$N has lost both of $S legs.",ch,NULL,victim,TO_CHAR);
	if (IS_BLEEDING(victim,BLEEDING_LEG_L) && IS_BLEEDING(victim,BLEEDING_LEG_R))
	    act("...Blood is spurting from both stumps.",ch,NULL,victim,TO_CHAR);
	else if (IS_BLEEDING(victim,BLEEDING_LEG_L))
	    act("...Blood is spurting from the left stump.",ch,NULL,victim,TO_CHAR);
	else if (IS_BLEEDING(victim,BLEEDING_LEG_R))
	    act("...Blood is spurting from the right stump.",ch,NULL,victim,TO_CHAR);
	return;
    }
    if (IS_LEG_L(victim,LOST_LEG))
    {
	act("$N has lost $S left leg.",ch,NULL,victim,TO_CHAR);
	if (IS_BLEEDING(victim,BLEEDING_LEG_L))
	    act("...Blood is spurting from the stump.",ch,NULL,victim,TO_CHAR);
	return;
    }
    if (IS_LEG_L(victim,BROKEN_LEG) && IS_LEG_R(victim,BROKEN_LEG))
	act("$N legs are both broken.",ch,NULL,victim,TO_CHAR);
    else if (IS_LEG_L(victim,BROKEN_LEG))
	act("$N's left leg is broken.",ch,NULL,victim,TO_CHAR);
    if (IS_LEG_L(victim,LOST_FOOT) && IS_LEG_R(victim,LOST_FOOT))
    {
	act("$N has lost both of $S feet.",ch,NULL,victim,TO_CHAR);
	if (IS_BLEEDING(victim,BLEEDING_FOOT_L) && IS_BLEEDING(victim,BLEEDING_FOOT_R))
	    act("...Blood is spurting from both stumps.",ch,NULL,victim,TO_CHAR);
	else if (IS_BLEEDING(victim,BLEEDING_FOOT_L))
	    act("...Blood is spurting from the left stump.",ch,NULL,victim,TO_CHAR);
	else if (IS_BLEEDING(victim,BLEEDING_FOOT_R))
	    act("...Blood is spurting from the right stump.",ch,NULL,victim,TO_CHAR);
	return;
    }
    if (IS_LEG_L(victim,LOST_FOOT))
    {
	act("$N has lost $S left foot.",ch,NULL,victim,TO_CHAR);
	if (IS_BLEEDING(victim,BLEEDING_FOOT_L))
	    act("...Blood is spurting from the stump.",ch,NULL,victim,TO_CHAR);
	return;
    }
    if (IS_LEG_L(victim,LOST_TOE_A)) toes += 1;
    if (IS_LEG_L(victim,LOST_TOE_B)) toes += 1;
    if (IS_LEG_L(victim,LOST_TOE_C)) toes += 1;
    if (IS_LEG_L(victim,LOST_TOE_D)) toes += 1;
    if (toes == 1) sprintf(toe,"toe");
    else sprintf(toe,"toes");
    if (toes > 0 && IS_LEG_L(victim,LOST_TOE_BIG))
    {
	sprintf(buf,"$N has lost %d %s and $S big toe from $S left foot.",toes,toe);
	act(buf,ch,NULL,victim,TO_CHAR);
    }
    else if (toes > 0)
    {
	sprintf(buf,"$N has lost %d %s from $S left foot.",toes,toe);
	act(buf,ch,NULL,victim,TO_CHAR);
    }
    else if (IS_LEG_L(victim,LOST_TOE_BIG))
    {
	sprintf(buf,"$N has lost the big toe from $S left foot.");
	act(buf,ch,NULL,victim,TO_CHAR);
    }
    toes = 0;
    if (IS_LEG_L(victim,BROKEN_TOE_A) && !IS_LEG_L(victim,LOST_TOE_A)) toes += 1;
    if (IS_LEG_L(victim,BROKEN_TOE_B) && !IS_LEG_L(victim,LOST_TOE_B)) toes += 1;
    if (IS_LEG_L(victim,BROKEN_TOE_C) && !IS_LEG_L(victim,LOST_TOE_C)) toes += 1;
    if (IS_LEG_L(victim,BROKEN_TOE_D) && !IS_LEG_L(victim,LOST_TOE_D)) toes += 1;
    if (toes == 1) sprintf(toe,"toe");
    else sprintf(toe,"toes");
    if (toes > 0 && IS_LEG_L(victim,BROKEN_TOE_BIG) && !IS_LEG_L(victim,LOST_TOE_BIG))
    {
	sprintf(buf,"$N has broken %d %s and $S big toe from $S left foot.",toes,toe);
	act(buf,ch,NULL,victim,TO_CHAR);
    }
    else if (toes > 0)
    {
	sprintf(buf,"$N has broken %d %s on $S left foot.",toes,toe);
	act(buf,ch,NULL,victim,TO_CHAR);
    }
    else if (IS_LEG_L(victim,BROKEN_TOE_BIG) && !IS_LEG_L(victim,LOST_TOE_BIG))
    {
	sprintf(buf,"$N has broken the big toe on $S left foot.");
	act(buf,ch,NULL,victim,TO_CHAR);
    }
    return;
}

void check_right_leg( CHAR_DATA *ch, CHAR_DATA *victim )
{
    char buf    [MAX_STRING_LENGTH];
    char toe [10];
    int toes = 0;

    if (IS_LEG_L(victim,LOST_LEG) && IS_LEG_R(victim,LOST_LEG))
	return;
    if (IS_LEG_R(victim,LOST_LEG))
    {
	act("$N has lost $S right leg.",ch,NULL,victim,TO_CHAR);
	if (IS_BLEEDING(victim,BLEEDING_LEG_R))
	    act("...Blood is spurting from the stump.",ch,NULL,victim,TO_CHAR);
	return;
    }
    if (!IS_LEG_L(victim,BROKEN_LEG) && IS_LEG_R(victim,BROKEN_LEG))
	act("$N's right leg is broken.",ch,NULL,victim,TO_CHAR);
    if (IS_LEG_L(victim,LOST_FOOT) && IS_LEG_R(victim,LOST_FOOT))
	return;
    if (IS_LEG_R(victim,LOST_FOOT))
    {
	act("$N has lost $S right foot.",ch,NULL,victim,TO_CHAR);
	if (IS_BLEEDING(victim,BLEEDING_FOOT_R))
	    act("...Blood is spurting from the stump.",ch,NULL,victim,TO_CHAR);
	return;
    }
    if (IS_LEG_R(victim,LOST_TOE_A)) toes += 1;
    if (IS_LEG_R(victim,LOST_TOE_B)) toes += 1;
    if (IS_LEG_R(victim,LOST_TOE_C)) toes += 1;
    if (IS_LEG_R(victim,LOST_TOE_D)) toes += 1;
    if (toes == 1) sprintf(toe,"toe");
    else sprintf(toe,"toes");
    if (toes > 0 && IS_LEG_R(victim,LOST_TOE_BIG))
    {
	sprintf(buf,"$N has lost %d %s and $S big toe from $S right foot.",toes,toe);
	act(buf,ch,NULL,victim,TO_CHAR);
    }
    else if (toes > 0)
    {
	sprintf(buf,"$N has lost %d %s from $S right foot.",toes,toe);
	act(buf,ch,NULL,victim,TO_CHAR);
    }
    else if (IS_LEG_R(victim,LOST_TOE_BIG))
    {
	sprintf(buf,"$N has lost the big toe from $S right foot.");
	act(buf,ch,NULL,victim,TO_CHAR);
    }
    toes = 0;
    if (IS_LEG_R(victim,BROKEN_TOE_A) && !IS_LEG_R(victim,LOST_TOE_A)) toes += 1;
    if (IS_LEG_R(victim,BROKEN_TOE_B) && !IS_LEG_R(victim,LOST_TOE_B)) toes += 1;
    if (IS_LEG_R(victim,BROKEN_TOE_C) && !IS_LEG_R(victim,LOST_TOE_C)) toes += 1;
    if (IS_LEG_R(victim,BROKEN_TOE_D) && !IS_LEG_R(victim,LOST_TOE_D)) toes += 1;
    if (toes == 1) sprintf(toe,"toe");
    else sprintf(toe,"toes");
    if (toes > 0 && IS_LEG_R(victim,BROKEN_TOE_BIG) && !IS_LEG_R(victim,LOST_TOE_BIG))
    {
	sprintf(buf,"$N has broken %d %s and $S big toe on $S right foot.",toes,toe);
	act(buf,ch,NULL,victim,TO_CHAR);
    }
    else if (toes > 0)
    {
	sprintf(buf,"$N has broken %d %s on $S right foot.",toes,toe);
	act(buf,ch,NULL,victim,TO_CHAR);
    }
    else if (IS_LEG_R(victim,BROKEN_TOE_BIG) && !IS_LEG_R(victim,LOST_TOE_BIG))
    {
	sprintf(buf,"$N has broken the big toe on $S right foot.");
	act(buf,ch,NULL,victim,TO_CHAR);
    }
    return;
}

void obj_score( CHAR_DATA *ch, OBJ_DATA *obj )
{
    char buf[MAX_STRING_LENGTH];
    AFFECT_DATA *paf;
    int itemtype;

    sprintf( buf,"You are %s.\n\r",obj->short_descr);
    send_to_char( buf, ch );

    sprintf( buf,"Type %s, Extra flags %s.\n\r",item_type_name(obj),
	extra_bit_name(obj->extra_flags));
    send_to_char( buf, ch );

    sprintf( buf,"You weigh %d pounds and are worth %d gold coins.\n\r",obj->weight,obj->cost);
    send_to_char( buf, ch );

    if (obj->questmaker != NULL && strlen(obj->questmaker) > 1 &&
	obj->questowner != NULL && strlen(obj->questowner) > 1)
    {
	sprintf( buf, "You were created by %s, and are owned by %s.\n\r", obj->questmaker,obj->questowner );
	send_to_char( buf, ch );
    }
    else if (obj->questmaker != NULL && strlen(obj->questmaker) > 1)
    {
	sprintf( buf, "You were created by %s.\n\r", obj->questmaker );
	send_to_char( buf, ch );
    }
    else if (obj->questowner != NULL && strlen(obj->questowner) > 1)
    {
	sprintf( buf, "You are owned by %s.\n\r", obj->questowner );
	send_to_char( buf, ch );
    }

    switch ( obj->item_type )
    {
    case ITEM_SCROLL: 
    case ITEM_POTION:
	sprintf( buf, "You contain level %d spells of:", obj->value[0] );
	send_to_char( buf, ch );

	if ( obj->value[1] >= 0 && obj->value[1] < MAX_SKILL )
	{
	    send_to_char( " '", ch );
	    send_to_char( skill_table[obj->value[1]].name, ch );
	    send_to_char( "'", ch );
	}

	if ( obj->value[2] >= 0 && obj->value[2] < MAX_SKILL )
	{
	    send_to_char( " '", ch );
	    send_to_char( skill_table[obj->value[2]].name, ch );
	    send_to_char( "'", ch );
	}

	if ( obj->value[3] >= 0 && obj->value[3] < MAX_SKILL )
	{
	    send_to_char( " '", ch );
	    send_to_char( skill_table[obj->value[3]].name, ch );
	    send_to_char( "'", ch );
	}

	send_to_char( ".\n\r", ch );
	break;

    case ITEM_QUEST:
	sprintf( buf, "Your quest point value is %d.\n\r", obj->value[0] );
	send_to_char( buf, ch );
	break;

    case ITEM_WAND: 
    case ITEM_STAFF: 
	sprintf( buf, "You have %d(%d) charges of level %d",
	    obj->value[1], obj->value[2], obj->value[0] );
	send_to_char( buf, ch );

	if ( obj->value[3] >= 0 && obj->value[3] < MAX_SKILL )
	{
	    send_to_char( " '", ch );
	    send_to_char( skill_table[obj->value[3]].name, ch );
	    send_to_char( "'", ch );
	}

	send_to_char( ".\n\r", ch );
	break;
      
    case ITEM_WEAPON:
	sprintf( buf, "You inflict %d to %d damage in combat (average %d).\n\r",
	    obj->value[1], obj->value[2],
	    ( obj->value[1] + obj->value[2] ) / 2 );
	send_to_char( buf, ch );

	if (obj->value[0] >= 1000)
	    itemtype = obj->value[0] - ((obj->value[0] / 1000) * 1000);
	else
	    itemtype = obj->value[0];

	if (itemtype > 0)
	{
	    if (obj->level < 10)
		sprintf(buf,"You are a minor spell weapon.\n\r");
	    else if (obj->level < 20)
		sprintf(buf,"You are a lesser spell weapon.\n\r");
	    else if (obj->level < 30)
		sprintf(buf,"You are an average spell weapon.\n\r");
	    else if (obj->level < 40)
		sprintf(buf,"You are a greater spell weapon.\n\r");
	    else if (obj->level < 50)
		sprintf(buf,"You are a major spell weapon.\n\r");
	    else
		sprintf(buf,"You are a supreme spell weapon.\n\r");
	    send_to_char(buf,ch);
	}

	if (itemtype == 1)
	    sprintf (buf, "You are dripping with corrosive acid.\n\r");
	else if (itemtype == 4)
	    sprintf (buf, "You radiate an aura of darkness.\n\r");
	else if (itemtype == 30)
	    sprintf (buf, "You are the bane of all evil.\n\r");
	else if (itemtype == 34)
	    sprintf (buf, "You drink the souls of your victims.\n\r");
	else if (itemtype == 37)
	    sprintf (buf, "You have been tempered in hellfire.\n\r");
	else if (itemtype == 48)
	    sprintf (buf, "You crackle with sparks of lightning.\n\r");
	else if (itemtype == 53)
	    sprintf (buf, "You are dripping with a dark poison.\n\r");
	else if (itemtype > 0)
	    sprintf (buf, "You have been imbued with the power of %s.\n\r",skill_table[itemtype].name);
	if (itemtype > 0)
	    send_to_char( buf, ch );

	if (obj->value[0] >= 1000)
	    itemtype = obj->value[0] / 1000;
	else
	    break;

	if (itemtype == 4 || itemtype == 1)
	    sprintf (buf, "You radiate an aura of darkness.\n\r");
	else if (itemtype == 27 || itemtype == 2)
	    sprintf (buf, "You allow your wielder to see invisible things.\n\r");
	else if (itemtype == 39 || itemtype == 3)
	    sprintf (buf, "You grant your wielder the power of flight.\n\r");
	else if (itemtype == 45 || itemtype == 4)
	    sprintf (buf, "You allow your wielder to see in the dark.\n\r");
	else if (itemtype == 46 || itemtype == 5)
	    sprintf (buf, "You render your wielder invisible to the human eye.\n\r");
	else if (itemtype == 52 || itemtype == 6)
	    sprintf (buf, "You allow your wielder to walk through solid doors.\n\r");
	else if (itemtype == 54 || itemtype == 7)
	    sprintf (buf, "You protect your wielder from evil.\n\r");
	else if (itemtype == 57 || itemtype == 8)
	    sprintf (buf, "You protect your wielder in combat.\n\r");
	else if (itemtype == 9)
	    sprintf (buf, "You allow your wielder to walk in complete silence.\n\r");
	else if (itemtype == 10)
	    sprintf (buf, "You surround your wielder with a shield of lightning.\n\r");
	else if (itemtype == 11)
	    sprintf (buf, "You surround your wielder with a shield of fire.\n\r");
	else if (itemtype == 12)
	    sprintf (buf, "You surround your wielder with a shield of ice.\n\r");
	else if (itemtype == 13)
	    sprintf (buf, "You surround your wielder with a shield of acid.\n\r");
	else if (itemtype == 14)
	    sprintf (buf, "You protect your wielder from attacks from DarkBlade clan guardians.\n\r");
	else if (itemtype == 15)
	    sprintf (buf, "You surround your wielder with a shield of chaos.\n\r");
	else if (itemtype == 16)
	    sprintf (buf, "You regenerate the wounds of your wielder.\n\r");
	else if (itemtype == 17)
	    sprintf (buf, "You enable your wielder to move at supernatural speed.\n\r");
	else if (itemtype == 18)
	    sprintf (buf, "You can slice through armour without difficulty.\n\r");
	else if (itemtype == 19)
	    sprintf (buf, "You protect your wielder from player attacks.\n\r");
	else if (itemtype == 20)
	    sprintf (buf, "You surround your wielder with a shield of darkness.\n\r");
	else if (itemtype == 21)
	    sprintf (buf, "You grant your wielder superior protection.\n\r");
	else if (itemtype == 22)
	    sprintf (buf, "You grant your wielder supernatural vision.\n\r");
	else if (itemtype == 23)
	    sprintf (buf, "You make your wielder fleet-footed.\n\r");
	else if (itemtype == 24)
	    sprintf (buf, "You conceal your wielder from sight.\n\r");
	else if (itemtype == 25)
	    sprintf (buf, "You invoke the power of your wielders beast.\n\r");
	else
	    sprintf (buf, "You are bugged...please report it.\n\r");
	if (itemtype > 0)
	    send_to_char( buf, ch );
	break;

    case ITEM_ARMOR:
	sprintf( buf, "Your armor class is %d.\n\r", obj->value[0] );
	send_to_char( buf, ch );
	if (obj->value[3] < 1)
	    break;
	if (obj->value[3] == 4 || obj->value[3] == 1)
	    sprintf (buf, "You radiate an aura of darkness.\n\r");
	else if (obj->value[3] == 27 || obj->value[3] == 2)
	    sprintf (buf, "You allow your wearer to see invisible things.\n\r");
	else if (obj->value[3] == 39 || obj->value[3] == 3)
	    sprintf (buf, "You grant your wearer the power of flight.\n\r");
	else if (obj->value[3] == 45 || obj->value[3] == 4)
	    sprintf (buf, "You allow your wearer to see in the dark.\n\r");
	else if (obj->value[3] == 46 || obj->value[3] == 5)
	    sprintf (buf, "You render your wearer invisible to the human eye.\n\r");
	else if (obj->value[3] == 52 || obj->value[3] == 6)
	    sprintf (buf, "You allow your wearer to walk through solid doors.\n\r");
	else if (obj->value[3] == 54 || obj->value[3] == 7)
	    sprintf (buf, "You protect your wearer from evil.\n\r");
	else if (obj->value[3] == 57 || obj->value[3] == 8)
	    sprintf (buf, "You protect your wearer in combat.\n\r");
	else if (obj->value[3] == 9)
	    sprintf (buf, "You allow your wearer to walk in complete silence.\n\r");
	else if (obj->value[3] == 10)
	    sprintf (buf, "You surround your wearer with a shield of lightning.\n\r");
	else if (obj->value[3] == 11)
	    sprintf (buf, "You surround your wearer with a shield of fire.\n\r");
	else if (obj->value[3] == 12)
	    sprintf (buf, "You surround your wearer with a shield of ice.\n\r");
	else if (obj->value[3] == 13)
	    sprintf (buf, "You surround your wearer with a shield of acid.\n\r");
	else if (obj->value[3] == 14)
	    sprintf (buf, "You protect your wearer from attacks from DarkBlade clan guardians.\n\r");
	else if (obj->value[3] == 15)
	    sprintf (buf, "You surround your wielder with a shield of chaos.\n\r");
	else if (obj->value[3] == 16)
	    sprintf (buf, "You regenerate the wounds of your wielder.\n\r");
	else if (obj->value[3] == 17)
	    sprintf (buf, "You enable your wearer to move at supernatural speed.\n\r");
	else if (obj->value[3] == 18)
	    sprintf (buf, "You can slice through armour without difficulty.\n\r");
	else if (obj->value[3] == 19)
	    sprintf (buf, "You protect your wearer from player attacks.\n\r");
	else if (obj->value[3] == 20)
	    sprintf (buf, "You surround your wearer with a shield of darkness.\n\r");
	else if (obj->value[3] == 21)
	    sprintf (buf, "You grant your wearer superior protection.\n\r");
	else if (obj->value[3] == 22)
	    sprintf (buf, "You grant your wearer supernatural vision.\n\r");
	else if (obj->value[3] == 23)
	    sprintf (buf, "You make your wearer fleet-footed.\n\r");
	else if (obj->value[3] == 24)
	    sprintf (buf, "You conceal your wearer from sight.\n\r");
	else if (obj->value[3] == 25)
	    sprintf (buf, "You invoke the power of your wearers beast.\n\r");
	else
	    sprintf (buf, "You are bugged...please report it.\n\r");
	if (obj->value[3] > 0)
	    send_to_char( buf, ch );
	break;
    }

    for ( paf = obj->pIndexData->affected; paf != NULL; paf = paf->next )
    {
	if ( paf->location != APPLY_NONE && paf->modifier != 0 )
	{
	    sprintf( buf, "You affect %s by %d.\n\r",
		affect_loc_name( paf->location ), paf->modifier );
	    send_to_char( buf, ch );
	}
    }

    for ( paf = obj->affected; paf != NULL; paf = paf->next )
    {
	if ( paf->location != APPLY_NONE && paf->modifier != 0 )
	{
	    sprintf( buf, "You affect %s by %d.\n\r",
		affect_loc_name( paf->location ), paf->modifier );
	    send_to_char( buf, ch );
	}
    }
    return;
}

/* Do_prompt from Morgenes from Aldara Mud */
void do_prompt( CHAR_DATA *ch, char *argument )
{
   char buf [ MAX_STRING_LENGTH ];

   buf[0] = '\0';
   if ( IS_NPC(ch) ) return;

   if ( argument[0] == '\0' )
   {
       do_help( ch, "prompt" );
       return;
   }

   if( !strcmp( argument, "on" ) )
   {
      if (IS_EXTRA(ch, EXTRA_PROMPT))
         send_to_char("But you already have customised prompt on!\n\r",ch);
      else
      {
         send_to_char("Ok.\n\r",ch);
         SET_BIT(ch->extra, EXTRA_PROMPT);
      }
      return;
   }
   else if( !strcmp( argument, "off" ) )
   {
      if (!IS_EXTRA(ch, EXTRA_PROMPT))
         send_to_char("But you already have customised prompt off!\n\r",ch);
      else
      {
         send_to_char("Ok.\n\r",ch);
         REMOVE_BIT(ch->extra, EXTRA_PROMPT);
      }
      return;
   }
   else if( !strcmp( argument, "clear" ) )
   {
      free_string(ch->prompt);
      ch->prompt = str_dup( "" );
      return;
   }
   else
   {
      if ( strlen( argument ) > 50 )
	  argument[50] = '\0';
      smash_tilde( argument );
      strcat( buf, argument );
   }

   free_string( ch->prompt );
   ch->prompt = str_dup( buf );
   send_to_char( "Ok.\n\r", ch );
   return;
} 

/* Do_prompt from Morgenes from Aldara Mud */
void do_cprompt( CHAR_DATA *ch, char *argument )
{
   char buf [ MAX_STRING_LENGTH ];

   buf[0] = '\0';
   if ( IS_NPC(ch) ) return;

   if ( argument[0] == '\0' )
   {
       do_help( ch, "cprompt" );
       return;
   }

   if( !strcmp( argument, "clear" ) )
   {
      free_string(ch->cprompt);
      ch->cprompt = str_dup( "" );
      return;
   }
   else
   {
      if ( strlen( argument ) > 50 )
	  argument[50] = '\0';
      smash_tilde( argument );
      strcat( buf, argument );
   }

   free_string( ch->cprompt );
   ch->cprompt = str_dup( buf );
   send_to_char( "Ok.\n\r", ch );
   return;
} 

void 	do_finger( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_STRING_LENGTH];
    char strsave[MAX_INPUT_LENGTH];
    char *buf;
    char buf2[MAX_INPUT_LENGTH];
    FILE *fp;
    int  num;
    int  num2;
    int  extra;

    if ( IS_NPC(ch) ) return;
    one_argument(argument,arg);
    if (!check_parse_name( argument ))
    {
	send_to_char( "Thats an illegal name.\n\r", ch );
	return;
    }

    if ( !char_exists(TRUE,argument) )
    {
	send_to_char( "That player doesn't exist.\n\r", ch );
	return;
    }

    if (!str_cmp(argument,"Zaphonite") || !str_cmp(argument,"Lobo"))
    {
	send_to_char("They don't want you to do that.\n\r",ch);
	return;
    }

    fclose( fpReserve );
    sprintf( strsave, "%sbackup/%s", PLAYER_DIR, capitalize(argument) );
    if ( ( fp = fopen( strsave, "r" ) ) != NULL )
    {
	send_to_char("----------------------------------------------------------------------------\n\r",ch);
	buf=fread_string( fp );
	send_to_char(buf,ch);
	send_to_char(" ",ch);
	buf=fread_string( fp );
	send_to_char(buf,ch);
	send_to_char(".\n\r",ch);
	send_to_char("----------------------------------------------------------------------------\n\r",ch);
	send_to_char("Last connected ",ch);
	buf=fread_string( fp );
	send_to_char("at ",ch);
	buf=fread_string( fp );
	send_to_char(buf,ch);
	send_to_char(".\n\r",ch);
	send_to_char("----------------------------------------------------------------------------\n\r",ch);
	extra=fread_number( fp );
	num=fread_number( fp );
	send_to_char("Sex: ",ch);
	buf=fread_string( fp );
	if (num == SEX_MALE) send_to_char("Male. ",ch);
	else if (num == SEX_FEMALE) 
	{
	    send_to_char("Female. ",ch);
	    if (IS_SET(extra, EXTRA_PREGNANT)) other_age(ch,extra,TRUE,buf);
	}
	else send_to_char("None. ",ch);
	buf=fread_string( fp );
	other_age(ch,extra,FALSE,buf);
	num=fread_number( fp );
	num2=fread_number( fp );
	switch ( num )
	{
	    default:
		send_to_char("They are mortal, ",ch);
		break;
	    case LEVEL_AVATAR:
	    case LEVEL_APPRENTICE:
	    case LEVEL_MAGE:
	    case LEVEL_ARCHMAGE:
	    {
		if (num2 < 1)
		    send_to_char("They are a Avatar, ",ch);
		else if (num2 < 5)
		    send_to_char("They are a Immortal, ",ch);
		else if (num2 < 10)
		    send_to_char("They are a Godling, ",ch);
		else if (num2 < 15)
		    send_to_char("They are a Demigod, ",ch);
		else if (num2 < 20)
		    send_to_char("They are a Lesser God, ",ch);
		else if (num2 < 25)
		    send_to_char("They are a Greater God, ",ch);
		else
		    send_to_char("They are a Supreme God, ",ch);
		break;
	    }
	    case LEVEL_BUILDER:
		send_to_char("They are a Builder, ",ch);
		break;
	    case LEVEL_QUESTMAKER:
		send_to_char("They are a Quest Maker, ",ch);
		break;
	    case LEVEL_ENFORCER:
		send_to_char("They are an Enforcer, ",ch);
		break;
	    case LEVEL_JUDGE:
		send_to_char("They are a Judge, ",ch);
		break;
	    case LEVEL_HIGHJUDGE:
		send_to_char("They are a High Judge, ",ch);
		break;
	    case LEVEL_IMPLEMENTOR:
		send_to_char("They are an Implementor, ",ch);
		break;
	}
	num=fread_number( fp );
	if (num > 0) num2 = (2*(num / 7200)); else num2 = 0;
	sprintf(buf2,"and have been playing for %d hours.\n\r",num2);
	send_to_char(buf2,ch);
	buf=fread_string( fp );
	if (strlen(buf) > 2)
	{
	    if (IS_SET(extra, EXTRA_MARRIED))
		sprintf(buf2,"They are married to %s.\n\r",buf);
	    else
		sprintf(buf2,"They are engaged to %s.\n\r",buf);
	    send_to_char(buf2,ch);
	}
	num=fread_number( fp );
	num2=fread_number( fp );
	sprintf(buf2,"Player kills: %d, Player Deaths: %d.\n\r",num,num2);
	send_to_char(buf2,ch);
	num=fread_number( fp );
	num2=fread_number( fp );
	sprintf(buf2,"Arena kills: %d, Arena Deaths: %d.\n\r",num,num2);
        send_to_char(buf2,ch);
        num=fread_number(fp);
        num2=fread_number(fp);
        sprintf(buf2,"Mob Kills: %d, Mob Deaths: %d.\n\r",num,num2);
	send_to_char(buf2,ch);
	send_to_char("----------------------------------------------------------------------------\n\r",ch);
    }
    else
    {
	bug( "Do_finger: fopen", 0 );
    }
    fclose( fp );
    fpReserve = fopen( NULL_FILE, "r" );
    return;
}



 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
 *                                                                         *
 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
 *  Chastain, Michael Quan, and Mitchell Tse.                              *
 *                                                                         *
 *  In order to use any part of this Merc Diku Mud, you must comply with   *
 *  both the original Diku license in 'license.doc' as well the Merc       *
 *  license in 'license.txt'.  In particular, you may not remove either of *
 *  these copyright notices.                                               *
 *                                                                         *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 ***************************************************************************/

#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"



void horn args( ( CHAR_DATA *ch ) );


char *	const	dir_name	[]		=
{
    "north", "east", "south", "west", "up", "down"
};

const	sh_int	rev_dir		[]		=
{
    2, 3, 0, 1, 5, 4
};

const	sh_int	movement_loss	[SECT_MAX]	=
{
    1, 2, 2, 3, 4, 6, 4, 1, 6, 10, 6
};



/*
 * Local functions.
 */
int	find_door	args( ( CHAR_DATA *ch, char *arg ) );
bool	has_key		args( ( CHAR_DATA *ch, int key ) );
int	count_imms	args( ( CHAR_DATA *ch ) );
bool	check_track	args( ( CHAR_DATA *ch, int direction ) );
void	add_tracks	args( ( CHAR_DATA *ch, int direction ) );
void	show_page	args( ( CHAR_DATA *ch, OBJ_DATA *book, int pnum, bool pagefalse ) );
void	show_runes	args( ( CHAR_DATA *ch, OBJ_DATA *page, bool endline ) );
bool	are_runes	args( ( OBJ_DATA *page ) );
void	drow_hate	args( ( CHAR_DATA *ch) );


void move_char( CHAR_DATA *ch, int door )
{
    CHAR_DATA *fch;
    CHAR_DATA *fch_next;
    CHAR_DATA *mount;
    ROOM_INDEX_DATA *in_room;
    ROOM_INDEX_DATA *to_room;
    EXIT_DATA *pexit;
    DESCRIPTOR_DATA *d;
    char buf  [MAX_STRING_LENGTH];
    char poly [MAX_STRING_LENGTH];
    char mount2 [MAX_INPUT_LENGTH];
    char leave [20];
    int revdoor;

    if ( door < 0 || door > 5 )

    {
	bug( "Do_move: bad door %d.", door );
	return;
    }

    in_room = ch->in_room;
    if ( ( pexit   = in_room->exit[door] ) == NULL
    ||   ( to_room = pexit->to_room      ) == NULL )
    {
	send_to_char( "Alas, you cannot go that way.\n\r", ch );
	return;
    }
/*
if ((door= DIR_NORTH && ((obj=get_obj_list(ch,"walln",in_room->contents)
!= NULL) || (obj=get_obj_list(ch,"walls",to_room->contents)) != NULL))

|| if (door= DIR_SOUTH && ((obj=get_obj_list(ch,"walls",in_room->contents)
!= NULL) || (obj=get_obj_list(ch,"walln",to_room->contents)) != NULL))
|| if (door= DIR_EAST && ((obj=get_obj_list(ch,"walle",in_room->contents)
!= NULL) || (obj=get_obj_list(ch,"wallw",to_room->contents)) != NULL))
|| if (door= DIR_WEST && ((obj=get_obj_list(ch,"wallw",in_room->contents)
!= NULL) || (obj=get_obj_list(ch,"walle",to_room->contents)) != NULL))
|| if (door= DIR_UP && ((obj=get_obj_list(ch,"wallu",in_room->contents)
!= NULL) || (obj=get_obj_list(ch,"walld",to_room->contents)) != NULL))
|| if (door= DIR_DOWN && ((obj=get_obj_list(ch,"walld",in_room->contents)
!= NULL) || (obj=get_obj_list(ch,"wallu",to_room->contents)) != NULL)))
{
send_to_char("You are unable to pass the flowing water.\n\r",ch);
return;
}
*/
    if ( IS_SET(pexit->exit_info, EX_CLOSED)
    &&   !IS_AFFECTED(ch, AFF_PASS_DOOR)
    &&   !IS_AFFECTED(ch, AFF_ETHEREAL)
    &&   !IS_AFFECTED(ch, AFF_SHADOWPLANE) )
    {
	if (!IS_NPC(ch) && IS_CLASS(ch, CLASS_WEREWOLF) &&
	    ch->power[DISC_WERE_BOAR] > 0)
	{
	    act( "You smash open the $d.", ch, NULL, pexit->keyword, TO_CHAR );
	    act( "$n smashes open the $d.", ch, NULL, pexit->keyword, TO_ROOM );
	    REMOVE_BIT(pexit->exit_info, EX_CLOSED);
	}
	else
	{
	    act( "The $d is closed.", ch, NULL, pexit->keyword, TO_CHAR );
	    return;
	}
    }

    if ( IS_AFFECTED(ch, AFF_CHARM)
    &&   ch->master != NULL
    &&   in_room == ch->master->in_room )
    {
	send_to_char( "What?  And leave your beloved master?\n\r", ch );
	return;
    }

    if (IS_NPC(ch) && (mount=ch->mount) != NULL && IS_SET(ch->mounted,IS_MOUNT))
    {
	send_to_char( "You better wait for instructions from your rider.\n\r", ch );
	return;
    }

    if ( room_is_private( to_room ))
    {
	if ( IS_NPC( ch ) || ch->trust < MAX_LEVEL)
	{
		send_to_char( "That room is private right now.\n\r", ch );
		return;
	}
	else 
		send_to_char( "That room is private (Access granted).\n\r", ch);
    }

    if ( (IS_LEG_L(ch,BROKEN_LEG) || IS_LEG_L(ch,LOST_LEG)) &&
	 (IS_LEG_R(ch,BROKEN_LEG) || IS_LEG_R(ch,LOST_LEG)) &&
	 (IS_ARM_L(ch,BROKEN_ARM) || IS_ARM_L(ch,LOST_ARM) ||
	    get_eq_char(ch, WEAR_HOLD) != NULL) &&
	 (IS_ARM_R(ch,BROKEN_ARM) || IS_ARM_R(ch,LOST_ARM) ||
	    get_eq_char(ch, WEAR_WIELD) != NULL))
    {
	send_to_char( "You need at least one free arm to drag yourself with.\n\r", ch );
	return;
    }
    else if ( IS_BODY(ch,BROKEN_SPINE) &&
	 (IS_ARM_L(ch,BROKEN_ARM) || IS_ARM_L(ch,LOST_ARM) ||
	    get_eq_char(ch, WEAR_HOLD) != NULL) &&
	 (IS_ARM_R(ch,BROKEN_ARM) || IS_ARM_R(ch,LOST_ARM) ||
	    get_eq_char(ch, WEAR_WIELD) != NULL))
    {
	send_to_char( "You cannot move with a broken spine.\n\r", ch );
	return;
    }

    if ( !IS_NPC(ch) )
    {
	int move;
	if ( in_room->sector_type == SECT_AIR
	||   to_room->sector_type == SECT_AIR )
	{
	    if ( !IS_AFFECTED(ch, AFF_FLYING) &&
	(!IS_NPC(ch) && (!IS_CLASS(ch, CLASS_DROW) ||
!IS_SET(ch->pcdata->powers[1], DPOWER_LEVITATION))) &&
		 (!IS_NPC(ch) && !IS_VAMPAFF(ch, VAM_FLYING) &&
		 (!IS_NPC(ch) && !IS_DEMAFF(ch,DEM_UNFOLDED)))
	    &&   !((mount=ch->mount) != NULL && IS_SET(ch->mounted,IS_RIDING) &&
		 IS_AFFECTED(mount, AFF_FLYING) ) )
	    {
		send_to_char( "You can't fly.\n\r", ch );
		return;
	    }
	}

	if ( in_room->sector_type == SECT_WATER_NOSWIM
	||   to_room->sector_type == SECT_WATER_NOSWIM )
	{
	    OBJ_DATA *obj;
	    bool found;

	    /*
	     * Look for a boat.
	     */
	    found = FALSE;
	    if ( !IS_NPC(ch) && IS_CLASS(ch, CLASS_VAMPIRE))
	    {
		if ( IS_VAMPAFF(ch, VAM_FLYING) )
		    found = TRUE;
		else if ( IS_POLYAFF(ch, POLY_SERPENT) )
		    found = TRUE;
		else if ( IS_AFFECTED(ch, AFF_SHADOWPLANE) )
		    found = TRUE;
		else if ((mount=ch->mount) != NULL && IS_SET(ch->mounted, IS_RIDING) 
		    && IS_AFFECTED(mount, AFF_FLYING))
		    found = TRUE;
		else
		{
		    send_to_char( "You are unable to cross running water.\n\r", ch );
		    return;
		}
	    }
	    if ( IS_AFFECTED(ch, AFF_FLYING) )
		found = TRUE;
	    else if ( !IS_NPC( ch) && IS_DEMAFF(ch, DEM_UNFOLDED) )
		found = TRUE;
	else if (!IS_NPC(ch) && (IS_CLASS(ch, CLASS_DROW) &&
IS_SET(ch->pcdata->powers[1], DPOWER_LEVITATION)))
		found = TRUE;
	    if ( !found )
	    {
	    	for ( obj = ch->carrying; obj != NULL; obj = obj->next_content )
	    	{
		    if ( obj->item_type == ITEM_BOAT )
		    {
		    	found = TRUE;
		    	break;
		    }
	    	}
	    	if ( !found )
	    	{
		    send_to_char( "You need a boat to go there.\n\r", ch );
		    return;
	    	}
	    }
	}
	else if ( !IS_AFFECTED(ch, AFF_FLYING) && IS_POLYAFF(ch, POLY_FISH) )
	{
	    bool from_ok = FALSE;
	    bool to_ok = FALSE;
	    if ( in_room->sector_type == SECT_WATER_NOSWIM ) from_ok = TRUE;
	    if ( in_room->sector_type == SECT_WATER_SWIM   ) from_ok = TRUE;
	    if ( to_room->sector_type == SECT_WATER_NOSWIM ) to_ok   = TRUE;
	    if ( to_room->sector_type == SECT_WATER_SWIM   ) to_ok   = TRUE;
	    if ( !from_ok || !to_ok )
	    {
		send_to_char("You cannot cross land.\n\r",ch);
		return;
	    }
	}

	move = movement_loss[UMIN(SECT_MAX-1, in_room->sector_type)]
	     + movement_loss[UMIN(SECT_MAX-1, to_room->sector_type)]
	     ;

	if (IS_HERO(ch)) move = 0;

	if(ch->move <= 0)
	{
		send_to_char("You are too Exhausted.\n\r",ch);
		return;
	}

	if (IS_SET(ch->mounted, IS_RIDING) && (ch->move < move || ch->move < 1))
	{
	    send_to_char( "You are too exhausted.\n\r", ch );
	    return;
	}

        if (IS_SET(pexit->exit_info, EX_IRON_WALL)
	&& !IS_AFFECTED(ch, AFF_PASS_DOOR) )
    {
	send_to_char("A towering wall of iron blocks your path.\n\r", ch);
	act("$n's path is blocked by the wall of iron.", ch, NULL, NULL, TO_ROOM);
	return;
    }

    if (IS_SET(pexit->exit_info, EX_MUSHROOM_WALL))
    {
	send_to_char("The mushrooms block your path.\n\r", ch);
	return;
    }

    if (IS_SET(pexit->exit_info, EX_ICE_WALL)
	&& ch->power[DISC_DAEM_GELU] < 5 )
    {
	send_to_char("A huge wall of ice blocks your way.\n\r", ch);
	return;
    }

    if (IS_SET(pexit->exit_info, EX_FIRE_WALL)
	&& ch->class == 0)
    {
	act("$n bursts through the wall of fire.", ch, NULL, NULL, TO_ROOM);
	send_to_char("You jump through the flames and are unaffected.\n\r", ch);
    }

    else if (IS_SET(pexit->exit_info, EX_FIRE_WALL)
	&& ch->class != 0 && !IS_NPC(ch) && ch->level > 2)
    {
	act("$n bursts through the wall of fire.", ch, NULL, NULL, TO_ROOM);
	send_to_char("You jump through the flames.\n\r", ch);
	ch->hit -= dice(6, 50);
      stc("The flames sear your flesh.\n\r",ch);
    }

    if (IS_SET(pexit->exit_info, EX_SWORD_WALL)
	&& ch->class == 0)
    {
	act("$n bursts through the wall of swords.", ch, NULL, NULL, TO_ROOM);
	send_to_char("You jump through the swords and are unaffected.\n\r", ch);
    }

    else if (IS_SET(pexit->exit_info, EX_SWORD_WALL)
	&& ch->class != 0 && !IS_NPC(ch) && ch->level > 2)
    {
	act("$n jumps through the wall of swords.", ch, NULL, NULL, TO_ROOM);
	send_to_char("You jump through the swords.\n\r", ch);
	send_to_char("Aaaaaaaaarghhhhhhh! That hurt!\n\r", ch);
	ch->hit -= dice(6, 70);
    }

    if (IS_SET(pexit->exit_info, EX_ASH_WALL) )
    {
	send_to_char("You scream in agony as the wall of ash rips apart your life force.\n\r", ch);
	act("$n screams in agony as the wall of ash rips $s life force apart.", ch, NULL, NULL, TO_ROOM);
	ch->hit /= 2;
	ch->move /= 2;
    }

	WAIT_STATE( ch, 1 );
	if (!IS_SET(ch->mounted, IS_RIDING)) ch->move -= move;
    }

    /* Check for mount message - KaVir */
    if ( (mount = ch->mount) != NULL && ch->mounted == IS_RIDING )
    {
	if (IS_NPC(mount))
	    sprintf(mount2," on %s.",mount->short_descr);
	else
	    sprintf(mount2," on %s.",mount->name);
    }
    else
	sprintf(mount2,".");

    if ( IS_HEAD(ch,LOST_HEAD) || IS_EXTRA(ch,EXTRA_OSWITCH) )
	sprintf(leave,"rolls");
    else if ( IS_AFFECTED(ch,AFF_ETHEREAL) )
	sprintf(leave,"floats");
    else if ( ch->in_room->sector_type == SECT_WATER_SWIM )
	sprintf(leave,"swims");
    else if ( IS_SET(ch->polyaff,POLY_SERPENT) )
	sprintf(leave,"slithers");
    else if ( IS_SET(ch->polyaff,POLY_WOLF) )
	sprintf(leave,"stalks");
    else if ( IS_SET(ch->polyaff,POLY_FROG) )
	sprintf(leave,"hops");
    else if ( IS_SET(ch->polyaff,POLY_FISH) )
	sprintf(leave,"swims");
    else if ( !IS_NPC(ch) && IS_DEMAFF(ch,DEM_UNFOLDED) )
	sprintf(leave,"flies");
    else if ( IS_BODY(ch,BROKEN_SPINE) )
	sprintf(leave,"drags $mself");
    else if ( IS_LEG_L(ch,LOST_LEG) && IS_LEG_R(ch,LOST_LEG) )
	sprintf(leave,"drags $mself");
    else if ( (IS_LEG_L(ch,BROKEN_LEG) || IS_LEG_L(ch,LOST_LEG) || IS_LEG_L(ch,LOST_FOOT)) &&
	 (IS_LEG_R(ch,BROKEN_LEG) || IS_LEG_R(ch,LOST_LEG) || IS_LEG_R(ch,LOST_FOOT)) )
	sprintf(leave,"crawls");
    else if ( ch->hit < (ch->max_hit/4) )
	sprintf(leave,"crawls");
    else if ( (IS_LEG_R(ch,LOST_LEG) || IS_LEG_R(ch,LOST_FOOT)) &&
	 (!IS_LEG_L(ch,BROKEN_LEG) && !IS_LEG_L(ch,LOST_LEG) && 
	  !IS_LEG_L(ch,LOST_FOOT)) )
	sprintf(leave,"hops");
    else if ( (IS_LEG_L(ch,LOST_LEG) || IS_LEG_L(ch,LOST_FOOT)) &&
	 (!IS_LEG_R(ch,BROKEN_LEG) && !IS_LEG_R(ch,LOST_LEG) &&
	  !IS_LEG_R(ch,LOST_FOOT)) )
	sprintf(leave,"hops");
    else if ( (IS_LEG_L(ch,BROKEN_LEG) || IS_LEG_L(ch,LOST_FOOT)) &&
	 (!IS_LEG_R(ch,BROKEN_LEG) && !IS_LEG_R(ch,LOST_LEG) &&
	  !IS_LEG_R(ch,LOST_FOOT)) )
	sprintf(leave,"limps");
    else if ( (IS_LEG_R(ch,BROKEN_LEG) || IS_LEG_R(ch,LOST_FOOT)) &&
	 (!IS_LEG_L(ch,BROKEN_LEG) && !IS_LEG_L(ch,LOST_LEG) &&
	  !IS_LEG_L(ch,LOST_FOOT)) )
	sprintf(leave,"limps");
    else if ( ch->hit < (ch->max_hit/3) )
	sprintf(leave,"limps");
    else if ( ch->hit < (ch->max_hit/2) )
	sprintf(leave,"staggers");
    else if ( !IS_NPC(ch) )
    {
    
	if (ch->pcdata->condition[COND_DRUNK] > 10)
	    sprintf(leave,"staggers");
	else
	    sprintf(leave,"walks");
    }
    else
	sprintf(leave,"walks");

    if (form_data[ch->cur_form].move_word[0] != '\0')
    {
	leave[0] = '\0';
	sprintf(leave, form_data[ch->cur_form].move_word);
    }

    if (!IS_NPC(ch) && ch->stance[0] != -1) do_stance(ch,"");
    for ( d = descriptor_list; d != NULL; d = d->next )
    {
	CHAR_DATA *victim;

	if ( ( victim = d->character ) == NULL )
	    continue;

        if ( ch->in_room == NULL || victim->in_room == NULL ) continue;

        if ( ch == victim || ch->in_room != victim->in_room) continue;

	if ( d->connected != CON_PLAYING || !can_see( ch, victim ) )
	    continue;

	if ( !IS_NPC(ch) && !IS_AFFECTED(ch, AFF_SNEAK) && IS_AFFECTED(ch,AFF_POLYMORPH)
	&& ( IS_NPC(ch) || !IS_SET(ch->act, PLR_WIZINVIS) )
	&& can_see(victim,ch))
	{
	    if (((mount = ch->mount) != NULL && ch->mounted == IS_RIDING &&
	    IS_AFFECTED(mount,AFF_FLYING)) || IS_AFFECTED(ch,AFF_FLYING) ||
	    (!IS_NPC(ch) && IS_VAMPAFF(ch,VAM_FLYING)) )
		sprintf(poly,"%s flies $T%s",ch->morph,mount2);
	    else if ( (mount = ch->mount) != NULL && ch->mounted == IS_RIDING )
		sprintf(poly,"%s rides $T%s",ch->morph,mount2);
	    else
		sprintf(poly,"%s %s $T%s",ch->morph,leave,mount2);
	    act( poly, victim, NULL, dir_name[door], TO_CHAR );
	}
	else if ( !IS_AFFECTED(ch, AFF_SNEAK)
	&& ( IS_NPC(ch) || !IS_SET(ch->act, PLR_WIZINVIS) )
	&& can_see(victim,ch))
	{
	    if (((mount = ch->mount) != NULL && ch->mounted == IS_RIDING &&
	    IS_AFFECTED(mount,AFF_FLYING)) || IS_AFFECTED(ch,AFF_FLYING) ||
	    (!IS_NPC(ch) && IS_VAMPAFF(ch,VAM_FLYING)) )
		sprintf(poly,"$n flies %s%s",dir_name[door],mount2);
	    else if ( (mount = ch->mount) != NULL && ch->mounted == IS_RIDING )
		sprintf(poly,"$n rides %s%s",dir_name[door],mount2);
	    else
		sprintf(poly,"$n %s %s%s",leave,dir_name[door],mount2);
	    act( poly, ch, NULL, victim, TO_VICT );
	}
    }
    char_from_room( ch );
    char_to_room( ch, to_room );
    if      ( door == 0 ) {revdoor = 2;sprintf(buf,"the south");}
    else if ( door == 1 ) {revdoor = 3;sprintf(buf,"the west");}
    else if ( door == 2 ) {revdoor = 0;sprintf(buf,"the north");}
    else if ( door == 3 ) {revdoor = 1;sprintf(buf,"the east");}
    else if ( door == 4 ) {revdoor = 5;sprintf(buf,"below");}
    else                  {revdoor = 4;sprintf(buf,"above");}

    for ( d = descriptor_list; d != NULL; d = d->next )
    {
	CHAR_DATA *victim;

	if ( ( victim = d->character ) == NULL )
	    continue;

        if ( ch->in_room == NULL || victim->in_room == NULL ) continue;

        if ( ch == victim || ch->in_room != victim->in_room) continue;

	if ( d->connected != CON_PLAYING || !can_see( ch, victim ) )
	    continue;

	if ( !IS_NPC(ch) && !IS_AFFECTED(ch, AFF_SNEAK) && IS_AFFECTED(ch,AFF_POLYMORPH)
	&& ( IS_NPC(ch) || !IS_SET(ch->act, PLR_WIZINVIS) ) && can_see(victim,ch))
	{
	    if (((mount = ch->mount) != NULL && ch->mounted == IS_RIDING &&
	    IS_AFFECTED(mount,AFF_FLYING)) || IS_AFFECTED(ch,AFF_FLYING) ||
	    (!IS_NPC(ch) && IS_VAMPAFF(ch,VAM_FLYING)) )
		sprintf(poly,"%s flies in from %s%s",ch->morph,buf,mount2);
	    else if ( (mount = ch->mount) != NULL && ch->mounted == IS_RIDING )
		sprintf(poly,"%s rides in from %s%s",ch->morph,buf,mount2);
	    else
		sprintf(poly,"%s %s in from %s%s",ch->morph,leave,buf,mount2);
	    act( poly, ch, NULL, victim, TO_VICT );
	}
	else if ( !IS_AFFECTED(ch, AFF_SNEAK) && can_see(victim,ch)
	&& ( IS_NPC(ch) || !IS_SET(ch->act, PLR_WIZINVIS) ) )
	{
	    if (((mount = ch->mount) != NULL && ch->mounted == IS_RIDING &&
	    IS_AFFECTED(mount,AFF_FLYING)) || IS_AFFECTED(ch,AFF_FLYING) ||
	    (!IS_NPC(ch) && IS_VAMPAFF(ch,VAM_FLYING)) )
		sprintf( poly, "$n flies in from %s%s",buf,mount2);
	    else if ( (mount = ch->mount) != NULL && ch->mounted == IS_RIDING )
		sprintf(poly,"$n rides in from %s%s",buf,mount2);
	    else
		sprintf( poly, "$n %s in from %s%s",leave,buf,mount2);
	    act( poly, ch, NULL, victim, TO_VICT );
	}
    }

    do_look( ch, "auto" );

    for ( fch = in_room->people; fch != NULL; fch = fch_next )
    {
	fch_next = fch->next_in_room;
	if ( (mount = fch->mount) != NULL && mount == ch && IS_SET(fch->mounted,IS_MOUNT))
	{
	    act( "$N digs $S heels into you.", fch, NULL, ch, TO_CHAR );
	    char_from_room(fch);
	    char_to_room(fch,ch->in_room);
	}

	if ( fch->master == ch && fch->position == POS_STANDING 
		&& fch->in_room != ch->in_room)
	{
	    act( "You follow $N.", fch, NULL, ch, TO_CHAR );
	    move_char( fch, door );
	}
    }
    room_text(ch,">ENTER<");
    return;
}

/*

void do_humanform( CHAR_DATA *ch, char *argument )
{
    OBJ_DATA *obj;

    if (IS_NPC(ch)) return;
    if ( ( obj = ch->pcdata->chobj ) == NULL )
    {
	send_to_char("You are already in human form.\n\r",ch);
	return;
    }

    ch->pcdata->obj_vnum = 0;
    obj->chobj = NULL;
    ch->pcdata->chobj = NULL;
    REMOVE_BIT(ch->affected_by, AFF_POLYMORPH);
    REMOVE_BIT(ch->extra, EXTRA_OSWITCH);
    free_string(ch->morph);
    ch->morph = str_dup("");
    act("$p transforms into $n.",ch,obj,NULL,TO_ROOM);
    act("Your reform your human body.",ch,obj,NULL,TO_CHAR);
    extract_obj(obj);
    if (ch->in_room->vnum == ROOM_VNUM_IN_OBJECT)
    {
	char_from_room(ch);
	char_to_room(ch,get_room_index(ROOM_VNUM_HELL));
    }
    return;
}
void do_notravel( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];

    one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if (IS_IMMUNE(ch, IMM_TRAVEL))
    {
	REMOVE_BIT(ch->immune, IMM_TRAVEL);
	send_to_char("You can now be the target of travel or burrow.\n\r", ch);
	return;
    }
    else if (!IS_IMMUNE(ch, IMM_TRAVEL)) 
    {
	SET_BIT(ch->immune, IMM_TRAVEL);
	send_to_char("You can no longer be the target of travel or burrow.\n\r", ch);
	return;
    }
    else
	send_to_char( "Excuse you?\n\r", ch );
    return;
}
*/
void do_north( CHAR_DATA *ch, char *argument )
{
char wall[MAX_STRING_LENGTH];

OBJ_DATA *obj;
    ROOM_INDEX_DATA *in_room;
   if (IS_AFFECTED(ch,AFF_WEBBED))
    {
	send_to_char("You are unable to move with all this sticky webbing on.\n\r",ch);
	return;
    }
        if (IS_AFFECTED(ch, AFF_TENDRILS))
    {
send_to_char("You are unable to move tangled in these tendrils.\n\r",ch);
	return;
    }
sprintf(wall,"walln");
obj = get_obj_list(ch,wall,ch->in_room->contents);
if (obj != NULL)
{
send_to_char("\n\rYou cant pass the flowing wall of water.\n\r",ch);
return;
}
 

    in_room = ch->in_room;
    move_char( ch, DIR_NORTH );
    if (!IS_NPC(ch) && ch->in_room != in_room)
    {
	ROOM_INDEX_DATA *old_room;
	old_room = ch->in_room;
	char_from_room(ch);
	char_to_room(ch, in_room);
	add_tracks( ch, DIR_NORTH );
	char_from_room(ch);
	char_to_room(ch, old_room);
    }
/*
    if (!IS_NPC(ch) && ch->in_room != in_room) add_tracks( ch, DIR_SOUTH );
*/
	drow_hate(ch);

    return;
}



void do_east( CHAR_DATA *ch, char *argument )
{
    ROOM_INDEX_DATA *in_room;
OBJ_DATA *obj;
char wall[MAX_STRING_LENGTH];

    if (IS_AFFECTED(ch, AFF_WEBBED))
    {
	send_to_char("You are unable to move with all this sticky webbing on.\n\r",ch);
	return;
    }
    if (IS_AFFECTED(ch, AFF_TENDRILS))
    {
send_to_char("You are unable to move tangled in these tendrils.\n\r",ch);
	return;
    }

sprintf(wall,"walle");
obj = get_obj_list(ch,wall,ch->in_room->contents);
if (obj != NULL)
{
send_to_char("\n\rYou cant pass the flowing wall of water.\n\r",ch);
return;
}
 

    in_room = ch->in_room;
    move_char( ch, DIR_EAST );
    if (!IS_NPC(ch) && ch->in_room != in_room)
    {
	ROOM_INDEX_DATA *old_room;
	old_room = ch->in_room;
	char_from_room(ch);
	char_to_room(ch, in_room);
	add_tracks( ch, DIR_EAST );
	char_from_room(ch);
	char_to_room(ch, old_room);
    }
/*
    if (!IS_NPC(ch) && ch->in_room != in_room) add_tracks( ch, DIR_WEST );
*/
	drow_hate(ch);
    return;
}



void do_south( CHAR_DATA *ch, char *argument )
{
char wall[MAX_STRING_LENGTH];

    ROOM_INDEX_DATA *in_room;
OBJ_DATA *obj;

    if (IS_AFFECTED(ch, AFF_WEBBED))
    {
	send_to_char("You are unable to move with all this sticky webbing on.\n\r",ch);
	return;
    }
    if (IS_AFFECTED(ch, AFF_TENDRILS))
    {
send_to_char("You are unable to move tangled in these tendrils.\n\r",ch);
	return;
    }
sprintf(wall,"walls");
obj = get_obj_list(ch,wall,ch->in_room->contents);
if (obj != NULL)
{
send_to_char("\n\rYou cant pass the flowing wall of water.\n\r",ch);
return;
}
 

    in_room = ch->in_room;
    move_char( ch, DIR_SOUTH );
    if (!IS_NPC(ch) && ch->in_room != in_room)
    {
	ROOM_INDEX_DATA *old_room;
	old_room = ch->in_room;
	char_from_room(ch);
	char_to_room(ch, in_room);
	add_tracks( ch, DIR_SOUTH );
	char_from_room(ch);
	char_to_room(ch, old_room);
    }
/*
    if (!IS_NPC(ch) && ch->in_room != in_room) add_tracks( ch, DIR_NORTH );
*/
	drow_hate(ch);
    return;
}



void do_west( CHAR_DATA *ch, char *argument )
{
    ROOM_INDEX_DATA *in_room;
OBJ_DATA *obj;
char wall[MAX_STRING_LENGTH];

    if (IS_AFFECTED(ch, AFF_WEBBED))
    {
	send_to_char("You are unable to move with all this sticky webbing on.\n\r",ch);
	return;
    }
    if (IS_AFFECTED(ch, AFF_TENDRILS))
    {
send_to_char("You are unable to move tangled in these tendrils.\n\r",ch);
	return;
    }
sprintf(wall,"wallw");
obj = get_obj_list(ch,wall,ch->in_room->contents);
if (obj != NULL)
{
send_to_char("\n\rYou cant pass the flowing wall of water.\n\r",ch);
return;
}
 

    in_room = ch->in_room;
    move_char( ch, DIR_WEST );
    if (!IS_NPC(ch) && ch->in_room != in_room)
    {
	ROOM_INDEX_DATA *old_room;
	old_room = ch->in_room;
	char_from_room(ch);
	char_to_room(ch, in_room);
	add_tracks( ch, DIR_WEST );
	char_from_room(ch);
	char_to_room(ch, old_room);
    }
/*
    if (!IS_NPC(ch) && ch->in_room != in_room) add_tracks( ch, DIR_EAST );
*/
	drow_hate(ch);
    return;
}



void do_up( CHAR_DATA *ch, char *argument )
{
    ROOM_INDEX_DATA *in_room;
OBJ_DATA *obj;
char wall[MAX_STRING_LENGTH];

    if (IS_AFFECTED(ch, AFF_WEBBED))
    {
	send_to_char("You are unable to move with all this sticky webbing on.\n\r",ch);
	return;
    }
    if (IS_AFFECTED(ch, AFF_TENDRILS))
    {
send_to_char("You are unable to move tangled in these tendrils.\n\r",ch);
	return;
    }
sprintf(wall,"wallu");
obj = get_obj_list(ch,wall,ch->in_room->contents);
if (obj != NULL)
{
send_to_char("\n\rYou cant pass the flowing wall of water.\n\r",ch);
return;
}
 

    in_room = ch->in_room;
    move_char( ch, DIR_UP );
    if (!IS_NPC(ch) && ch->in_room != in_room)
    {
	ROOM_INDEX_DATA *old_room;
	old_room = ch->in_room;
	char_from_room(ch);
	char_to_room(ch, in_room);
	add_tracks( ch, DIR_UP );
	char_from_room(ch);
	char_to_room(ch, old_room);
    }
/*
    if (!IS_NPC(ch) && ch->in_room != in_room) add_tracks( ch, DIR_DOWN );
*/
	drow_hate(ch);
    return;
}



void do_down( CHAR_DATA *ch, char *argument )
{
    ROOM_INDEX_DATA *in_room;
    OBJ_DATA *obj;
char wall[MAX_STRING_LENGTH];

    if (IS_AFFECTED(ch, AFF_WEBBED))
    {
	send_to_char("You are unable to move with all this sticky webbing on.\n\r",ch);
	return;
    }
    if (IS_AFFECTED(ch, AFF_TENDRILS))
    {
send_to_char("You are unable to move tangled in these tendrils.\n\r",ch);
	return;
    }
sprintf(wall,"walld");
obj = get_obj_list(ch,wall,ch->in_room->contents);
if (obj != NULL)
{
send_to_char("\n\rYou cant pass the flowing wall of water.\n\r",ch);
return;
}
 

    in_room = ch->in_room;
    move_char( ch, DIR_DOWN );
    if (!IS_NPC(ch) && ch->in_room != in_room)
    {
	ROOM_INDEX_DATA *old_room;
	old_room = ch->in_room;
	char_from_room(ch);
	char_to_room(ch, in_room);
	add_tracks( ch, DIR_DOWN );
	char_from_room(ch);
	char_to_room(ch, old_room);
    }
/*
    if (!IS_NPC(ch) && ch->in_room != in_room) add_tracks( ch, DIR_UP );
*/
	drow_hate(ch);
    return;
}



int find_door( CHAR_DATA *ch, char *arg )
{
    EXIT_DATA *pexit;
    int door;

	 if ( !str_cmp( arg, "n" ) || !str_cmp( arg, "north" ) ) door = 0;
    else if ( !str_cmp( arg, "e" ) || !str_cmp( arg, "east"  ) ) door = 1;
    else if ( !str_cmp( arg, "s" ) || !str_cmp( arg, "south" ) ) door = 2;
    else if ( !str_cmp( arg, "w" ) || !str_cmp( arg, "west"  ) ) door = 3;
    else if ( !str_cmp( arg, "u" ) || !str_cmp( arg, "up"    ) ) door = 4;
    else if ( !str_cmp( arg, "d" ) || !str_cmp( arg, "down"  ) ) door = 5;
    else
    {
	for ( door = 0; door <= 5; door++ )
	{
	    if ( ( pexit = ch->in_room->exit[door] ) != NULL
	    &&   IS_SET(pexit->exit_info, EX_ISDOOR)
	    &&   pexit->keyword != NULL
	    &&   is_name( arg, pexit->keyword ) )
		return door;
	}
	act( "I see no $T here.", ch, NULL, arg, TO_CHAR );
	return -1;
    }

    if ( ( pexit = ch->in_room->exit[door] ) == NULL )
    {
	act( "I see no door $T here.", ch, NULL, arg, TO_CHAR );
	return -1;
    }

    if ( !IS_SET(pexit->exit_info, EX_ISDOOR) )
    {
	send_to_char( "You can't do that.\n\r", ch );
	return -1;
    }

    return door;
}

/* random room generation procedure */
ROOM_INDEX_DATA  *get_random_room(CHAR_DATA *ch)
{
    ROOM_INDEX_DATA *room;

    for ( ; ; )
    {
        room = get_room_index( number_range( 0, 32000 ) );
        if ( room != NULL )
        if ( !IS_SET(room->room_flags, ROOM_PRIVATE)
        &&   !IS_SET(room->room_flags, ROOM_SOLITARY) 
	&&   !IS_SET(room->room_flags, ROOM_SAFE) )
            break;
    }

    return room;
}

ROOM_INDEX_DATA  *get_rand_room()
{
    ROOM_INDEX_DATA *room;

    for ( ; ; )
    {
        room = get_room_index( number_range( 0, 32000 ) );
        if ( room != NULL )
        if ( !IS_SET(room->room_flags, ROOM_PRIVATE)
        &&   !IS_SET(room->room_flags, ROOM_SOLITARY) 
	&&   !IS_SET(room->room_flags, ROOM_SAFE) 
	&&  room->vnum > 300)
            break;
    }

    return room;
}

ROOM_INDEX_DATA  *get_treemeld_room()
{
    ROOM_INDEX_DATA *room;

    for ( ; ; )
    {
        room = get_room_index( number_range( 0, 32000 ) );
        if ( room != NULL
	    && room->sector_type == SECT_FOREST ) break;
    }

    return room;
}

ROOM_INDEX_DATA  *get_rand_room_by_sect( int sect )
{
    ROOM_INDEX_DATA *room;

    for ( ; ; )
    {
        room = get_room_index( number_range( 0, 32000 ) );
        if ( room != NULL
	    && room->sector_type == sect ) break;
    }

    return room;
}

/* Designed for the portal spell, but can also have other uses...KaVir
 * V0 = Where the portal will take you.
 * V1 = Number of uses (0 is infinate).
 * V2 = if 2, cannot be entered.
 * V3 = The room the portal is currently in.
 */
void do_enter( CHAR_DATA *ch, char *argument )
{
    ROOM_INDEX_DATA *pRoomIndex;
    ROOM_INDEX_DATA *location;
    char arg[MAX_INPUT_LENGTH];
    char poly [MAX_INPUT_LENGTH];
    OBJ_DATA *obj;
    OBJ_DATA *portal;
    OBJ_DATA *portal_next;
    CHAR_DATA *mount;
    bool found;

    argument = one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char( "Enter what?\n\r", ch );
	return;
    }

    obj = get_obj_list( ch, arg, ch->in_room->contents );
    if ( obj == NULL )
    {
	act( "I see no $T here.", ch, NULL, arg, TO_CHAR );
	return;
    }
    if ( obj->item_type != ITEM_PORTAL )
    {
	act( "You cannot enter that.", ch, NULL, arg, TO_CHAR );
	return;
    }

    if (IS_AFFECTED(ch, AFF_SHADOWPLANE) &&
	!IS_SET(obj->extra_flags, ITEM_SHADOWPLANE) )
    {
	send_to_char( "You are too insubstantual.\n\r", ch );
	return;
    }
    else if (!IS_AFFECTED(ch, AFF_SHADOWPLANE) &&
	IS_SET(obj->extra_flags, ITEM_SHADOWPLANE) )
    {
	send_to_char( "It is too insubstantual.\n\r", ch );
	return;
    }

    if ( obj->value[2] == 2 || obj->value[2] == 3 )
    {
	act( "It seems to be closed.", ch, NULL, arg, TO_CHAR );
	return;
    }

    pRoomIndex = get_room_index(obj->value[0]);
    location = ch->in_room;

    if ( pRoomIndex == NULL )
    {
	act( "You are unable to enter.", ch, NULL, arg, TO_CHAR );
	return;
    }

    act( "You step into $p.",  ch, obj, NULL, TO_CHAR );
    if ( !IS_NPC(ch) && IS_AFFECTED(ch,AFF_POLYMORPH) )
	sprintf(poly,"%s steps into $p.",ch->morph);
    else
	sprintf(poly,"$n steps into $p.");
    act( poly,  ch, obj, NULL, TO_ROOM );
    char_from_room(ch);
    char_to_room(ch,pRoomIndex);
    if ( !IS_NPC(ch) && IS_AFFECTED(ch,AFF_POLYMORPH) )
	sprintf(poly,"%s steps out of $p.",ch->morph);
    else
	sprintf(poly,"$n steps out of $p.");
    act( poly,  ch, obj, NULL, TO_ROOM );
    char_from_room(ch);
    char_to_room(ch,location);
/* Leave this out for now, as it doesn't seem to work properly. KaVir
    if ((obj->value[2] == 1) && (CAN_WEAR(obj,ITEM_TAKE)))
    {
	obj->value[2] = 2;
	REMOVE_BIT(obj->wear_flags, ITEM_TAKE);
    }
*/
    if (obj->value[1] != 0)
    {
	obj->value[1] = obj->value[1] - 1;
	if (obj->value[1] < 1)
	{
	    act( "$p vanishes.",  ch, obj, NULL, TO_CHAR );
	    act( "$p vanishes.",  ch, obj, NULL, TO_ROOM );
	    extract_obj(obj);
	}
    }
    char_from_room(ch);
    char_to_room(ch,pRoomIndex);
    found = FALSE;
    for ( portal = ch->in_room->contents; portal != NULL; portal = portal_next )
    {
	portal_next = portal->next_content;
	if ( ( obj->value[0] == portal->value[3]  )
	    && (obj->value[3] == portal->value[0]) )
	{
	    found = TRUE;
/* Leave this out for now, as it doesn't seem to work properly. KaVir
	    if ((portal->value[2] == 2) && (!CAN_WEAR(obj,ITEM_TAKE)))
	    {
		portal->value[2] = 1;
		SET_BIT(obj->wear_flags, ITEM_TAKE);
	    }
*/
	    if (IS_AFFECTED(ch, AFF_SHADOWPLANE) &&
		!IS_SET(portal->extra_flags, ITEM_SHADOWPLANE) )
	    {
		REMOVE_BIT(ch->affected_by, AFF_SHADOWPLANE);
		break;
	    }
	    else if (!IS_AFFECTED(ch, AFF_SHADOWPLANE) &&
		IS_SET(portal->extra_flags, ITEM_SHADOWPLANE) )
	    {
		SET_BIT(ch->affected_by, AFF_SHADOWPLANE);
		break;
	    }
    	    if (portal->value[1] != 0)
    	    {
		portal->value[1] = portal->value[1] - 1;
		if (portal->value[1] < 1)
		{
		    act( "$p vanishes.",  ch, portal, NULL, TO_CHAR );
		    act( "$p vanishes.",  ch, portal, NULL, TO_ROOM );
		    extract_obj(portal);
		}
	    }
    	}
    }
    do_look(ch,"auto");
    if ( ( mount = ch->mount ) == NULL ) return;
    char_from_room( mount );
    char_to_room( mount, ch->in_room );
    return;
}


void do_open( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;
    int door;

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char( "Open what?\n\r", ch );
	return;
    }

    if ( ( obj = get_obj_here( ch, arg ) ) != NULL )
    {
	/* 'open object' */
	if ( obj->item_type != ITEM_CONTAINER && obj->item_type != ITEM_BOOK)
	    { send_to_char( "That's not a container.\n\r", ch ); return; }
	if ( !IS_SET(obj->value[1], CONT_CLOSED) )
	    { send_to_char( "It's already open.\n\r",      ch ); return; }
	if ( !IS_SET(obj->value[1], CONT_CLOSEABLE) && obj->item_type != ITEM_BOOK)
	    { send_to_char( "You can't do that.\n\r",      ch ); return; }
	if ( IS_SET(obj->value[1], CONT_LOCKED) )
	    { send_to_char( "It's locked.\n\r",            ch ); return; }

	REMOVE_BIT(obj->value[1], CONT_CLOSED);
	send_to_char( "Ok.\n\r", ch );
	act( "$n opens $p.", ch, obj, NULL, TO_ROOM );
	return;
    }

    if ( ( door = find_door( ch, arg ) ) >= 0 )
    {
	/* 'open door' */
	ROOM_INDEX_DATA *to_room;
	EXIT_DATA *pexit;
	EXIT_DATA *pexit_rev;

	pexit = ch->in_room->exit[door];
	if ( !IS_SET(pexit->exit_info, EX_CLOSED) )
	    { send_to_char( "It's already open.\n\r",      ch ); return; }
	if (  IS_SET(pexit->exit_info, EX_LOCKED) )
	    { send_to_char( "It's locked.\n\r",            ch ); return; }

	REMOVE_BIT(pexit->exit_info, EX_CLOSED);
	act( "$n opens the $d.", ch, NULL, pexit->keyword, TO_ROOM );
	send_to_char( "Ok.\n\r", ch );

	/* open the other side */
	if ( ( to_room   = pexit->to_room               ) != NULL
	&&   ( pexit_rev = to_room->exit[rev_dir[door]] ) != NULL
	&&   pexit_rev->to_room == ch->in_room )
	{
	    CHAR_DATA *rch;

	    REMOVE_BIT( pexit_rev->exit_info, EX_CLOSED );
	    for ( rch = to_room->people; rch != NULL; rch = rch->next_in_room )
		act( "The $d opens.", rch, NULL, pexit_rev->keyword, TO_CHAR );
	}
    }

    return;
}



void do_close( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;
    int door;

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char( "Close what?\n\r", ch );
	return;
    }

    if ( ( obj = get_obj_here( ch, arg ) ) != NULL )
    {
	/* 'close object' */
	if ( obj->item_type != ITEM_CONTAINER && obj->item_type != ITEM_BOOK)
	    { send_to_char( "That's not a container.\n\r", ch ); return; }
	if ( IS_SET(obj->value[1], CONT_CLOSED) )
	    { send_to_char( "It's already closed.\n\r",    ch ); return; }
	if ( !IS_SET(obj->value[1], CONT_CLOSEABLE) && obj->item_type != ITEM_BOOK )
	    { send_to_char( "You can't do that.\n\r",      ch ); return; }

	SET_BIT(obj->value[1], CONT_CLOSED);
	if (obj->item_type == ITEM_BOOK) obj->value[2] = 0;
	send_to_char( "Ok.\n\r", ch );
	act( "$n closes $p.", ch, obj, NULL, TO_ROOM );
	return;
    }

    if ( ( door = find_door( ch, arg ) ) >= 0 )
    {
	/* 'close door' */
	ROOM_INDEX_DATA *to_room;
	EXIT_DATA *pexit;
	EXIT_DATA *pexit_rev;

	pexit	= ch->in_room->exit[door];
	if ( IS_SET(pexit->exit_info, EX_CLOSED) )
	    { send_to_char( "It's already closed.\n\r",    ch ); return; }

	SET_BIT(pexit->exit_info, EX_CLOSED);
	act( "$n closes the $d.", ch, NULL, pexit->keyword, TO_ROOM );
	send_to_char( "Ok.\n\r", ch );

	/* close the other side */
	if ( ( to_room   = pexit->to_room               ) != NULL
	&&   ( pexit_rev = to_room->exit[rev_dir[door]] ) != 0
	&&   pexit_rev->to_room == ch->in_room )
	{
	    CHAR_DATA *rch;

	    SET_BIT( pexit_rev->exit_info, EX_CLOSED );
	    for ( rch = to_room->people; rch != NULL; rch = rch->next_in_room )
		act( "The $d closes.", rch, NULL, pexit_rev->keyword, TO_CHAR );
	}
    }

    return;
}



void do_turn( CHAR_DATA *ch, char *argument )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;
    int value = 0;

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if ( arg1[0] == '\0' || arg2[0] == '\0' )
    {
	send_to_char( "Syntax: Turn <book> <forward/back>.\n\r", ch );
	return;
    }

    if (is_number(arg2)) value = atoi(arg2);

    if ( ( obj = get_obj_here( ch, arg1 ) ) == NULL )
    {
	send_to_char("You don't have that book.\n\r",ch);
	return;
    }

    if ( obj->item_type != ITEM_BOOK)
    { send_to_char( "That's not a book.\n\r", ch ); return; }
    if ( IS_SET(obj->value[1], CONT_CLOSED) )
    { send_to_char( "First you should open it.\n\r",    ch ); return; }

    if (!str_cmp(arg2,"f") || !str_cmp(arg2,"forward"))
    {
	if (obj->value[2] >= obj->value[3])
	{
	    send_to_char("But you are already at the end of the book.\n\r",ch);
	    return;
	}
	obj->value[2] += 1;
	act( "You flip forward a page in $p.", ch, obj, NULL, TO_CHAR );
	act( "$n flips forward a page in $p.", ch, obj, NULL, TO_ROOM );
    }
    else if (!str_cmp(arg2,"b") || !str_cmp(arg2,"backward"))
    {
	if (obj->value[2] <= 0)
	{
	    send_to_char("But you are already at the beginning of the book.\n\r",ch);
	    return;
	}
	obj->value[2] -= 1;
	act( "You flip backward a page in $p.", ch, obj, NULL, TO_CHAR );
	act( "$n flips backward a page in $p.", ch, obj, NULL, TO_ROOM );
    }
    else if (is_number(arg2) && value >= 0 && value <= obj->value[3])
    {
	if (value == obj->value[2])
	{
	    act("$p is already open at that page.",ch,obj,NULL,TO_CHAR);
	    return;
	}
	else if (value < obj->value[2])
	{
	    act( "You flip backwards through $p.", ch, obj, NULL, TO_CHAR );
	    act( "$n flips backwards through $p.", ch, obj, NULL, TO_ROOM );
	}
	else
	{
	    act( "You flip forwards through $p.", ch, obj, NULL, TO_CHAR );
	    act( "$n flips forwards through $p.", ch, obj, NULL, TO_ROOM );
	}
	obj->value[2] = value;
    }
    else
	send_to_char("Do you wish to turn forward or backward a page?\n\r",ch);
    return;
}

void do_read( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    OBJ_DATA *obj;

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char( "What do you wish to read?\n\r", ch );
	return;
    }

    if ( ( obj = get_obj_here( ch, arg ) ) == NULL )
    {
	send_to_char("You don't have that book.\n\r",ch);
	return;
    }

    if ( obj->item_type == ITEM_PAGE)
    {
	if (!str_cmp(obj->victpoweruse,"(null)"))
	    sprintf(buf,"Untitled page.\n\r");
	else
	    sprintf(buf,"%s.\n\r",obj->victpoweruse);
	buf[0] = UPPER(buf[0]);
	send_to_char(buf,ch);
	if (obj->chpoweruse == NULL || obj->chpoweruse == '\0' ||
	    !str_cmp(obj->chpoweruse,"(null)"))
	{
	    if (!are_runes(obj))
		send_to_char("This page is blank.\n\r",ch);
	    else if (IS_AFFECTED(ch, AFF_DETECT_MAGIC) && 
		!IS_SET(obj->quest, QUEST_MASTER_RUNE) &&
		!IS_SET(obj->spectype, ADV_STARTED))
		show_runes(ch, obj, FALSE);
	    else
		send_to_char("This page is blank.\n\r",ch);
	    return;
	}
	send_to_char("--------------------------------------------------------------------------------\n\r",ch);
	send_to_char(obj->chpoweruse,ch);
	send_to_char("\n\r--------------------------------------------------------------------------------\n\r",ch);
	if (IS_AFFECTED(ch, AFF_DETECT_MAGIC) && 
	    !IS_SET(obj->spectype, ADV_STARTED) &&
	    !IS_SET(obj->quest, QUEST_MASTER_RUNE )) show_runes(ch, obj, TRUE);
	return;
    }

    if ( obj->item_type != ITEM_BOOK)
    { send_to_char( "That's not a book.\n\r", ch ); return; }
    if ( IS_SET(obj->value[1], CONT_CLOSED) )
    {
	if (!str_cmp(obj->victpoweruse,"(null)"))
	    sprintf(buf,"The book is untitled.\n\r");
	else
	    sprintf(buf,"The book is titled '%s'.\n\r",obj->victpoweruse);
	buf[0] = UPPER(buf[0]);
	send_to_char(buf,ch);
	return;
    }

    if (obj->value[2] == 0)
    {
	int page;

	send_to_char("Index page.\n\r",ch);
	if (obj->value[3] <= 0)
	{
	    send_to_char("<No pages>\n\r",ch);
	    return;
	}
	for ( page = 1; page <= obj->value[3]; page ++ )
	{
	    sprintf(buf,"Page %d:",page);
	    send_to_char(buf,ch);
	    show_page(ch,obj,page,TRUE);
	}
    }
    else
    {
	sprintf(buf,"Page %d:",obj->value[2]);
	send_to_char(buf,ch);
	show_page(ch,obj,obj->value[2],FALSE);
    }
    return;
}

void do_write( CHAR_DATA *ch, char *argument )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    char arg3[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    OBJ_DATA *obj;
    OBJ_DATA *object;
    CHAR_DATA *mobile;

    smash_tilde( argument );
    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );
    strcpy( arg3, argument );

    if (IS_NPC(ch)) return;
    if ( arg1[0] == '\0' || arg2[0] == '\0' || arg3[0] == '\0' )
    {
	send_to_char("Syntax: Write <page> <title/line> <text>.\n\r",ch);
	return;
    }

    if ( ( ( ( obj = get_eq_char(ch, WEAR_HOLD) ) != NULL) && 
	( obj->item_type != ITEM_TOOL || !IS_SET(obj->value[0],TOOL_PEN) ) )
	|| obj == NULL)
    {
	if ( ( ( ( obj = get_eq_char(ch, WEAR_WIELD) ) != NULL) && 
	    ( obj->item_type != ITEM_TOOL || !IS_SET(obj->value[0],TOOL_PEN) ) )
	    || obj == NULL)
	{
	    send_to_char("You are not holding a pen.\n\r",ch);
	    return;
	}
    }

    if ( ( obj = get_obj_carry( ch, arg1) ) == NULL )
    {
	send_to_char("You are not carrying that item.\n\r",ch);
	return;
    }
    if ( obj->item_type != ITEM_PAGE && obj->item_type != ITEM_BOOK )
    {
	send_to_char("You cannot write on that.\n\r",ch);
	return;
    }
    if (!str_cmp( arg2,"title"))
    {
	free_string( obj->victpoweruse );
	obj->victpoweruse = str_dup( arg3 );
	send_to_char("Ok.\n\r",ch);
	act("$n writes something on $p.",ch,obj,NULL,TO_ROOM);
	return;
    }
    else if (str_cmp( arg2,"line"))
    {
	send_to_char("You can write a TITLE or a LINE.\n\r",ch);
	return;
    }
    else if ( obj->item_type == ITEM_BOOK )
    {
	send_to_char("You can only write a title on the book.\n\r",ch);
	return;
    }
	else if (IS_SET(obj->spectype, ADV_FINISHED)) {
		send_to_char("It is already finished!\n\r", ch );
		return;}

    if (obj->chpoweruse != NULL) strcpy(buf,obj->chpoweruse);
	else return;
    if (!str_cmp(buf,"(null)"))
    {
	arg3[0] = UPPER(arg3[0]);
	free_string( obj->chpoweruse );
	obj->chpoweruse = str_dup( arg3 );
	send_to_char("Ok.\n\r",ch);
	act("$n writes something on $p.",ch,obj,NULL,TO_ROOM);
	if (!IS_CLASS(ch, CLASS_MAGE) && !IS_IMMORTAL(ch) 
	  && !IS_SET(obj->spectype, ADV_FINISHED))
	    SET_BIT(obj->spectype, ADV_FAILED);
	else if (!str_cmp(arg3,"start.damage.spell") && obj->spectype == 0)
	    {SET_BIT(obj->spectype, ADV_STARTED);
	    SET_BIT(obj->spectype, ADV_DAMAGE);}
	else if (!str_cmp(arg3,"start.affect.spell") && obj->spectype == 0)
	    {SET_BIT(obj->spectype, ADV_STARTED);
	    SET_BIT(obj->spectype, ADV_AFFECT);}
	else if (!str_cmp(arg3,"start.action.spell") && obj->spectype == 0)
	    {SET_BIT(obj->spectype, ADV_STARTED);
	    SET_BIT(obj->spectype, ADV_ACTION);}
	else if (!str_cmp(arg3,"start.spell") && obj->spectype == 0)
	    SET_BIT(obj->spectype, ADV_STARTED);
	else if (!IS_SET(obj->spectype, ADV_FINISHED))
	    SET_BIT(obj->spectype, ADV_FAILED);
	return;
    }
    if (obj->chpoweruse != NULL && buf[0] != '\0')
    {
	if (strlen(buf)+strlen(arg3) >= MAX_STRING_LENGTH-4)
	{
	    send_to_char("Line too long.\n\r",ch);
	    return;
	}
	else
	{
	    free_string( obj->chpoweruse );
	    strcat( buf, "\n\r" );
	    strcat( buf, arg3 );
	    obj->chpoweruse = str_dup( buf );

	    argument = one_argument( argument, arg1 );
	    strcpy( arg2, argument );

	    if (!IS_CLASS(ch, CLASS_MAGE) && !IS_IMMORTAL(ch) 
		&& !IS_SET(obj->spectype, ADV_FINISHED))
		SET_BIT(obj->spectype, ADV_FAILED);
	    else if (!str_cmp(arg1,"start.damage.spell") && obj->spectype == 0)
		{SET_BIT(obj->spectype, ADV_STARTED);
		SET_BIT(obj->spectype, ADV_DAMAGE);}
	    else if (!str_cmp(arg1,"start.affect.spell") && obj->spectype == 0)
		{SET_BIT(obj->spectype, ADV_STARTED);
		SET_BIT(obj->spectype, ADV_AFFECT);}
	    else if (!str_cmp(arg1,"start.action.spell") && obj->spectype == 0)
		{SET_BIT(obj->spectype, ADV_STARTED);
		SET_BIT(obj->spectype, ADV_ACTION);}
	    else if (!str_cmp(arg1,"start.spell") && obj->spectype == 0)
		SET_BIT(obj->spectype, ADV_STARTED);
	    else if (!str_cmp(arg1,"end.spell") 
		&& IS_SET(obj->spectype, ADV_STARTED) 
		&& !IS_SET(obj->spectype, ADV_FINISHED))
	    {
		SET_BIT(obj->spectype, ADV_FINISHED);
		obj->toughness = ch->pcdata->powers[MPOWER_RUNE0];
		obj->points += 1;
	    }
	    else if (!str_cmp(arg1,"damage.spell") 
		&& IS_SET(obj->spectype, ADV_STARTED) 
		&& !IS_SET(obj->spectype, ADV_DAMAGE)
		&& !IS_SET(obj->spectype, ADV_AFFECT)
		&& !IS_SET(obj->spectype, ADV_ACTION)
		&& !IS_SET(obj->spectype, ADV_FINISHED))
		SET_BIT(obj->spectype, ADV_DAMAGE);
	    else if (!str_cmp(arg1,"affect.spell") 
		&& IS_SET(obj->spectype, ADV_STARTED) 
		&& !IS_SET(obj->spectype, ADV_DAMAGE)
		&& !IS_SET(obj->spectype, ADV_AFFECT)
		&& !IS_SET(obj->spectype, ADV_ACTION)
		&& !IS_SET(obj->spectype, ADV_FINISHED))
		SET_BIT(obj->spectype, ADV_AFFECT);
	    else if (!str_cmp(arg1,"action.spell") 
		&& IS_SET(obj->spectype, ADV_STARTED) 
		&& !IS_SET(obj->spectype, ADV_DAMAGE)
		&& !IS_SET(obj->spectype, ADV_AFFECT)
		&& !IS_SET(obj->spectype, ADV_ACTION)
		&& !IS_SET(obj->spectype, ADV_FINISHED))
		SET_BIT(obj->spectype, ADV_AFFECT);
	    else if (!str_cmp(arg1,"area.affect") 
		&& IS_SET(obj->spectype, ADV_STARTED) 
		&& !IS_SET(obj->spectype, ADV_AREA_AFFECT)
		&& !IS_SET(obj->spectype, ADV_FINISHED))
		{SET_BIT(obj->spectype, ADV_AREA_AFFECT);obj->points += 100;}
	    else if (!str_cmp(arg1,"victim.target") 
		&& IS_SET(obj->spectype, ADV_STARTED) 
		&& !IS_SET(obj->spectype, ADV_VICTIM_TARGET)
		&& !IS_SET(obj->spectype, ADV_FINISHED))
		{SET_BIT(obj->spectype, ADV_VICTIM_TARGET);obj->points += 5;}
	    else if (!str_cmp(arg1,"object.target") 
		&& IS_SET(obj->spectype, ADV_STARTED) 
		&& !IS_SET(obj->spectype, ADV_OBJECT_TARGET)
		&& !IS_SET(obj->spectype, ADV_FINISHED))
		{SET_BIT(obj->spectype, ADV_OBJECT_TARGET);obj->points += 5;}
	    else if (!str_cmp(arg1,"global.target") 
		&& IS_SET(obj->spectype, ADV_STARTED) 
		&& !IS_SET(obj->spectype, ADV_GLOBAL_TARGET)
		&& !IS_SET(obj->spectype, ADV_FINISHED))
		{SET_BIT(obj->spectype, ADV_GLOBAL_TARGET);obj->points += 50;}
	    else if (!str_cmp(arg1,"next.page") 
		&& IS_SET(obj->spectype, ADV_STARTED) 
		&& !IS_SET(obj->spectype, ADV_NEXT_PAGE)
		&& !IS_SET(obj->spectype, ADV_FINISHED))
		{SET_BIT(obj->spectype, ADV_NEXT_PAGE);obj->points += 5;}
	    else if (!str_cmp(arg1,"parameter:") 
		&& IS_SET(obj->spectype, ADV_STARTED) 
		&& !IS_SET(obj->spectype, ADV_PARAMETER)
		&& !IS_SET(obj->spectype, ADV_FINISHED))
	    {
		if ( arg2[0] == '\0' )
		    SET_BIT(obj->spectype, ADV_FAILED);
		else
		{
		    SET_BIT(obj->spectype, ADV_PARAMETER);
		    free_string(obj->chpoweron);
		    obj->chpoweron = str_dup(arg2);
		}
	    }
	    else if (!str_cmp(arg1,"spell.first") 
		&& IS_SET(obj->spectype, ADV_STARTED) 
		&& !IS_SET(obj->spectype, ADV_SPELL_FIRST)
		&& !IS_SET(obj->spectype, ADV_FINISHED))
		SET_BIT(obj->spectype, ADV_SPELL_FIRST);
	    else if (!str_cmp(arg1,"not.caster") 
		&& IS_SET(obj->spectype, ADV_STARTED) 
		&& !IS_SET(obj->spectype, ADV_NOT_CASTER)
		&& !IS_SET(obj->spectype, ADV_FINISHED))
		SET_BIT(obj->spectype, ADV_NOT_CASTER);
	    else if (!str_cmp(arg1,"no.players") 
		&& IS_SET(obj->spectype, ADV_STARTED) 
		&& !IS_SET(obj->spectype, ADV_NO_PLAYERS)
		&& !IS_SET(obj->spectype, ADV_FINISHED))
		SET_BIT(obj->spectype, ADV_NO_PLAYERS);
	    else if (!str_cmp(arg1,"second.victim") 
		&& IS_SET(obj->spectype, ADV_STARTED) 
		&& !IS_SET(obj->spectype, ADV_SECOND_VICTIM)
		&& !IS_SET(obj->spectype, ADV_FINISHED))
		{SET_BIT(obj->spectype, ADV_SECOND_VICTIM);obj->points += 5;}
	    else if (!str_cmp(arg1,"second.object") 
		&& IS_SET(obj->spectype, ADV_STARTED) 
		&& !IS_SET(obj->spectype, ADV_SECOND_OBJECT)
		&& !IS_SET(obj->spectype, ADV_FINISHED))
		{SET_BIT(obj->spectype, ADV_SECOND_OBJECT);obj->points += 5;}
	    else if (!str_cmp(arg1,"reversed")
		&& IS_SET(obj->spectype, ADV_STARTED) 
		&& !IS_SET(obj->spectype, ADV_REVERSED)
		&& !IS_SET(obj->spectype, ADV_FINISHED))
		SET_BIT(obj->spectype, ADV_REVERSED);
	    else if (!str_cmp(arg1,"min.damage:")
		&& IS_SET(obj->spectype, ADV_STARTED) 
		&& IS_SET(obj->spectype, ADV_DAMAGE)
		&& !IS_SET(obj->spectype, ADV_FINISHED))
	    {
		if ( arg2[0] == '\0' || !is_number(arg2) || 
		    atoi(arg2) < 0 || atoi(arg2) > 500)
		    SET_BIT(obj->spectype, ADV_FAILED);
		else {obj->value[1] = atoi(arg2);obj->points += (atoi(arg2)*0.5);}
	    }
	    else if (!str_cmp(arg1,"max.damage:")
		&& IS_SET(obj->spectype, ADV_STARTED) 
		&& IS_SET(obj->spectype, ADV_DAMAGE)
		&& !IS_SET(obj->spectype, ADV_FINISHED))
	    {
		if ( arg2[0] == '\0' || !is_number(arg2) || 
		    atoi(arg2) < 0 || atoi(arg2) > 1000)
		    SET_BIT(obj->spectype, ADV_FAILED);
		else {obj->value[2] = atoi(arg2);obj->points += (atoi(arg2)*0.5);}
	    }
	    else if (!str_cmp(arg1,"move")
		&& IS_SET(obj->spectype, ADV_STARTED) 
		&& IS_SET(obj->spectype, ADV_ACTION)
		&& obj->value[1] == ACTION_NONE
		&& !IS_SET(obj->spectype, ADV_FINISHED))
		{obj->value[1] = ACTION_MOVE;obj->points += 500;}
	    else if (!str_cmp(arg1,"mob:")
		&& IS_SET(obj->spectype, ADV_STARTED) 
		&& IS_SET(obj->spectype, ADV_ACTION)
		&& obj->value[1] == ACTION_NONE
		&& !IS_SET(obj->spectype, ADV_FINISHED))
	    {
		obj->value[1] = ACTION_MOB;
		if ( arg2[0] == '\0' ||
		    ( mobile = get_char_world2( ch, arg2 ) ) == NULL)
		    SET_BIT(obj->spectype, ADV_FAILED);
		else {obj->value[2] = mobile->pIndexData->vnum;obj->points += 500;}
	    }
	    else if (!str_cmp(arg1,"object:")
		&& IS_SET(obj->spectype, ADV_STARTED) 
		&& IS_SET(obj->spectype, ADV_ACTION)
		&& obj->value[1] == ACTION_NONE
		&& !IS_SET(obj->spectype, ADV_FINISHED))
	    {
		obj->value[1] = ACTION_OBJECT;
		if ( arg2[0] == '\0' ||
		    ( object = get_obj_world2( ch, arg2 ) ) == NULL)
		    SET_BIT(obj->spectype, ADV_FAILED);
		else if (IS_SET(object->quest, QUEST_ARTIFACT))
		    SET_BIT(object->spectype, ADV_FAILED);
		else if (strlen(object->questowner) > 2)
		    SET_BIT(object->spectype, ADV_FAILED);
		else {obj->value[2] = object->pIndexData->vnum;obj->points += 500;}
	    }
	    else if (!str_cmp(arg1,"apply:")
		&& IS_SET(obj->spectype, ADV_STARTED) 
		&& IS_SET(obj->spectype, ADV_AFFECT)
		&& !IS_SET(obj->spectype, ADV_FINISHED))
	    {
		if ( arg2[0] == '\0' )
		    SET_BIT(obj->spectype, ADV_FAILED);
		else if ((!str_cmp(arg2,"strength") || !str_cmp(arg2,"str")) && 
		    !IS_SET(obj->value[1], ADV_STR))
		    SET_BIT(obj->value[1], ADV_STR);
		else if ((!str_cmp(arg2,"dexterity") || !str_cmp(arg2,"dex")) && 
		    !IS_SET(obj->value[1], ADV_DEX))
		    SET_BIT(obj->value[1], ADV_DEX);
		else if ((!str_cmp(arg2,"intelligence") || !str_cmp(arg2,"int")) && 
		    !IS_SET(obj->value[1], ADV_INT))
		    SET_BIT(obj->value[1], ADV_INT);
		else if ((!str_cmp(arg2,"wisdom") || !str_cmp(arg2,"wis")) && 
		    !IS_SET(obj->value[1], ADV_WIS))
		    SET_BIT(obj->value[1], ADV_WIS);
		else if ((!str_cmp(arg2,"constitution") || !str_cmp(arg2,"con")) && 
		    !IS_SET(obj->value[1], ADV_CON))
		    SET_BIT(obj->value[1], ADV_CON);
		else if (!str_cmp(arg2,"mana") && 
		    !IS_SET(obj->value[1], ADV_MANA))
		    SET_BIT(obj->value[1], ADV_MANA);
		else if ((!str_cmp(arg2,"hp") || !str_cmp(arg2,"hits") || 
		    !str_cmp(arg2,"hitpoints")) && 
		    !IS_SET(obj->value[1], ADV_HIT))
		    SET_BIT(obj->value[1], ADV_HIT);
		else if ((!str_cmp(arg2,"move") || !str_cmp(arg2,"movement")) && 
		    !IS_SET(obj->value[1], ADV_MOVE))
		    SET_BIT(obj->value[1], ADV_MOVE);
		else if ((!str_cmp(arg2,"ac") || !str_cmp(arg2,"armour") ||
		    !str_cmp(arg2,"armor")) && 
		    !IS_SET(obj->value[1], ADV_AC))
		    SET_BIT(obj->value[1], ADV_AC);
		else if ((!str_cmp(arg2,"hr") || !str_cmp(arg2,"hit") ||
		    !str_cmp(arg2,"hitroll")) && 
		    !IS_SET(obj->value[1], ADV_HITROLL))
		    SET_BIT(obj->value[1], ADV_HITROLL);
		else if ((!str_cmp(arg2,"dr") || !str_cmp(arg2,"dam") ||
		    !str_cmp(arg2,"damroll")) && 
		    !IS_SET(obj->value[1], ADV_DAMROLL))
		    SET_BIT(obj->value[1], ADV_DAMROLL);
		else if ((!str_cmp(arg2,"save") || !str_cmp(arg2,"save.spell") ||
		    !str_cmp(arg2,"save_spell")) && 
		    !IS_SET(obj->value[1], ADV_SAVING_SPELL))
		    SET_BIT(obj->value[1], ADV_SAVING_SPELL);
		else {SET_BIT(obj->spectype, ADV_FAILED);return;}
		obj->points += 25;
	    }
	    else if (!str_cmp(arg1,"affect:")
		&& IS_SET(obj->spectype, ADV_STARTED) 
		&& IS_SET(obj->spectype, ADV_AFFECT)
		&& !IS_SET(obj->spectype, ADV_FINISHED))
	    {
		if ( arg2[0] == '\0' )
		    SET_BIT(obj->spectype, ADV_FAILED);
		else if ((!str_cmp(arg2,"blind") || !str_cmp(arg2,"blindness")) && 
		    !IS_SET(obj->value[3], AFF_BLIND))
		    SET_BIT(obj->value[3], AFF_BLIND);
		else if ((!str_cmp(arg2,"invis") || !str_cmp(arg2,"invisible")
		    || !str_cmp(arg2,"invisibility")) && 
		    !IS_SET(obj->value[3], AFF_BLIND))
		    SET_BIT(obj->value[3], AFF_BLIND);
		else if (!str_cmp(arg2,"detect.evil") && 
		    !IS_SET(obj->value[3], AFF_DETECT_EVIL))
		    SET_BIT(obj->value[3], AFF_DETECT_EVIL);
		else if ((!str_cmp(arg2,"detect.invis") || !str_cmp(arg2,"detect.invisible")
		    || !str_cmp(arg2,"detect.invisibility")) && 
		    !IS_SET(obj->value[3], AFF_DETECT_INVIS))
		    SET_BIT(obj->value[3], AFF_DETECT_INVIS);
		else if (!str_cmp(arg2,"detect.magic") && 
		    !IS_SET(obj->value[3], AFF_DETECT_MAGIC))
		    SET_BIT(obj->value[3], AFF_DETECT_MAGIC);
		else if (!str_cmp(arg2,"detect.hidden") && 
		    !IS_SET(obj->value[3], AFF_DETECT_HIDDEN))
		    SET_BIT(obj->value[3], AFF_DETECT_HIDDEN);
		else if ((!str_cmp(arg2,"shadowplane") || 
		    !str_cmp(arg2,"shadow.plane")) && 
		    !IS_SET(obj->value[3], AFF_SHADOWPLANE))
		    SET_BIT(obj->value[3], AFF_SHADOWPLANE);
		else if ((!str_cmp(arg2,"sanct") || 
		    !str_cmp(arg2,"sanctuary")) && 
		    !IS_SET(obj->value[3], AFF_SANCTUARY))
		    SET_BIT(obj->value[3], AFF_SANCTUARY);
		else if (!str_cmp(arg2,"faerie.fire") && 
		    !IS_SET(obj->value[3], AFF_FAERIE_FIRE))
		    SET_BIT(obj->value[3], AFF_FAERIE_FIRE);
		else if ((!str_cmp(arg2,"infravision") || 
		    !str_cmp(arg2,"infrared") || !str_cmp(arg2,"infra")) && 
		    !IS_SET(obj->value[3], AFF_SANCTUARY))
		    SET_BIT(obj->value[3], AFF_SANCTUARY);
		else if (!str_cmp(arg2,"curse") && 
		    !IS_SET(obj->value[3], AFF_CURSE))
		    SET_BIT(obj->value[3], AFF_CURSE);
		else if ((!str_cmp(arg2,"flaming") || !str_cmp(arg2,"burning"))
		    && !IS_SET(obj->value[3], AFF_FLAMING))
		    SET_BIT(obj->value[3], AFF_FLAMING);
		else if (!str_cmp(arg2,"poison") && 
		    !IS_SET(obj->value[3], AFF_POISON))
		    SET_BIT(obj->value[3], AFF_POISON);
		else if ((!str_cmp(arg2,"protect") || !str_cmp(arg2,"protection"))
		    && !IS_SET(obj->value[3], AFF_PROTECT))
		    SET_BIT(obj->value[3], AFF_PROTECT);
		else if (!str_cmp(arg2,"ethereal") && 
		    !IS_SET(obj->value[3], AFF_ETHEREAL))
		    SET_BIT(obj->value[3], AFF_ETHEREAL);
		else if (!str_cmp(arg2,"sneak") && 
		    !IS_SET(obj->value[3], AFF_SNEAK))
		    SET_BIT(obj->value[3], AFF_SNEAK);
		else if (!str_cmp(arg2,"hide") && 
		    !IS_SET(obj->value[3], AFF_HIDE))
		    SET_BIT(obj->value[3], AFF_HIDE);
		else if (!str_cmp(arg2,"sleep") && 
		    !IS_SET(obj->value[3], AFF_SLEEP))
		    SET_BIT(obj->value[3], AFF_SLEEP);/*
		else if (!str_cmp(arg2,"charm") && 
		    !IS_SET(obj->value[3], AFF_CHARM))
		    SET_BIT(obj->value[3], AFF_CHARM);*/
		else if ((!str_cmp(arg2,"fly") || !str_cmp(arg2,"flying"))
		    && !IS_SET(obj->value[3], AFF_FLYING))
		    SET_BIT(obj->value[3], AFF_FLYING);
		else if ((!str_cmp(arg2,"passdoor") || !str_cmp(arg2,"pass.door"))
		    && !IS_SET(obj->value[3], AFF_PASS_DOOR))
		    SET_BIT(obj->value[3], AFF_PASS_DOOR);
		else if ((!str_cmp(arg2,"shadowsight") || 
		    !str_cmp(arg2,"shadow.sight")) && 
		    !IS_SET(obj->value[3], AFF_SHADOWSIGHT))
		    SET_BIT(obj->value[3], AFF_SHADOWSIGHT);
		else if ((!str_cmp(arg2,"web") || !str_cmp(arg2,"webbed"))
		    && !IS_SET(obj->value[3], AFF_WEBBED))
		    SET_BIT(obj->value[3], AFF_WEBBED);
/*
		else if (!str_cmp(arg2,"contraception") && 
		    !IS_SET(obj->value[3], AFF_CONTRACEPTION))
		    SET_BIT(obj->value[3], AFF_CONTRACEPTION);
*/
		else {SET_BIT(obj->spectype, ADV_FAILED);return;}
		obj->points += 25;
	    }
	    else if (!str_cmp(arg1,"bonus:")
		&& IS_SET(obj->spectype, ADV_STARTED) 
		&& IS_SET(obj->spectype, ADV_AFFECT)
		&& !IS_SET(obj->spectype, ADV_FINISHED))
	    {
		if ( arg2[0] == '\0' || !is_number(arg2) || 
		    atoi(arg2) < 0 || atoi(arg2) > 100)
		    SET_BIT(obj->spectype, ADV_FAILED);
		else {obj->value[2] = atoi(arg2);obj->points += (atoi(arg2)*15);}
	    }
	    else if (!str_cmp(arg1,"duration:")
		&& IS_SET(obj->spectype, ADV_STARTED) 
		&& IS_SET(obj->spectype, ADV_AFFECT)
		&& obj->level == 0
		&& !IS_SET(obj->spectype, ADV_FINISHED))
	    {
		if ( arg2[0] == '\0' || !is_number(arg2) || 
		    atoi(arg2) < 1 || atoi(arg2) > 60)
		    SET_BIT(obj->spectype, ADV_FAILED);
		else {obj->level = atoi(arg2);obj->points += (atoi(arg2)*10);}
	    }
	    else if ((!str_cmp(arg1,"message.one:") || !str_cmp(arg1,"message.1:")) 
		&& IS_SET(obj->spectype, ADV_STARTED) 
		&& !IS_SET(obj->spectype, ADV_MESSAGE_1)
		&& !IS_SET(obj->spectype, ADV_FINISHED))
	    {
		if ( arg2[0] == '\0' )
		    SET_BIT(obj->spectype, ADV_FAILED);
		else
		{
		    SET_BIT(obj->spectype, ADV_MESSAGE_1);
		    free_string(obj->chpoweroff);
		    obj->chpoweroff = str_dup(arg2);
		}
	    }
	    else if ((!str_cmp(arg1,"message.two:") || !str_cmp(arg1,"message.2:")) 
		&& IS_SET(obj->spectype, ADV_STARTED) 
		&& !IS_SET(obj->spectype, ADV_MESSAGE_2)
		&& !IS_SET(obj->spectype, ADV_FINISHED))
	    {
		if ( arg2[0] == '\0' )
		    SET_BIT(obj->spectype, ADV_FAILED);
		else
		{
		    SET_BIT(obj->spectype, ADV_MESSAGE_2);
		    free_string(obj->victpoweron);
		    obj->victpoweron = str_dup(arg2);
		}
	    }
	    else if ((!str_cmp(arg1,"message.three:") || !str_cmp(arg1,"message.3:")) 
		&& IS_SET(obj->spectype, ADV_STARTED) 
		&& !IS_SET(obj->spectype, ADV_MESSAGE_3)
		&& !IS_SET(obj->spectype, ADV_FINISHED))
	    {
		if ( arg2[0] == '\0' )
		    SET_BIT(obj->spectype, ADV_FAILED);
		else
		{
		    SET_BIT(obj->spectype, ADV_MESSAGE_3);
		    free_string(obj->victpoweroff);
		    obj->victpoweroff = str_dup(arg2);
		}
	    }
	    else if (!IS_SET(obj->spectype, ADV_FINISHED))
		SET_BIT(obj->spectype, ADV_FAILED);
	}
    }
    else return;
    act("$n writes something on $p.",ch,obj,NULL,TO_ROOM);
    send_to_char("Ok.\n\r",ch);
    return;
}

void show_page( CHAR_DATA *ch, OBJ_DATA *book, int pnum, bool pagefalse )
{
    OBJ_DATA *page;
    OBJ_DATA *page_next;
    char buf[MAX_STRING_LENGTH];
    bool found = FALSE;

    for ( page = book->contains; page != NULL; page = page_next )
    {
	page_next = page->next_content;
	if (page->value[0] == pnum)
	{
	    found = TRUE;
	    if (!str_cmp(page->victpoweruse,"(null)"))
		sprintf(buf,"Untitled page.\n\r");
	    else
		sprintf(buf,"%s.\n\r",page->victpoweruse);
	    buf[0] = UPPER(buf[0]);
	    send_to_char(buf,ch);
	    if (!pagefalse)
	    {
		if (page->chpoweruse == NULL || page->chpoweruse == '\0' ||
			!str_cmp(page->chpoweruse,"(null)"))
		{
		    if (!are_runes(page))
			send_to_char("This page is blank.\n\r",ch);
		    else if (IS_AFFECTED(ch, AFF_DETECT_MAGIC) && 
			!IS_SET(page->quest, QUEST_MASTER_RUNE) &&
			!IS_SET(page->spectype, ADV_STARTED))
			show_runes(ch, page, FALSE);
		    else
			send_to_char("This page is blank.\n\r",ch);
		    return;
		}
		send_to_char("--------------------------------------------------------------------------------\n\r",ch);
		send_to_char(page->chpoweruse,ch);
		send_to_char("\n\r--------------------------------------------------------------------------------\n\r",ch);
		if (IS_AFFECTED(ch, AFF_DETECT_MAGIC) && 
		    !IS_SET(page->quest, QUEST_MASTER_RUNE) && 
		    !IS_SET(page->spectype, ADV_STARTED))
		    show_runes(ch, page, TRUE);
	    }
	}
    }
    if (!found)
	send_to_char("This page has been torn out.\n\r",ch);
    return;
}

void show_runes( CHAR_DATA *ch, OBJ_DATA *page, bool endline )
{
    if (page->value[1] + page->value[2] + page->value[3] < 1) return;
    send_to_char("This page contains the following symbols:\n\r",ch);
    send_to_char("Runes:",ch);
    if (page->value[1] > 0)
    {
	if (IS_SET(page->value[1], RUNE_FIRE  )) send_to_char(" Fire",  ch);
	if (IS_SET(page->value[1], RUNE_AIR   )) send_to_char(" Air",   ch);
	if (IS_SET(page->value[1], RUNE_EARTH )) send_to_char(" Earth", ch);
	if (IS_SET(page->value[1], RUNE_WATER )) send_to_char(" Water", ch);
	if (IS_SET(page->value[1], RUNE_DARK  )) send_to_char(" Dark",  ch);
	if (IS_SET(page->value[1], RUNE_LIGHT )) send_to_char(" Light", ch);
	if (IS_SET(page->value[1], RUNE_LIFE  )) send_to_char(" Life",  ch);
	if (IS_SET(page->value[1], RUNE_DEATH )) send_to_char(" Death", ch);
	if (IS_SET(page->value[1], RUNE_MIND  )) send_to_char(" Mind",  ch);
	if (IS_SET(page->value[1], RUNE_SPIRIT)) send_to_char(" Spirit",ch);
    }
    else send_to_char(" None",ch);
    send_to_char(".\n\r",ch);
    send_to_char("Glyphs:",ch);
    if (page->value[2] > 0)
    {
	if (IS_SET(page->value[2], GLYPH_CREATION)) send_to_char(" Creation", ch);
	if (IS_SET(page->value[2], GLYPH_DESTRUCTION)) send_to_char(" Destruction",  ch);
	if (IS_SET(page->value[2], GLYPH_SUMMONING)) send_to_char(" Summoning",ch);
	if (IS_SET(page->value[2], GLYPH_TRANSFORMATION)) send_to_char(" Transformation",ch);
	if (IS_SET(page->value[2], GLYPH_TRANSPORTATION)) send_to_char(" Transportation", ch);
	if (IS_SET(page->value[2], GLYPH_ENHANCEMENT)) send_to_char(" Enhancement",ch);
	if (IS_SET(page->value[2], GLYPH_REDUCTION )) send_to_char(" Reduction", ch);
	if (IS_SET(page->value[2], GLYPH_CONTROL)) send_to_char(" Control",ch);
	if (IS_SET(page->value[2], GLYPH_PROTECTION)) send_to_char(" Protection",ch);
	if (IS_SET(page->value[2], GLYPH_INFORMATION)) send_to_char(" Information",ch);
    }
    else send_to_char(" None",ch);
    send_to_char(".\n\r",ch);
    send_to_char("Sigils:",ch);
    if (page->value[3] > 0)
    {
	if (IS_SET(page->value[3], SIGIL_SELF      )) send_to_char(" Self", ch);
	if (IS_SET(page->value[3], SIGIL_TARGETING )) send_to_char(" Targeting", ch);
	if (IS_SET(page->value[3], SIGIL_AREA      )) send_to_char(" Area", ch);
	if (IS_SET(page->value[3], SIGIL_OBJECT    )) send_to_char(" Object", ch);
    }
    else send_to_char(" None",ch);
    send_to_char(".\n\r",ch);
    if (endline) send_to_char("--------------------------------------------------------------------------------\n\r",ch);
    return;
}

bool are_runes( OBJ_DATA *page )
{
    if (page->value[1] + page->value[2] + page->value[3] < 1) return FALSE;
    return TRUE;
}

bool has_key( CHAR_DATA *ch, int key )
{
    OBJ_DATA *obj;

    for ( obj = ch->carrying; obj != NULL; obj = obj->next_content )
    {
	if ( obj->pIndexData->vnum == key )
	    return TRUE;
    }

    return FALSE;
}



void do_lock( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;
    int door;

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char( "Lock what?\n\r", ch );
	return;
    }

    if ( ( obj = get_obj_here( ch, arg ) ) != NULL )
    {
	/* 'lock object' */
	if ( obj->item_type != ITEM_CONTAINER )
	    { send_to_char( "That's not a container.\n\r", ch ); return; }
	if ( !IS_SET(obj->value[1], CONT_CLOSED) )
	    { send_to_char( "It's not closed.\n\r",        ch ); return; }
	if ( obj->value[2] < 0 )
	    { send_to_char( "It can't be locked.\n\r",     ch ); return; }
	if ( !has_key( ch, obj->value[2] ) )
	    { send_to_char( "You lack the key.\n\r",       ch ); return; }
	if ( IS_SET(obj->value[1], CONT_LOCKED) )
	    { send_to_char( "It's already locked.\n\r",    ch ); return; }

	SET_BIT(obj->value[1], CONT_LOCKED);
	send_to_char( "*Click*\n\r", ch );
	act( "$n locks $p.", ch, obj, NULL, TO_ROOM );
	return;
    }

    if ( ( door = find_door( ch, arg ) ) >= 0 )
    {
	/* 'lock door' */
	ROOM_INDEX_DATA *to_room;
	EXIT_DATA *pexit;
	EXIT_DATA *pexit_rev;

	pexit	= ch->in_room->exit[door];
	if ( !IS_SET(pexit->exit_info, EX_CLOSED) )
	    { send_to_char( "It's not closed.\n\r",        ch ); return; }
	if ( pexit->key < 0 )
	    { send_to_char( "It can't be locked.\n\r",     ch ); return; }
	if ( !has_key( ch, pexit->key) )
	    { send_to_char( "You lack the key.\n\r",       ch ); return; }
	if ( IS_SET(pexit->exit_info, EX_LOCKED) )
	    { send_to_char( "It's already locked.\n\r",    ch ); return; }

	SET_BIT(pexit->exit_info, EX_LOCKED);
	send_to_char( "*Click*\n\r", ch );
	act( "$n locks the $d.", ch, NULL, pexit->keyword, TO_ROOM );

	/* lock the other side */
	if ( ( to_room   = pexit->to_room               ) != NULL
	&&   ( pexit_rev = to_room->exit[rev_dir[door]] ) != 0
	&&   pexit_rev->to_room == ch->in_room )
	{
	    SET_BIT( pexit_rev->exit_info, EX_LOCKED );
	}
    }

    return;
}



void do_unlock( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;
    int door;

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char( "Unlock what?\n\r", ch );
	return;
    }

    if ( ( obj = get_obj_here( ch, arg ) ) != NULL )
    {
	/* 'unlock object' */
	if ( obj->item_type != ITEM_CONTAINER )
	    { send_to_char( "That's not a container.\n\r", ch ); return; }
	if ( !IS_SET(obj->value[1], CONT_CLOSED) )
	    { send_to_char( "It's not closed.\n\r",        ch ); return; }
	if ( obj->value[2] < 0 )
	    { send_to_char( "It can't be unlocked.\n\r",   ch ); return; }
	if ( !has_key( ch, obj->value[2] ) )
	    { send_to_char( "You lack the key.\n\r",       ch ); return; }
	if ( !IS_SET(obj->value[1], CONT_LOCKED) )
	    { send_to_char( "It's already unlocked.\n\r",  ch ); return; }

	REMOVE_BIT(obj->value[1], CONT_LOCKED);
	send_to_char( "*Click*\n\r", ch );
	act( "$n unlocks $p.", ch, obj, NULL, TO_ROOM );
	return;
    }

    if ( ( door = find_door( ch, arg ) ) >= 0 )
    {
	/* 'unlock door' */
	ROOM_INDEX_DATA *to_room;
	EXIT_DATA *pexit;
	EXIT_DATA *pexit_rev;

	pexit = ch->in_room->exit[door];
	if ( !IS_SET(pexit->exit_info, EX_CLOSED) )
	    { send_to_char( "It's not closed.\n\r",        ch ); return; }
	if ( pexit->key < 0 )
	    { send_to_char( "It can't be unlocked.\n\r",   ch ); return; }
	if ( !has_key( ch, pexit->key) )
	    { send_to_char( "You lack the key.\n\r",       ch ); return; }
	if ( !IS_SET(pexit->exit_info, EX_LOCKED) )
	    { send_to_char( "It's already unlocked.\n\r",  ch ); return; }

	REMOVE_BIT(pexit->exit_info, EX_LOCKED);
	send_to_char( "*Click*\n\r", ch );
	act( "$n unlocks the $d.", ch, NULL, pexit->keyword, TO_ROOM );

	/* unlock the other side */
	if ( ( to_room   = pexit->to_room               ) != NULL
	&&   ( pexit_rev = to_room->exit[rev_dir[door]] ) != NULL
	&&   pexit_rev->to_room == ch->in_room )
	{
	    REMOVE_BIT( pexit_rev->exit_info, EX_LOCKED );
	}
    }

    return;
}



void do_pick( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *gch;
    OBJ_DATA *obj;
    int door;

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char( "Pick what?\n\r", ch );
	return;
    }

    WAIT_STATE( ch, skill_table[gsn_pick_lock].beats );

    /* look for guards */
    for ( gch = ch->in_room->people; gch; gch = gch->next_in_room )
    {
	if ( IS_NPC(gch) && IS_AWAKE(gch) && ch->level + 5 < gch->level )
	{
	    act( "$N is standing too close to the lock.",
		ch, NULL, gch, TO_CHAR );
	    return;
	}
    }

    if ( !IS_NPC(ch) && number_percent( ) > ch->pcdata->learned[gsn_pick_lock] )
    {
	send_to_char( "You failed.\n\r", ch);
	return;
    }

    if ( ( obj = get_obj_here( ch, arg ) ) != NULL )
    {
	/* 'pick object' */
	if ( obj->item_type != ITEM_CONTAINER )
	    { send_to_char( "That's not a container.\n\r", ch ); return; }
	if ( !IS_SET(obj->value[1], CONT_CLOSED) )
	    { send_to_char( "It's not closed.\n\r",        ch ); return; }
	if ( obj->value[2] < 0 )
	    { send_to_char( "It can't be unlocked.\n\r",   ch ); return; }
	if ( !IS_SET(obj->value[1], CONT_LOCKED) )
	    { send_to_char( "It's already unlocked.\n\r",  ch ); return; }
	if ( IS_SET(obj->value[1], CONT_PICKPROOF) )
	    { send_to_char( "You failed.\n\r",             ch ); return; }

	REMOVE_BIT(obj->value[1], CONT_LOCKED);
	send_to_char( "*Click*\n\r", ch );
	act( "$n picks $p.", ch, obj, NULL, TO_ROOM );
	return;
    }

    if ( ( door = find_door( ch, arg ) ) >= 0 )
    {
	/* 'pick door' */
	ROOM_INDEX_DATA *to_room;
	EXIT_DATA *pexit;
	EXIT_DATA *pexit_rev;

	pexit = ch->in_room->exit[door];
	if ( !IS_SET(pexit->exit_info, EX_CLOSED) )
	    { send_to_char( "It's not closed.\n\r",        ch ); return; }
	if ( pexit->key < 0 )
	    { send_to_char( "It can't be picked.\n\r",     ch ); return; }
	if ( !IS_SET(pexit->exit_info, EX_LOCKED) )
	    { send_to_char( "It's already unlocked.\n\r",  ch ); return; }
	if ( IS_SET(pexit->exit_info, EX_PICKPROOF) )
	    { send_to_char( "You failed.\n\r",             ch ); return; }

	REMOVE_BIT(pexit->exit_info, EX_LOCKED);
	send_to_char( "*Click*\n\r", ch );
	act( "$n picks the $d.", ch, NULL, pexit->keyword, TO_ROOM );

	/* pick the other side */
	if ( ( to_room   = pexit->to_room               ) != NULL
	&&   ( pexit_rev = to_room->exit[rev_dir[door]] ) != NULL
	&&   pexit_rev->to_room == ch->in_room )
	{
	    REMOVE_BIT( pexit_rev->exit_info, EX_LOCKED );
	}
    }

    return;
}




void do_stand( CHAR_DATA *ch, char *argument )
{
    switch ( ch->position )
    {
    case POS_SLEEPING:
	if ( IS_AFFECTED(ch, AFF_SLEEP) )
	    { send_to_char( "You can't wake up!\n\r", ch ); return; }

	send_to_char( "You wake and stand up.\n\r", ch );
	act( "$n wakes and stands up.", ch, NULL, NULL, TO_ROOM );
	ch->position = POS_STANDING;
	break;

    case POS_RESTING:
    case POS_SITTING:
	send_to_char( "You stand up.\n\r", ch );
	act( "$n stands up.", ch, NULL, NULL, TO_ROOM );
	ch->position = POS_STANDING;
	break;

    case POS_MEDITATING:
	send_to_char( "You uncross your legs and stand up.\n\r", ch );
	act( "$n uncrosses $s legs and stands up.", ch, NULL, NULL, TO_ROOM );
	ch->position = POS_STANDING;
	break;

    case POS_STANDING:
	send_to_char( "You are already standing.\n\r", ch );
	break;

    case POS_FIGHTING:
	send_to_char( "You are already fighting!\n\r", ch );
	break;
    }

    return;
}



void do_rest( CHAR_DATA *ch, char *argument )
{
    switch ( ch->position )
    {
    case POS_SLEEPING:
	send_to_char( "You are already sleeping.\n\r", ch );
	break;

    case POS_RESTING:
	send_to_char( "You are already resting.\n\r", ch );
	break;

    case POS_MEDITATING:
    case POS_SITTING:
    case POS_STANDING:
	send_to_char( "You rest.\n\r", ch );
	act( "$n rests.", ch, NULL, NULL, TO_ROOM );
	ch->position = POS_RESTING;
	break;

    case POS_FIGHTING:
	send_to_char( "You are already fighting!\n\r", ch );
	break;
    }

    return;
}



void do_sit( CHAR_DATA *ch, char *argument )
{
    switch ( ch->position )
    {
    case POS_SLEEPING:
	send_to_char( "You are already sleeping.\n\r", ch );
	break;

    case POS_RESTING:
	send_to_char( "You are already resting.\n\r", ch );
	break;

    case POS_MEDITATING:
	send_to_char( "You are already meditating.\n\r", ch );
	break;

    case POS_SITTING:
	send_to_char( "You are already sitting.\n\r", ch );
	break;

    case POS_STANDING:
	send_to_char( "You sit down.\n\r", ch );
	act( "$n sits down.", ch, NULL, NULL, TO_ROOM );
	ch->position = POS_SITTING;
	break;

    case POS_FIGHTING:
	send_to_char( "You are already fighting!\n\r", ch );
	break;
    }

    return;
}



void do_meditate( CHAR_DATA *ch, char *argument )
{
    if (IS_NPC(ch) || (!IS_CLASS(ch, CLASS_MAGE) && !IS_CLASS(ch, CLASS_MONK) 
&& !IS_CLASS(ch, CLASS_NINJA) && !IS_CLASS(ch, CLASS_DROW)))
    {
	send_to_char("You are unable to attain the correct state of mind.\n\r",ch);
	return;
    }

    switch ( ch->position )
    {
    case POS_SLEEPING:
	send_to_char( "You are already sleeping.\n\r", ch );
	break;

    case POS_RESTING:
	send_to_char( "You are already resting.\n\r", ch );
	break;

    case POS_MEDITATING:
	send_to_char( "You are already meditating.\n\r", ch );
	break;

    case POS_SITTING:
	send_to_char( "You cross your legs and start meditating.\n\r", ch );
	act( "$n crosses $s legs and starts meditating.", ch, NULL, NULL, TO_ROOM );
	ch->position = POS_MEDITATING;
	break;

    case POS_STANDING:
	send_to_char( "You sit down, cross your legs and start meditating.\n\r", ch );
	act( "$n sits down, crosses $s legs and starts meditating.", ch, NULL, NULL, TO_ROOM );
	ch->position = POS_MEDITATING;
	break;

    case POS_FIGHTING:
	send_to_char( "You are already fighting!\n\r", ch );
	break;
    }

    return;
}

void do_healing( CHAR_DATA *ch, char *argument )
{
    if (IS_NPC(ch) || (!IS_CLASS(ch, CLASS_VAMPIRE) && ch->power[DISC_VAMP_PROT] < 8))
    {
	send_to_char("You are unable to assume a state of healing.\n\r",ch);
	return;
    }

    switch ( ch->position )
    {
    case POS_SLEEPING:
	send_to_char( "You are already sleeping.\n\r", ch );
	break;

    case POS_RESTING:
	send_to_char( "You are already resting.\n\r", ch );
	break;

    case POS_MEDITATING:
	send_to_char( "You are already in a healing position.\n\r", ch );
	break;

    case POS_SITTING:
	send_to_char( "You close your eyes and become completely relaxed.\n\r", ch );
	act( "$n closes $m eyes and looks completely relaxed.", ch, NULL, NULL, TO_ROOM );
	ch->position = POS_MEDITATING;
	break;

    case POS_STANDING:
	send_to_char( "You close your eyes and become completely relaxed.\n\r", ch );
	act( "$n closes $m eyes and looks completely relaxed.", ch, NULL, NULL, TO_ROOM );
	ch->position = POS_MEDITATING;
	break;

    case POS_FIGHTING:
	send_to_char( "You are already fighting!\n\r", ch );
	break;
    }

    return;
}

void do_sleep( CHAR_DATA *ch, char *argument )
{
    switch ( ch->position )
    {
    case POS_SLEEPING:
	send_to_char( "You are already sleeping.\n\r", ch );
	break;

    case POS_SITTING:
    case POS_MEDITATING:
    case POS_RESTING:
    case POS_STANDING: 
	send_to_char( "You sleep.\n\r", ch );
	act( "$n sleeps.", ch, NULL, NULL, TO_ROOM );
	ch->position = POS_SLEEPING;
	break;

    case POS_FIGHTING:
	send_to_char( "You are already fighting!\n\r", ch );
	break;
    }

    return;
}



void do_wake( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;

    one_argument( argument, arg );
    if ( arg[0] == '\0' )
	{ do_stand( ch, argument ); return; }

    if ( !IS_AWAKE(ch) )
	{ send_to_char( "You are asleep yourself!\n\r",       ch ); return; }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
	{ send_to_char( "They aren't here.\n\r",              ch ); return; }

    if ( IS_AWAKE(victim) )
	{ act( "$N is already awake.", ch, NULL, victim, TO_CHAR ); return; }

    if ( IS_AFFECTED(victim, AFF_SLEEP) )
	{ act( "You can't wake $M!",   ch, NULL, victim, TO_CHAR );  return; }

    if (victim->position < POS_SLEEPING)
	{ act( "$E doesn't respond!",   ch, NULL, victim, TO_CHAR );  return; }

    act( "You wake $M.", ch, NULL, victim, TO_CHAR );
    act( "$n wakes you.", ch, NULL, victim, TO_VICT );
    victim->position = POS_STANDING;
    return;
}



void do_sneak( CHAR_DATA *ch, char *argument )
{
    AFFECT_DATA af;

    send_to_char( "You attempt to move silently.\n\r", ch );
    affect_strip( ch, gsn_sneak );

    if ( IS_NPC(ch) || number_percent( ) < ch->pcdata->learned[gsn_sneak] )
    {
	af.type      = gsn_sneak;
	af.duration  = ch->level;
	af.location  = APPLY_NONE;
	af.modifier  = 0;
	af.bitvector = AFF_SNEAK;
	affect_to_char( ch, &af );
    }

    return;
}



void do_hide( CHAR_DATA *ch, char *argument )
{

	if (!IS_NPC(ch) && (IS_CLASS(ch, CLASS_MONK) || IS_CLASS(ch,
		CLASS_NINJA))) {
	send_to_char("You cannot use this power.\n\r", ch );
	return;}

    send_to_char( "You attempt to hide.\n\r", ch );

    if ( IS_AFFECTED(ch, AFF_HIDE) )
	REMOVE_BIT(ch->affected_by, AFF_HIDE);

    if ( IS_NPC(ch) || number_percent( ) < ch->pcdata->learned[gsn_hide] )
	SET_BIT(ch->affected_by, AFF_HIDE);

    return;
}



/*
 * Contributed by Alander.
 */
void do_visible( CHAR_DATA *ch, char *argument )
{
    affect_strip ( ch, gsn_invis			);
    affect_strip ( ch, gsn_mass_invis			);
    affect_strip ( ch, gsn_sneak			);
    REMOVE_BIT   ( ch->affected_by, AFF_HIDE		);
    REMOVE_BIT   ( ch->affected_by, AFF_INVISIBLE	);
    REMOVE_BIT   ( ch->affected_by, AFF_SNEAK		);
    send_to_char( "Ok.\n\r", ch );
    return;
}



void do_unpolymorph( CHAR_DATA *ch, char *argument )
{
    if (!is_affected(ch, gsn_polymorph) )
    {
	send_to_char("But you are not polymorphed!\n\r",ch);
	return;
    }
    act("$n's body begins to distort.",ch,NULL,NULL,TO_ROOM);
    affect_strip ( ch, gsn_polymorph );
    act("$n resumes $s normal form.",ch,NULL,NULL,TO_ROOM);
    send_to_char( "You resume your normal form.\n\r", ch );
    return;
}



void do_recall( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    CHAR_DATA *victim;
    CHAR_DATA *mount;
    ROOM_INDEX_DATA *location;
  
    act( "$n's body flickers with green energy.", ch, NULL, NULL, TO_ROOM );
    act( "Your body flickers with green energy.", ch, NULL, NULL, TO_CHAR );

    if ( ch->position == POS_FIGHTING)
    {
     send_to_char( "You can't recall while fighting.\n\r",ch);
     return;
    }

    if ( ( location = get_room_index( ch->home ) ) == NULL )
    {
	send_to_char( "You are completely lost.\n\r", ch );
	return;
    }
/*
    if ( IS_AFFECTED(ch, AFF_DARKNESS))
	{
	REMOVE_BIT(ch->affected_by, AFF_DARKNESS);
	return;
	}
*/
    if ( ch->in_room == location )
	return;

    if ( IS_SET(ch->in_room->room_flags, ROOM_NO_RECALL)
    ||   IS_AFFECTED(ch, AFF_CURSE) )
    {
	send_to_char( "You are unable to recall.\n\r", ch );
	return;
    }
    
    if ( IS_SET(ch->flag2, AFF_TOTALBLIND) )
    {
	stc("You are unable to recall.\n\r",ch);
	return;
    }
/*
    if ( ( victim = ch->fighting ) != NULL )
    {
	if ( number_bits( 1 ) == 0 )
	{
	    WAIT_STATE( ch, 4 );
	    sprintf( buf, "You failed!\n\r" );
	    send_to_char( buf, ch );
	    return;
	}
	sprintf( buf, "You recall from combat!\n\r");
	send_to_char( buf, ch );
	stop_fighting( ch, TRUE );
    }*/

    act( "$n disappears.", ch, NULL, NULL, TO_ROOM );
    char_from_room( ch );
    char_to_room( ch, location );
    act( "$n appears in the room.", ch, NULL, NULL, TO_ROOM );
    do_look( ch, "auto" );
    if ( ( mount = ch->mount ) == NULL ) return;
    char_from_room( mount );
    char_to_room( mount, ch->in_room );
    return;
}

void do_home( CHAR_DATA *ch, char *argument )
{
    char arg [MAX_INPUT_LENGTH];

    argument = one_argument( argument, arg );

    if ( IS_NPC(ch) ) return;

    if ( arg[0] == '\0' || str_cmp(arg,"here") )
    {
	send_to_char( "If you wish this to be your room, you must type 'home here'.\n\r", ch );
	return;
    }

    if ( ch->in_room->vnum == ch->home )
    {
	send_to_char( "But this is already your home!\n\r", ch );
	return;
    }

    if ( IS_SET(ch->in_room->room_flags, ROOM_NO_RECALL) ||
	 IS_SET(ch->in_room->room_flags, ROOM_SAFE) )
    {
	send_to_char( "You are unable to make this room your home.\n\r", ch );
	return;
    }

    ch->home = ch->in_room->vnum;
    send_to_char( "This room is now your home.\n\r", ch );

    return;
}


void do_escape( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    ROOM_INDEX_DATA *location;

    if (IS_NPC(ch) || !IS_HERO(ch))
	return;
  
    if ( ch->position >= POS_SLEEPING )
    {
	send_to_char( "You can only do this if you are dying.\n\r", ch );
	return;
    }

    if ( ( location = get_room_index( ROOM_VNUM_TEMPLE ) ) == NULL )
    {
	send_to_char( "You are completely lost.\n\r", ch );
	return;
    }

    if ( ch->in_room == location )
	return;
    ch->move = 0;
    ch->mana = 0;
    act( "$n fades out of existance.", ch, NULL, NULL, TO_ROOM );
    char_from_room( ch );
    char_to_room( ch, location );
    act( "$n fades into existance.", ch, NULL, NULL, TO_ROOM );
    do_look( ch, "auto" );
    sprintf(buf,"%s has escaped defenceless from a fight.",ch->pcdata->switchname);
    do_info(ch,buf);
    if (IS_SET(ch->newbits, NEW_DARKNESS)) {
        REMOVE_BIT(ch->newbits, NEW_DARKNESS);
        if (ch->in_room != NULL)
        if (IS_SET(ch->in_room->room_flags, ROOM_TOTAL_DARKNESS))
        REMOVE_BIT(ch->in_room->room_flags, ROOM_TOTAL_DARKNESS);
        return;
        }
    return;
}


int disc_points_needed(CHAR_DATA *ch)
{
    
    if (IS_NPC(ch)) return 1;

    return (ch->power[ch->pcdata->disc_research] + 1) * 10;
}

void gain_disc_points(CHAR_DATA *ch, int points)
{   
    if (IS_NPC(ch)) return;

    if (ch->pcdata->disc_points == 666) return;
    if (ch->pcdata->disc_research == -1) return;

    ch->pcdata->disc_points += points;

    if (ch->pcdata->disc_points < 0)
    {
	ch->pcdata->disc_points = 0;
	return;
    }

    if (ch->pcdata->disc_points >= 
	    disc_points_needed(ch) )
    {
	ch->pcdata->disc_points = 666;
	WAIT_STATE(ch, 6);
	stc("#4You have finished researching your discipline.\n\r", ch);
	stc("You may now use the 'train' command.#n\n\r", ch);
	return;
    }
}


void do_research(CHAR_DATA *ch, char *argument)
{
    int i;
    int needed;
    int maxlevel;
    char buf[MAX_STRING_LENGTH];

    maxlevel = 0;

/*
     if (IS_CLASS(ch, CLASS_VAMPIRE))
     {
        if (ch->pcdata->rank == AGE_CHILDE || ch->pcdata->rank == AGE_NEONATE)
          maxlevel = 5;
        else if (ch->pcdata->rank == AGE_ANCILLA)
          maxlevel = 7;
        else if (ch->pcdata->rank == AGE_ELDER)
          maxlevel = 9;
        else
          maxlevel = 10;
      }
*/
      if (IS_CLASS(ch, CLASS_DEMON))
      {
	if (ch->generation <= 5)
	  maxlevel = 5;
	else if (ch->generation == 6)
	  maxlevel = 6;
	else if (ch->generation == 7)
	  maxlevel = 7;
	else if (ch->generation == 8)
	  maxlevel = 8;
	else if (ch->generation == 9)
	  maxlevel = 9;
	else if (ch->generation == 10)
	  maxlevel = 10;
	else
	  maxlevel = 10;    
    }

     else maxlevel = 10;

    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch, CLASS_DEMON))
    {
	stc("Only demons can research disciplines.\n\r", ch);
	return;
    }

    if (!str_cmp(argument, "cancel"))
    {
	if (ch->pcdata->disc_research == -1)
	{
	    stc("You are not currently researching a discipline.\n\r",ch);
	    return;
	}
	stc("You stop your research.\n\r", ch);
	ch->pcdata->disc_research = -1;
	ch->pcdata->disc_points = 0;
 	return;
    }

    if (argument[0] == '\0')
    {
	stc("What do you wish to research.\n\r", ch);
	return;
    }

    if (ch->pcdata->disc_research != -1)
    {
	stc("You are already researching a discipline.\n\r", ch);
	stc("Type 'research cancel' to stop.\n\r",ch);
	return;
    }
 
    for ( i = 0 ; i < MAX_DISCIPLINES ; i++)
    {
	if (discipline[i][0] != '\0'
	    && !str_prefix(argument, discipline[i]) )
	{
		needed = ((ch->power[i] - 5) * 5);
	    if (ch->power[i] < 0)	    
	    {
    		stc("You don't know any disciplines of that name.\n\r", ch);
		return;
	    }

/*
          if ( IS_CLASS(ch, CLASS_VAMPIRE)
	     && ch->power[i] >= maxlevel)
	  {
		stc("You need to age more before progressing in this discipline.\n\r",ch);
	        return;
	  }
*/
	  if ( IS_CLASS(ch, CLASS_DEMON)
	    && ch->power[i] >= maxlevel)
	  {
		stc("You must obtain a higher rank before progressing.\n\r",ch);
		return;
	  }


	  if ( ch->power[i] >= 10 )
	  {
		stc("You have reached full mastery of this discipline.\n\r",ch);
	        return;
	  }

	    sprintf(buf, "You begin your research into %s.\n\r",
		discipline[i]);
	    stc(buf, ch);
	    ch->pcdata->disc_points = 0;
	    ch->pcdata->disc_research = i;
	    return;
	}
    }
    stc("You don't know any disciplines of that name.\n\r", ch);
}

const  char * wwgift [MAX_GIFTS] =
{
	"",
	"Homid",		"Metis",
	"Lupus",		"Ragabash",
	"Theurge",		"Philodox",
	"Galliard",		"Ahroun",
	"Black Furies",		"Bone Gnawers",
	"Children of Gaia",	"Fianna",
	"Get of Fenris",	"Glass Walkers",
	"Red Talons",		"Shadow Lords",
	"Silent Striders",	"Silver Fangs",
	"Stargazers",		"Uktena",
	"Wendigo"
};

const  char * discipline [MAX_DISCIPLINES] =
{
	  "",			"",
        "celerity",		"fortitude",
        "obtenebration",	"presence",
        "quietus",		"thaumaturgy",
        "auspex",		"dominate",
	"obfuscate",	        "potence",
	"protean",	        "serpentis",
	"vicissitude",          "daimoinon",	    
        "animalism",		"",

/* Werewolf */

	"bear",			"lynx",
        "boar",			"owl",
        "spider",		"wolf",
	"hawk",			"mantis",
	"raptor",	        "luna",
	"pain",			"congregation",

/* Daemon */
	"hellfire",		"attack",
	"temptation",		"morphosis",
	"corruption",		"geluge",
	"discord",		"nether",
	"immunae",		"chimerstry",
        "thanatosis",           "obeah",
	"necromancy",    	"melpominee"

};

void do_disciplines(CHAR_DATA *ch, char *argument)    
{
    char buf[MAX_INPUT_LENGTH];
    char buf2[MAX_INPUT_LENGTH];
    int loop;
    int percent = 0, i;
    int indent = 0;

    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch, CLASS_DEMON))
    {
	stc("Only Demons may improve their disciplines.\n\r",ch);
	return;
    }

//    if (IS_CLASS(ch, CLASS_WEREWOLF))
//        sprintf(buf, "---===[ Guardians ]===---");
//    else
        sprintf(buf, "---===[ Disciplines ]===---");


    cent_to_char(buf, ch);
    send_to_char("\n\r", ch);

    for (loop = 0; loop < MAX_DISCIPLINES; loop++)
    {
	if (discipline[loop][0] != '\0'
	&& strlen(discipline[loop]) != 0
	&& ch->power[loop] >= 0 )
	{
	    sprintf(buf2, discipline[loop]);
	    buf2[0] = UPPER(buf2[0]);

	    sprintf(buf,"     %-14s: %-2d",
		buf2,
		ch->power[loop]);
	    send_to_char(buf,ch);
	    indent++;
	    if (indent == 3)
	    {
		stc("\n\r", ch);
		indent = 0;
	    }
	}
    }
    if (indent != 0) stc("\n\r", ch);

    /* This tells them if they are currently researching */
    if (ch->pcdata->disc_research < 0)
    {
	send_to_char("\n\r", ch);
	divide6_to_char(ch);
	return;
    }

    if (ch->power[ch->pcdata->disc_research] < 0)
    {
	send_to_char("\n\r", ch);
	divide6_to_char(ch);
	return;
    }

    if (ch->pcdata->disc_points == 666)
    {
	stc("\n\r", ch);
	sprintf(buf, "You have finished researching %s.",
	    discipline[ch->pcdata->disc_research]);
	cent_to_char(buf, ch);
	stc("\n\r", ch);
	divide6_to_char(ch);
	return;
    }

    if (ch->pcdata->disc_research < MAX_DISCIPLINES)
    {
	send_to_char("\n\r", ch);
	sprintf(buf, "You are currently researching %s.",
	    discipline[ch->pcdata->disc_research]);
    	cent_to_char(buf, ch);
    }

    percent = ch->pcdata->disc_points * 40 / disc_points_needed(ch);

    sprintf(buf, "-[#1");

    for( i = 0 ; i < percent ; i++)
	strcat(buf, "*");

    for( i = percent ; i < 40 ; i++)
	strcat(buf, " ");

    strcat(buf, "#n]-");

    cent_to_char(buf, ch);
}

void do_train( CHAR_DATA *ch, char *argument )
{
    char arg1[MAX_STRING_LENGTH];
    char arg2[MAX_STRING_LENGTH];
    char buf[MAX_STRING_LENGTH];
    sh_int *pAbility;
    char *pOutput;
    int cost;
    int magic;
    int immcost;
    int primal;
    int silver;
    int gnosis;
    int focus;
    int ancilla;
    int methuselah;
    int elder;
    int beast;
    int max_stat = 18;
    bool last = TRUE;
    bool is_ok = FALSE;

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if ( IS_NPC(ch) )
	return;

    if ( arg1[0] == '\0' )
    {
	sprintf( buf, "You have %d experience points.\n\r", ch->exp );
	send_to_char( buf, ch );
	strcpy(arg1,"foo");
    }

         if (!str_cmp(arg1,"str")   ) is_ok = TRUE;
    else if (!str_cmp(arg1,"int")   ) is_ok = TRUE;
    else if (!str_cmp(arg1,"wis")   ) is_ok = TRUE;
    else if (!str_cmp(arg1,"dex")   ) is_ok = TRUE;
    else if (!str_cmp(arg1,"con")   ) is_ok = TRUE;
    else if (!str_cmp(arg1,"hp")    ) is_ok = TRUE;
    else if (!str_cmp(arg1,"mana")  ) is_ok = TRUE;
    else if (!str_cmp(arg1,"move")  ) is_ok = TRUE;
    else if (!str_cmp(arg1,"slash") || !str_cmp(arg1,"smash") ||
!str_cmp(arg1,"beast") || !str_cmp(arg1,"grab") || !str_cmp(arg1,"charm") ||
!str_cmp(arg1,"heat") || !str_cmp(arg1,"cold") || !str_cmp(arg1,"lightning") ||
!str_cmp(arg1,"acid") || !str_cmp(arg1,"drain") || !str_cmp(arg1,"hurl") ||
!str_cmp(arg1,"backstab") || !str_cmp(arg1,"kick") || !str_cmp(arg1,"disarm") ||
!str_cmp(arg1,"steal") || !str_cmp(arg1,"stab")) 	is_ok = TRUE;
    else if (!str_cmp(arg1,"primal")) is_ok = TRUE;
	else if (!str_cmp(arg1,"sunlight") && IS_CLASS(ch, CLASS_VAMPIRE))
	is_ok = TRUE;
    else if (!str_cmp(arg1,"ancilla") && IS_CLASS(ch,CLASS_VAMPIRE) && 
    (ch->pcdata->rank == AGE_NEONATE))
        is_ok = TRUE;
    else if (!str_cmp(arg1,"ancilla") && IS_CLASS(ch,CLASS_VAMPIRE) &&
    (ch->pcdata->rank == AGE_CHILDE))
        is_ok = TRUE;
    else if (!str_cmp(arg1,"silver") && IS_CLASS(ch,CLASS_WEREWOLF))
        is_ok = TRUE;
    else if (!str_cmp(arg1,"gnosis") && IS_CLASS(ch, CLASS_WEREWOLF) )
	is_ok = TRUE;
    else if (!str_cmp(arg1,"control") && IS_CLASS(ch, CLASS_VAMPIRE)
	&& ch->beast > 0 )
	is_ok = TRUE;
    else if (!str_cmp(arg1,"focus") && IS_CLASS(ch, CLASS_MONK) )
	is_ok = TRUE;
    else if (!str_cmp(arg1,"elder") && IS_CLASS(ch,CLASS_VAMPIRE) &&
(ch->pcdata->rank == AGE_ANCILLA))
	is_ok = TRUE;
    else if (!str_cmp(arg1,"methuselah") && IS_CLASS(ch,CLASS_VAMPIRE) &&
(ch->pcdata->rank == AGE_ELDER))    
        is_ok = TRUE;
 else if (!str_cmp(arg1,"magic") && IS_CLASS(ch,CLASS_DROW))
	is_ok = TRUE;


/*Vorador put this back in, with the cap. */
	if (!str_cmp(arg1,"mv") || !str_cmp(arg1,"move"))
        {
 	arg2[0] = '\0';
           if (ch->exp < ch->max_move * 50) {
 	     send_to_char("You don't have the experience required to improve movement by 50\r\n", ch);
	     return;
	     } else if (ch->max_move + 50 > 15000) {
		send_to_char("You cannot train movement points over 15000, sorry.\r\n", ch); 
  	        return;
             } 
       else 
       {
            ch->exp-=ch->max_move*50;
		ch->max_move+= 50;
		send_to_char("Ok.\r\n", ch);
 		return;
 	 }
}

	if (!str_cmp(arg1,"mn") || !str_cmp(arg1,"mana"))
        {
arg2[0] = '\0';
   	  if (ch->exp < ch->max_mana * 50) {
            send_to_char("You don't have the experience required to improve mana by 50.\r\n", ch);
            return;
            } else if (ch->max_mana + 50 >15000) {
               send_to_char("You cannot train mana points over 15000, sorry.\r\n", ch);
                return;
		} else {
		  ch->exp-=ch->max_mana*50;
		ch->max_mana+= 50;
                send_to_char("Ok.\r\n", ch);
                return;
	  }
     }
	if (!str_cmp(arg1,"hp") || !str_cmp(arg1,"hit"))
	{
arg2[0] = '\0';
	  if (ch->exp < ch->max_hit * 50)
	  {
	    send_to_char("You dont have the experience required to improve hp by 50.\n\r",ch);
	    return;
	  } else if (ch->max_hit+50 > 15000) {
 		  send_to_char("You cannot train hit points over 15000, sorry.\r\n", ch);
                return;
		 } else {              
		ch->exp-=ch->max_hit*50;
		ch->max_hit+= 50;
 		send_to_char("Ok.\r\n", ch);
		return;
}
	}
if (str_cmp(arg1,"magic")) 
    if ( arg2[0] != '\0' && is_ok )
    {
	int amount = 0;
         
	if (!is_number(arg2))
	{
	    send_to_char("Please enter a numeric value.\n\r",ch);
	    return;
	}
	amount = atoi( arg2 );
	if (amount < 1 || amount > 50)
	{
	    send_to_char("Please enter a value between 1 and 50.\n\r",ch);
	    return;
	}
	if (amount > 1)
	{
	    sprintf(buf,"%s %d",arg1,amount-1);
	    do_train(ch,buf);
	    last = FALSE;
	}
    }

    cost = 200;
    immcost = count_imms(ch);
    primal = (1+ch->practice)*500;
    magic = (1+ch->pcdata->stats[DROW_MAGIC])*100;
    silver = (1+ch->siltol)*2500;
    gnosis = ( 1 + ch->gnosis[GMAXIMUM] ) * 250000;
    if ( ch->beast > 25 )
     beast = 5;
    else if ( ch->beast > 15 )
     beast = 10;
    else if ( ch->beast > 10 )
     beast = 15;
    else if ( ch->beast > 2 )
     beast = 20;
    else
     beast = 25;
    focus = 50000;
    ancilla =1500000;
    elder = 7500000;
    methuselah = 15000000;
    if (IS_CLASS(ch, CLASS_HIGHLANDER)) max_stat = 25;

    if ( !str_cmp( arg1, "str" ) )
    {
	pAbility    = &ch->pcdata->perm_str;
	pOutput     = "strength";
    }

    else if ( !str_cmp( arg1, "int" ) )
    {
	pAbility    = &ch->pcdata->perm_int;
	pOutput     = "intelligence";
    }

    else if ( !str_cmp( arg1, "wis" ) )
    {
	pAbility    = &ch->pcdata->perm_wis;
	pOutput     = "wisdom";
    }

    else if ( !str_cmp( arg1, "dex" ) )
    {
	pAbility    = &ch->pcdata->perm_dex;
	pOutput     = "dexterity";
    }

    else if ( !str_cmp( arg1, "con" ) )
    {
	pAbility    = &ch->pcdata->perm_con;
	pOutput     = "constitution";
    }

    else if ( !str_cmp( arg1, "avatar") && (ch->level == 2))
    {
        cost        = 1000;
	pAbility    = &ch->level;
	pOutput     = "level";
    }

    else if ( !str_cmp( arg1, "primal") )
    {
        cost        = primal;
	pAbility    = &ch->practice;
	pOutput     = "primal";
    }
    else if (!str_cmp(arg1, "magic") && IS_CLASS(ch, CLASS_DROW))
	{
	  sh_int quiet_pointer=ch->pcdata->stats[DROW_MAGIC];
	  cost = magic;
	  pAbility = &quiet_pointer;
	  pOutput = "drow magic resistance";
      }
	
    else if ( !str_cmp( arg1, "silver") && IS_CLASS(ch, CLASS_WEREWOLF) )
    {
	sh_int quiet_pointer=ch->siltol; /* dirrent type of int*/
        cost        = silver;
	pAbility    = &quiet_pointer;
	pOutput     = "tolerance to silver";
    }
    else if ( !str_cmp( arg1, "focus") && IS_CLASS(ch, CLASS_MONK))
    {
	sh_int quiet_pointer = ch->focus[MAXIMUM];
	cost 	    = focus;
	pAbility    = &quiet_pointer;
	pOutput     = "monk focus";
    }
    else if ( !str_cmp( arg1, "gnosis") && IS_CLASS(ch, CLASS_WEREWOLF))
    {
	sh_int quiet_pointer = ch->gnosis[GMAXIMUM];
	cost 	    = gnosis;
        pAbility    = &quiet_pointer;
        pOutput     = "gnosis points";
    }
    else if ( !str_cmp( arg1, "control") && IS_CLASS(ch, CLASS_VAMPIRE))
    {
	sh_int quiet_pointer = ch->beast;
	cost 	    = beast;
	pAbility    = &quiet_pointer;
	pOutput     = "control over your beast";
    }

    else if ( !str_cmp( arg1, "ancilla") && IS_CLASS(ch, CLASS_VAMPIRE) &&
 
((ch->pcdata->rank ==AGE_NEONATE) || (ch->pcdata->rank == AGE_CHILDE))) 
{
    
    if (ch->exp < ancilla)
    {
       send_to_char( "You need 1500000 exp to become ancilla!\n\r",ch);
       return;
    }
      ch->exp -= 1500000;
      ch->pcdata->rank = AGE_ANCILLA;
      sprintf(buf,"%s is now an Ancilla!", ch->name);
      do_info(ch,buf);
      send_to_char( "You are now an Ancilla.\n\r",ch);
      return;
 }
   else if ( !str_cmp( arg1, "elder") && IS_CLASS(ch,CLASS_VAMPIRE) &&
   (ch->pcdata->rank == AGE_ANCILLA))
      {
        if (ch->exp < elder)
        {
         send_to_char("You need 7500000 exp to become an elder.\n\r",ch);
         return; 
        }
        ch->exp -= 7500000;   
        ch->pcdata->rank = AGE_ELDER;
        sprintf(buf,"%s is now an Elder!", ch->name);
        do_info(ch,buf);
        send_to_char( "You are now an Elder!\n\r",ch);
        return;
}
   else if ( !str_cmp( arg1, "methuselah") && IS_CLASS(ch, CLASS_VAMPIRE)
&& (ch->pcdata->rank == AGE_ELDER))
  {
     if (ch->exp < methuselah)
      {
      send_to_char( "You need 15000000 exp to become Methuselah!\n\r",ch);
      return;
      }
    ch->exp -= 15000000;
    ch->pcdata->rank = AGE_METHUSELAH;
    sprintf(buf,"%s is now a Methuselah!", ch->name);
    do_info(ch, buf);
    send_to_char( "You are now Methuselah!\n\r",ch);
    return;
}

    else if ( !str_cmp( arg1, "sunlight") && !IS_IMMUNE(ch,IMM_SUNLIGHT)
&& IS_CLASS(ch,CLASS_VAMPIRE))
   {
      if (ch->exp < 1000000)
      {
      send_to_char("You dont have enough experience.\n\r",ch);
	return;
      }

ch->exp = ch->exp - 1000000;
SET_BIT(ch->immune, IMM_SUNLIGHT);
send_to_char("You are now immune to sunlight.\n\r",ch);
return;
}


    
else if ( !str_cmp( arg1, "slash") && !IS_IMMUNE(ch,IMM_SLASH) )
    
    {
	if (ch->exp < immcost)
	{
	    send_to_char( "You don't have enough exp.\n\r", ch );
	    return;
	}
	ch->exp = ch->exp - immcost;
	SET_BIT(ch->immune, IMM_SLASH);
	send_to_char( "You are now more resistant to slashing and slicing weapons.\n\r", ch );
	return;
    }

    else if ( !str_cmp( arg1, "stab") && !IS_IMMUNE(ch,IMM_STAB) )
    {
	if (ch->exp < immcost)
	{
	    send_to_char( "You don't have enough exp.\n\r", ch );
	    return;
	}
	ch->exp = ch->exp - immcost;
	SET_BIT(ch->immune, IMM_STAB);
	send_to_char( "You are now more resistant to stabbing and piercing weapons.\n\r", ch );
	return;
    }

    else if ( !str_cmp( arg1, "smash") && !IS_IMMUNE(ch,IMM_SMASH) )
    {
	if (ch->exp < immcost)
	{
	    send_to_char( "You don't have enough exp.\n\r", ch );
	    return;
	}
	ch->exp = ch->exp - immcost;
	SET_BIT(ch->immune, IMM_SMASH);
	send_to_char( "You are now more resistant to blasting, pounding and crushing weapons.\n\r", ch );
	return;
    }

    else if ( !str_cmp( arg1, "beast") && !IS_IMMUNE(ch,IMM_ANIMAL) )
    {
	if (ch->exp < immcost)
	{
	    send_to_char( "You don't have enough exp.\n\r", ch );
	    return;
	}
	ch->exp = ch->exp - immcost;
	SET_BIT(ch->immune, IMM_ANIMAL);
	send_to_char( "You are now more resistant to claw and bite attacks.\n\r", ch );
	return;
    }

    else if ( !str_cmp( arg1, "grab") && !IS_IMMUNE(ch,IMM_MISC) )
    {
	if (ch->exp < immcost)
	{
	    send_to_char( "You don't have enough exp.\n\r", ch );
	    return;
	}
	ch->exp = ch->exp - immcost;
	SET_BIT(ch->immune, IMM_MISC);
	send_to_char( "You are now more resistant to grepping, sucking and whipping weapons.\n\r", ch );
	return;
    }

    else if ( !str_cmp( arg1, "charm") && !IS_IMMUNE(ch,IMM_CHARM) )
    {
	if (ch->exp < immcost)
	{
	    send_to_char( "You don't have enough exp.\n\r", ch );
	    return;
	}
	ch->exp = ch->exp - immcost;
	SET_BIT(ch->immune, IMM_CHARM);
	send_to_char( "You are now immune to charm spells.\n\r", ch );
	return;
    }

    else if ( !str_cmp( arg1, "heat") && !IS_IMMUNE(ch,IMM_HEAT) )
    {
	if (ch->exp < immcost)
	{
	    send_to_char( "You don't have enough exp.\n\r", ch );
	    return;
	}
	ch->exp = ch->exp - immcost;
	SET_BIT(ch->immune, IMM_HEAT);
	send_to_char( "You are now immune to heat and fire spells.\n\r", ch );
	return;
    }

    else if ( !str_cmp( arg1, "cold") && !IS_IMMUNE(ch,IMM_COLD) )
    {
	if (ch->exp < immcost)
	{
	    send_to_char( "You don't have enough exp.\n\r", ch );
	    return;
	}
	ch->exp = ch->exp - immcost;
	SET_BIT(ch->immune, IMM_COLD);
	send_to_char( "You are now immune to cold spells.\n\r", ch );
	return;
    }

    else if ( !str_cmp( arg1, "lightning") && !IS_IMMUNE(ch,IMM_LIGHTNING) )
    {
	if (ch->exp < immcost)
	{
	    send_to_char( "You don't have enough exp.\n\r", ch );
	    return;
	}
	ch->exp = ch->exp - immcost;
	SET_BIT(ch->immune, IMM_LIGHTNING);
	send_to_char( "You are now immune to lightning and electrical spells.\n\r", ch );
	return;
    }

    else if ( !str_cmp( arg1, "acid") && !IS_IMMUNE(ch,IMM_ACID) )
    {
	if (ch->exp < immcost)
	{
	    send_to_char( "You don't have enough exp.\n\r", ch );
	    return;
	}
	ch->exp = ch->exp - immcost;
	SET_BIT(ch->immune, IMM_ACID);
	send_to_char( "You are now immune to acid spells.\n\r", ch );
	return;
    }

    else if ( !str_cmp( arg1, "sleep") && !IS_IMMUNE(ch,IMM_SLEEP) )
    {
	if (ch->exp < immcost)
	{
	    send_to_char( "You don't have enough exp.\n\r", ch );
	    return;
	}
	ch->exp = ch->exp - immcost;
	SET_BIT(ch->immune, IMM_SLEEP);
	send_to_char( "You are now immune to the sleep spell.\n\r", ch );
	return;
    }

    else if ( !str_cmp( arg1, "drain") && !IS_IMMUNE(ch,IMM_DRAIN) )
    {
	if (ch->exp < immcost)
	{
	    send_to_char( "You don't have enough exp.\n\r", ch );
	    return;
	}
	ch->exp = ch->exp - immcost;
	SET_BIT(ch->immune, IMM_DRAIN);
	send_to_char( "You are now immune to the energy drain spell.\n\r", ch );
	return;
    }


    else if ( !str_cmp( arg1, "voodoo") && !IS_IMMUNE(ch,IMM_VOODOO) )
    {
	if (ch->exp < immcost)
	{
	    send_to_char( "You don't have enough exp.\n\r", ch );
	    return;
	}
	ch->exp = ch->exp - immcost;
	SET_BIT(ch->immune, IMM_VOODOO);
	send_to_char( "You are now immune to voodoo magic.\n\r", ch );
	return;
    }

    else if ( !str_cmp( arg1, "hurl") && !IS_IMMUNE(ch,IMM_HURL) )
    {
	if (ch->exp < immcost)
	{
	    send_to_char( "You don't have enough exp.\n\r", ch );
	    return;
	}
	ch->exp = ch->exp - immcost;
	SET_BIT(ch->immune, IMM_HURL);
	send_to_char( "You are now immune to being hurled.\n\r", ch );
	return;
    }

    else if ( !str_cmp( arg1, "backstab") && !IS_IMMUNE(ch,IMM_BACKSTAB) )
    {
	if (ch->exp < immcost)
	{
	    send_to_char( "You don't have enough exp.\n\r", ch );
	    return;
	}
	ch->exp = ch->exp - immcost;
	SET_BIT(ch->immune, IMM_BACKSTAB);
	send_to_char( "You are now immune to being backstabbed.\n\r", ch );
	return;
    }

    else if ( !str_cmp( arg1, "kick") && !IS_IMMUNE(ch,IMM_KICK) )
    {
	if (ch->exp < immcost)
	{
	    send_to_char( "You don't have enough exp.\n\r", ch );
	    return;
	}
	ch->exp = ch->exp - immcost;
	SET_BIT(ch->immune, IMM_KICK);
	send_to_char( "You are now immune to being kicked.\n\r", ch );
	return;
    }

    else if ( !str_cmp( arg1, "disarm") && !IS_IMMUNE(ch,IMM_DISARM) )
    {
	if (ch->exp < immcost)
	{
	    send_to_char( "You don't have enough exp.\n\r", ch );
	    return;
	}
	ch->exp = ch->exp - immcost;
	SET_BIT(ch->immune, IMM_DISARM);
	send_to_char( "You are now immune to being disarmed.\n\r", ch );
	return;
    }

    else if ( !str_cmp( arg1, "steal") && !IS_IMMUNE(ch,IMM_STEAL) )
    {
	if (ch->exp < immcost)
	{
	    send_to_char( "You don't have enough exp.\n\r", ch );
	    return;
	}
	ch->exp = ch->exp - immcost;
	SET_BIT(ch->immune, IMM_STEAL);
	send_to_char( "You are now immune to being stolen from.\n\r", ch );
	return;
    }

    else
    {
	sprintf( buf, "You can train the following:\n\r" );
	send_to_char( buf, ch );

	send_to_char( "Stats:", ch );
	if ( ch->pcdata->perm_str < max_stat ) send_to_char( " Str", ch );
	if ( ch->pcdata->perm_int < max_stat ) send_to_char( " Int", ch );
	if ( ch->pcdata->perm_wis < max_stat ) send_to_char( " Wis", ch );
	if ( ch->pcdata->perm_dex < max_stat ) send_to_char( " Dex", ch );
	if ( ch->pcdata->perm_con < max_stat ) send_to_char( " Con", ch );
	if ( ( ch->pcdata->perm_str >= max_stat )
		&& ( ch->pcdata->perm_wis >= max_stat )
		&& ( ch->pcdata->perm_int >= max_stat )
		&& ( ch->pcdata->perm_dex >= max_stat )
		&& ( ch->pcdata->perm_con >= max_stat ) )
	    send_to_char( " None left to train.\n\r", ch );
	else
	    send_to_char( ".\n\r", ch );

	if ( ch->level == 2 )
	{
	   sprintf( buf, "Become an avatar - 1000 exp.\n\r" );
	   send_to_char( buf, ch );
	}
       	
        if ( ch->max_hit      < 15000 )
        {
           sprintf( buf, "Hit              - %d exp per 50 points.\n\r",(ch->max_hit*50) ); 
           send_to_char( buf, ch );
        }

	if ( ch->max_mana      < 15000 )
	{
	   sprintf( buf, "Mana             - %d exp per 50 points.\n\r",(ch->max_mana *50) );
	   send_to_char( buf, ch );
	}
	if ( ch->max_move      < 15000 )
	{
	   sprintf( buf, "Move             - %d exp per 50 points.\n\r",(ch->max_move*50) );
	   send_to_char( buf, ch );
	}
	if ( ch->practice        < 999 )
	{
	   sprintf( buf, "Primal           - %d exp per point of primal energy.\n\r", (1+ch->practice)*500 );
	   send_to_char( buf, ch );
	}
       if (IS_CLASS(ch,CLASS_VAMPIRE) )
        {
       if  ( ch->pcdata->rank == AGE_CHILDE)
         send_to_char("Age: Ancilla\n\r",ch); 	
       else if (ch->pcdata->rank == AGE_NEONATE)
         send_to_char("Age: Ancilla\n\r",ch);
       else if (ch->pcdata->rank == AGE_ANCILLA)
        send_to_char("Age: Elder\n\r",ch);
        else if (ch->pcdata->rank == AGE_ELDER)
       send_to_char("Age: Methuselah\n\r",ch);
        }
       if ( IS_CLASS(ch, CLASS_VAMPIRE) && !IS_IMMUNE(ch, IMM_SUNLIGHT))
       {
	   stc("Immunity to Sunlight - 1,000,000 experience.\n\r",ch);
       }
       if ( ch->siltol < 100 && IS_CLASS(ch, CLASS_WEREWOLF))
	{
	   sprintf( buf, "Silver tolerance - %d exp per point of tolerance.\n\r", silver );
	   send_to_char( buf, ch );
	}
       if ( ch->gnosis[GMAXIMUM] < 20 && IS_CLASS(ch, CLASS_WEREWOLF))
       {
	   sprintf( buf, "Gnosis Points - %d exp per point of Gnosis.\n\r", gnosis );
	   stc( buf, ch );
       }
       if ( ch->beast > 0 && IS_CLASS(ch, CLASS_VAMPIRE) )
       {
	   sprintf( buf, "Beast Control- %d primal per point of Beast.\n\r", beast );
	   stc( buf, ch );
       }
       if ( ch->focus[MAXIMUM] < 100 && IS_CLASS(ch, CLASS_MONK))
       {
	   sprintf( buf, "Focus Points - %d exp per point of Focus.\n\r", focus );
	   stc( buf, ch );
       }
	if (ch->pcdata->stats[DROW_MAGIC] < 100 && IS_CLASS(ch, CLASS_DROW))
	{ sprintf( buf, "Magic resistance - %d drow points per point of magic.\n\r", magic );
	  send_to_char( buf, ch);}
	
	sprintf( buf, "Natural resistances and immunities - %d exp each.\n\r", immcost );
	send_to_char( buf, ch );

	/* Weapon resistance affects */
	send_to_char( "Weapon resistances:", ch );
	if ( !IS_IMMUNE(ch, IMM_SLASH)  ) send_to_char( " Slash", ch );
	if ( !IS_IMMUNE(ch, IMM_STAB)   ) send_to_char( " Stab", ch );
	if ( !IS_IMMUNE(ch, IMM_SMASH)  ) send_to_char( " Smash", ch );
	if ( !IS_IMMUNE(ch, IMM_ANIMAL) ) send_to_char( " Beast", ch );
	if ( !IS_IMMUNE(ch, IMM_MISC)   ) send_to_char( " Grab", ch );
	if ( IS_IMMUNE(ch, IMM_SLASH) && IS_IMMUNE(ch, IMM_STAB) && 
	IS_IMMUNE(ch, IMM_SMASH) && IS_IMMUNE(ch, IMM_ANIMAL) && 
	IS_IMMUNE(ch, IMM_MISC) )
	   send_to_char( " None left to learn.\n\r", ch );
	else
	   send_to_char( ".\n\r", ch );

	/* Spell immunity affects */
	send_to_char( "Magical immunities:", ch );
	if ( !IS_IMMUNE(ch, IMM_CHARM)     ) send_to_char( " Charm", ch );
	if ( !IS_IMMUNE(ch, IMM_HEAT)      ) send_to_char( " Heat", ch );
	if ( !IS_IMMUNE(ch, IMM_COLD)      ) send_to_char( " Cold", ch );
	if ( !IS_IMMUNE(ch, IMM_LIGHTNING) ) send_to_char( " Lightning", ch );
	if ( !IS_IMMUNE(ch, IMM_ACID)      ) send_to_char( " Acid", ch );
	if ( !IS_IMMUNE(ch, IMM_SLEEP)     ) send_to_char( " Sleep", ch );
	if ( !IS_IMMUNE(ch, IMM_DRAIN)     ) send_to_char( " Drain", ch );
	if ( !IS_IMMUNE(ch, IMM_VOODOO)    ) send_to_char( " Voodoo", ch );
	if ( IS_IMMUNE(ch, IMM_CHARM) && IS_IMMUNE(ch, IMM_HEAT) && 
	IS_IMMUNE(ch, IMM_COLD) && IS_IMMUNE(ch, IMM_LIGHTNING) && 
	IS_IMMUNE(ch, IMM_ACID) && IS_IMMUNE(ch, IMM_SLEEP) &&
	IS_IMMUNE(ch, IMM_DRAIN) && IS_IMMUNE(ch, IMM_VOODOO) )
	   send_to_char( " None left to learn.\n\r", ch );
	else
	   send_to_char( ".\n\r", ch );

	/* Skill immunity affects */
	send_to_char( "Skill immunities:", ch );
	if ( !IS_IMMUNE(ch, IMM_HURL)     ) send_to_char( " Hurl", ch );
	if ( !IS_IMMUNE(ch, IMM_BACKSTAB) ) send_to_char( " Backstab", ch );
	if ( !IS_IMMUNE(ch, IMM_KICK)     ) send_to_char( " Kick", ch );
	if ( !IS_IMMUNE(ch, IMM_DISARM)   ) send_to_char( " Disarm", ch );
	if ( !IS_IMMUNE(ch, IMM_STEAL)    ) send_to_char( " Steal", ch );
	if ( IS_IMMUNE(ch, IMM_HURL) && IS_IMMUNE(ch, IMM_BACKSTAB) && 
	IS_IMMUNE(ch, IMM_KICK)      && IS_IMMUNE(ch, IMM_DISARM)   && 
	IS_IMMUNE(ch, IMM_STEAL) )
	   send_to_char( " None left to learn.\n\r", ch );
	else
	   send_to_char( ".\n\r", ch );

	return;
    }

    if ( (*pAbility >= max_stat) && (!str_cmp( arg1, "str")))
    {
	if (last) act( "Your $T is already at maximum.", ch, NULL, pOutput, TO_CHAR );
	return;
    }
    if ( (*pAbility >= max_stat) && (!str_cmp( arg1, "int")))
    {
	if (last) act( "Your $T is already at maximum.", ch, NULL, pOutput, TO_CHAR );
	return;
    }
    if ( (*pAbility >= max_stat) && (!str_cmp( arg1, "wis")))
    {
	if (last) act( "Your $T is already at maximum.", ch, NULL, pOutput, TO_CHAR );
	return;
    }
    if ( (*pAbility >= max_stat) && (!str_cmp( arg1, "dex")))
    {
	if (last) act( "Your $T is already at maximum.", ch, NULL, pOutput, TO_CHAR );
	return;
    }
    if ( (*pAbility >= max_stat) && (!str_cmp( arg1, "con")))
    {
	if (last) act( "Your $T is already at maximum.", ch, NULL, pOutput, TO_CHAR );
	return;
    }
    if ( (*pAbility >= 15000) && (!str_cmp( arg1, "hp")))
    {
        if (last) act( "Your $T is already at maximum.", ch, NULL, pOutput, TO_CHAR );
        return;
    }
    if ( (*pAbility >= 15000) && (!str_cmp( arg1, "mana")))
    {
	if (last) act( "Your $T is already at maximum.", ch, NULL, pOutput, TO_CHAR );
	return;
    }
    if ( (*pAbility >= 15000) && (!str_cmp( arg1, "move")))
    {
	if (last) act( "Your $T is already at maximum.", ch, NULL, pOutput, TO_CHAR );
	return;
    }
    if ( (*pAbility >= 999) && (!str_cmp( arg1, "primal")))
    {
	if (last) act( "Your $T is already at maximum.", ch, NULL, pOutput, TO_CHAR );
	return;
    }
    if ((*pAbility >= 100) && (!str_cmp(arg1, "magic"))) {
		if (last) act("Your $T is already at a maximum.", ch, NULL, pOutput, TO_CHAR);
		return;}

    if ( (*pAbility >= 20 ) && (!str_cmp( arg1, "gnosis") ))
    {
	if (last) act( "Your $T is already at maximum.",ch,NULL,pOutput,TO_CHAR);
	return;
    }

    if ( (*pAbility == 0 ) && (!str_cmp( arg2, "control") ) )
    {
	if (last) act( "You have already mastered your beast.",ch,NULL,pOutput,TO_CHAR);
	return;
    }

    if ( ( *pAbility >= 100 ) && (!str_cmp( arg1, "focus") ) )
    {
	if (last) act( "Your $T is already at maximum.",ch,NULL,pOutput,TO_CHAR);
	return;
    }

    if ( (*pAbility >= 100) && (!str_cmp( arg1, "silver")))
    {
	if (last) act( "Your $T is already at maximum.", ch, NULL, pOutput, TO_CHAR );
	return;
    }

    if ( cost < 1 ) cost = 1;
    if ( cost > ch->pcdata->stats[DROW_POWER] && !str_cmp(arg1, "magic"))
	{ if (last) send_to_char( "You don't have enough drow power points.\n\r", ch);
	return;}
else     if ( cost > ch->exp )
    {
	if (last) send_to_char( "You don't have enough exp.\n\r", ch );
	return;
    }
if (!str_cmp(arg1, "magic"))
	ch->pcdata->stats[DROW_POWER] -= cost;
else
    ch->exp		-= cost;
	if (!str_cmp( arg1, "silver"))
		ch->siltol += 1;
	else if (!str_cmp(arg1, "gnosis"))
	{
	   ch->gnosis[GCURRENT]++;
	   ch->gnosis[GMAXIMUM]++;
	}
	
	else if (!str_cmp(arg1, "focus"))
        {
	   ch->focus[CURRENT]++;
	   ch->focus[MAXIMUM]++;
	}
        else if (!str_cmp(arg1, "control"))
	  ch->beast--;
	else if (!str_cmp(arg1, "magic"))
		ch->pcdata->stats[DROW_MAGIC] += 1;
	else
    *pAbility		+= 1;
    if ( !str_cmp( arg1, "avatar") )
    {
	act( "You become an avatar!", ch, NULL, NULL, TO_CHAR );
	sprintf( buf, "%s has become an avatar!",ch->pcdata->switchname );
	do_info(ch,buf);
	if (IS_CLASS(ch, CLASS_DEMON)) ch->alignment = -1000;
	if (ch->level < ch->trust) ch->level = ch->trust;
	if (!IS_NPC(ch) && IS_VAMPAFF(ch, VAM_MORTAL))
	    do_mortalvamp(ch,"");
    }
    else if (last)
	act( "Your $T increases!", ch, NULL, pOutput, TO_CHAR );
    return;
}

void do_mount( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;

    argument = one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char( "Mount what?\n\r", ch );
	return;
    }

    if (IS_AFFECTED(ch, AFF_POLYMORPH) && !IS_VAMPAFF(ch, VAM_DISGUISED))
    {
	send_to_char( "You cannot ride in this form.\n\r",ch );
	return;
    }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r",ch );
	return;
    }

    if ( ch == victim )
    {
	send_to_char( "You cannot ride on your own back!\n\r",ch );
	return;
    }

    if ( ch->mounted > 0 )
    {
	send_to_char( "You are already riding.\n\r",ch );
	return;
    }

    if ( !IS_NPC(victim) || victim->mounted > 0 || (IS_NPC(victim) && !IS_SET(victim->act, ACT_MOUNT) ) )
    {
	send_to_char( "You cannot mount them.\n\r",ch );
	return;
    }

    if ( victim->position < POS_STANDING )
    {
	if ( victim->position < POS_SLEEPING )
	    act( "$N is too badly hurt for that.", ch, NULL, victim, TO_CHAR );
	else if ( victim->position == POS_SLEEPING )
	    act( "First you better wake $m up.", ch, NULL, victim, TO_CHAR );
	else if ( victim->position == POS_RESTING )
	    act( "First $e better stand up.", ch, NULL, victim, TO_CHAR );
	else if ( victim->position == POS_MEDITATING )
	    act( "First $e better stand up.", ch, NULL, victim, TO_CHAR );
	else if ( victim->position == POS_SITTING )
	    act( "First $e better stand up.", ch, NULL, victim, TO_CHAR );
	else if ( victim->position == POS_SLEEPING )
	    act( "First you better wake $m up.", ch, NULL, victim, TO_CHAR );
	else if ( victim->position == POS_FIGHTING )
	    act( "Not while $e's fighting.", ch, NULL, victim, TO_CHAR );
	return;
    }

    if (!IS_NPC(ch) && ch->stance[0] != -1) do_stance(ch,"");

    ch->mounted     = IS_RIDING;
    victim->mounted = IS_MOUNT;
    ch->mount = victim;
    victim->mount = ch;

    act( "You clamber onto $N's back.", ch, NULL, victim, TO_CHAR );
    act( "$n clambers onto $N's back.", ch, NULL, victim, TO_ROOM );
    return;
}

void do_dismount( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;

    if ( ch->mounted == 0 )
    {
	send_to_char( "But you are not riding!\n\r",ch );
	return;
    }

    if ( (victim = ch->mount) == NULL )
    {
	send_to_char( "But you are not riding!\n\r",ch );
	return;
    }

    act( "You clamber off $N's back.", ch, NULL, victim, TO_CHAR );
    act( "$n clambers off $N's back.", ch, NULL, victim, TO_ROOM );

    ch->mounted     = IS_ON_FOOT;
    victim->mounted = IS_ON_FOOT;

    ch->mount = NULL;
    victim->mount = NULL;

    return;
}

void do_tie( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char arg [MAX_INPUT_LENGTH];
    char buf [MAX_INPUT_LENGTH];

    argument = one_argument( argument, arg );
    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }
    if (victim == ch)
    {
	send_to_char( "You cannot tie yourself up!\n\r", ch );
	return;
    }
    if (IS_EXTRA(victim,TIED_UP))
    {
	send_to_char( "But they are already tied up!\n\r", ch );
	return;
    }
    if (victim->position > POS_STUNNED || victim->hit > 0)
    {
	send_to_char( "You can only tie up a defenceless person.\n\r", ch );
	return;
    }
    act("You quickly tie up $N.",ch,NULL,victim,TO_CHAR);
    act("$n quickly ties up $N.",ch,NULL,victim,TO_ROOM);
    send_to_char("You have been tied up!\n\r",victim);
    SET_BIT(victim->extra,TIED_UP);
    sprintf(buf,"%s has been tied up by %s.",victim->pcdata->switchname,ch->pcdata->switchname);
    do_info(ch,buf);
    return;
}

void do_untie( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char arg [MAX_INPUT_LENGTH];

    argument = one_argument( argument, arg );
    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }
    if (!IS_EXTRA(victim,TIED_UP))
    {
	send_to_char( "But they are not tied up!\n\r", ch );
	return;
    }
    if (victim == ch)
    {
	send_to_char( "You cannot untie yourself!\n\r", ch );
	return;
    }
    act("You quickly untie $N.",ch,NULL,victim,TO_CHAR);
    act("$n quickly unties $N.",ch,NULL,victim,TO_NOTVICT);
    act("$n quickly unties you.",ch,NULL,victim,TO_VICT);
    REMOVE_BIT(victim->extra,TIED_UP);
    return;
}

void do_gag( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char arg [MAX_INPUT_LENGTH];

    argument = one_argument( argument, arg );
    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }
    if (victim == ch && !IS_EXTRA(victim,GAGGED) && IS_EXTRA(victim,TIED_UP))
    {
	send_to_char( "You cannot gag yourself!\n\r", ch );
	return;
    }
    if (!IS_EXTRA(victim,TIED_UP) && !IS_EXTRA(victim,GAGGED))
    {
	send_to_char( "You can only gag someone who is tied up!\n\r", ch );
	return;
    }
    if (!IS_EXTRA(victim,GAGGED))
    {
    	act("You place a gag over $N's mouth.",ch,NULL,victim,TO_CHAR);
    	act("$n places a gag over $N's mouth.",ch,NULL,victim,TO_NOTVICT);
    	act("$n places a gag over your mouth.",ch,NULL,victim,TO_VICT);
    	SET_BIT(victim->extra,GAGGED);
	return;
    }
    if (ch == victim)
    {
    	act("You remove the gag from your mouth.",ch,NULL,victim,TO_CHAR);
    	act("$n removes the gag from $s mouth.",ch,NULL,victim,TO_ROOM);
    	REMOVE_BIT(victim->extra,GAGGED);
	return;
    }
    act("You remove the gag from $N's mouth.",ch,NULL,victim,TO_CHAR);
    act("$n removes the gag from $N's mouth.",ch,NULL,victim,TO_NOTVICT);
    act("$n removes the gag from your mouth.",ch,NULL,victim,TO_VICT);
    REMOVE_BIT(victim->extra,GAGGED);
    return;
}

void do_blindfold( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char arg [MAX_INPUT_LENGTH];

    argument = one_argument( argument, arg );
    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }
    if (victim == ch && !IS_EXTRA(victim,BLINDFOLDED) && IS_EXTRA(victim,TIED_UP))
    {
	send_to_char( "You cannot blindfold yourself!\n\r", ch );
	return;
    }
    if (!IS_EXTRA(victim,TIED_UP) && !IS_EXTRA(victim,BLINDFOLDED))
    {
	send_to_char( "You can only blindfold someone who is tied up!\n\r", ch );
	return;
    }
    if (!IS_EXTRA(victim,BLINDFOLDED))
    {
    	act("You place a blindfold over $N's eyes.",ch,NULL,victim,TO_CHAR);
    	act("$n places a blindfold over $N's eyes.",ch,NULL,victim,TO_NOTVICT);
    	act("$n places a blindfold over your eyes.",ch,NULL,victim,TO_VICT);
    	SET_BIT(victim->extra,BLINDFOLDED);
	return;
    }
    if (ch == victim)
    {
    	act("You remove the blindfold from your eyes.",ch,NULL,victim,TO_CHAR);
    	act("$n removes the blindfold from $s eyes.",ch,NULL,victim,TO_ROOM);
    	REMOVE_BIT(victim->extra,BLINDFOLDED);
	return;
    }
    act("You remove the blindfold from $N's eyes.",ch,NULL,victim,TO_CHAR);
    act("$n removes the blindfold from $N's eyes.",ch,NULL,victim,TO_NOTVICT);
    act("$n removes the blindfold from your eyes.",ch,NULL,victim,TO_VICT);
    REMOVE_BIT(victim->extra,BLINDFOLDED);
    return;
}


int count_imms( CHAR_DATA *ch )
{
    int count = 0;

    if ( IS_IMMUNE(ch, IMM_SLASH)     ) count += 1;
    if ( IS_IMMUNE(ch, IMM_STAB)      ) count += 1;
    if ( IS_IMMUNE(ch, IMM_SMASH)     ) count += 1;
    if ( IS_IMMUNE(ch, IMM_ANIMAL)    ) count += 1;
    if ( IS_IMMUNE(ch, IMM_MISC)      ) count += 1;
    if ( IS_IMMUNE(ch, IMM_CHARM)     ) count += 1;
    if ( IS_IMMUNE(ch, IMM_HEAT)      ) count += 1;
    if ( IS_IMMUNE(ch, IMM_COLD)      ) count += 1;
    if ( IS_IMMUNE(ch, IMM_LIGHTNING) ) count += 1;
    if ( IS_IMMUNE(ch, IMM_ACID)      ) count += 1;
    if ( IS_IMMUNE(ch, IMM_SLEEP)     ) count += 1;
    if ( IS_IMMUNE(ch, IMM_DRAIN)     ) count += 1;
    if ( IS_IMMUNE(ch, IMM_VOODOO)    ) count += 1;
    if ( IS_IMMUNE(ch, IMM_HURL)      ) count += 1;
    if ( IS_IMMUNE(ch, IMM_BACKSTAB)  ) count += 1;
    if ( IS_IMMUNE(ch, IMM_KICK)      ) count += 1;
    if ( IS_IMMUNE(ch, IMM_DISARM)    ) count += 1;
    if ( IS_IMMUNE(ch, IMM_STEAL)     ) count += 1;
    return ( ( count * 10000 ) + 10000 );
}

void do_track( CHAR_DATA *ch, char *argument )
{
    bool found = FALSE;
    if (!IS_NPC(ch) && number_percent() > ch->pcdata->learned[gsn_track])
    {
	send_to_char("You cannot sense any trails from this room.\n\r",ch);
	return;
    }
    if (check_track(ch,0)) found = TRUE;
    if (check_track(ch,1)) found = TRUE;
    if (check_track(ch,2)) found = TRUE;
    if (check_track(ch,3)) found = TRUE;
    if (check_track(ch,4)) found = TRUE;
    if (found == FALSE)
    {
	send_to_char("You cannot sense any trails from this room.\n\r",ch);
	return;
    }
    act("$n carefully examines the ground for tracks.",ch,NULL,NULL,TO_ROOM);
    return;
}

void do_hunt( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];

    argument = one_argument( argument, arg );
/*
    send_to_char("This command is temporarily disabled.\n\r",ch);
    return;
*/
    if ( arg[0] == '\0' )
    {
	if (strlen(ch->hunting) > 1)
	{
	    free_string(ch->hunting);
	    ch->hunting = str_dup( "" );
	    send_to_char( "You stop hunting your prey.\n\r", ch );
	}
	else send_to_char( "Who do you wish to hunt?\n\r", ch );
	return;
    }
    if (!str_cmp(arg,ch->name))
    {
	send_to_char("How can you hunt yourself?\n\r",ch);
	return;
    }
    ch->hunting = str_dup(arg);
    send_to_char( "Ok.\n\r", ch );
    return;
}

void check_hunt( CHAR_DATA *ch )
{
    CHAR_DATA *victim;
    bool found = FALSE;
    int direction = 0;
    ROOM_INDEX_DATA *in_room;
    in_room = ch->in_room;
    if (!IS_NPC(ch) && number_percent() > ch->pcdata->learned[gsn_track])
    {
	send_to_char("You cannot sense any trails from this room.\n\r",ch);
	free_string(ch->hunting);
	ch->hunting = str_dup( "" );
	return;
    }
    if (check_track(ch,0)) {found = TRUE;direction = ch->in_room->track_dir[0];}
    else if (check_track(ch,1)) {found = TRUE;direction = ch->in_room->track_dir[1];}
    else if (check_track(ch,2)) {found = TRUE;direction = ch->in_room->track_dir[2];}
    else if (check_track(ch,3)) {found = TRUE;direction = ch->in_room->track_dir[3];}
    else if (check_track(ch,4)) {found = TRUE;direction = ch->in_room->track_dir[4];}
    else if ( ( victim = get_char_room( ch, ch->hunting ) ) == NULL )
    {
	send_to_char("You cannot sense any trails from this room.\n\r",ch);
	free_string(ch->hunting);
	ch->hunting = str_dup( "" );
	return;
    }
    if (strlen(ch->hunting) < 2) return;
    if ( ( victim = get_char_room( ch, ch->hunting ) ) != NULL ) return;
    act("$n carefully examines the ground for tracks.",ch,NULL,NULL,TO_ROOM);
    move_char(ch,direction);
    if (in_room == ch->in_room || victim != NULL)
    {
	free_string(ch->hunting);
	ch->hunting = str_dup( "" );
    }
    return;
}

void add_tracks( CHAR_DATA *ch, int direction )
{
    int loop;

    if (IS_NPC(ch)) return;
    if (IS_CLASS(ch, CLASS_WEREWOLF) && ch->power[DISC_WERE_LYNX] > 0)
	return;
	if (IS_CLASS(ch, CLASS_NINJA) && ch->pcdata->powers[NPOWER_SORA] >= 4)
	return;
    if (IS_ITEMAFF(ch, ITEMA_STALKER)) return;
    for ( loop = 0; loop <= 4; loop++ )
    {
    	if (ch->in_room->track[loop] != NULL && !str_cmp(ch->in_room->track[loop],ch->name))
    	{
	    free_string(ch->in_room->track[loop]);
	    ch->in_room->track[loop] = str_dup("");
    	}
    }
    if (strlen(ch->in_room->track[0]) < 2)
    {
	free_string(ch->in_room->track[0]);
	ch->in_room->track[0]     = str_dup(ch->pcdata->switchname);
	ch->in_room->track_dir[0] = direction;
    }
    else if (strlen(ch->in_room->track[1]) < 2)
    {
	free_string(ch->in_room->track[1]);
	ch->in_room->track[1]     = str_dup(ch->pcdata->switchname);
	ch->in_room->track_dir[1] = direction;
    }
    else if (strlen(ch->in_room->track[2]) < 2)
    {
	free_string(ch->in_room->track[2]);
	ch->in_room->track[2]     = str_dup(ch->pcdata->switchname);
	ch->in_room->track_dir[2] = direction;
    }
    else if (strlen(ch->in_room->track[3]) < 2)
    {
	free_string(ch->in_room->track[3]);
	ch->in_room->track[3]     = str_dup(ch->pcdata->switchname);
	ch->in_room->track_dir[3] = direction;
    }
    else if (strlen(ch->in_room->track[4]) < 2)
    {
	free_string(ch->in_room->track[4]);
	ch->in_room->track[4]     = str_dup(ch->pcdata->switchname);
	ch->in_room->track_dir[4] = direction;
    }
    else
    {
	free_string(ch->in_room->track[0]);
	ch->in_room->track[0]     = str_dup(ch->in_room->track[1]);
	ch->in_room->track_dir[0] = ch->in_room->track_dir[1];
	free_string(ch->in_room->track[1]);
	ch->in_room->track[1]     = str_dup(ch->in_room->track[2]);
	ch->in_room->track_dir[1] = ch->in_room->track_dir[2];
	free_string(ch->in_room->track[2]);
	ch->in_room->track[2]     = str_dup(ch->in_room->track[3]);
	ch->in_room->track_dir[2] = ch->in_room->track_dir[3];
	free_string(ch->in_room->track[3]);
	ch->in_room->track[3]     = str_dup(ch->in_room->track[4]);
	ch->in_room->track_dir[3] = ch->in_room->track_dir[4];
	free_string(ch->in_room->track[4]);
	ch->in_room->track[4]     = str_dup(ch->name);
	ch->in_room->track_dir[4] = direction;
    }
    return;
}

bool check_track( CHAR_DATA *ch, int direction )
{
    CHAR_DATA *victim;
    char buf [MAX_INPUT_LENGTH];
    char vict [MAX_INPUT_LENGTH];
    int door;

    strcpy(vict,ch->hunting);
    if (!str_cmp(ch->hunting,vict))
    {
	if ( ( victim = get_char_room( ch, vict ) ) != NULL )
	{
	    act("You have found $N!",ch,NULL,victim,TO_CHAR);
	    free_string(ch->hunting);
	    ch->hunting = str_dup( "" );
	    return TRUE;
	}
    }
    if (strlen(ch->in_room->track[direction]) < 2) return FALSE;
    if (!str_cmp(ch->in_room->track[direction],ch->name)) return FALSE;
    if (strlen(ch->hunting) > 1 && str_cmp(ch->in_room->track[direction],ch->hunting)) return FALSE;
    door = ch->in_room->track_dir[direction];
    sprintf(buf,"You sense the trail of %s leading $T from here.",ch->in_room->track[direction]);
    act( buf, ch, NULL, dir_name[door], TO_CHAR );
    return TRUE;
}

void do_roll( CHAR_DATA *ch, char *argument )
{
    OBJ_DATA *obj;
    char arg[MAX_INPUT_LENGTH];

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch, CLASS_DEMON))
    {
	stc("Huh?\n\r",ch);
	return;
    }

    if ( ( obj = ch->pcdata->chobj ) == NULL )
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }

    if ( obj->chobj == NULL || obj->chobj != ch )
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }

    if ( obj->in_room == NULL )
    {
	send_to_char("You are unable to move.\n\r",ch);
	return;
    }

    if      (!str_cmp(arg,"n") || !str_cmp(arg,"north")) do_north(ch,"");
    else if (!str_cmp(arg,"s") || !str_cmp(arg,"south")) do_south(ch,"");
    else if (!str_cmp(arg,"e") || !str_cmp(arg,"east" )) do_east(ch,"");
    else if (!str_cmp(arg,"w") || !str_cmp(arg,"west" )) do_west(ch,"");
    else if (!str_cmp(arg,"u") || !str_cmp(arg,"up"   )) do_up(ch,"");
    else if (!str_cmp(arg,"d") || !str_cmp(arg,"down" )) do_down(ch,"");
    else
    {
	send_to_char("Do you wish to roll north, south, east, west, up or down?\n\r",ch);
	return;
    }
    obj_from_room(obj);
    obj_to_room(obj,ch->in_room);
    return;
}

void do_leap( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    OBJ_DATA *container;
    OBJ_DATA *obj;
    char arg[MAX_INPUT_LENGTH];

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch,CLASS_DEMON) && !IS_SET(ch->special,SPC_CHAMPION))
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }

    if ( ( obj = ch->pcdata->chobj ) == NULL )
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }

    if ( obj->chobj == NULL || obj->chobj != ch )
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }

    if ( obj->in_room != NULL && arg[0] == '\0' )
    {
	send_to_char("Where do you want to leap?\n\r",ch);
	return;
    }

    if ( obj->in_room != NULL )
    {
	if ( ( victim = get_char_room( ch, arg ) ) != NULL )
	{
	    act("$p leaps into your hands.",victim,obj,NULL,TO_CHAR);
	    act("$p leaps into $n's hands.",victim,obj,NULL,TO_ROOM);
	    obj_from_room(obj);
	    obj_to_char(obj,victim);
	    return;
	}
	else if ( ( container = get_obj_room( ch, arg ) ) != NULL )
	{
	    if (container->item_type != ITEM_CONTAINER &&
		container->item_type != ITEM_CORPSE_NPC &&
		container->item_type != ITEM_CORPSE_PC)
	    {
		send_to_char("You cannot leap into that sort of object.\n\r",ch);
		return;
	    }
	    act("$p leap into $P.",ch,obj,container,TO_CHAR);
	    act("$p leaps into $P.",ch,obj,container,TO_ROOM);
	    obj_from_room(obj);
	    obj_to_obj(obj,container);
	    return;
	}
	else send_to_char( "Nothing here by that name.\n\r",ch );
	return;
    }
    if ( obj->carried_by != NULL )
    {
	act("$p leaps from your hands.",obj->carried_by,obj,NULL,TO_CHAR);
	act("$p leaps from $n's hands.",obj->carried_by,obj,NULL,TO_ROOM);
	obj_from_char(obj);
	obj_to_room(obj,ch->in_room);
	return;
    }
    else if ( (container = obj->in_obj) != NULL && container->in_room != NULL )
    {
	obj_from_obj(obj);
	obj_to_room(obj,container->in_room);
	char_from_room(ch);
	char_to_room(ch,container->in_room);
	act("$p leap from $P.",ch,obj,container,TO_CHAR);
	act("$p leaps from $P.",ch,obj,container,TO_ROOM);
	return;
    }
    if (obj->in_room != NULL)
	send_to_char("You seem unable to leap anywhere.\n\r",ch);
    else
	send_to_char("You seem to be stuck!\n\r",ch);
    return;
}


void drow_hate( CHAR_DATA *ch)
{
	CHAR_DATA *vch;
	CHAR_DATA *vch_next;

	if (IS_NPC(ch)) return;
	
	if (!IS_CLASS(ch, CLASS_DROW) || !IS_SET(ch->newbits, NEW_DROWHATE)) return;
	
	if (number_percent() < 25) {

	for (vch = char_list; vch != NULL; vch = vch_next)
	{
	vch_next = vch->next;
	if ( ch == vch) continue;
	if ( vch->in_room == NULL) continue;
	if ( vch->in_room == ch->in_room) {
		send_to_char("You scream out in hatred and attack!\n\r", ch );
		act("$n screams out in hatred and attacks!",ch,NULL,vch,TO_ROOM);
		do_kill(ch,vch->name);
		return;}
	}
	}

	return;
}


1073 

 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
 *                                                                         *
 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
 *  Chastain, Michael Quan, and Mitchell Tse.                              *
 *                                                                         *
 *  In order to use any part of this Merc Diku Mud, you must comply with   *
 *  both the original Diku license in 'license.doc' as well the Merc       *
 *  license in 'license.txt'.  In particular, you may not remove either of *
 *  these copyright notices.                                               *
 *                                                                         *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 ***************************************************************************/

#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"



/*
 * Local functions.
 */
#define CD CHAR_DATA
void	get_obj		args( ( CHAR_DATA *ch, OBJ_DATA *obj,
			    OBJ_DATA *container ) );
CD *	find_keeper	args( ( CHAR_DATA *ch ) );
int	get_cost	args( ( CHAR_DATA *keeper, OBJ_DATA *obj, bool fBuy ) );
void	sheath		args( ( CHAR_DATA *ch, bool right ) );
void	draw		args( ( CHAR_DATA *ch, bool right ) );
char	*special_item_name args( ( OBJ_DATA *obj ) );
void 	call_all	args( ( CHAR_DATA *ch ) );
#undef	CD




void do_call( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;
    CHAR_DATA *victim = NULL;
    ROOM_INDEX_DATA *chroom;
    ROOM_INDEX_DATA *objroom;

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char( "What object do you wish to call?\n\r", ch );
	return;
    }

    if (IS_NPC(ch)) {send_to_char("Not while switched.\n\r",ch); return;}

    if (!IS_HEAD(ch, LOST_HEAD))
    {
    	act("Your eyes flicker with yellow energy.",ch,NULL,NULL,TO_CHAR);
    	act("$n's eyes flicker with yellow energy.",ch,NULL,NULL,TO_ROOM);
    }

    if (!str_cmp(arg,"all"))
    {
	call_all(ch);
	return;
    }

    if ( ( obj = get_obj_world( ch, arg ) ) == NULL )
    {
	send_to_char( "Nothing like that in hell, earth, or heaven.\n\r", ch );
	return;
    }

    if (obj->questowner == NULL || strlen(obj->questowner) < 2 ||
	str_cmp(obj->questowner,ch->pcdata->switchname) || obj->item_type == ITEM_PAGE)
    {
	send_to_char( "Nothing happens.\n\r", ch );
	return;
    }

    if (obj->carried_by != NULL && obj->carried_by != ch)
    {
	victim = obj->carried_by;
	if (!IS_NPC(victim) && victim->desc != NULL && victim->desc->connected != CON_PLAYING) return;
    	act("$p suddenly vanishes from your hands!",victim,obj,NULL,TO_CHAR);
    	act("$p suddenly vanishes from $n's hands!",victim,obj,NULL,TO_ROOM);
	obj_from_char(obj);
    }
    else if (obj->in_room != NULL)
    {
    	chroom = ch->in_room;
    	objroom = obj->in_room;
    	char_from_room(ch);
    	char_to_room(ch,objroom);
    	act("$p vanishes from the ground!",ch,obj,NULL,TO_ROOM);
	if (chroom == objroom) act("$p vanishes from the ground!",ch,obj,NULL,TO_CHAR);
    	char_from_room(ch);
    	char_to_room(ch,chroom);
	obj_from_room(obj);
    }
    else if (obj->in_obj != NULL) obj_from_obj(obj);
    else
    {
	if (!IS_HEAD(ch, LOST_HEAD))
	    send_to_char( "Nothing happens.\n\r", ch );
	return;
    }

    obj_to_char(obj,ch);
    if (IS_SET(obj->extra_flags,ITEM_SHADOWPLANE))
	REMOVE_BIT(obj->extra_flags,ITEM_SHADOWPLANE);
    act("$p materializes in your hands.",ch,obj,NULL,TO_CHAR);
    act("$p materializes in $n's hands.",ch,obj,NULL,TO_ROOM);
    do_autosave(ch,"");
    if (victim != NULL) do_autosave(victim,"");
    return;
}

void call_all( CHAR_DATA *ch )
{
    OBJ_DATA *obj;
    OBJ_DATA *in_obj;
    CHAR_DATA *victim = NULL;
    DESCRIPTOR_DATA *d;
    ROOM_INDEX_DATA *chroom;
    ROOM_INDEX_DATA *objroom;
    bool found = FALSE;

    for ( obj = object_list; obj != NULL; obj = obj->next )
    {
	if ( obj->questowner == NULL || strlen(obj->questowner) < 2 || 
	    str_cmp( ch->pcdata->switchname, obj->questowner ) || obj->item_type == ITEM_PAGE)
	    continue;

	found = TRUE;

	for ( in_obj = obj; in_obj->in_obj != NULL; in_obj = in_obj->in_obj )
	    ;

	if (in_obj->carried_by != NULL)
	{
	    if (in_obj->carried_by == ch) continue;
	}

	if (obj->carried_by != NULL)
	{
	    if (obj->carried_by == ch || obj->carried_by->desc == NULL || 
		obj->carried_by->desc->connected != CON_PLAYING) 
	    {
		if (!IS_NPC(obj->carried_by)) return;
	    }
	    act("$p suddenly vanishes from your hands!",obj->carried_by,obj,NULL,TO_CHAR);
	    act("$p suddenly vanishes from $n's hands!",obj->carried_by,obj,NULL,TO_ROOM);
	    SET_BIT(obj->carried_by->extra, EXTRA_CALL_ALL);
	    obj_from_char(obj);
	}
	else if (obj->in_room != NULL)
	{
	    chroom = ch->in_room;
	    objroom = obj->in_room;
	    char_from_room(ch);
	    char_to_room(ch,objroom);
	    act("$p vanishes from the ground!",ch,obj,NULL,TO_ROOM);
	    if (chroom == objroom) act("$p vanishes from the ground!",ch,obj,NULL,TO_CHAR);
	    char_from_room(ch);
	    char_to_room(ch,chroom);
	    obj_from_room(obj);
	}
	else if (obj->in_obj != NULL) obj_from_obj(obj);
	else continue;
	obj_to_char(obj,ch);
	if (IS_SET(obj->extra_flags,ITEM_SHADOWPLANE))
	    REMOVE_BIT(obj->extra_flags,ITEM_SHADOWPLANE);
	if (!IS_HEAD(ch, LOST_HEAD))
	{
	    act("$p materializes in your hands.",ch,obj,NULL,TO_CHAR);
	    act("$p materializes in $n's hands.",ch,obj,NULL,TO_ROOM);
	}
    }

    if ( !found && !IS_HEAD(ch, LOST_HEAD) )
	send_to_char( "Nothing happens.\n\r", ch );

    for ( d = descriptor_list; d != NULL; d = d->next )
    {
	if ( d->connected != CON_PLAYING ) continue;
	if ( (victim = d->character) == NULL ) continue;
	if ( IS_NPC(victim) ) continue;
	if ( ch != victim && !IS_EXTRA(victim,EXTRA_CALL_ALL) ) continue;
	REMOVE_BIT(victim->extra, EXTRA_CALL_ALL);
	do_autosave(victim,"");
    }
    return;
}

void get_obj( CHAR_DATA *ch, OBJ_DATA *obj, OBJ_DATA *container )
{
    OBJ_DATA *obj2;
    OBJ_DATA *obj_next;
    ROOM_INDEX_DATA *objroom;
    bool move_ch = FALSE;

    /* Objects should only have a shadowplane flag when on the floor */
    if  ( IS_AFFECTED(ch,AFF_SHADOWPLANE) &&
	obj->in_room != NULL &&
	(!IS_SET(obj->extra_flags, ITEM_SHADOWPLANE) ) )
    {
	send_to_char( "Your hand passes right through it!\n\r", ch );
	return;
    }
    if  (!IS_AFFECTED(ch,AFF_SHADOWPLANE) &&
	obj->in_room != NULL &&
	( IS_SET(obj->extra_flags, ITEM_SHADOWPLANE) ) )
    {
	send_to_char( "Your hand passes right through it!\n\r", ch );
	return;
    }
    if ( !CAN_WEAR(obj, ITEM_TAKE) )
    {
	send_to_char( "You can't take that.\n\r", ch );
	return;
    }

    if ( ch->carry_number + 1 > can_carry_n( ch ) )
    {
	act( "$d: you can't carry that many items.",
	    ch, NULL, obj->name, TO_CHAR );
	return;
    }

    if ( ch->carry_weight + get_obj_weight( obj ) > can_carry_w( ch ) )
    {
	act( "$d: you can't carry that much weight.",
	    ch, NULL, obj->name, TO_CHAR );
	return;
    }

    if ( container != NULL )
    {

    	if  ( IS_AFFECTED(ch,AFF_SHADOWPLANE) &&
	     !IS_SET(container->extra_flags, ITEM_SHADOWPLANE) &&
	     (container->carried_by == NULL || container->carried_by != ch) )
    	{
	    send_to_char( "Your hand passes right through it!\n\r", ch );
	    return;
    	}
    	if  (!IS_AFFECTED(ch,AFF_SHADOWPLANE) &&
	      IS_SET(container->extra_flags, ITEM_SHADOWPLANE) &&
	     (container->carried_by == NULL || container->carried_by != ch) )
    	{
	    send_to_char( "Your hand passes right through it!\n\r", ch );
	    return;
        }
	act( "You get $p from $P.", ch, obj, container, TO_CHAR );
	act( "$n gets $p from $P.", ch, obj, container, TO_ROOM );
	for ( obj2 = container->contains; obj2 != NULL; obj2 = obj_next )
	{
	    obj_next = obj2->next_content;
	    if ( obj2->chobj != NULL )
		{act( "A hand reaches inside $P and takes $p out.", obj2->chobj, obj, container, TO_CHAR );
		move_ch = TRUE;}
	}
	obj_from_obj( obj );
    }
    else
    {
	act( "You pick up $p.", ch, obj, container, TO_CHAR );
	act( "$n picks $p up.", ch, obj, container, TO_ROOM );
	if (obj != NULL) obj_from_room( obj );
    }

    if ( obj->item_type == ITEM_MONEY )
    {
	ch->gold += obj->value[0];
	extract_obj( obj );
    }
    else
    {
	obj_to_char( obj, ch );
	if ( move_ch && obj->chobj != NULL )
	{
	    if (obj->carried_by != NULL && obj->carried_by != obj->chobj)
	    	objroom = get_room_index(obj->carried_by->in_room->vnum);
	    else objroom = NULL;
	    if (objroom != NULL && get_room_index(obj->chobj->in_room->vnum) != objroom)
	    {
	    	char_from_room(obj->chobj);
	    	char_to_room(obj->chobj,objroom);
		do_look(obj->chobj,"auto");
	    }
	}
    	if (IS_AFFECTED(ch,AFF_SHADOWPLANE) &&
	    (IS_SET(obj->extra_flags, ITEM_SHADOWPLANE) ) )
	    REMOVE_BIT(obj->extra_flags, ITEM_SHADOWPLANE);
    }

    return;
}



void do_newbiepack( CHAR_DATA *ch, char *argument )
{

        char buf[MAX_STRING_LENGTH];

        if (IS_SET(ch->newbits,NEWBIE_PACK))
        {
        send_to_char("Due to abuse you now may only create 1 newbie pack\n\r",ch);
        return;
        }

        else if (ch->level >= 4)
        {
        send_to_char("You must be a mortal or avatar to create a newbie pack!\n\r",ch);
        return;
}

        else if (ch->level == 1)
        {
        ch->level = 12;
        ch->trust = 12;
        do_oload(ch,"3032");
        do_oload(ch,"30333");
        do_oload(ch,"30334");
        do_oload(ch,"30335");
        do_oload(ch,"30336");
        do_oload(ch,"30337");
	do_oload(ch,"30338");
        do_oload(ch,"30339");
        do_oload(ch,"30339");
        do_oload(ch,"30340");
        do_oload(ch,"30340");
        do_oload(ch,"30341");
        do_oload(ch,"30342");
        do_oload(ch,"30342");
        do_oload(ch,"30343");
        do_oload(ch,"30343");
        do_oload(ch,"30344");
        do_oload(ch,"2622");
        do_oload(ch,"2204");
        ch->level = 1;
        ch->trust = 0;
        do_open(ch,"pack");
        sprintf(buf,"all pack");
        do_put(ch,buf);
        send_to_char("You now have a newbie pack!\n\r", ch);
        SET_BIT(ch->newbits,NEWBIE_PACK);
        }
ch->level = 1;
ch->trust = 0;
return;
}

void do_get( CHAR_DATA *ch, char *argument )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;
    OBJ_DATA *obj_next;
    OBJ_DATA *container;
    bool found;

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if (IS_AFFECTED(ch,AFF_ETHEREAL) )
    {
	send_to_char( "You cannot pick things up while ethereal.\n\r", ch );
	return;
    }

    /* Get type. */
    if ( arg1[0] == '\0' )
    {
	send_to_char( "Get what?\n\r", ch );
	return;
    }

    if ( arg2[0] == '\0' )
    {
	if ( str_cmp( arg1, "all" ) && str_prefix( "all.", arg1 ) )
	{
	    /* 'get obj' */
	    obj = get_obj_list( ch, arg1, ch->in_room->contents );
	    if ( obj == NULL )
	    {
		act( "I see no $T here.", ch, NULL, arg1, TO_CHAR );
		return;
	    }
	if (IS_NPC(ch) && IS_SET(obj->quest, QUEST_ARTIFACT)) {
	send_to_char("You can't pick that up.\n\r", ch );
	return;}
	if (IS_NPC(ch) && obj->item_type ==  ITEM_KINGDOM_POWER) {
	send_to_char("You can't pick that up.\n\r", ch );
	return;}

	    get_obj( ch, obj, NULL );
	}
	else
	{
	    /* 'get all' or 'get all.obj' */
	    found = FALSE;
	    for ( obj = ch->in_room->contents; obj != NULL; obj = obj_next )
	    {
		obj_next = obj->next_content;
		if ( ( arg1[3] == '\0' || is_name( &arg1[4], obj->name ) )
		&&   can_see_obj( ch, obj ) )
		{
		    found = TRUE;
		    get_obj( ch, obj, NULL );
		}
	    }

	    if ( !found ) 
	    {
		if ( arg1[3] == '\0' )
		    send_to_char( "I see nothing here.\n\r", ch );
		else
		    act( "I see no $T here.", ch, NULL, &arg1[4], TO_CHAR );
	    }
	}
    }
    else
    {
	/* 'get ... container' */
	if ( !str_cmp( arg2, "all" ) || !str_prefix( "all.", arg2 ) )
	{
	    send_to_char( "You can't do that.\n\r", ch );
	    return;
	}

	if ( ( container = get_obj_here( ch, arg2 ) ) == NULL )
	{
	    act( "I see no $T here.", ch, NULL, arg2, TO_CHAR );
	    return;
	}

	switch ( container->item_type )
	{
	default:
	    send_to_char( "That's not a container.\n\r", ch );
	    return;

	case ITEM_CONTAINER:
	case ITEM_CORPSE_NPC:
	    break;

	case ITEM_CORPSE_PC:
	    {
		char name[MAX_INPUT_LENGTH];
		char *pd;

		if ( IS_NPC(ch) )
		{
		    send_to_char( "You can't do that.\n\r", ch );
		    return;
		}

		pd = container->short_descr;
		pd = one_argument( pd, name );
		pd = one_argument( pd, name );
		pd = one_argument( pd, name );
/*
		if ( str_cmp( name, ch->name ) && !IS_IMMORTAL(ch) )
		{
		    send_to_char( "You can't do that.\n\r", ch );
		    return;
		}
*/
	    }
	}

	if ( IS_SET(container->value[1], CONT_CLOSED) )
	{
	    act( "The $d is closed.", ch, NULL, container->name, TO_CHAR );
	    return;
	}

	if ( str_cmp( arg1, "all" ) && str_prefix( "all.", arg1 ) )
	{
	    /* 'get obj container' */
	    obj = get_obj_list( ch, arg1, container->contains );
	    if ( obj == NULL)
	    {
		act( "I see nothing like that in the $T.",
		    ch, NULL, arg2, TO_CHAR );
		return;
	    }
	    get_obj( ch, obj, container );
	}
	else
	{
	    /* 'get all container' or 'get all.obj container' */
	    found = FALSE;
	    for ( obj = container->contains; obj != NULL; obj = obj_next )
	    {
		obj_next = obj->next_content;
		if ( ( arg1[3] == '\0' || is_name( &arg1[4], obj->name ) )
		&&   can_see_obj( ch, obj ) )
		{
		    found = TRUE;
		    get_obj( ch, obj, container );
		}
	    }

	    if ( !found )
	    {
		if ( arg1[3] == '\0' )
		    act( "I see nothing in the $T.",
			ch, NULL, arg2, TO_CHAR );
		else
		    act( "I see nothing like that in the $T.",
			ch, NULL, arg2, TO_CHAR );
	    }
	}
    }
    do_autosave(ch,"");
    return;
}



void do_put( CHAR_DATA *ch, char *argument )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    OBJ_DATA *container;
    OBJ_DATA *obj;
    OBJ_DATA *obj2;
    OBJ_DATA *obj_next;
    OBJ_DATA *obj_next2;
    ROOM_INDEX_DATA *objroom = get_room_index(ROOM_VNUM_IN_OBJECT);

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if ( arg1[0] == '\0' || arg2[0] == '\0' )
    {
	send_to_char( "Put what in what?\n\r", ch );
	return;
    }

    if ( !str_cmp( arg2, "all" ) || !str_prefix( "all.", arg2 ) )
    {
	send_to_char( "You can't do that.\n\r", ch );
	return;
    }
/* I'll leave this out for now - KaVir
    if ( ( ( container = get_obj_carry( ch, arg2 ) ) == NULL ) &&
         ( ( container = get_obj_wear(  ch, arg2 ) ) == NULL ) &&
	   ( IS_AFFECTED(ch,AFF_ETHEREAL) ) )
    {
	send_to_char( "You can't let go of it!\n\r", ch );
	return;
    }
*/
    if ( ( container = get_obj_here( ch, arg2 ) ) == NULL )
    {
	act( "I see no $T here.", ch, NULL, arg2, TO_CHAR );
	return;
    }

    if ( container->item_type != ITEM_CONTAINER )
    {
	send_to_char( "That's not a container.\n\r", ch );
	return;
    }

    if ( IS_SET(container->value[1], CONT_CLOSED) )
    {
	act( "The $d is closed.", ch, NULL, container->name, TO_CHAR );
	return;
    }

    if ( str_cmp( arg1, "all" ) && str_prefix( "all.", arg1 ) )
    {
	/* 'put obj container' */
	if ( ( obj = get_obj_carry( ch, arg1 ) ) == NULL )
	{
	    send_to_char( "You do not have that item.\n\r", ch );
	    return;
	}

	if ( obj == container )
	{
	    send_to_char( "You can't fold it into itself.\n\r", ch );
	    return;
	}

	if ( IS_SET( obj->quest, QUEST_ARTIFACT) )
	{
	    send_to_char("You cannot put artifacts in a container.\n\r",ch);
	    return;
	}

	if (obj->item_type == ITEM_KINGDOM_POWER) {
	send_to_char("You can't put that there.\n\r", ch );
	return;}

	if ( !can_drop_obj( ch, obj ) )
	{
	    send_to_char( "You can't let go of it.\n\r", ch );
	    return;
	}

	if ( get_obj_weight( obj ) + get_obj_weight( container )
	     > container->value[0] )
	{
	    send_to_char( "It won't fit.\n\r", ch );
	    return;
	}

	for ( obj2 = container->contains; obj2 != NULL; obj2 = obj_next2 )
	{
	    obj_next2 = obj2->next_content;
	    if ( obj2->chobj != NULL && obj != obj2)
		act( "A hand reaches inside $P and drops $p.", obj2->chobj, obj, container, TO_CHAR );
	}
	obj_from_char( obj );
	obj_to_obj( obj, container );
	act( "$n puts $p in $P.", ch, obj, container, TO_ROOM );
	act( "You put $p in $P.", ch, obj, container, TO_CHAR );
    }
    else
    {
	/* 'put all container' or 'put all.obj container' */
	for ( obj = ch->carrying; obj != NULL; obj = obj_next )
	{
	    obj_next = obj->next_content;

	    if ( ( arg1[3] == '\0' || is_name( &arg1[4], obj->name ) )
	    &&   can_see_obj( ch, obj )
	    &&   obj->wear_loc == WEAR_NONE
	    &&   obj != container
	    &&   !IS_SET( obj->quest, QUEST_ARTIFACT)
	    &&   can_drop_obj( ch, obj )
	    &&   get_obj_weight( obj ) + get_obj_weight( container )
		 <= container->value[0] )
	    {
		for ( obj2 = container->contains; obj2 != NULL; obj2 = obj_next2 )
		{
		    obj_next2 = obj2->next_content;
		    if ( obj2->chobj != NULL && obj2->chobj->in_room != NULL)
		    {
			if (objroom != get_room_index(obj2->chobj->in_room->vnum))
			{
		    	    char_from_room(obj2->chobj);
		    	    char_to_room(obj2->chobj,objroom);
			    do_look(obj2->chobj,"auto");
			}
			if (obj != obj2)
			    act( "A hand reaches inside $P and drops $p.", obj2->chobj, obj, container, TO_CHAR );
		    }
		}
		obj_from_char( obj );
		obj_to_obj( obj, container );
		act( "$n puts $p in $P.", ch, obj, container, TO_ROOM );
		act( "You put $p in $P.", ch, obj, container, TO_CHAR );
	    }
	}
    }
    do_autosave(ch,"");
    return;
}



void do_drop( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;
    OBJ_DATA *obj_next;
    bool found;

    argument = one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char( "Drop what?\n\r", ch );
	return;
    }

    if ( is_number( arg ) )
    {
	/* 'drop NNNN coins' */
	int amount;

	amount   = atoi(arg);
	argument = one_argument( argument, arg );
	if ( amount <= 0
	|| ( str_cmp( arg, "coins" ) && str_cmp( arg, "coin" ) ) )
	{
	    send_to_char( "Sorry, you can't do that.\n\r", ch );
	    return;
	}

	/* Otherwise causes complications if there's a pile on each plane */
	if (IS_AFFECTED(ch,AFF_SHADOWPLANE) )
	{
	    send_to_char( "You cannot drop coins in the shadowplane.\n\r", ch );
	    return;
	}

	if ( ch->gold < amount )
	{
	    send_to_char( "You haven't got that many coins.\n\r", ch );
	    return;
	}

	ch->gold -= amount;

	for ( obj = ch->in_room->contents; obj != NULL; obj = obj_next )
	{
	    obj_next = obj->next_content;

	    switch ( obj->pIndexData->vnum )
	    {
	    case OBJ_VNUM_MONEY_ONE:
		amount += 1;
		extract_obj( obj );
		break;

	    case OBJ_VNUM_MONEY_SOME:
		amount += obj->value[0];
		extract_obj( obj );
		break;
	    }
	}
	obj_to_room( create_money( amount ), ch->in_room );
	act( "$n drops some gold.", ch, NULL, NULL, TO_ROOM );
	send_to_char( "OK.\n\r", ch );
	do_autosave(ch,"");
	return;
    }

    if ( str_cmp( arg, "all" ) && str_prefix( "all.", arg ) )
    {
	/* 'drop obj' */
	if ( ( obj = get_obj_carry( ch, arg ) ) == NULL )
	{
	    send_to_char( "You do not have that item.\n\r", ch );
	    return;
	}

	if ( !can_drop_obj( ch, obj ) )
	{
	    send_to_char( "You can't let go of it.\n\r", ch );
	    return;
	}

	obj_from_char( obj );
	obj_to_room( obj, ch->in_room );
	/* Objects should only have a shadowplane flag when on the floor */
	if (IS_AFFECTED(ch,AFF_SHADOWPLANE) &&
	    (!IS_SET(obj->extra_flags, ITEM_SHADOWPLANE) ) )
	    SET_BIT(obj->extra_flags, ITEM_SHADOWPLANE);
	act( "$n drops $p.", ch, obj, NULL, TO_ROOM );
	act( "You drop $p.", ch, obj, NULL, TO_CHAR );
    }
    else
    {
	/* 'drop all' or 'drop all.obj' */
	found = FALSE;
	for ( obj = ch->carrying; obj != NULL; obj = obj_next )
	{
	    obj_next = obj->next_content;

	    if ( ( arg[3] == '\0' || is_name( &arg[4], obj->name ) )
	    &&   can_see_obj( ch, obj )
	    &&   obj->wear_loc == WEAR_NONE
	    &&   can_drop_obj( ch, obj ) )
	    {
		found = TRUE;
		obj_from_char( obj );
		obj_to_room( obj, ch->in_room );
		/* Objects should only have a shadowplane flag when on the floor */
		if (IS_AFFECTED(ch,AFF_SHADOWPLANE) &&
		    (!IS_SET(obj->extra_flags, ITEM_SHADOWPLANE) ) )
		    SET_BIT(obj->extra_flags, ITEM_SHADOWPLANE);
		act( "$n drops $p.", ch, obj, NULL, TO_ROOM );
		act( "You drop $p.", ch, obj, NULL, TO_CHAR );
	    }
	}

	if ( !found )
	{
	    if ( arg[3] == '\0' )
		act( "You are not carrying anything.",
		    ch, NULL, arg, TO_CHAR );
	    else
		act( "You are not carrying any $T.",
		    ch, NULL, &arg[4], TO_CHAR );
	}
    }

    do_autosave(ch,"");
    return;
}



void do_give( CHAR_DATA *ch, char *argument )
{
    char arg1 [MAX_INPUT_LENGTH];
    char arg2 [MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    OBJ_DATA  *obj;

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if ( arg1[0] == '\0' || arg2[0] == '\0' )
    {
	send_to_char( "Give what to whom?\n\r", ch );
	return;
    }

    if ( is_number( arg1 ) )
    {
	/* 'give NNNN coins victim' */
	int amount;

	amount   = atoi(arg1);
	if ( amount <= 0
	|| ( str_cmp( arg2, "coins" ) && str_cmp( arg2, "coin" ) ) )
	{
	    send_to_char( "Sorry, you can't do that.\n\r", ch );
	    return;
	}

	argument = one_argument( argument, arg2 );
	if ( arg2[0] == '\0' )
	{
	    send_to_char( "Give what to whom?\n\r", ch );
	    return;
	}

	if ( ( victim = get_char_room( ch, arg2 ) ) == NULL )
	{
	    send_to_char( "They aren't here.\n\r", ch );
	    return;
	}

    	if (IS_AFFECTED(victim,AFF_ETHEREAL) )
    	{
	    send_to_char( "You cannot give things to ethereal people.\n\r", ch );
	    return;
    	}

	if ( ch->gold < amount )
	{
	    send_to_char( "You haven't got that much gold.\n\r", ch );
	    return;
	}

	ch->gold     -= amount;
	victim->gold += amount;
	act( "$n gives you some gold.", ch, NULL, victim, TO_VICT    );
	act( "$n gives $N some gold.",  ch, NULL, victim, TO_NOTVICT );
	act( "You give $N some gold.",  ch, NULL, victim, TO_CHAR    );
	send_to_char( "OK.\n\r", ch );
	return;
    }

    if ( ( obj = get_obj_carry( ch, arg1 ) ) == NULL )
    {
	send_to_char( "You do not have that item.\n\r", ch );
	return;
    }

    if ( obj->wear_loc != WEAR_NONE )
    {
	send_to_char( "You must remove it first.\n\r", ch );
	return;
    }

    

    if ( ( victim = get_char_room( ch, arg2 ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( IS_SET(obj->quest, QUEST_ARTIFACT) && IS_NPC(victim) )
    {
        stc("Behave.  Don't give artis to mobs.\n\r",ch);
	return;
    }

    if (obj->item_type == ITEM_KINGDOM_POWER && IS_NPC(victim)) {
	send_to_char("They don't want that.\n\r", ch );
	return;}


    if ( !can_drop_obj( ch, obj ) )
    {
	send_to_char( "You can't let go of it.\n\r", ch );
	return;
    }

    if (IS_AFFECTED(victim,AFF_ETHEREAL) )
    {
	send_to_char( "You cannot give things to ethereal people.\n\r", ch );
	return;
    }

    if ( victim->carry_number + 1 > can_carry_n( victim ) )
    {
	act( "$N has $S hands full.", ch, NULL, victim, TO_CHAR );
	return;
    }

    if ( victim->carry_weight + get_obj_weight( obj ) > can_carry_w( victim ) )
    {
	act( "$N can't carry that much weight.", ch, NULL, victim, TO_CHAR );
	return;
    }

    if ( !can_see_obj( victim, obj ) )
    {
	act( "$N can't see it.", ch, NULL, victim, TO_CHAR );
	return;
    }

    obj_from_char( obj );
    obj_to_char( obj, victim );
    act( "$n gives $p to $N.", ch, obj, victim, TO_NOTVICT );
    act( "$n gives you $p.",   ch, obj, victim, TO_VICT    );
    act( "You give $p to $N.", ch, obj, victim, TO_CHAR    );
    return;
}




void do_fill( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;
    OBJ_DATA *fountain;
    bool found;
    int liquid;

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char( "Fill what?\n\r", ch );
	return;
    }

    if ( ( obj = get_obj_carry( ch, arg ) ) == NULL )
    {
	send_to_char( "You do not have that item.\n\r", ch );
	return;
    }

    found = FALSE;
    for ( fountain = ch->in_room->contents; fountain != NULL;
	fountain = fountain->next_content )
    {
	if ( fountain->item_type == ITEM_FOUNTAIN )
	{
	    found = TRUE;
	    break;
	}
    }

    if ( !found )
    {
	send_to_char( "There is no fountain here!\n\r", ch );
	return;
    }

    if (IS_AFFECTED(ch, AFF_SHADOWPLANE) &&
	fountain->in_room != NULL &&
	!IS_SET(fountain->extra_flags, ITEM_SHADOWPLANE) )
    {
	send_to_char( "You are too insubstantual.\n\r", ch );
	return;
    }
    else if (!IS_AFFECTED(ch, AFF_SHADOWPLANE) &&
	fountain->in_room != NULL &&
	IS_SET(fountain->extra_flags, ITEM_SHADOWPLANE) )
    {
	send_to_char( "It is too insubstantual.\n\r", ch );
	return;
    }
    else if (IS_AFFECTED(ch,AFF_ETHEREAL) )
    {
	send_to_char( "You cannot fill containers while ethereal.\n\r", ch );
	return;
    }

    if ( obj->item_type != ITEM_DRINK_CON )
    {
	send_to_char( "You can't fill that.\n\r", ch );
	return;
    }

    if ( obj->value[1] >= obj->value[0] )
    {
	send_to_char( "Your container is already full.\n\r", ch );
	return;
    }

    if ( (obj->value[2] != fountain->value[2]) && obj->value[1] > 0)
    {
	send_to_char( "You cannot mix two different liquids.\n\r", ch );
	return;
    }

    act( "$n dips $p into $P.", ch, obj, fountain, TO_ROOM );
    act( "You dip $p into $P.", ch, obj, fountain, TO_CHAR );
    obj->value[2] = fountain->value[2];
    obj->value[1] = obj->value[0];
    liquid = obj->value[2];
    act( "$n fills $p with $T.", ch, obj, liq_table[liquid].liq_name, TO_ROOM );
    act( "You fill $p with $T.", ch, obj, liq_table[liquid].liq_name, TO_CHAR );
    return;
}



void do_drink( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;
    int amount;
    int liquid;

    one_argument( argument, arg );


    if ( arg[0] == '\0' )
    {
	for ( obj = ch->in_room->contents; obj; obj = obj->next_content )
	{
	    if ( obj->item_type == ITEM_FOUNTAIN )
		break;
	}

	if ( obj == NULL )
	{
	    send_to_char( "Drink what?\n\r", ch );
	    return;
	}
    }
    else
    {
	if ( ( obj = get_obj_here( ch, arg ) ) == NULL )
	{
	    send_to_char( "You can't find it.\n\r", ch );
	    return;
	}
    }

    if ( !IS_NPC(ch) && ch->pcdata->condition[COND_DRUNK] > 10 )
    {
	send_to_char( "You fail to reach your mouth.  *Hic*\n\r", ch );
	return;
    }

    switch ( obj->item_type )
    {
    default:
	send_to_char( "You can't drink from that.\n\r", ch );
	break;

    case ITEM_POTION:
	do_quaff(ch,obj->name);
	return;
    case ITEM_FOUNTAIN:
	if ( ( liquid = obj->value[2] ) >= LIQ_MAX )
	{
	    bug( "Do_drink: bad liquid number %d.", liquid );
	    liquid = obj->value[2] = 0;
	}

	if (IS_AFFECTED(ch, AFF_SHADOWPLANE) &&
		obj->in_room != NULL &&
		!IS_SET(obj->extra_flags, ITEM_SHADOWPLANE) )
	{
	    send_to_char( "You are too insubstantual.\n\r", ch );
	    break;
	}
	else if (!IS_AFFECTED(ch, AFF_SHADOWPLANE) &&
		obj->in_room != NULL &&
		IS_SET(obj->extra_flags, ITEM_SHADOWPLANE) )
	{
	    send_to_char( "It is too insubstantual.\n\r", ch );
	    break;
	}
    	else if (IS_AFFECTED(ch,AFF_ETHEREAL) )
    	{
	    send_to_char( "You can only drink from things you are carrying while ethereal.\n\r", ch );
	    return;
    	}

	if ( liquid != 13 && IS_CLASS(ch,CLASS_VAMPIRE) )
	{
	    send_to_char( "You can only drink blood.\n\r", ch );
	    break;
	}


	if ( liquid == 13 && IS_CLASS(ch, CLASS_VAMPIRE))
	{
	    ch->pcdata->condition[COND_THIRST] += number_range(200,300);
        }

	act( "$n drinks $T from $p.", ch, obj, liq_table[liquid].liq_name, TO_ROOM );
	act( "You drink $T from $p.", ch, obj, liq_table[liquid].liq_name, TO_CHAR );

	amount = number_range(25, 50);
	amount = UMIN(amount, obj->value[1]);
	
	gain_condition( ch, COND_DRUNK,
	    amount * liq_table[liquid].liq_affect[COND_DRUNK  ] );
	gain_condition( ch, COND_FULL,
	    amount * liq_table[liquid].liq_affect[COND_FULL   ] );
	gain_condition( ch, COND_THIRST,
	    amount * liq_table[liquid].liq_affect[COND_THIRST ] );

	if ( !IS_NPC(ch) && !IS_CLASS(ch, CLASS_VAMPIRE) &&
		ch->pcdata->condition[COND_DRUNK]  > 10 )
	    send_to_char( "You feel drunk.\n\r", ch );
	if ( !IS_NPC(ch) && !IS_CLASS(ch, CLASS_VAMPIRE) &&
		ch->pcdata->condition[COND_FULL]   > 50 )
	    send_to_char( "You are full.\n\r", ch );
	if ( !IS_NPC(ch) && !IS_CLASS(ch, CLASS_VAMPIRE) &&
		ch->pcdata->condition[COND_THIRST] > 50 )
	    send_to_char( "You do not feel thirsty.\n\r", ch );
	if ( !IS_NPC(ch) && IS_CLASS(ch, CLASS_VAMPIRE) &&
		ch->pcdata->condition[COND_THIRST] >= 20000/ch->generation
)
	    send_to_char( "Your blood thirst is sated.\n\r", ch );

	if ( obj->value[3] != 0 && (!IS_NPC(ch) && !IS_CLASS(ch, CLASS_VAMPIRE)))
	{
	    /* The shit was poisoned ! */
	    AFFECT_DATA af;

	    act( "$n chokes and gags.", ch, NULL, NULL, TO_ROOM );
	    send_to_char( "You choke and gag.\n\r", ch );
	    af.type      = gsn_poison;
	    af.duration  = 3 * amount;
	    af.location  = APPLY_NONE;
	    af.modifier  = 0;
	    af.bitvector = AFF_POISON;
	    affect_join( ch, &af );
	}
	break;

    case ITEM_DRINK_CON:
	if ( obj->value[1] <= 0 )
	{
	    send_to_char( "It is already empty.\n\r", ch );
	    return;
	}

	if ( ( liquid = obj->value[2] ) >= LIQ_MAX )
	{
	    bug( "Do_drink: bad liquid number %d.", liquid );
	    liquid = obj->value[2] = 0;
	}

	if ( liquid != 13 && IS_CLASS(ch,CLASS_VAMPIRE) )
	{
	    send_to_char( "You can only drink blood.\n\r", ch );
	    break;
	}


        if ( liquid == 13 && IS_CLASS(ch, CLASS_VAMPIRE))
        {
            ch->pcdata->condition[COND_THIRST] += number_range(200,300);
        }  

	act( "$n drinks $T from $p.", ch, obj, liq_table[liquid].liq_name, TO_ROOM );
	act( "You drink $T from $p.",
	    ch, obj, liq_table[liquid].liq_name, TO_CHAR );

	amount = number_range(25, 50);
	amount = UMIN(amount, obj->value[1]);
	
	gain_condition( ch, COND_DRUNK,
	    amount * liq_table[liquid].liq_affect[COND_DRUNK  ] );
	gain_condition( ch, COND_FULL,
	    amount * liq_table[liquid].liq_affect[COND_FULL   ] );
	gain_condition( ch, COND_THIRST,
	    amount * liq_table[liquid].liq_affect[COND_THIRST ] );

	if ( !IS_NPC(ch) && !IS_CLASS(ch, CLASS_VAMPIRE) &&
		ch->pcdata->condition[COND_DRUNK]  > 10 )
	    send_to_char( "You feel drunk.\n\r", ch );
	if ( !IS_NPC(ch) && !IS_CLASS(ch, CLASS_VAMPIRE) &&
		ch->pcdata->condition[COND_FULL]   > 50 )
	    send_to_char( "You are full.\n\r", ch );
	if ( !IS_NPC(ch) && !IS_CLASS(ch, CLASS_VAMPIRE) &&
		ch->pcdata->condition[COND_THIRST] > 50 )
	    send_to_char( "You do not feel thirsty.\n\r", ch );
	if ( !IS_NPC(ch) && IS_CLASS(ch, CLASS_VAMPIRE) &&
		ch->pcdata->condition[COND_THIRST] >= 20000 /
ch->generation )
	    send_to_char( "Your blood thirst is sated.\n\r", ch );
	
	if ( obj->value[3] != 0 && (!IS_NPC(ch) && !IS_CLASS(ch, CLASS_VAMPIRE)))
	{
	    /* The shit was poisoned ! */
	    AFFECT_DATA af;

	    act( "$n chokes and gags.", ch, NULL, NULL, TO_ROOM );
	    send_to_char( "You choke and gag.\n\r", ch );
	    af.type      = gsn_poison;
	    af.duration  = 3 * amount;
	    af.location  = APPLY_NONE;
	    af.modifier  = 0;
	    af.bitvector = AFF_POISON;
	    affect_join( ch, &af );
	}
	
	obj->value[1] -= amount;
	if ( obj->value[1] <= 0 )
	{
		obj->value[1] = 0;
	}
	break;
    }

    return;
}


void do_empty( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;
    int liquid;

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char( "Empty what?\n\r", ch );
	return;
    }

    if ( ( obj = get_obj_here( ch, arg ) ) == NULL )
    {
	send_to_char( "You can't find it.\n\r", ch );
	return;
    }

    switch ( obj->item_type )
    {
    default:
	send_to_char( "You cannot empty that.\n\r", ch );
	break;

    case ITEM_DRINK_CON:
	if ( obj->value[1] <= 0 )
	{
	    send_to_char( "It is already empty.\n\r", ch );
	    return;
	}

	if ( ( liquid = obj->value[2] ) >= LIQ_MAX )
	{
	    bug( "Do_drink: bad liquid number %d.", liquid );
	    liquid = obj->value[2] = 0;
	}

	act( "$n empties $T from $p.", ch, obj, liq_table[liquid].liq_name, TO_ROOM );
	act( "You empty $T from $p.",
	    ch, obj, liq_table[liquid].liq_name, TO_CHAR );
	
	obj->value[1] = 0;
	break;
    }

    return;
}



void do_eat( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;
    int level;

    one_argument( argument, arg );
    if ( arg[0] == '\0' )
    {
	send_to_char( "Eat what?\n\r", ch );
	return;
    }

    if ( ( obj = get_obj_carry( ch, arg ) ) == NULL )
    {
	send_to_char( "You do not have that item.\n\r", ch );
	return;
    }

    if ( !IS_IMMORTAL(ch) )
    {
	if ( !IS_NPC(ch) && IS_CLASS(ch, CLASS_VAMPIRE) && obj->item_type == ITEM_FOOD)
	{   
	    send_to_char( "You are unable to stomach it.\n\r", ch );
	    return;
	}

	if ( obj->item_type != ITEM_FOOD && obj->item_type != ITEM_PILL &&
	     obj->item_type != ITEM_EGG && obj->item_type != ITEM_QUEST 
	  && obj->item_type != ITEM_DTOKEN)
	{
	    if (IS_NPC(ch) || !IS_SET(ch->special,SPC_WOLFMAN) || 
		obj->item_type != ITEM_TRASH)
	    {
		send_to_char( "That's not edible.\n\r", ch );
		return;
	    }
	}

	if ( !IS_NPC(ch) && ch->pcdata->condition[COND_FULL] > 50 &&
	    obj->item_type != ITEM_TRASH && obj->item_type != ITEM_QUEST &&
	    obj->item_type != ITEM_PILL)
	{
	    send_to_char( "You are too full to eat more.\n\r", ch );
	    return;
	}
    }

    act( "$n eats $p.",  ch, obj, NULL, TO_ROOM );
    act( "You eat $p.", ch, obj, NULL, TO_CHAR );

    switch ( obj->item_type )
    {
    default:
	break;

    case ITEM_FOOD:
	if ( !IS_NPC(ch) )
	{
	    int condition;

	    condition = ch->pcdata->condition[COND_FULL];
	    gain_condition( ch, COND_FULL, obj->value[0] );
	    if ( condition == 0 && ch->pcdata->condition[COND_FULL] > 10 )
		send_to_char( "You are no longer hungry.\n\r", ch );
	    else if ( ch->pcdata->condition[COND_FULL] > 50 )
		send_to_char( "You are full.\n\r", ch );
	}

	if ( obj->value[3] != 0 )
	{
	    /* The shit was poisoned! */
	    AFFECT_DATA af;

	    act( "$n chokes and gags.", ch, NULL, NULL, TO_ROOM );
	    send_to_char( "You choke and gag.\n\r", ch );

	    af.type      = gsn_poison;
	    af.duration  = 2 * obj->value[0];
	    af.location  = APPLY_NONE;
	    af.modifier  = 0;
	    af.bitvector = AFF_POISON;
	    affect_join( ch, &af );
	}
	break;

    case ITEM_PILL:
	level = obj->value[0];
	if (level < 1) level = 1;
	if (level > MAX_SPELL) level = MAX_SPELL;

	obj_cast_spell( obj->value[1], level, ch, ch, NULL );
	obj_cast_spell( obj->value[2], level, ch, ch, NULL );
	obj_cast_spell( obj->value[3], level, ch, ch, NULL );
	if (ch->position == POS_FIGHTING) 
	{
	    if (!IS_IMMORTAL( ch))
		WAIT_STATE(ch, 6 );
	}
	break;

    case ITEM_QUEST:
	if ( !IS_NPC(ch) ) ch->pcdata->quest += obj->value[0];
	break;

    case ITEM_DTOKEN:
	if ( !IS_NPC(ch) && IS_CLASS(ch, CLASS_DEMON) )
           ch->pcdata->stats[DEMON_CURRENT] += obj->value[0];
	break;

    case ITEM_EGG:
	if ( !IS_NPC(ch) )
	{
	    int condition;

	    condition = ch->pcdata->condition[COND_FULL];
	    gain_condition( ch, COND_FULL, obj->value[1] );
	    if ( condition == 0 && ch->pcdata->condition[COND_FULL] > 10 )
		send_to_char( "You are no longer hungry.\n\r", ch );
	    else if ( ch->pcdata->condition[COND_FULL] > 50 )
		send_to_char( "You are full.\n\r", ch );
	}

	/* Note to myself...remember to set v2 for mobiles that hatch within
	 * the player (like aliens ;).  KaVir.
	 */

	if ( obj->value[3] != 0 )
	{
	    /* The shit was poisoned! */
	    AFFECT_DATA af;

	    act( "$n chokes and gags.", ch, NULL, NULL, TO_ROOM );
	    send_to_char( "You choke and gag.\n\r", ch );

	    af.type      = gsn_poison;
	    af.duration  = 2 * obj->value[0];
	    af.location  = APPLY_NONE;
	    af.modifier  = 0;
	    af.bitvector = AFF_POISON;
	    affect_join( ch, &af );
	}
	break;
    }

    if (obj != NULL) extract_obj( obj );
    return;
}



/*
 * Remove an object.
 */
bool remove_obj( CHAR_DATA *ch, int iWear, bool fReplace )
{
    OBJ_DATA *obj;

    if ( ( obj = get_eq_char( ch, iWear ) ) == NULL )
	return TRUE;

    if ( !fReplace )
	return FALSE;

    if ( IS_SET(obj->extra_flags, ITEM_NOREMOVE) )
    {
	act( "You can't remove $p.", ch, obj, NULL, TO_CHAR );
	return FALSE;
    }

    unequip_char( ch, obj );
    act( "$n stops using $p.", ch, obj, NULL, TO_ROOM );
    act( "You stop using $p.", ch, obj, NULL, TO_CHAR );
    return TRUE;
}



/*
 * Wear one object.
 * Optional replacement of existing objects.
 * Big repetitive code, ick.
 */
void wear_obj( CHAR_DATA *ch, OBJ_DATA *obj, bool fReplace )
{
    bool wolf_ok = FALSE;

    if (!IS_NPC(ch) && IS_CLASS(ch, CLASS_WEREWOLF) && 
	IS_SET(obj->spectype, SITEM_WOLFWEAPON)) wolf_ok = TRUE;

    if ( CAN_WEAR( obj, ITEM_WIELD ) || CAN_WEAR( obj, ITEM_HOLD ) ||
	CAN_WEAR( obj, ITEM_WEAR_SHIELD ) || obj->item_type == ITEM_LIGHT )
    {
	if ( get_eq_char( ch, WEAR_WIELD    ) != NULL
	&&   get_eq_char( ch, WEAR_HOLD     ) != NULL
	&&   get_eq_char( ch, WEAR_LIGHT    ) != NULL
	&&   get_eq_char( ch, WEAR_SHIELD   ) != NULL
	&&   !remove_obj( ch, WEAR_LIGHT , fReplace )
	&&   !remove_obj( ch, WEAR_SHIELD, fReplace )
	&&   !remove_obj( ch, WEAR_WIELD , fReplace )
	&&   !remove_obj( ch, WEAR_HOLD  , fReplace ) )
	    return;
	if (!IS_NPC(ch) && !IS_FORM(ch,ITEM_WIELD))
	{
	    send_to_char("You are unable to use it.\n\r",ch);
	    return;
	}
	if (get_eq_char( ch, WEAR_WIELD ) == NULL && is_ok_to_wear(ch,wolf_ok,"right_hand"))
	{
	    if ( obj->item_type == ITEM_LIGHT )
	    {
	    	act( "$n lights $p and clutches it in $s right hand.", ch, obj, NULL, TO_ROOM );
	    	act( "You light $p and clutch it in your right hand.",  ch, obj, NULL, TO_CHAR );
	    }
	    else
	    {
	    	act( "$n clutches $p in $s right hand.",    ch, obj, NULL, TO_ROOM );
	    	act( "You clutch $p in your right hand.",  ch, obj, NULL, TO_CHAR );
	    }	
	    if (obj->item_type == ITEM_WEAPON)
	    {
		if (IS_CLASS(ch, CLASS_HIGHLANDER))
		if ((get_eq_char(ch, WEAR_WIELD) == NULL) && IS_SET(obj->spectype, SITEM_HIGHLANDER))
	        {
		if ( obj->pIndexData->vnum == 30000 || IS_OBJ_STAT(obj,ITEM_LOYAL))
		{
		    if ( obj->questowner != NULL && str_cmp(ch->pcdata->switchname,obj->questowner) && strlen(obj->questowner) > 1 )
		    {
			act( "$p leaps out of $n's hand.", ch, obj, NULL, TO_ROOM );
			act( "$p leaps out of your hand.", ch, obj, NULL, TO_CHAR );
			obj_from_char(obj);
			obj_to_room(obj,ch->in_room);
			return;
		    }
		}
		equip_char( ch, obj, WEAR_WIELD );
		if (!IS_NPC(ch)) do_skill(ch, ch->name);
		return;
  		}
	    }
	    equip_char( ch, obj, WEAR_WIELD );
	    return;
	}
	else if (get_eq_char( ch, WEAR_HOLD ) == NULL && is_ok_to_wear(ch,wolf_ok,"left_hand"))
	{
	    if ( obj->item_type == ITEM_LIGHT )
	    {
	    	act( "$n lights $p and clutches it in $s left hand.", ch, obj, NULL, TO_ROOM );
	    	act( "You light $p and clutch it in your left hand.",  ch, obj, NULL, TO_CHAR );
	    }
	    else
	    {
	    	act( "$n clutches $p in $s left hand.",    ch, obj, NULL, TO_ROOM );
	    	act( "You clutch $p in your left hand.",  ch, obj, NULL, TO_CHAR );
	    }
	    if (obj->item_type == ITEM_WEAPON)
	    {
		if ( !IS_NPC(ch) && (obj->pIndexData->vnum == 30000 || IS_OBJ_STAT(obj,ITEM_LOYAL)))
		{
		    if ( obj->questowner != NULL && str_cmp(ch->pcdata->switchname,obj->questowner) && strlen(obj->questowner) > 1 )
		    {
			act( "$p leaps out of $n's hand.", ch, obj, NULL, TO_ROOM );
			act( "$p leaps out of your hand.", ch, obj, NULL, TO_CHAR );
			obj_from_char(obj);
			obj_to_room(obj,ch->in_room);
			return;
		    }
		} 
		equip_char( ch, obj, WEAR_HOLD );
		if (!IS_NPC(ch)) do_skill(ch, ch->name);
		return;
	    }
	    equip_char( ch, obj, WEAR_HOLD );
	    return;
	}
        else if (get_eq_char( ch, WEAR_THIRD ) == NULL && is_ok_to_wear(ch,wolf_ok,"third_hand"))
	{
	    if ( obj->item_type == ITEM_LIGHT )
	    {
	    	act( "$n lights $p and clutches it in $s right hand.", ch, obj, NULL, TO_ROOM );
	    	act( "You light $p and clutch it in your right hand.", ch, obj, NULL, TO_CHAR );
	    }
	    else
	    {
	    	act( "$n clutches $p in $s third hand.",    ch, obj, NULL, TO_ROOM );
	    	act( "You clutch $p in your third hand.",  ch, obj, NULL, TO_CHAR );
	    }	
	    if (obj->item_type == ITEM_WEAPON)
	    {
		if ( !IS_NPC(ch) && IS_CLASS(ch, CLASS_HIGHLANDER))
		if ((get_eq_char(ch, WEAR_WIELD) == NULL) && IS_SET(obj->spectype, SITEM_HIGHLANDER)) {
		if ( obj->pIndexData->vnum == 30000 || IS_OBJ_STAT(obj,ITEM_LOYAL))
		{
		    if ( obj->questowner != NULL && str_cmp(ch->pcdata->switchname,obj->questowner) && strlen(obj->questowner) > 1 ) 
		    {
			act( "$p leaps out of $n's hand.", ch, obj, NULL, TO_ROOM );
			act( "$p leaps out of your hand.", ch, obj, NULL, TO_CHAR );
			obj_from_char(obj);
			obj_to_room(obj,ch->in_room);
			return;
		    }
		}
	      
		equip_char( ch, obj, WEAR_THIRD );
		if (!IS_NPC(ch)) do_skill(ch, ch->name);
		return;
  		}
	    }
	    equip_char( ch, obj, WEAR_THIRD );
	    return;
	}
	else if (get_eq_char( ch, WEAR_FOURTH ) == NULL && is_ok_to_wear(ch,wolf_ok,"fourth_hand"))
	{
	    if ( obj->item_type == ITEM_LIGHT )
	    {
	    	act( "$n lights $p and clutches it in $s fourth hand.", ch, obj, NULL, TO_ROOM );
	    	act( "You light $p and clutch it in your fourth hand.", ch, obj, NULL, TO_CHAR );
	    }
	    else
	    {
	    	act( "$n clutches $p in $s fourth hand.",    ch, obj, NULL, TO_ROOM );
	    	act( "You clutch $p in your fourth hand.",  ch, obj, NULL, TO_CHAR );
	    }
	    if (obj->item_type == ITEM_WEAPON)
	    {
		if ( !IS_NPC(ch) && ( obj->pIndexData->vnum == 30000 || IS_OBJ_STAT(obj,ITEM_LOYAL)))
		{
		    if ( obj->questowner != NULL && str_cmp(ch->pcdata->switchname,obj->questowner) && strlen(obj->questowner) > 1 )
		    {
			act( "$p leaps out of $n's hand.", ch, obj, NULL, TO_ROOM );
			act( "$p leaps out of your hand.", ch, obj, NULL, TO_CHAR );
			obj_from_char(obj);
			obj_to_room(obj,ch->in_room);
			return;
		    }
		}
		equip_char( ch, obj, WEAR_FOURTH );
		if (!IS_NPC(ch)) do_skill(ch, ch->name);
		return;
	    }
	    equip_char( ch, obj, WEAR_FOURTH );
	    return;
	}
	if (!is_ok_to_wear(ch,wolf_ok,"left_hand") && !is_ok_to_wear(ch,wolf_ok,"right_hand"))
	    send_to_char( "You cannot use anything in your hands.\n\r", ch );
	else
	    send_to_char( "You have no free hands.\n\r", ch );
	return;
    }

    if ( obj->item_type == ITEM_LIGHT )
    {
	if ( !remove_obj( ch, WEAR_LIGHT, fReplace ) )
	    return;
	act( "$n lights $p and holds it.", ch, obj, NULL, TO_ROOM );
	act( "You light $p and hold it.",  ch, obj, NULL, TO_CHAR );
	equip_char( ch, obj, WEAR_LIGHT );
	return;
    }

    if ( CAN_WEAR( obj, ITEM_WEAR_FINGER ) )
    {
	if ( get_eq_char( ch, WEAR_FINGER_L ) != NULL
	&&   get_eq_char( ch, WEAR_FINGER_R ) != NULL
	&&   !remove_obj( ch, WEAR_FINGER_L, fReplace )
	&&   !remove_obj( ch, WEAR_FINGER_R, fReplace ) )
	    return;
	if (!IS_NPC(ch) && !IS_FORM(ch,ITEM_WEAR_FINGER))
	{
	    send_to_char("You are unable to wear it.\n\r",ch);
	    return;
	}

	if ( get_eq_char( ch, WEAR_FINGER_L ) == NULL && is_ok_to_wear(ch,wolf_ok,"left_finger"))
	{
	    act( "$n wears $p on $s left finger.",    ch, obj, NULL, TO_ROOM );
	    act( "You wear $p on your left finger.",  ch, obj, NULL, TO_CHAR );
	    equip_char( ch, obj, WEAR_FINGER_L );
	    return;
	}
	else if ( get_eq_char( ch, WEAR_FINGER_R ) == NULL && is_ok_to_wear(ch,wolf_ok,"right_finger"))
	{
	    act( "$n wears $p on $s right finger.",   ch, obj, NULL, TO_ROOM );
	    act( "You wear $p on your right finger.", ch, obj, NULL, TO_CHAR );
	    equip_char( ch, obj, WEAR_FINGER_R );
	    return;
	}
	if (!is_ok_to_wear(ch,wolf_ok,"left_finger") && !is_ok_to_wear(ch,wolf_ok,"right_finger"))
	    send_to_char( "You cannot wear any rings.\n\r", ch );
	else
	    send_to_char( "You cannot wear any more rings.\n\r", ch );
	return;
    }

    if ( CAN_WEAR( obj, ITEM_WEAR_NECK ) )
    {
	if ( get_eq_char( ch, WEAR_NECK_1 ) != NULL
	&&   get_eq_char( ch, WEAR_NECK_2 ) != NULL
	&&   !remove_obj( ch, WEAR_NECK_1, fReplace )
	&&   !remove_obj( ch, WEAR_NECK_2, fReplace ) )
	    return;
	if (!IS_NPC(ch) && !IS_FORM(ch,ITEM_WEAR_NECK))
	{
	    send_to_char("You are unable to wear it.\n\r",ch);
	    return;
	}

	if ( get_eq_char( ch, WEAR_NECK_1 ) == NULL )
	{
	    act( "$n slips $p around $s neck.",   ch, obj, NULL, TO_ROOM );
	    act( "You slip $p around your neck.", ch, obj, NULL, TO_CHAR );
	    equip_char( ch, obj, WEAR_NECK_1 );
	    return;
	}

	if ( get_eq_char( ch, WEAR_NECK_2 ) == NULL )
	{
	    act( "$n slips $p around $s neck.",   ch, obj, NULL, TO_ROOM );
	    act( "You slip $p around your neck.", ch, obj, NULL, TO_CHAR );
	    equip_char( ch, obj, WEAR_NECK_2 );
	    return;
	}
	bug( "Wear_obj: no free neck.", 0 );
	send_to_char( "You are already wearing two things around your neck.\n\r", ch );
	return;
    }

    if ( CAN_WEAR( obj, ITEM_WEAR_BODY ) )
    {
	if ( !remove_obj( ch, WEAR_BODY, fReplace ) )
	    return;

	if (!IS_NPC(ch) && !IS_FORM(ch,ITEM_WEAR_BODY))
	{
	    send_to_char("You are unable to wear it.\n\r",ch);
	    return;
	}
	act( "$n fits $p on $s body.",   ch, obj, NULL, TO_ROOM );
	act( "You fit $p on your body.", ch, obj, NULL, TO_CHAR );
	equip_char( ch, obj, WEAR_BODY );
	return;
    }

    if ( CAN_WEAR( obj, ITEM_WEAR_HEAD ) )
    {
	if ( !remove_obj( ch, WEAR_HEAD, fReplace ) )
	    return;
	if (!IS_NPC(ch) && !IS_FORM(ch,ITEM_WEAR_HEAD))
	{
	    send_to_char("You are unable to wear it.\n\r",ch);
	    return;
	}
	if (!is_ok_to_wear(ch,wolf_ok,"head"))
	{
	    send_to_char("You have no head to wear it on.\n\r",ch);
	    return;
	}
	act( "$n places $p on $s head.",   ch, obj, NULL, TO_ROOM );
	act( "You place $p on your head.", ch, obj, NULL, TO_CHAR );
	equip_char( ch, obj, WEAR_HEAD );
	return;
    }

    if ( CAN_WEAR( obj, ITEM_WEAR_FACE ) )
    {
	if ( !remove_obj( ch, WEAR_FACE, fReplace ) )
	    return;
	if (!IS_NPC(ch) && !IS_FORM(ch,ITEM_WEAR_HEAD))
	{
	    send_to_char("You are unable to wear it.\n\r",ch);
	    return;
	}
	if (!is_ok_to_wear(ch,wolf_ok,"face"))
	{
	    send_to_char("You have no face to wear it on.\n\r",ch);
	    return;
	}
	act( "$n places $p on $s face.",   ch, obj, NULL, TO_ROOM );
	act( "You place $p on your face.", ch, obj, NULL, TO_CHAR );
	equip_char( ch, obj, WEAR_FACE );
	return;
    }

    if ( CAN_WEAR( obj, ITEM_WEAR_LEGS ) )
    {
	if ( !remove_obj( ch, WEAR_LEGS, fReplace ) )
	    return;
	if (!IS_NPC(ch) && !IS_FORM(ch,ITEM_WEAR_LEGS))
	{
	    send_to_char("You are unable to wear it.\n\r",ch);
	    return;
	}
	if (!is_ok_to_wear(ch,wolf_ok,"legs"))
	{
	    send_to_char("You have no legs to wear them on.\n\r",ch);
	    return;
	}
	act( "$n slips $s legs into $p.",   ch, obj, NULL, TO_ROOM );
	act( "You slip your legs into $p.", ch, obj, NULL, TO_CHAR );
	equip_char( ch, obj, WEAR_LEGS );
	return;
    }

    if ( CAN_WEAR( obj, ITEM_WEAR_FEET ) )
    {
	if ( !remove_obj( ch, WEAR_FEET, fReplace ) )
	    return;
	if (!IS_NPC(ch) && !IS_FORM(ch,ITEM_WEAR_FEET))
	{
	    send_to_char("You are unable to wear it.\n\r",ch);
	    return;
	}
	if (!is_ok_to_wear(ch,wolf_ok,"feet"))
	{
	    send_to_char("You have no feet to wear them on.\n\r",ch);
	    return;
	}
	act( "$n slips $s feet into $p.",   ch, obj, NULL, TO_ROOM );
	act( "You slip your feet into $p.", ch, obj, NULL, TO_CHAR );
	equip_char( ch, obj, WEAR_FEET );
	return;
    }

    if ( CAN_WEAR( obj, ITEM_WEAR_HANDS ) )
    {
	if ( !remove_obj( ch, WEAR_HANDS, fReplace ) )
	    return;
	if (!IS_NPC(ch) && !IS_FORM(ch,ITEM_WEAR_HANDS))
	{
	    send_to_char("You are unable to wear it.\n\r",ch);
	    return;
	}
	if (!is_ok_to_wear(ch,wolf_ok,"hands"))
	{
	    send_to_char("You have no hands to wear them on.\n\r",ch);
	    return;
	}
	act( "$n pulls $p onto $s hands.",   ch, obj, NULL, TO_ROOM );
	act( "You pull $p onto your hands.", ch, obj, NULL, TO_CHAR );
	equip_char( ch, obj, WEAR_HANDS );
	return;
    }

    if ( CAN_WEAR( obj, ITEM_WEAR_ARMS ) )
    {
	if ( !remove_obj( ch, WEAR_ARMS, fReplace ) )
	    return;
	if (!IS_NPC(ch) && !IS_FORM(ch,ITEM_WEAR_ARMS))
	{
	    send_to_char("You are unable to wear it.\n\r",ch);
	    return;
	}
	if (!is_ok_to_wear(ch,wolf_ok,"arms"))
	{
	    send_to_char("You have no arms to wear them on.\n\r",ch);
	    return;
	}
	act( "$n slides $s arms into $p.",   ch, obj, NULL, TO_ROOM );
	act( "You slide your arms into $p.", ch, obj, NULL, TO_CHAR );
	equip_char( ch, obj, WEAR_ARMS );
	return;
    }

    if ( CAN_WEAR( obj, ITEM_WEAR_ABOUT ) )
    {
	if ( !remove_obj( ch, WEAR_ABOUT, fReplace ) )
	    return;
	if (!IS_NPC(ch) && !IS_FORM(ch,ITEM_WEAR_ABOUT))
	{
	    send_to_char("You are unable to wear it.\n\r",ch);
	    return;
	}
	act( "$n pulls $p about $s body.",   ch, obj, NULL, TO_ROOM );
	act( "You pull $p about your body.", ch, obj, NULL, TO_CHAR );
	equip_char( ch, obj, WEAR_ABOUT );
	return;
    }

    if ( CAN_WEAR( obj, ITEM_WEAR_WAIST ) )
    {
	if ( !remove_obj( ch, WEAR_WAIST, fReplace ) )
	    return;
	if (!IS_NPC(ch) && !IS_FORM(ch,ITEM_WEAR_WAIST))
	{
	    send_to_char("You are unable to wear it.\n\r",ch);
	    return;
	}
	act( "$n ties $p around $s waist.",   ch, obj, NULL, TO_ROOM );
	act( "You tie $p around your waist.", ch, obj, NULL, TO_CHAR );
	equip_char( ch, obj, WEAR_WAIST );
	return;
    }

    if ( CAN_WEAR( obj, ITEM_WEAR_WRIST ) )
    {
	if ( get_eq_char( ch, WEAR_WRIST_L ) != NULL
	&&   get_eq_char( ch, WEAR_WRIST_R ) != NULL
	&&   !remove_obj( ch, WEAR_WRIST_L, fReplace )
	&&   !remove_obj( ch, WEAR_WRIST_R, fReplace ) )
	    return;
	if (!IS_NPC(ch) && !IS_FORM(ch,ITEM_WEAR_WRIST))
	{
	    send_to_char("You are unable to wear it.\n\r",ch);
	    return;
	}

	if ( get_eq_char( ch, WEAR_WRIST_L ) == NULL && is_ok_to_wear(ch,wolf_ok,"right_wrist"))
	{
	    act( "$n slides $s left wrist into $p.",
		ch, obj, NULL, TO_ROOM );
	    act( "You slide your left wrist into $p.",
		ch, obj, NULL, TO_CHAR );
	    equip_char( ch, obj, WEAR_WRIST_L );
	    return;
	}
	else if ( get_eq_char( ch, WEAR_WRIST_R ) == NULL && is_ok_to_wear(ch,wolf_ok,"left_wrist"))
	{
	    act( "$n slides $s left wrist into $p.",
		ch, obj, NULL, TO_ROOM );
	    act( "You slide your right wrist into $p.",
		ch, obj, NULL, TO_CHAR );
	    equip_char( ch, obj, WEAR_WRIST_R );
	    return;
	}
	if (!is_ok_to_wear(ch,wolf_ok,"left_wrist") && !is_ok_to_wear(ch,wolf_ok,"right_wrist"))
	    send_to_char( "You cannot wear anything on your wrists.\n\r", ch );
	else
	    send_to_char( "You cannot wear any more on your wrists.\n\r", ch );
	return;
    }

    if ( CAN_WEAR( obj, ITEM_WEAR_SHIELD ) )
    {
	if ( !remove_obj( ch, WEAR_SHIELD, fReplace ) )
	    return;
	if (!IS_NPC(ch) && !IS_FORM(ch,ITEM_WEAR_SHIELD))
	{
	    send_to_char("You are unable to wear it.\n\r",ch);
	    return;
	}
	act( "$n straps $p onto $s shield arm.", ch, obj, NULL, TO_ROOM );
	act( "You strap $p onto your shield arm.", ch, obj, NULL, TO_CHAR );
	equip_char( ch, obj, WEAR_SHIELD );
	return;
    }

    if ( CAN_WEAR( obj, ITEM_WIELD ) )
    {
	if ( !remove_obj( ch, WEAR_WIELD, fReplace ) )
	    return;
	if (!IS_NPC(ch) && !IS_FORM(ch,ITEM_WIELD))
	{
	    send_to_char("You are unable to wield it.\n\r",ch);
	    return;
	}

	if ( get_obj_weight( obj ) > str_app[get_curr_str(ch)].wield )
	{
	    send_to_char( "It is too heavy for you to wield.\n\r", ch );
	    return;
	}

	act( "$n wields $p.", ch, obj, NULL, TO_ROOM );
	act( "You wield $p.", ch, obj, NULL, TO_CHAR );

	if ( !IS_NPC(ch) && ( obj->pIndexData->vnum == 30000 || IS_OBJ_STAT(obj,ITEM_LOYAL)))
	{
	    if ( obj->questowner != NULL && str_cmp(ch->pcdata->switchname,obj->questowner) && strlen(obj->questowner) > 1 )
	    {
		act( "$p leaps out of $n's hand.", ch, obj, NULL, TO_ROOM );
		act( "$p leaps out of your hand.", ch, obj, NULL, TO_CHAR );
		obj_from_char(obj);
		obj_to_room(obj,ch->in_room);
		return;
	    }
	}
	equip_char( ch, obj, WEAR_WIELD );
	if (!IS_NPC(ch)) do_skill(ch, ch->name);
	return;
    }

    if ( fReplace )
	send_to_char( "You can't wear, wield or hold that.\n\r", ch );

    return;
}



void do_wear( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;

    one_argument( argument, arg );

    
    if (!IS_NPC(ch) && IS_POLYAFF(ch,POLY_ZULOFORM) && IS_CLASS(ch,
CLASS_VAMPIRE))
{ 
send_to_char( "You are too mad to decide what you want to wear!\n\r",ch);
return;
}

     if (form_data[ch->cur_form].can_wear == FALSE && ch->cur_form != 0)
     {
	stc("You cannot wear objects in this form.\n\r",ch);
	return;
     }


     if (IS_AFFECTED(ch,AFF_POLYMORPH) && !IS_NPC(ch) && 
	!IS_VAMPAFF(ch,VAM_DISGUISED) && !IS_CLASS(ch, CLASS_WEREWOLF) &&
!IS_CLASS(ch, CLASS_DEMON))
    {
	send_to_char( "You cannot wear anything in this form.\n\r", ch );
	return;
    }

    if ( arg[0] == '\0' )
    {
	send_to_char( "Wear, wield, or hold what?\n\r", ch );
	return;
    }

    if ( !str_cmp( arg, "all" ) )
    {
	OBJ_DATA *obj_next;

	for ( obj = ch->carrying; obj != NULL; obj = obj_next )
	{
	    obj_next = obj->next_content;
	    if ( obj->wear_loc == WEAR_NONE && can_see_obj( ch, obj ) )
		wear_obj( ch, obj, FALSE );
	}
	return;
    }
    else
    {
	if ( ( obj = get_obj_carry( ch, arg ) ) == NULL )
	{
	    send_to_char( "You do not have that item.\n\r", ch );
	    return;
	}

	wear_obj( ch, obj, TRUE );
    }

    return;
}



void do_remove( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char( "Remove what?\n\r", ch );
	return;
    }

    
   if (!IS_NPC(ch) && IS_CLASS(ch, CLASS_HIGHLANDER) && IS_POLYAFF(ch,
POLY_ZULOFORM))
{
send_to_char("Your too mad to remove anything!\n\r",ch);
return;
}

        if (!form_data[ch->cur_form].can_wear && ch->cur_form != 0)
	{
	    stc("You cannot remove anything in this form.\n\r",ch);
	    return;
	}

    if ( !str_cmp( arg, "all" ) )
    {
	OBJ_DATA *obj_next;

	for ( obj = ch->carrying; obj != NULL; obj = obj_next )
	{
	    obj_next = obj->next_content;
	    if ( obj->wear_loc != WEAR_NONE && can_see_obj( ch, obj ) )
		remove_obj( ch, obj->wear_loc, TRUE );
	}
	return;
    }
    if ( ( obj = get_obj_wear( ch, arg ) ) == NULL )
    {
	send_to_char( "You do not have that item.\n\r", ch );
	return;
    }
    remove_obj( ch, obj->wear_loc, TRUE );
    return;
}



void do_sacrifice( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;
    CHAR_DATA *victim;
    char buf[MAX_INPUT_LENGTH];
    int expgain;

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char("Sacrifice what?\n\r",ch);
	return;
    }

    if ( ( victim = get_char_room(ch, arg) ) != NULL )
    {
       do_offer(ch, arg);
       return;
    }

    obj = get_obj_list( ch, arg, ch->in_room->contents );
    if ( obj == NULL )
    {
	send_to_char( "You can't find it.\n\r", ch );
	return;
    }

    if ( !CAN_WEAR(obj, ITEM_TAKE) || obj->item_type == ITEM_QUEST ||
	 obj->item_type == ITEM_MONEY || obj->item_type == ITEM_TREASURE ||
	 obj->item_type == ITEM_QUESTCARD || IS_SET(obj->quest, QUEST_ARTIFACT) ||
	obj->item_type == ITEM_KINGDOM_POWER ||
	( obj->questowner != NULL && strlen(obj->questowner) > 1 && str_cmp(ch->name,obj->questowner)))
    {
	act( "You are unable to drain any energy from $p.", ch, obj, 0, TO_CHAR );
	return;
    }
    else if (obj->chobj != NULL && !IS_NPC(obj->chobj) &&
	obj->chobj->pcdata->obj_vnum != 0)
    {
	act( "You are unable to drain any energy from $p.", ch, obj, 0, TO_CHAR );
	return;
    }
    expgain = obj->cost / 100;
    if (expgain < 1)
	expgain = 1;
    if (expgain > 50)
	expgain = 50;
    ch->exp += expgain;
    sprintf( buf,"You drain %d exp of energy from $p.", expgain );
    act( buf, ch, obj, NULL, TO_CHAR );
    act( "$p disintegrates into a fine powder.", ch, obj, NULL, TO_CHAR );
    act( "$n drains the energy from $p.", ch, obj, NULL, TO_ROOM );
    act( "$p disintegrates into a fine powder.", ch, obj, NULL, TO_ROOM );
    if (obj->points > 0 && !IS_NPC(ch) && obj->item_type != ITEM_PAGE)
    {
	sprintf( buf, "You receive a refund of %d quest points from $p.", obj->points);
	act( buf, ch, obj, NULL, TO_CHAR );
	ch->pcdata->quest += obj->points;
    }
    extract_obj( obj );
    return;
}



void do_quaff( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;
    int level;

    one_argument( argument, arg );

	if (IS_NPC(ch)) return;

    if ( arg[0] == '\0' )
    {
	send_to_char( "Quaff what?\n\r", ch );
	return;
    }

    if ( ( obj = get_obj_carry( ch, arg ) ) == NULL )
    {
	send_to_char( "You do not have that potion.\n\r", ch );
	return;
    }

    if ( obj->item_type != ITEM_POTION )
    {
	send_to_char( "You can quaff only potions.\n\r", ch );
	return;
    }
	if (IS_NPC(ch)) return;

    act( "$n quaffs $p.", ch, obj, NULL, TO_ROOM );
    act( "You quaff $p.", ch, obj, NULL ,TO_CHAR );

    level = obj->value[0];
    if (level < 1) level = 1;
    if (level > MAX_SPELL) level = MAX_SPELL;

    obj_cast_spell( obj->value[1], level, ch, ch, NULL );
    obj_cast_spell( obj->value[2], level, ch, ch, NULL );
    obj_cast_spell( obj->value[3], level, ch, ch, NULL );

    extract_obj( obj );
    if (ch->position == POS_FIGHTING) 
    {
	if (!IS_IMMORTAL( ch))
		WAIT_STATE(ch, 6 );
    }
    return;
}



void do_recite( CHAR_DATA *ch, char *argument )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    OBJ_DATA *scroll;
    OBJ_DATA *obj;
    int level;

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

	if (IS_NPC(ch)) return;

    if ( ( scroll = get_obj_carry( ch, arg1 ) ) == NULL )
    {
	send_to_char( "You do not have that scroll.\n\r", ch );
	return;
    }

    if ( scroll->item_type != ITEM_SCROLL )
    {
	send_to_char( "You can recite only scrolls.\n\r", ch );
	return;
    }

    obj = NULL;
    if ( arg2[0] == '\0' )
    {
	victim = ch;
    }
    else
    {
	if ( ( victim = get_char_room ( ch, arg2 ) ) == NULL
	&&   ( obj    = get_obj_here  ( ch, arg2 ) ) == NULL )
	{
	    send_to_char( "You can't find it.\n\r", ch );
	    return;
	}
    }
	if (IS_NPC(ch)) return;

    act( "$n recites $p.", ch, scroll, NULL, TO_ROOM );
    act( "You recite $p.", ch, scroll, NULL, TO_CHAR );

    level = scroll->value[0];
    if (level < 1) level = 1;
    if (level > MAX_SPELL) level = MAX_SPELL;

    obj_cast_spell( scroll->value[1], level, ch, victim, obj );
    obj_cast_spell( scroll->value[2], level, ch, victim, obj );
    obj_cast_spell( scroll->value[3], level, ch, victim, obj );

    extract_obj( scroll );
    if (ch->position == POS_FIGHTING) 
    {
    	if (!IS_IMMORTAL( ch))
		WAIT_STATE(ch, 6 );
    }
    return;
}



void do_brandish( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *vch;
    CHAR_DATA *vch_next;
    OBJ_DATA *temp;
    OBJ_DATA *staff;
    int sn;
    int level;

    staff = get_eq_char( ch, WEAR_WIELD );
    temp = get_eq_char( ch, WEAR_HOLD );

	if (IS_NPC(ch)) return;

    if ( staff == NULL && temp == NULL )
    {
	send_to_char( "You hold nothing in your hand.\n\r", ch );
	return;
    }

    if ( staff == NULL ) staff = temp;
    if ( temp == NULL  ) temp = staff;

    if ( staff->item_type != ITEM_STAFF ) staff=temp;

    if ( staff->item_type != ITEM_STAFF )
    {
	send_to_char( "You can brandish only with a staff.\n\r", ch );
	return;
    }

    if ( ( sn = staff->value[3] ) < 0
    ||   sn >= MAX_SKILL
    ||   skill_table[sn].spell_fun == 0 )
    {
	bug( "Do_brandish: bad sn %d.", sn );
	return;
    }
	if (IS_NPC(ch)) return;

    if (!IS_IMMORTAL( ch))
	WAIT_STATE( ch, 2 * PULSE_VIOLENCE );

    if ( staff->value[2] > 0 )
    {
	act( "$n brandishes $p.", ch, staff, NULL, TO_ROOM );
	act( "You brandish $p.",  ch, staff, NULL, TO_CHAR );
	for ( vch = ch->in_room->people; vch; vch = vch_next )
	{
	    vch_next	= vch->next_in_room;

	    switch ( skill_table[sn].target )
	    {
	    default:
		bug( "Do_brandish: bad target for sn %d.", sn );
		return;

	    case TAR_IGNORE:
		if ( vch != ch )
		    continue;
		break;

	    case TAR_CHAR_OFFENSIVE:
		if ( IS_NPC(ch) ? IS_NPC(vch) : !IS_NPC(vch) )
		    continue;
		break;
		
	    case TAR_CHAR_DEFENSIVE:
		if ( IS_NPC(ch) ? !IS_NPC(vch) : IS_NPC(vch) )
		    continue;
		break;

	    case TAR_CHAR_SELF:
		if ( vch != ch )
		    continue;
		break;
	    }

	    level = staff->value[0];
	    if (level < 1) level = 1;
	    if (level > MAX_SPELL) level = MAX_SPELL;

	    obj_cast_spell( staff->value[3], level, ch, vch, NULL );
	}
    }

    if ( --staff->value[2] <= 0 )
    {
	act( "$n's $p blazes bright and is gone.", ch, staff, NULL, TO_ROOM );
	act( "Your $p blazes bright and is gone.", ch, staff, NULL, TO_CHAR );
	extract_obj( staff );
    }

    return;
}



void do_zap( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    OBJ_DATA *temp;
    OBJ_DATA *wand;
    OBJ_DATA *obj;
    int level;

    one_argument( argument, arg );

	if (IS_NPC(ch)) return;

    if ( arg[0] == '\0' && ch->fighting == NULL )
    {
	send_to_char( "Zap whom or what?\n\r", ch );
	return;
    }

    wand = get_eq_char( ch, WEAR_WIELD );
    temp = get_eq_char( ch, WEAR_HOLD );

    if ( wand == NULL && temp == NULL )
    {
	send_to_char( "You hold nothing in your hand.\n\r", ch );
	return;
    }

    if ( wand == NULL ) wand = temp;
    if ( temp == NULL ) temp = wand;

    if ( wand->item_type != ITEM_WAND ) wand=temp;

    if ( wand->item_type != ITEM_WAND )
    {
	send_to_char( "You can zap only with a wand.\n\r", ch );
	return;
    }
	if (IS_NPC(ch)) return;

    obj = NULL;
    if ( arg[0] == '\0' )
    {
	if ( ch->fighting != NULL )
	{
	    victim = ch->fighting;
	}
	else
	{
	    send_to_char( "Zap whom or what?\n\r", ch );
	    return;
	}
    }
    else
    {
	if ( ( victim = get_char_room ( ch, arg ) ) == NULL
	&&   ( obj    = get_obj_here  ( ch, arg ) ) == NULL )
	{
	    send_to_char( "You can't find it.\n\r", ch );
	    return;
	}
    }

    if (!IS_IMMORTAL( ch))
	WAIT_STATE( ch, 2 * PULSE_VIOLENCE );

    if ( wand->value[2] > 0 )
    {
	if ( victim != NULL )
	{
	    act( "$n zaps $N with $p.", ch, wand, victim, TO_ROOM );
	    act( "You zap $N with $p.", ch, wand, victim, TO_CHAR );
	}
	else
	{
	    act( "$n zaps $P with $p.", ch, wand, obj, TO_ROOM );
	    act( "You zap $P with $p.", ch, wand, obj, TO_CHAR );
	}

	level = wand->value[0];
	if (level < 1) level = 1;
	if (level > MAX_SPELL) level = MAX_SPELL;

	obj_cast_spell( wand->value[3], level, ch, victim, obj );
    }

    if ( --wand->value[2] <= 0 )
    {
	act( "$n's $p explodes into fragments.", ch, wand, NULL, TO_ROOM );
	act( "Your $p explodes into fragments.", ch, wand, NULL, TO_CHAR );
	extract_obj( wand );
    }

    return;
}



void do_steal( CHAR_DATA *ch, char *argument )
{
    char buf  [MAX_STRING_LENGTH];
    char arg1 [MAX_INPUT_LENGTH];
    char arg2 [MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    OBJ_DATA *obj;
    int percent;

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if ( arg1[0] == '\0' || arg2[0] == '\0' )
    {
	send_to_char( "Steal what from whom?\n\r", ch );
	return;
    }

    if ( ( victim = get_char_room( ch, arg2 ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( victim == ch )
    {
	send_to_char( "That's pointless.\n\r", ch );
	return;
    }

    if ( IS_IMMORTAL( victim ))
    {
	send_to_char("Steal from an immortal are you crasy!\n\r", ch);
	return;
    }

    if (!IS_IMMORTAL( ch))
    	WAIT_STATE( ch, skill_table[gsn_steal].beats );

    percent  = number_percent( ) + ( IS_AWAKE(victim) ? 10 : -50 );

    if ( ( ch->level + number_range(1,20) < victim->level          )
    ||   ( !IS_NPC(ch) && !IS_NPC(victim) && ch->level < 3         )
    ||   ( !IS_NPC(ch) && !IS_NPC(victim) && victim->level < 3     )
    ||   ( victim->position == POS_FIGHTING                        )
    ||   ( !IS_NPC(victim) && IS_IMMUNE(victim,IMM_STEAL)          )
    ||   ( !IS_NPC(victim) && IS_IMMORTAL(victim)                  )
    ||   ( !IS_NPC(ch) && percent > ch->pcdata->learned[gsn_steal] ) )
    {
	/*
	 * Failure.
	 */
	send_to_char( "Oops.\n\r", ch );
	act( "$n tried to steal from you.\n\r", ch, NULL, victim, TO_VICT    );
	act( "$n tried to steal from $N.\n\r",  ch, NULL, victim, TO_NOTVICT );
	sprintf( buf, "%s is a bloody thief!", ch->name );
	do_shout( victim, buf );
	if ( !IS_NPC(ch) )
	{
	    if ( IS_NPC(victim) )
	    {
		multi_hit( victim, ch, TYPE_UNDEFINED );
	    }
	    else
	    {
		log_string( buf );
		save_char_obj( ch );
	    }
	}

	return;
    }

    if ( !str_cmp( arg1, "coin"  )
    ||   !str_cmp( arg1, "coins" )
    ||   !str_cmp( arg1, "gold"  ) )
    {
	int amount;

	amount = victim->gold * number_range(1, 10) / 100;
	if ( amount <= 0 )
	{
	    send_to_char( "You couldn't get any gold.\n\r", ch );
	    return;
	}

	ch->gold     += amount;
	victim->gold -= amount;
	sprintf( buf, "Bingo!  You got %d gold coins.\n\r", amount );
	send_to_char( buf, ch );
	do_autosave(ch,"");
	do_autosave(victim,"");
	return;
    }

    if ( ( obj = get_obj_carry( victim, arg1 ) ) == NULL )
    {
	send_to_char( "You can't find it.\n\r", ch );
	return;
    }
	
    if ( !can_drop_obj( ch, obj )
    ||   IS_SET(obj->extra_flags, ITEM_LOYAL)
    ||   IS_SET(obj->extra_flags, ITEM_INVENTORY) )
    {
	send_to_char( "You can't pry it away.\n\r", ch );
	return;
    }

    if ( ch->carry_number + 1 > can_carry_n( ch ) )
    {
	send_to_char( "You have your hands full.\n\r", ch );
	return;
    }

    if ( ch->carry_weight + get_obj_weight( obj ) > can_carry_w( ch ) )
    {
	send_to_char( "You can't carry that much weight.\n\r", ch );
	return;
    }

    obj_from_char( obj );
    obj_to_char( obj, ch );
    send_to_char( "You got it!\n\r", ch );
    do_autosave(ch,"");
    do_autosave(victim,"");
    return;
}



/*
 * Shopping commands.
 */
CHAR_DATA *find_keeper( CHAR_DATA *ch )
{
    CHAR_DATA *keeper;
    SHOP_DATA *pShop;
    char buf [MAX_STRING_LENGTH];

    pShop = NULL;
    for ( keeper = ch->in_room->people; keeper; keeper = keeper->next_in_room )
    {
	if ( IS_NPC(keeper) && (pShop = keeper->pIndexData->pShop) != NULL )
	    break;
    }

    if ( pShop == NULL )
    {
	send_to_char( "You can't do that here.\n\r", ch );
	return NULL;
    }

    /*
     * Shop hours.
     */
    if ( time_info.hour < pShop->open_hour )
    {
	strcpy( buf, "Sorry, come back later." );
	do_say( keeper, buf );
	return NULL;
    }
    
    if ( time_info.hour > pShop->close_hour )
    {
	strcpy( buf, "Sorry, come back tomorrow." );
	do_say( keeper, buf );
	return NULL;
    }

    /*
     * Invisible or hidden people.
     */
    if ( !can_see( keeper, ch ) )
    {
	strcpy( buf, "I don't trade with folks I can't see." );
	do_say( keeper, buf );
	return NULL;
    }

    return keeper;
}



int get_cost( CHAR_DATA *keeper, OBJ_DATA *obj, bool fBuy )
{
    SHOP_DATA *pShop;
    int cost;

    if ( obj == NULL || ( pShop = keeper->pIndexData->pShop ) == NULL )
	return 0;

    if ( fBuy )
    {
	cost = obj->cost * pShop->profit_buy  / 100;
    }
    else
    {
	OBJ_DATA *obj2;
	int itype;

	cost = 0;
	for ( itype = 0; itype < MAX_TRADE; itype++ )
	{
	    if ( obj->item_type == pShop->buy_type[itype] )
	    {
		cost = obj->cost * pShop->profit_sell / 100;
		break;
	    }
	}

	for ( obj2 = keeper->carrying; obj2; obj2 = obj2->next_content )
	{
	    if ( obj->pIndexData == obj2->pIndexData )
	    {
		cost = 0;
		break;
	    }
	}
    }

    if ( obj->item_type == ITEM_STAFF || obj->item_type == ITEM_WAND )
	cost = cost * obj->value[2] / obj->value[1];

    return cost;
}



void do_buy( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];

    argument = one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char( "Buy what?\n\r", ch );
	return;
    }

    if ( IS_SET(ch->in_room->room_flags, ROOM_PET_SHOP) )
    {
	char buf[MAX_STRING_LENGTH];
	CHAR_DATA *pet;
	ROOM_INDEX_DATA *pRoomIndexNext;
	ROOM_INDEX_DATA *in_room;

	if ( IS_NPC(ch) )
	    return;

	pRoomIndexNext = get_room_index( ch->in_room->vnum + 1 );
	if ( pRoomIndexNext == NULL )
	{
	    bug( "Do_buy: bad pet shop at vnum %d.", ch->in_room->vnum );
	    send_to_char( "Sorry, you can't buy that here.\n\r", ch );
	    return;
	}

	in_room     = ch->in_room;
	ch->in_room = pRoomIndexNext;
	pet         = get_char_room( ch, arg );
	ch->in_room = in_room;

	if ( pet == NULL || !IS_SET(pet->act, ACT_PET) )
	{
	    send_to_char( "Sorry, you can't buy that here.\n\r", ch );
	    return;
	}

	if ( ch->gold < 10 * pet->level * pet->level )
	{
	    send_to_char( "You can't afford it.\n\r", ch );
	    return;
	}

	if ( ch->level < pet->level )
	{
	    send_to_char( "You're not ready for this pet.\n\r", ch );
	    return;
	}

	ch->gold		-= 10 * pet->level * pet->level;
	pet			= create_mobile( pet->pIndexData );
	SET_BIT(pet->act, ACT_PET);
	SET_BIT(pet->affected_by, AFF_CHARM);

	argument = one_argument( argument, arg );
	if ( arg[0] != '\0' )
	{
	    sprintf( buf, "%s %s", pet->name, arg );
	    free_string( pet->name );
	    pet->name = str_dup( buf );
	}

	sprintf( buf, "%sA neck tag says 'I belong to %s'.\n\r",
	    pet->description, ch->name );
	free_string( pet->description );
	pet->description = str_dup( buf );

	char_to_room( pet, ch->in_room );
	add_follower( pet, ch );
	send_to_char( "Enjoy your pet.\n\r", ch );
	act( "$n bought $N as a pet.", ch, NULL, pet, TO_ROOM );
	return;
    }
    else
    {
	CHAR_DATA *keeper;
	OBJ_DATA *obj;
	int cost;

	if ( ( keeper = find_keeper( ch ) ) == NULL )
	    return;

	obj  = get_obj_carry( keeper, arg );
	cost = get_cost( keeper, obj, TRUE );

	if ( cost <= 0 || !can_see_obj( ch, obj ) )
	{
	    act( "$n tells you 'I don't sell that -- try 'list''.",
		keeper, NULL, ch, TO_VICT );
	    ch->reply = keeper;
	    return;
	}

	if ( ch->gold < cost )
	{
	    act( "$n tells you 'You can't afford to buy $p'.",
		keeper, obj, ch, TO_VICT );
	    ch->reply = keeper;
	    return;
	}
	
	if ( (obj->level > ch->level) && ch->level < 3 )
	{
	    act( "$n tells you 'You can't use $p yet'.",
		keeper, obj, ch, TO_VICT );
	    ch->reply = keeper;
	    return;
	}

	if ( ch->carry_number + 1 > can_carry_n( ch ) )
	{
	    send_to_char( "You can't carry that many items.\n\r", ch );
	    return;
	}

	if ( ch->carry_weight + get_obj_weight( obj ) > can_carry_w( ch ) )
	{
	    send_to_char( "You can't carry that much weight.\n\r", ch );
	    return;
	}

	act( "$n buys $p.", ch, obj, NULL, TO_ROOM );
	act( "You buy $p.", ch, obj, NULL, TO_CHAR );
	ch->gold     -= cost;
	keeper->gold += cost;

	if ( IS_SET( obj->extra_flags, ITEM_INVENTORY ) )
	    obj = create_object( obj->pIndexData, obj->level );
	else
	    obj_from_char( obj );

	obj_to_char( obj, ch );
	return;
    }
}



void do_list( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];

    if ( IS_SET(ch->in_room->room_flags, ROOM_PET_SHOP) )
    {
	ROOM_INDEX_DATA *pRoomIndexNext;
	CHAR_DATA *pet;
	bool found;

	pRoomIndexNext = get_room_index( ch->in_room->vnum + 1 );
	if ( pRoomIndexNext == NULL )
	{
	    bug( "Do_list: bad pet shop at vnum %d.", ch->in_room->vnum );
	    send_to_char( "You can't do that here.\n\r", ch );
	    return;
	}

	found = FALSE;
	for ( pet = pRoomIndexNext->people; pet; pet = pet->next_in_room )
	{
	    if ( IS_SET(pet->act, ACT_PET) )
	    {
		if ( !found )
		{
		    found = TRUE;
		    send_to_char( "Pets for sale:\n\r", ch );
		}
		sprintf( buf, "[%2d] %8d - %s\n\r",
		    pet->level,
		    10 * pet->level * pet->level,
		    pet->short_descr );
		send_to_char( buf, ch );
	    }
	}
	if ( !found )
	    send_to_char( "Sorry, we're out of pets right now.\n\r", ch );
	return;
    }
    else
    {
	char arg[MAX_INPUT_LENGTH];
	CHAR_DATA *keeper;
	OBJ_DATA *obj;
	int cost;
	bool found;

	one_argument( argument, arg );

	if ( ( keeper = find_keeper( ch ) ) == NULL )
	    return;

	found = FALSE;
	for ( obj = keeper->carrying; obj; obj = obj->next_content )
	{
	    if ( obj->wear_loc == WEAR_NONE
	    &&   can_see_obj( ch, obj )
	    && ( cost = get_cost( keeper, obj, TRUE ) ) > 0
	    && ( arg[0] == '\0' || is_name( arg, obj->name ) ) )
	    {
		if ( !found )
		{
		    found = TRUE;
		    send_to_char( "[Lv Price] Item\n\r", ch );
		}

		sprintf( buf, "[%2d %5d] %s.\n\r",
		    obj->level, cost, capitalize( obj->short_descr ) );
		send_to_char( buf, ch );
	    }
	}

	if ( !found )
	{
	    if ( arg[0] == '\0' )
		send_to_char( "You can't buy anything here.\n\r", ch );
	    else
		send_to_char( "You can't buy that here.\n\r", ch );
	}
	return;
    }
}



void do_sell( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *keeper;
    OBJ_DATA *obj;
    int cost;

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char( "Sell what?\n\r", ch );
	return;
    }

    if ( ( keeper = find_keeper( ch ) ) == NULL )
	return;

    if ( ( obj = get_obj_carry( ch, arg ) ) == NULL )
    {
	act( "$n tells you 'You don't have that item'.",
	    keeper, NULL, ch, TO_VICT );
	ch->reply = keeper;
	return;
    }

    if ( !can_drop_obj( ch, obj ) )
    {
	send_to_char( "You can't let go of it.\n\r", ch );
	return;
    }

    if ( ( cost = get_cost( keeper, obj, FALSE ) ) <= 0 )
    {
	act( "$n looks uninterested in $p.", keeper, obj, ch, TO_VICT );
	return;
    }

    act( "$n sells $p.", ch, obj, NULL, TO_ROOM );
    sprintf( buf, "You sell $p for %d gold piece%s.",
	cost, cost == 1 ? "" : "s" );
    act( buf, ch, obj, NULL, TO_CHAR );
    ch->gold     += cost;
    keeper->gold -= cost;
    if ( keeper->gold < 0 )
	keeper->gold = 0;

    if ( obj->item_type == ITEM_TRASH )
    {
	extract_obj( obj );
    }
    else
    {
	obj_from_char( obj );
	obj_to_char( obj, keeper );
    }

    return;
}



void do_value( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *keeper;
    OBJ_DATA *obj;
    int cost;

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char( "Value what?\n\r", ch );
	return;
    }

    if ( ( keeper = find_keeper( ch ) ) == NULL )
	return;

    if ( ( obj = get_obj_carry( ch, arg ) ) == NULL )
    {
	act( "$n tells you 'You don't have that item'.",
	    keeper, NULL, ch, TO_VICT );
	ch->reply = keeper;
	return;
    }

    if ( !can_drop_obj( ch, obj ) )
    {
	send_to_char( "You can't let go of it.\n\r", ch );
	return;
    }

    if ( ( cost = get_cost( keeper, obj, FALSE ) ) <= 0 )
    {
	act( "$n looks uninterested in $p.", keeper, obj, ch, TO_VICT );
	return;
    }

    sprintf( buf, "$n tells you 'I'll give you %d gold coins for $p'.", cost );
    act( buf, keeper, obj, ch, TO_VICT );
    ch->reply = keeper;

    return;
}

void do_activate( CHAR_DATA *ch, char *argument )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;
    OBJ_DATA *obj2;
    CHAR_DATA *victim;
    CHAR_DATA *victim_next;
    CHAR_DATA *mount;
    CHAR_DATA *mob;
    ROOM_INDEX_DATA *pRoomIndex;

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if ( arg1[0] == '\0' )
    {
	send_to_char( "Which item do you wish to activate?\n\r", ch );
	return;
    }
    if ( (obj = get_obj_wear(ch,arg1)) == NULL ) 
    {
	if ( ( obj = get_obj_here( ch, arg1 ) ) == NULL )
	{
	    send_to_char( "You can't find that item.\n\r", ch );
	    return;
	}
	/* You should only be able to use nontake items on floor */
	if (CAN_WEAR(obj, ITEM_TAKE))
	{
	    send_to_char( "But you are not wearing it!\n\r", ch );
	    return;
	}
    }
    if ( obj == NULL || !IS_SET(obj->spectype, SITEM_ACTIVATE) )
    {
	send_to_char( "This item cannot be activated.\n\r", ch );
	return;
    }
    if ( IS_SET(obj->spectype, SITEM_TARGET) && arg2[0] == '\0' )
    {
	send_to_char( "Who do you wish to activate it on?\n\r", ch );
	return;
    }
    if ( IS_SET(obj->spectype, SITEM_TARGET) )
    {
	if ( ( victim = get_char_room( ch, arg2 ) ) == NULL )
	{
	    send_to_char( "Nobody here by that name.\n\r", ch );
	    return;
	}
    }
    else victim = ch;
    if (obj->chpoweruse != NULL && obj->chpoweruse != '\0'
	&& str_cmp(obj->chpoweruse,"(null)") )
	kavitem(str_dup(obj->chpoweruse),ch,obj,NULL,TO_CHAR);
    if (obj->victpoweruse != NULL && obj->victpoweruse != '\0'
	&& str_cmp(obj->victpoweruse,"(null)") )
	kavitem(str_dup(obj->victpoweruse),ch,obj,NULL,TO_ROOM);
    if ( IS_SET(obj->spectype, SITEM_SPELL))
    {
	int castlevel = obj->level;
	if (castlevel < 1) castlevel = 1;
	else if (castlevel > 60) castlevel = 60;
	obj_cast_spell( obj->specpower, castlevel, ch, victim, NULL );
    	if (!IS_IMMORTAL( ch))
		WAIT_STATE(ch,6);
	if ( IS_SET(obj->spectype, SITEM_DELAY1)) WAIT_STATE(ch,6);
	if ( IS_SET(obj->spectype, SITEM_DELAY2)) WAIT_STATE(ch,12);
	return;
    }
    else if ( IS_SET(obj->spectype, SITEM_TRANSPORTER))
    {
    	if (obj->chpoweron != NULL && obj->chpoweron != '\0'
	    && str_cmp(obj->chpoweron,"(null)") )
	    kavitem(str_dup(obj->chpoweron),ch,obj,NULL,TO_CHAR);
    	if (obj->victpoweron != NULL && obj->victpoweron != '\0'
	    && str_cmp(obj->victpoweron,"(null)") )
	    kavitem(str_dup(obj->victpoweron),ch,obj,NULL,TO_ROOM);
	pRoomIndex     = get_room_index(obj->specpower);
	obj->specpower = ch->in_room->vnum;
	if ( pRoomIndex == NULL ) return;
	char_from_room(ch);
	char_to_room(ch,pRoomIndex);
	do_look(ch,"auto");
    	if (obj->chpoweroff != NULL && obj->chpoweroff != '\0'
	    && str_cmp(obj->chpoweroff,"(null)") )
	    kavitem(str_dup(obj->chpoweroff),ch,obj,NULL,TO_CHAR);
    	if (obj->victpoweroff != NULL && obj->victpoweroff != '\0'
	    && str_cmp(obj->victpoweroff,"(null)") )
	    kavitem(str_dup(obj->victpoweroff),ch,obj,NULL,TO_ROOM);
       if (!IS_SET(obj->quest, QUEST_ARTIFACT) &&
           ( IS_SET(ch->in_room->room_flags, ROOM_NO_TELEPORT) ||
ch->in_room->vnum == 30000) &&
            CAN_WEAR(obj,ITEM_TAKE))
        {
            send_to_char("A powerful force hurls you from the room.\n\r",ch);
            act("$n is hurled from the room by a powerful force.",ch,NULL,NULL,TO_ROOM);
            ch->position = POS_STUNNED;
            char_from_room(ch);
            char_to_room(ch,get_room_index(ROOM_VNUM_LIMBO));
            act("$n appears in the room, and falls to the ground stunned.",ch,NULL,NULL,TO_ROOM);
        }
    	if ( (mount = ch->mount) == NULL) return;
    	char_from_room( mount );
    	char_to_room( mount, ch->in_room );
    	do_look( mount, "auto" );
	return;
    }
    else if ( IS_SET(obj->spectype, SITEM_TELEPORTER))
    {
    	if (obj->chpoweron != NULL && obj->chpoweron != '\0'
	    && str_cmp(obj->chpoweron,"(null)") )
	    kavitem(str_dup(obj->chpoweron),ch,obj,NULL,TO_CHAR);
    	if (obj->victpoweron != NULL && obj->victpoweron != '\0'
	    && str_cmp(obj->victpoweron,"(null)") )
	    kavitem(str_dup(obj->victpoweron),ch,obj,NULL,TO_ROOM);
	pRoomIndex     = get_room_index(obj->specpower);
	if ( pRoomIndex == NULL ) return;
	char_from_room(ch);
	char_to_room(ch,pRoomIndex);
	do_look(ch,"auto");
    	if (obj->chpoweroff != NULL && obj->chpoweroff != '\0'
	    && str_cmp(obj->chpoweroff,"(null)") )
	    kavitem(str_dup(obj->chpoweroff),ch,obj,NULL,TO_CHAR);
    	if (obj->victpoweroff != NULL && obj->victpoweroff != '\0'
	    && str_cmp(obj->victpoweroff,"(null)") )
	    kavitem(str_dup(obj->victpoweroff),ch,obj,NULL,TO_ROOM);
        if (!IS_SET(obj->quest, QUEST_ARTIFACT) &&
            IS_SET(ch->in_room->room_flags, ROOM_NO_TELEPORT) &&
            CAN_WEAR(obj,ITEM_TAKE))
        {
            send_to_char("A powerful force hurls you from the room.\n\r",ch);
            act("$n is hurled from the room by a powerful force.",ch,NULL,NULL,TO_ROOM);
            ch->position = POS_STUNNED;
            char_from_room(ch);
            char_to_room(ch,get_room_index(ROOM_VNUM_LIMBO));
            act("$n appears in the room, and falls to the ground stunned.",ch,NULL,NULL,TO_ROOM);
        }
    	if ( (mount = ch->mount) == NULL) return;
    	char_from_room( mount );
    	char_to_room( mount, ch->in_room );
    	do_look( mount, "auto" );
	return;
    }
    else if ( IS_SET(obj->spectype, SITEM_OBJECT))
    {
	if ( get_obj_index(obj->specpower) == NULL ) return;
	obj2 = create_object(get_obj_index(obj->specpower), ch->level);
	if ( CAN_WEAR(obj2,ITEM_TAKE) ) obj_to_char(obj2,ch);
	else                           obj_to_room(obj2,ch->in_room);
    }
    else if ( IS_SET(obj->spectype, SITEM_MOBILE))
    {
	if ( get_mob_index(obj->specpower) == NULL ) return;
	mob = create_mobile(get_mob_index(obj->specpower));
	char_to_room(mob,ch->in_room);
    }
    else if ( IS_SET(obj->spectype, SITEM_ACTION))
    {
	interpret(ch,obj->victpoweron);
	if (obj->victpoweroff != NULL && str_cmp(obj->victpoweroff,"(null)") &&
	    obj->victpoweroff != '\0')
	{
	    for ( victim = char_list; victim != NULL; victim = victim_next )
	    {
		victim_next	= victim->next;
		if ( victim->in_room == NULL ) continue;
		if ( victim == ch ) continue;
		if ( victim->in_room == ch->in_room )
		{
		    interpret(victim,obj->victpoweroff);
		    continue;
		}
	    }
	}
    }
    return;
}

void do_press( CHAR_DATA *ch, char *argument )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;
    OBJ_DATA *obj2;
    CHAR_DATA *victim;
    CHAR_DATA *victim_next;
    CHAR_DATA *mount;
    CHAR_DATA *mob;
    ROOM_INDEX_DATA *pRoomIndex;

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if ( arg1[0] == '\0' )
    {
	send_to_char( "Which item do you wish to press?\n\r", ch );
	return;
    }
    if ( (obj = get_obj_wear(ch,arg1)) == NULL ) 
    {
	if ( ( obj = get_obj_here( ch, arg1 ) ) == NULL )
	{
	    send_to_char( "You can't find that item.\n\r", ch );
	    return;
	}
	/* You should only be able to use nontake items on floor */
	if (CAN_WEAR(obj, ITEM_TAKE))
	{
	    send_to_char( "But you are not wearing it!\n\r", ch );
	    return;
	}
    }
    if ( obj == NULL || !IS_SET(obj->spectype, SITEM_PRESS) )
    {
	send_to_char( "There is nothing on this item to press.\n\r", ch );
	return;
    }
    if ( IS_SET(obj->spectype, SITEM_TARGET) && arg2[0] == '\0' )
    {
	send_to_char( "Who do you wish to use it on?\n\r", ch );
	return;
    }
    if ( IS_SET(obj->spectype, SITEM_TARGET) )
    {
	if ( ( victim = get_char_room( ch, arg2 ) ) == NULL )
	{
	    send_to_char( "Nobody here by that name.\n\r", ch );
	    return;
	}
    }
    else victim = ch;
    if (obj->chpoweruse != NULL && obj->chpoweruse != '\0'
	&& str_cmp(obj->chpoweruse,"(null)") )
	kavitem(str_dup(obj->chpoweruse),ch,obj,NULL,TO_CHAR);
    if (obj->victpoweruse != NULL && obj->victpoweruse != '\0'
	&& str_cmp(obj->victpoweruse,"(null)") )
	kavitem(str_dup(obj->victpoweruse),ch,obj,NULL,TO_ROOM);
    if ( IS_SET(obj->spectype, SITEM_SPELL))
    {
	int castlevel = obj->level;
	if (castlevel < 1) castlevel = 1;
	else if (castlevel > 60) castlevel = 60;
	obj_cast_spell( obj->specpower, castlevel, ch, victim, NULL );
 	if (!IS_IMMORTAL( ch))
		WAIT_STATE(ch,6);
	if ( IS_SET(obj->spectype, SITEM_DELAY1)) 
        {
	    if (!IS_IMMORTAL( ch))
		WAIT_STATE(ch,6);
	}
	if ( IS_SET(obj->spectype, SITEM_DELAY2)) 
	{
	    if (!IS_IMMORTAL( ch))
		WAIT_STATE(ch,12);
	}
	return;
    }
    else if ( IS_SET(obj->spectype, SITEM_TRANSPORTER))
    {
    	if (obj->chpoweron != NULL && obj->chpoweron != '\0'
	    && str_cmp(obj->chpoweron,"(null)") )
	    kavitem(str_dup(obj->chpoweron),ch,obj,NULL,TO_CHAR);
    	if (obj->victpoweron != NULL && obj->victpoweron != '\0'
	    && str_cmp(obj->victpoweron,"(null)") )
	    kavitem(str_dup(obj->victpoweron),ch,obj,NULL,TO_ROOM);
	pRoomIndex     = get_room_index(obj->specpower);
	obj->specpower = ch->in_room->vnum;
	if ( pRoomIndex == NULL ) return;
	char_from_room(ch);
	char_to_room(ch,pRoomIndex);
	do_look(ch,"auto");
    	if (obj->chpoweroff != NULL && obj->chpoweroff != '\0'
	    && str_cmp(obj->chpoweroff,"(null)") )
	    kavitem(str_dup(obj->chpoweroff),ch,obj,NULL,TO_CHAR);
    	if (obj->victpoweroff != NULL && obj->victpoweroff != '\0'
	    && str_cmp(obj->victpoweroff,"(null)") )
	    kavitem(str_dup(obj->victpoweroff),ch,obj,NULL,TO_ROOM);
       if (!IS_SET(obj->quest, QUEST_ARTIFACT) &&
            IS_SET(ch->in_room->room_flags, ROOM_NO_TELEPORT) &&
            CAN_WEAR(obj,ITEM_TAKE))
        {
            send_to_char("A powerful force hurls you from the room.\n\r",ch);
            act("$n is hurled from the room by a powerful force.",ch,NULL,NULL,TO_ROOM);
            ch->position = POS_STUNNED;
            char_from_room(ch);
            char_to_room(ch,get_room_index(ROOM_VNUM_LIMBO));
            act("$n appears in the room, and falls to the ground stunned.",ch,NULL,NULL,TO_ROOM);
        }
    	if ( (mount = ch->mount) == NULL) return;
    	char_from_room( mount );
    	char_to_room( mount, ch->in_room );
    	do_look( mount, "auto" );
	return;
    }
    else if ( IS_SET(obj->spectype, SITEM_TELEPORTER))
    {
    	if (obj->chpoweron != NULL && obj->chpoweron != '\0'
	    && str_cmp(obj->chpoweron,"(null)") )
	    kavitem(str_dup(obj->chpoweron),ch,obj,NULL,TO_CHAR);
    	if (obj->victpoweron != NULL && obj->victpoweron != '\0'
	    && str_cmp(obj->victpoweron,"(null)") )
	    kavitem(str_dup(obj->victpoweron),ch,obj,NULL,TO_ROOM);
	pRoomIndex     = get_room_index(obj->specpower);
	if ( pRoomIndex == NULL ) return;
	char_from_room(ch);
	char_to_room(ch,pRoomIndex);
	do_look(ch,"auto");
    	if (obj->chpoweroff != NULL && obj->chpoweroff != '\0'
	    && str_cmp(obj->chpoweroff,"(null)") )
	    kavitem(str_dup(obj->chpoweroff),ch,obj,NULL,TO_CHAR);
    	if (obj->victpoweroff != NULL && obj->victpoweroff != '\0'
	    && str_cmp(obj->victpoweroff,"(null)") )
	    kavitem(str_dup(obj->victpoweroff),ch,obj,NULL,TO_ROOM);
        if (!IS_SET(obj->quest, QUEST_ARTIFACT) &&
            IS_SET(ch->in_room->room_flags, ROOM_NO_TELEPORT) &&
            CAN_WEAR(obj,ITEM_TAKE))
        {
            send_to_char("A powerful force hurls you from the room.\n\r",ch);
            act("$n is hurled from the room by a powerful force.",ch,NULL,NULL,TO_ROOM);
            ch->position = POS_STUNNED;
            char_from_room(ch);
            char_to_room(ch,get_room_index(ROOM_VNUM_LIMBO));
            act("$n appears in the room, and falls to the ground stunned.",ch,NULL,NULL,TO_ROOM);
        }
    	if ( (mount = ch->mount) == NULL) return;
    	char_from_room( mount );
    	char_to_room( mount, ch->in_room );
    	do_look( mount, "auto" );
	return;
    }
    else if ( IS_SET(obj->spectype, SITEM_OBJECT))
    {
	if ( get_obj_index(obj->specpower) == NULL ) return;
	obj2 = create_object(get_obj_index(obj->specpower), ch->level);
	if ( CAN_WEAR(obj2,ITEM_TAKE) ) obj_to_char(obj2,ch);
	else                           obj_to_room(obj2,ch->in_room);
    }
    else if ( IS_SET(obj->spectype, SITEM_MOBILE))
    {
	if ( get_mob_index(obj->specpower) == NULL ) return;
	mob = create_mobile(get_mob_index(obj->specpower));
	char_to_room(mob,ch->in_room);
    }
    else if ( IS_SET(obj->spectype, SITEM_ACTION))
    {
	interpret(ch,obj->victpoweron);
	if (obj->victpoweroff != NULL && str_cmp(obj->victpoweroff,"(null)") &&
	    obj->victpoweroff != '\0')
	{
	    for ( victim = char_list; victim != NULL; victim = victim_next )
	    {
		victim_next	= victim->next;
		if ( victim->in_room == NULL ) continue;
		if ( victim == ch ) continue;
		if ( victim->in_room == ch->in_room )
		{
		    interpret(victim,obj->victpoweroff);
		    continue;
		}
	    }
	}
    }
    return;
}

void do_twist( CHAR_DATA *ch, char *argument )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;
    OBJ_DATA *obj2;
    CHAR_DATA *victim;
    CHAR_DATA *victim_next;
    CHAR_DATA *mount;
    CHAR_DATA *mob;
    ROOM_INDEX_DATA *pRoomIndex;

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if ( arg1[0] == '\0' )
    {
	send_to_char( "Which item do you wish to twist?\n\r", ch );
	return;
    }
    if ( (obj = get_obj_wear(ch,arg1)) == NULL ) 
    {
	if ( ( obj = get_obj_here( ch, arg1 ) ) == NULL )
	{
	    send_to_char( "You can't find that item.\n\r", ch );
	    return;
	}
	/* You should only be able to use nontake items on floor */
	if (CAN_WEAR(obj, ITEM_TAKE))
	{
	    send_to_char( "But you are not wearing it!\n\r", ch );
	    return;
	}
    }
    if ( obj == NULL || !IS_SET(obj->spectype, SITEM_TWIST) )
    {
	send_to_char( "This item cannot be twisted.\n\r", ch );
	return;
    }
    if ( IS_SET(obj->spectype, SITEM_TARGET) && arg2[0] == '\0' )
    {
	send_to_char( "Who do you wish to use it on?\n\r", ch );
	return;
    }
    if ( IS_SET(obj->spectype, SITEM_TARGET) )
    {
	if ( ( victim = get_char_room( ch, arg2 ) ) == NULL )
	{
	    send_to_char( "Nobody here by that name.\n\r", ch );
	    return;
	}
    }
    else victim = ch;
    if (obj->chpoweruse != NULL && obj->chpoweruse != '\0'
	&& str_cmp(obj->chpoweruse,"(null)") )
	kavitem(str_dup(obj->chpoweruse),ch,obj,NULL,TO_CHAR);
    if (obj->victpoweruse != NULL && obj->victpoweruse != '\0'
	&& str_cmp(obj->victpoweruse,"(null)") )
	kavitem(str_dup(obj->victpoweruse),ch,obj,NULL,TO_ROOM);
    if ( IS_SET(obj->spectype, SITEM_SPELL))
    {
	int castlevel = obj->level;
	if (castlevel < 1) castlevel = 1;
	else if (castlevel > 60) castlevel = 60;
	obj_cast_spell( obj->specpower, castlevel, ch, victim, NULL );
    	if (!IS_IMMORTAL( ch))
		WAIT_STATE(ch,6);
	if ( IS_SET(obj->spectype, SITEM_DELAY1)) 
	{
	    if (!IS_IMMORTAL( ch))
		WAIT_STATE(ch,6);
	}
	if ( IS_SET(obj->spectype, SITEM_DELAY2))
	{
     		if (!IS_IMMORTAL( ch))
			WAIT_STATE(ch,12);
	}
	return;
    }
    else if ( IS_SET(obj->spectype, SITEM_TRANSPORTER))
    {
    	if (obj->chpoweron != NULL && obj->chpoweron != '\0'
	    && str_cmp(obj->chpoweron,"(null)") )
	    kavitem(str_dup(obj->chpoweron),ch,obj,NULL,TO_CHAR);
    	if (obj->victpoweron != NULL && obj->victpoweron != '\0'
	    && str_cmp(obj->victpoweron,"(null)") )
	    kavitem(str_dup(obj->victpoweron),ch,obj,NULL,TO_ROOM);
	pRoomIndex     = get_room_index(obj->specpower);
	obj->specpower = ch->in_room->vnum;
	if ( pRoomIndex == NULL ) return;
	char_from_room(ch);
	char_to_room(ch,pRoomIndex);
	do_look(ch,"auto");
    	if (obj->chpoweroff != NULL && obj->chpoweroff != '\0'
	    && str_cmp(obj->chpoweroff,"(null)") )
	    kavitem(str_dup(obj->chpoweroff),ch,obj,NULL,TO_CHAR);
    	if (obj->victpoweroff != NULL && obj->victpoweroff != '\0'
	    && str_cmp(obj->victpoweroff,"(null)") )
	    kavitem(str_dup(obj->victpoweroff),ch,obj,NULL,TO_ROOM);
       if (!IS_SET(obj->quest, QUEST_ARTIFACT) &&
            IS_SET(ch->in_room->room_flags, ROOM_NO_TELEPORT) &&
            CAN_WEAR(obj,ITEM_TAKE))
        {
            send_to_char("A powerful force hurls you from the room.\n\r",ch);
            act("$n is hurled from the room by a powerful force.",ch,NULL,NULL,TO_ROOM);
            ch->position = POS_STUNNED;
            char_from_room(ch);
            char_to_room(ch,get_room_index(ROOM_VNUM_LIMBO));
            act("$n appears in the room, and falls to the ground stunned.",ch,NULL,NULL,TO_ROOM);
        }
    	if ( (mount = ch->mount) == NULL) return;
    	char_from_room( mount );
    	char_to_room( mount, ch->in_room );
    	do_look( mount, "auto" );
	return;
    }
    else if ( IS_SET(obj->spectype, SITEM_TELEPORTER))
    {
    	if (obj->chpoweron != NULL && obj->chpoweron != '\0'
	    && str_cmp(obj->chpoweron,"(null)") )
	    kavitem(str_dup(obj->chpoweron),ch,obj,NULL,TO_CHAR);
    	if (obj->victpoweron != NULL && obj->victpoweron != '\0'
	    && str_cmp(obj->victpoweron,"(null)") )
	    kavitem(str_dup(obj->victpoweron),ch,obj,NULL,TO_ROOM);
	pRoomIndex     = get_room_index(obj->specpower);
	if ( pRoomIndex == NULL ) return;
	char_from_room(ch);
	char_to_room(ch,pRoomIndex);
	do_look(ch,"auto");
    	if (obj->chpoweroff != NULL && obj->chpoweroff != '\0'
	    && str_cmp(obj->chpoweroff,"(null)") )
	    kavitem(str_dup(obj->chpoweroff),ch,obj,NULL,TO_CHAR);
    	if (obj->victpoweroff != NULL && obj->victpoweroff != '\0'
	    && str_cmp(obj->victpoweroff,"(null)") )
	    kavitem(str_dup(obj->victpoweroff),ch,obj,NULL,TO_ROOM);
       if (!IS_SET(obj->quest, QUEST_ARTIFACT) &&
            IS_SET(ch->in_room->room_flags, ROOM_NO_TELEPORT) &&
            CAN_WEAR(obj,ITEM_TAKE))
        {
            send_to_char("A powerful force hurls you from the room.\n\r",ch);
            act("$n is hurled from the room by a powerful force.",ch,NULL,NULL,TO_ROOM);
            ch->position = POS_STUNNED;
            char_from_room(ch);
            char_to_room(ch,get_room_index(ROOM_VNUM_LIMBO));
            act("$n appears in the room, and falls to the ground stunned.",ch,NULL,NULL,TO_ROOM);
        }
    	if ( (mount = ch->mount) == NULL) return;
    	char_from_room( mount );
    	char_to_room( mount, ch->in_room );
    	do_look( mount, "auto" );
	return;
    }
    else if ( IS_SET(obj->spectype, SITEM_OBJECT))
    {
	if ( get_obj_index(obj->specpower) == NULL ) return;
	obj2 = create_object(get_obj_index(obj->specpower), ch->level);
	if ( CAN_WEAR(obj2,ITEM_TAKE) ) obj_to_char(obj2,ch);
	else                           obj_to_room(obj2,ch->in_room);
    }
    else if ( IS_SET(obj->spectype, SITEM_MOBILE))
    {
	if ( get_mob_index(obj->specpower) == NULL ) return;
	mob = create_mobile(get_mob_index(obj->specpower));
	char_to_room(mob,ch->in_room);
    }
    else if ( IS_SET(obj->spectype, SITEM_ACTION))
    {
	interpret(ch,obj->victpoweron);
	if (obj->victpoweroff != NULL && str_cmp(obj->victpoweroff,"(null)") &&
	    obj->victpoweroff != '\0')
	{
	    for ( victim = char_list; victim != NULL; victim = victim_next )
	    {
		victim_next	= victim->next;
		if ( victim->in_room == NULL ) continue;
		if ( victim == ch ) continue;
		if ( victim->in_room == ch->in_room )
		{
		    interpret(victim,obj->victpoweroff);
		    continue;
		}
	    }
	}
    }
    return;
}

void do_pull( CHAR_DATA *ch, char *argument )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;
    OBJ_DATA *obj2;
    CHAR_DATA *victim;
    CHAR_DATA *victim_next;
    CHAR_DATA *mount;
    CHAR_DATA *mob;
    ROOM_INDEX_DATA *pRoomIndex;

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if ( arg1[0] == '\0' )
    {
	send_to_char( "What do you wish to pull?\n\r", ch );
	return;
    }
    if ( (obj = get_obj_wear(ch,arg1)) == NULL ) 
    {
	if ( ( obj = get_obj_here( ch, arg1 ) ) == NULL )
	{
	    send_to_char( "You can't find that item.\n\r", ch );
	    return;
	}
	/* You should only be able to use nontake items on floor */
	if (CAN_WEAR(obj, ITEM_TAKE))
	{
	    send_to_char( "But you are not wearing it!\n\r", ch );
	    return;
	}
    }
    if ( obj == NULL || !IS_SET(obj->spectype, SITEM_PULL) )
    {
	send_to_char( "This item cannot be pulled.\n\r", ch );
	return;
    }
    if ( IS_SET(obj->spectype, SITEM_TARGET) && arg2[0] == '\0' )
    {
	send_to_char( "Who do you wish to use it on?\n\r", ch );
	return;
    }
    if ( IS_SET(obj->spectype, SITEM_TARGET) )
    {
	if ( ( victim = get_char_room( ch, arg2 ) ) == NULL )
	{
	    send_to_char( "Nobody here by that name.\n\r", ch );
	    return;
	}
    }
    else victim = ch;
    if (obj->chpoweruse != NULL && obj->chpoweruse != '\0'
	&& str_cmp(obj->chpoweruse,"(null)") )
	kavitem(str_dup(obj->chpoweruse),ch,obj,NULL,TO_CHAR);
    if (obj->victpoweruse != NULL && obj->victpoweruse != '\0'
	&& str_cmp(obj->victpoweruse,"(null)") )
	kavitem(str_dup(obj->victpoweruse),ch,obj,NULL,TO_ROOM);
    if ( IS_SET(obj->spectype, SITEM_SPELL))
    {
	int castlevel = obj->level;
	if (castlevel < 1) castlevel = 1;
	else if (castlevel > 60) castlevel = 60;
	obj_cast_spell( obj->specpower, castlevel, ch, victim, NULL );
    	if (!IS_IMMORTAL( ch))
		WAIT_STATE(ch,6);
	if ( IS_SET(obj->spectype, SITEM_DELAY1))
	{
		if (!IS_IMMORTAL( ch))
			WAIT_STATE(ch,6);
	}
	if ( IS_SET(obj->spectype, SITEM_DELAY2)) 
	{
	    if (!IS_IMMORTAL( ch))
		WAIT_STATE(ch,12);
	}
	return;
    }
    else if ( IS_SET(obj->spectype, SITEM_TRANSPORTER))
    {
    	if (obj->chpoweron != NULL && obj->chpoweron != '\0'
	    && str_cmp(obj->chpoweron,"(null)") )
	    kavitem(str_dup(obj->chpoweron),ch,obj,NULL,TO_CHAR);
    	if (obj->victpoweron != NULL && obj->victpoweron != '\0'
	    && str_cmp(obj->victpoweron,"(null)") )
	    kavitem(str_dup(obj->victpoweron),ch,obj,NULL,TO_ROOM);
	pRoomIndex     = get_room_index(obj->specpower);
	obj->specpower = ch->in_room->vnum;
	if ( pRoomIndex == NULL ) return;
	char_from_room(ch);
	char_to_room(ch,pRoomIndex);
	do_look(ch,"auto");
    	if (obj->chpoweroff != NULL && obj->chpoweroff != '\0'
	    && str_cmp(obj->chpoweroff,"(null)") )
	    kavitem(str_dup(obj->chpoweroff),ch,obj,NULL,TO_CHAR);
    	if (obj->victpoweroff != NULL && obj->victpoweroff != '\0'
	    && str_cmp(obj->victpoweroff,"(null)") )
	    kavitem(str_dup(obj->victpoweroff),ch,obj,NULL,TO_ROOM);
       if (!IS_SET(obj->quest, QUEST_ARTIFACT) &&
            IS_SET(ch->in_room->room_flags, ROOM_NO_TELEPORT) &&
            CAN_WEAR(obj,ITEM_TAKE))
        {
            send_to_char("A powerful force hurls you from the room.\n\r",ch);
            act("$n is hurled from the room by a powerful force.",ch,NULL,NULL,TO_ROOM);
            ch->position = POS_STUNNED;
            char_from_room(ch);
            char_to_room(ch,get_room_index(ROOM_VNUM_LIMBO));
            act("$n appears in the room, and falls to the ground stunned.",ch,NULL,NULL,TO_ROOM);
        }
    	if ( (mount = ch->mount) == NULL) return;
    	char_from_room( mount );
    	char_to_room( mount, ch->in_room );
    	do_look( mount, "auto" );
	return;
    }
    else if ( IS_SET(obj->spectype, SITEM_TELEPORTER))
    {
    	if (obj->chpoweron != NULL && obj->chpoweron != '\0'
	    && str_cmp(obj->chpoweron,"(null)") )
	    kavitem(str_dup(obj->chpoweron),ch,obj,NULL,TO_CHAR);
    	if (obj->victpoweron != NULL && obj->victpoweron != '\0'
	    && str_cmp(obj->victpoweron,"(null)") )
	    kavitem(str_dup(obj->victpoweron),ch,obj,NULL,TO_ROOM);
	pRoomIndex     = get_room_index(obj->specpower);
	if ( pRoomIndex == NULL ) return;
	char_from_room(ch);
	char_to_room(ch,pRoomIndex);
	do_look(ch,"auto");
    	if (obj->chpoweroff != NULL && obj->chpoweroff != '\0'
	    && str_cmp(obj->chpoweroff,"(null)") )
	    kavitem(str_dup(obj->chpoweroff),ch,obj,NULL,TO_CHAR);
    	if (obj->victpoweroff != NULL && obj->victpoweroff != '\0'
	    && str_cmp(obj->victpoweroff,"(null)") )
	    kavitem(str_dup(obj->victpoweroff),ch,obj,NULL,TO_ROOM);
       if (!IS_SET(obj->quest, QUEST_ARTIFACT) &&
            IS_SET(ch->in_room->room_flags, ROOM_NO_TELEPORT) &&
            CAN_WEAR(obj,ITEM_TAKE))
        {
            send_to_char("A powerful force hurls you from the room.\n\r",ch);
            act("$n is hurled from the room by a powerful force.",ch,NULL,NULL,TO_ROOM);
            ch->position = POS_STUNNED;
            char_from_room(ch);
            char_to_room(ch,get_room_index(ROOM_VNUM_LIMBO));
            act("$n appears in the room, and falls to the ground stunned.",ch,NULL,NULL,TO_ROOM);
        }
    	if ( (mount = ch->mount) == NULL) return;
    	char_from_room( mount );
    	char_to_room( mount, ch->in_room );
    	do_look( mount, "auto" );
	return;
    }
    else if ( IS_SET(obj->spectype, SITEM_OBJECT))
    {
	if ( get_obj_index(obj->specpower) == NULL ) return;
	obj2 = create_object(get_obj_index(obj->specpower), ch->level);
	if ( CAN_WEAR(obj2,ITEM_TAKE) ) obj_to_char(obj2,ch);
	else                           obj_to_room(obj2,ch->in_room);
    }
    else if ( IS_SET(obj->spectype, SITEM_MOBILE))
    {
	if ( get_mob_index(obj->specpower) == NULL ) return;
	mob = create_mobile(get_mob_index(obj->specpower));
	char_to_room(mob,ch->in_room);
    }
    else if ( IS_SET(obj->spectype, SITEM_ACTION))
    {
	interpret(ch,obj->victpoweron);
	if (obj->victpoweroff != NULL && str_cmp(obj->victpoweroff,"(null)") &&
	    obj->victpoweroff != '\0')
	{
	    for ( victim = char_list; victim != NULL; victim = victim_next )
	    {
		victim_next	= victim->next;
		if ( victim->in_room == NULL ) continue;
		if ( victim == ch ) continue;
		if ( victim->in_room == ch->in_room )
		{
		    interpret(victim,obj->victpoweroff);
		    continue;
		}
	    }
	}
    }
    return;
}

bool is_ok_to_wear( CHAR_DATA *ch, bool wolf_ok, char *argument )
{
    char arg [MAX_INPUT_LENGTH];
    int count;
    argument = one_argument( argument, arg );

    if (!str_cmp(arg,"head"))
    {
	if (IS_HEAD(ch,LOST_HEAD)) return FALSE;
    }
    else if (!str_cmp(arg,"face"))
    {
	if (IS_HEAD(ch,LOST_HEAD)) return FALSE;
    }
    else if (!str_cmp(arg,"left_hand"))
    {
	if (!IS_NPC(ch) && IS_SET(ch->special, SPC_WOLFMAN) && !wolf_ok) return FALSE;
	if (IS_ARM_L(ch,LOST_ARM)) return FALSE;
	else if (IS_ARM_L(ch,BROKEN_ARM)) return FALSE;
	else if (IS_ARM_L(ch,LOST_HAND)) return FALSE;
	else if (IS_ARM_L(ch,BROKEN_THUMB)) return FALSE;
	else if (IS_ARM_L(ch,LOST_THUMB)) return FALSE;
	count = 0;
	if (IS_ARM_L(ch,LOST_FINGER_I)||IS_ARM_L(ch,BROKEN_FINGER_I)) count+= 1;
	if (IS_ARM_L(ch,LOST_FINGER_M)||IS_ARM_L(ch,BROKEN_FINGER_M)) count+= 1;
	if (IS_ARM_L(ch,LOST_FINGER_R)||IS_ARM_L(ch,BROKEN_FINGER_R)) count+= 1;
	if (IS_ARM_L(ch,LOST_FINGER_L)||IS_ARM_L(ch,BROKEN_FINGER_L)) count+= 1;
	if (count > 2) return FALSE;
    }
    else if (!str_cmp(arg,"right_hand"))
    {
	if (!IS_NPC(ch) && IS_SET(ch->special, SPC_WOLFMAN) && !wolf_ok) return FALSE;
	if (IS_ARM_R(ch,LOST_ARM)) return FALSE;
	else if (IS_ARM_R(ch,BROKEN_ARM)) return FALSE;
	else if (IS_ARM_R(ch,LOST_HAND)) return FALSE;
	else if (IS_ARM_R(ch,BROKEN_THUMB)) return FALSE;
	else if (IS_ARM_R(ch,LOST_THUMB)) return FALSE;
	count = 0;
	if (IS_ARM_R(ch,LOST_FINGER_I)||IS_ARM_R(ch,BROKEN_FINGER_I)) count+= 1;
	if (IS_ARM_R(ch,LOST_FINGER_M)||IS_ARM_R(ch,BROKEN_FINGER_M)) count+= 1;
	if (IS_ARM_R(ch,LOST_FINGER_R)||IS_ARM_R(ch,BROKEN_FINGER_R)) count+= 1;
	if (IS_ARM_R(ch,LOST_FINGER_L)||IS_ARM_R(ch,BROKEN_FINGER_L)) count+= 1;
	if (count > 2) return FALSE;
    }
    else if (!str_cmp(arg,"third_hand"))
    {
      if (!IS_SET(ch->newbits, THIRD_HAND)) return FALSE;
	if (!IS_NPC(ch) && IS_SET(ch->special, SPC_WOLFMAN) && !wolf_ok) return FALSE;
/*
	if (IS_ARM_T(ch,LOST_ARM)) return FALSE;
	else if (IS_ARM_T(ch,BROKEN_ARM)) return FALSE;
	else if (IS_ARM_T(ch,LOST_HAND)) return FALSE;
	else if (IS_ARM_T(ch,BROKEN_THUMB)) return FALSE;
	else if (IS_ARM_T(ch,LOST_THUMB)) return FALSE;
	count = 0;
	if (IS_ARM_T(ch,LOST_FINGER_I)||IS_ARM_T(ch,BROKEN_FINGER_I)) count+= 1;
	if (IS_ARM_T(ch,LOST_FINGER_M)||IS_ARM_T(ch,BROKEN_FINGER_M)) count+= 1;
	if (IS_ARM_T(ch,LOST_FINGER_R)||IS_ARM_T(ch,BROKEN_FINGER_R)) count+= 1;
	if (IS_ARM_T(ch,LOST_FINGER_L)||IS_ARM_T(ch,BROKEN_FINGER_L)) count+= 1;
	if (count > 2) return FALSE;
*/
    }
    else if (!str_cmp(arg,"fourth_hand"))
    {
      if (!IS_SET(ch->newbits, FOURTH_HAND)) return FALSE;
	if (!IS_NPC(ch) && IS_SET(ch->special, SPC_WOLFMAN) && !wolf_ok) return FALSE;
/*
	if (IS_ARM_F(ch,LOST_ARM)) return FALSE;
	else if (IS_ARM_F(ch,BROKEN_ARM)) return FALSE;
	else if (IS_ARM_F(ch,LOST_HAND)) return FALSE;
	else if (IS_ARM_F(ch,BROKEN_THUMB)) return FALSE;
	else if (IS_ARM_F(ch,LOST_THUMB)) return FALSE;
	count = 0;
	if (IS_ARM_F(ch,LOST_FINGER_I)||IS_ARM_F(ch,BROKEN_FINGER_I)) count+= 1;
	if (IS_ARM_F(ch,LOST_FINGER_M)||IS_ARM_F(ch,BROKEN_FINGER_M)) count+= 1;
	if (IS_ARM_F(ch,LOST_FINGER_R)||IS_ARM_F(ch,BROKEN_FINGER_R)) count+= 1;
	if (IS_ARM_F(ch,LOST_FINGER_L)||IS_ARM_F(ch,BROKEN_FINGER_L)) count+= 1;
	if (count > 2) return FALSE;
*/
    }
    else if (!str_cmp(arg,"left_wrist"))
    {
	if (IS_ARM_L(ch,LOST_ARM)) return FALSE;
	else if (IS_ARM_L(ch,LOST_HAND)) return FALSE;
    }
    else if (!str_cmp(arg,"right_wrist"))
    {
	if (IS_ARM_R(ch,LOST_ARM)) return FALSE;
	else if (IS_ARM_R(ch,LOST_HAND)) return FALSE;
    }
    else if (!str_cmp(arg,"left_finger"))
    {
	if (IS_ARM_L(ch,LOST_ARM)) return FALSE;
	else if (IS_ARM_L(ch,LOST_HAND)) return FALSE;
	else if (IS_ARM_L(ch,LOST_FINGER_R)) return FALSE;
    }
    else if (!str_cmp(arg,"right_finger"))
    {
	if (IS_ARM_R(ch,LOST_ARM)) return FALSE;
	else if (IS_ARM_R(ch,LOST_HAND)) return FALSE;
	else if (IS_ARM_R(ch,LOST_FINGER_R)) return FALSE;
    }
    else if (!str_cmp(arg,"arms"))
    {
	if (IS_ARM_L(ch,LOST_ARM) && IS_ARM_R(ch,LOST_ARM)) return FALSE;
    }
    else if (!str_cmp(arg,"hands"))
    {
	if (IS_ARM_L(ch,LOST_ARM) && IS_ARM_R(ch,LOST_ARM)) return FALSE;
	if (IS_ARM_L(ch,LOST_HAND) || IS_ARM_R(ch,LOST_HAND)) return FALSE;
    }
    else if (!str_cmp(arg,"legs"))
    {
	if (IS_LEG_L(ch,LOST_LEG) && IS_LEG_R(ch,LOST_LEG)) return FALSE;
    }
    else if (!str_cmp(arg,"feet"))
    {
	if (IS_LEG_L(ch,LOST_LEG) && IS_LEG_R(ch,LOST_LEG)) return FALSE;
	if (IS_LEG_L(ch,LOST_FOOT) || IS_LEG_R(ch,LOST_FOOT)) return FALSE;
    }
    return TRUE;
}

void do_qmake( CHAR_DATA *ch, char *argument )
{
    OBJ_INDEX_DATA *pObjIndex;
    OBJ_DATA *obj;
    char arg[MAX_INPUT_LENGTH];

    argument = one_argument( argument, arg );

    if (arg[0] == '\0')
    {
	send_to_char("Do you wish to qmake a MACHINE or a CARD?\n\r",ch);
	return;
    }
    if (!str_cmp(arg,"card"))
    {
    	if ( (pObjIndex = get_obj_index( OBJ_VNUM_QUESTCARD )) == NULL)
    	{
	    send_to_char("Missing object, please inform KaVir.\n\r",ch);
	    return;
    	}
        if (ch->in_room == NULL) return;
        obj = create_object(pObjIndex, 0);
        obj_to_char(obj, ch);
	quest_object(ch,obj);
    }
    else if (!str_cmp(arg,"machine"))
    {
    	if ( (pObjIndex = get_obj_index( OBJ_VNUM_QUESTMACHINE )) == NULL)
    	{
	    send_to_char("Missing object, please inform KaVir.\n\r",ch);
	    return;
    	}
        if (ch->in_room == NULL) return;
        obj = create_object(pObjIndex, 0);
        obj_to_room(obj, ch->in_room);
    }
    else
    {
	send_to_char("You can only qmake a MACHINE or a CARD.\n\r",ch);
	return;
    }
    send_to_char("Ok.\n\r",ch);
    return;
}

void do_recharge( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_INPUT_LENGTH];
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;
    OBJ_DATA *qobj;
    int count = 0;
    int value = 1;

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if ( arg1[0] == '\0' || arg2[0] == '\0' )
    {
	send_to_char( "Syntax: recharge <quest card> <quest machine>\n\r", ch );
	return;
    }
    if ( (obj = get_obj_carry(ch,arg1)) == NULL )
    {
	send_to_char( "You are not carrying that object.\n\r", ch );
	return;
    }
    if (obj->item_type != ITEM_QUESTCARD)
    {
	send_to_char( "That is not a quest card.\n\r", ch );
	return;
    }
    if ( (qobj = get_obj_here(ch,arg2)) == NULL )
    {
	send_to_char( "There is nothing for you to recharge it with.\n\r", ch );
	return;
    }
    if (qobj->item_type != ITEM_QUESTMACHINE)
    {
	send_to_char( "That is not a quest machine.\n\r", ch );
	return;
    }
    if (obj->value[0] == -1) count += 1;
    if (obj->value[1] == -1) count += 1;
    if (obj->value[2] == -1) count += 1;
    if (obj->value[3] == -1) count += 1;
    if (count == 4) quest_object( ch, obj );
    else
    {
	send_to_char( "You have not yet completed the current quest.\n\r", ch );
	return;
    }
    act("You place $p into a small slot in $P.",ch,obj,qobj,TO_CHAR);
    act("$n places $p into a small slot in $P.",ch,obj,qobj,TO_ROOM);
    act("$P makes a few clicks and returns $p.",ch,obj,qobj,TO_CHAR);
    act("$P makes a few clicks and returns $p.",ch,obj,qobj,TO_ROOM);
    value = obj->level;
    if (value < 1) value = 1; else if (value > 50) value = 50;

    obj = create_object(get_obj_index( OBJ_VNUM_PROTOPLASM ), 0);
    obj->value[0] = value;
    obj->level = value;
    obj->cost = value*1000;
    obj->item_type = ITEM_QUEST;
    obj_to_char(obj,ch);
    if (obj->questmaker != NULL) free_string(obj->questmaker);
    obj->questmaker = str_dup(ch->name);
    free_string( obj->name );
    obj->name = str_dup( "quest token" );
    free_string( obj->short_descr );
    sprintf(buf,"a %d point quest token",value);
    obj->short_descr = str_dup( buf );
    free_string( obj->description );
    sprintf(buf,"A %d point quest token lies on the floor.",value);
    obj->description = str_dup( buf );
    act("You take $p from $P.",ch,obj,qobj,TO_CHAR);
    act("$n takes $p from $P.",ch,obj,qobj,TO_ROOM);
    if (!IS_NPC(ch))
    {
	ch->pcdata->score[SCORE_NUM_QUEST]++;
	ch->pcdata->score[SCORE_QUEST] += value;
	sprintf(buf,"%s has completed a quest!.",ch->name);
    }
    else sprintf(buf,"%s has completed a quest!.",ch->pcdata->switchname);
    buf[0] = UPPER(buf[0]);
    do_info(ch,buf);
    do_autosave(ch,"");
    return;
}

void quest_object( CHAR_DATA *ch, OBJ_DATA *obj )
{
    static const sh_int quest_selection[] = 
    {
	 102,
	 9201, 9225,  605, 1329, 2276, 5112, 6513, 6517, 6519, 5001,
	 5005, 5011, 5012, 5013, 2902, 1352, 2348, 2361, 3005, 5011,
	 5012, 5013, 2902, 1352, 2348, 2361, 3005,  300,  303,  307,
	 7216, 1100,  100,30315, 5110, 6001, 3050,  301, 5230,30302,
	  663, 7303, 2915, 2275, 8600, 8601, 8602, 8603, 5030, 9321,
	 6010, 1304, 1307, 1332, 1333, 1342, 1356, 1361, 2304, 2322,
	 2331, 2382, 8003, 8005, 5300, 5302, 5309, 5310, 5311, 4000,
	  601,  664,  900,  906,  923,  311, 7203, 7206, 1101, 5214,
	 5223, 5228, 2804, 1612, 5207, 9302, 5301, 5224, 7801, 9313,
	 6304, 2003, 3425, 3423, 608,  1109,30319, 8903, 9317, 9307,
	 4050,  911, 2204, 4100, 3428,  310, 5113, 3402, 5319, 6512,
	 5114,  913,30316, 2106, 8007, 6601, 2333, 3610, 2015, 5022,
	 1394, 2202, 1401, 6005, 1614,  647, 1388, 9311, 3604, 4701,
	30325, 6106, 2003, 7190, 9322, 1384, 3412, 2342, 1374, 2210,
	 2332, 2901, 7200, 7824, 3410, 2013, 1510, 8306, 3414, 2005
    };
    int object;
    if (obj == NULL || obj->item_type != ITEM_QUESTCARD) return;

    object = number_range(obj->level, obj->level + 100);
    if (object < 1 || object > 150) object = 0;
    obj->value[0] = quest_selection[object];

    object = number_range(obj->level, obj->level + 100);
    if (object < 1 || object > 150) object = 0;
    obj->value[1] = quest_selection[object];

    object = number_range(obj->level, obj->level + 100);
    if (object < 1 || object > 150) object = 0;
    obj->value[2] = quest_selection[object];

    object = number_range(obj->level, obj->level + 100);
    if (object < 1 || object > 150) object = 0;
    obj->value[3] = quest_selection[object];
    return;
}

void do_complete( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    OBJ_DATA *qobj;
    OBJ_DATA *obj;
    OBJ_INDEX_DATA *pObjIndex;
    int count = 0;
    int count2 = 0;

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if ( arg1[0] == '\0' )
    {
	send_to_char( "Syntax: complete <quest card> <object>\n\r", ch );
	return;
    }

    if ( (qobj = get_obj_carry(ch,arg1)) == NULL )
    {
	send_to_char( "You are not carrying that object.\n\r", ch );
	return;
    }
    else if (qobj->item_type != ITEM_QUESTCARD)
    {
	send_to_char( "That is not a quest card.\n\r", ch );
	return;
    }
    if (qobj->value[0] == -1) count += 1;
    if (qobj->value[1] == -1) count += 1;
    if (qobj->value[2] == -1) count += 1;
    if (qobj->value[3] == -1) count += 1;

    if ( arg2[0] == '\0' )
    {
	if (count == 4) {send_to_char("This quest card has been completed.\n\r",ch);return;}
	send_to_char("You still need to find the following:\n\r",ch);
	if (qobj->value[0] != -1)
	    {pObjIndex = get_obj_index( qobj->value[0] );
	    if ( pObjIndex != NULL )
		sprintf(buf,"     %s.\n\r",pObjIndex->short_descr);
		buf[5] = UPPER(buf[5]);send_to_char(buf,ch);}
	if (qobj->value[1] != -1)
	    {pObjIndex = get_obj_index( qobj->value[1] );
	    if ( pObjIndex != NULL )
		sprintf(buf,"     %s.\n\r",pObjIndex->short_descr);
		buf[5] = UPPER(buf[5]);send_to_char(buf,ch);}
	if (qobj->value[2] != -1)
	    {pObjIndex = get_obj_index( qobj->value[2] );
	    if ( pObjIndex != NULL )
		sprintf(buf,"     %s.\n\r",pObjIndex->short_descr);
		buf[5] = UPPER(buf[5]);send_to_char(buf,ch);}
	if (qobj->value[3] != -1)
	    {pObjIndex = get_obj_index( qobj->value[3] );
	    if ( pObjIndex != NULL )
		sprintf(buf,"     %s.\n\r",pObjIndex->short_descr);
		buf[5] = UPPER(buf[5]);send_to_char(buf,ch);}
	return;
    }

    if (count == 4)
    {
	act( "But $p has already been completed!",ch,qobj,NULL,TO_CHAR );
	return;
    }

    if ( (obj = get_obj_carry(ch,arg2)) == NULL )
    {
	send_to_char( "You are not carrying that object.\n\r", ch );
	return;
    }
    if (obj->questmaker != NULL && strlen(obj->questmaker) > 1)
    {
	send_to_char( "You cannot use that item.\n\r", ch );
	return;
    }
    if (obj->pIndexData->vnum == 30037 || obj->pIndexData->vnum == 30041)
    {
	send_to_char( "That item has lost its quest value, you must collect a new one.\n\r", ch );
	return;
    }
    if (qobj->value[0] != -1)
	{pObjIndex = get_obj_index( qobj->value[0] );
	if ( pObjIndex != NULL &&
	!str_cmp(obj->short_descr, pObjIndex->short_descr))
	qobj->value[0] = -1;}
    if (qobj->value[1] != -1)
	{pObjIndex = get_obj_index( qobj->value[1] );
	if ( pObjIndex != NULL &&
	!str_cmp(obj->short_descr, pObjIndex->short_descr))
	qobj->value[1] = -1;}
    if (qobj->value[2] != -1)
	{pObjIndex = get_obj_index( qobj->value[2] );
	if ( pObjIndex != NULL &&
	!str_cmp(obj->short_descr, pObjIndex->short_descr))
	qobj->value[2] = -1;}
    if (qobj->value[3] != -1)
	{pObjIndex = get_obj_index( qobj->value[3] );
	if ( pObjIndex != NULL &&
	!str_cmp(obj->short_descr, pObjIndex->short_descr))
	qobj->value[3] = -1;}
    if (qobj->value[0] == -1) count2 += 1;
    if (qobj->value[1] == -1) count2 += 1;
    if (qobj->value[2] == -1) count2 += 1;
    if (qobj->value[3] == -1) count2 += 1;
    if (count == count2)
    {
	send_to_char( "That item is not required.\n\r", ch );
	return;
    }

    act("You touch $p to $P, and $p vanishes!",ch,obj,qobj,TO_CHAR);
    act("$n touches $p to $P, and $p vanishes!",ch,obj,qobj,TO_ROOM);
    obj_from_char(obj);
    extract_obj(obj);
    if (count >= 3) {act("$p has been completed!",ch,qobj,NULL,TO_CHAR);}
    else if (count == 2) {act("$p now requires one more object!",ch,qobj,NULL,TO_CHAR);}
    else if (count == 1) {act("$p now requires two more objects!",ch,qobj,NULL,TO_CHAR);}
    else if (count == 0) {act("$p now requires three more objects!",ch,qobj,NULL,TO_CHAR);}
    return;
}

void do_sheath( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];

    one_argument(argument,arg);

    if (arg[0] == '\0') send_to_char("Which hand, left or right?\n\r",ch);
    else if (!str_cmp(arg,"all") || !str_cmp(arg,"both"))
    {
	sheath(ch,TRUE );
	sheath(ch,FALSE);
    }
    else if (!str_cmp(arg,"l") || !str_cmp(arg,"left" )) sheath(ch,FALSE);
    else if (!str_cmp(arg,"r") || !str_cmp(arg,"right")) sheath(ch,TRUE );
    else send_to_char("Which hand, left or right?\n\r",ch);
    return;
}

void do_draw( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];

    one_argument(argument,arg);

    if (!IS_NPC(ch) && IS_SET(ch->special, SPC_WOLFMAN))
    {
	send_to_char("Not in this form.\n\r",ch);
	return;
    }
    if (arg[0] == '\0') send_to_char("Which hand, left or right?\n\r",ch);
    else if (!str_cmp(arg,"all") || !str_cmp(arg,"both"))
    {
	draw(ch,TRUE );
	draw(ch,FALSE);
    }
    else if (!str_cmp(arg,"l") || !str_cmp(arg,"left" )) draw(ch,FALSE);
    else if (!str_cmp(arg,"r") || !str_cmp(arg,"right")) draw(ch,TRUE );
    else send_to_char("Which hand, left or right?\n\r",ch);
    return;
}

void sheath( CHAR_DATA *ch, bool right )
{
    OBJ_DATA *obj;
    OBJ_DATA *obj2;
    int scabbard;

    if (right)
    {
	scabbard = WEAR_SCABBARD_R;
	if ( (obj = get_eq_char(ch,WEAR_WIELD)) == NULL )
	{
	    send_to_char("You are not holding anything in your right hand.\n\r",ch);
	    return;
	}
	else if ( (obj2 = get_eq_char(ch,scabbard)) != NULL)
	{
	    act("You already have $p in your right scabbard.",ch,obj2,NULL,TO_CHAR);
	    return;
	}
    	act("You slide $p into your right scabbard.",ch,obj,NULL,TO_CHAR);
    	act("$n slides $p into $s right scabbard.",ch,obj,NULL,TO_ROOM);
    }
    else
    {
	scabbard = WEAR_SCABBARD_L;
	if ( (obj = get_eq_char(ch,WEAR_HOLD)) == NULL )
	{
	    send_to_char("You are not holding anything in your left hand.\n\r",ch);
	    return;
	}
	else if ( (obj2 = get_eq_char(ch,scabbard)) != NULL)
	{
	    act("You already have $p in your left scabbard.",ch,obj2,NULL,TO_CHAR);
	    return;
	}
    	act("You slide $p into your left scabbard.",ch,obj,NULL,TO_CHAR);
    	act("$n slides $p into $s left scabbard.",ch,obj,NULL,TO_ROOM);
    }
    if (obj->item_type != ITEM_WEAPON)
    {
	act("$p is not a weapon.",ch,obj,NULL,TO_CHAR);
	return;
    }
    unequip_char(ch,obj);
    obj->wear_loc = scabbard;
    return;
}

void draw( CHAR_DATA *ch, bool right )
{
    OBJ_DATA *obj;
    OBJ_DATA *obj2;
    int scabbard;
    int worn;
    if (right)
    {
	scabbard = WEAR_SCABBARD_R;
	worn = WEAR_WIELD;
	if ( (obj = get_eq_char(ch,scabbard)) == NULL )
	{
	    send_to_char("Your right scabbard is empty.\n\r",ch);
	    return;
	}
	else if ( (obj2 = get_eq_char(ch,WEAR_WIELD)) != NULL)
	{
	    act("You already have $p in your right hand.",ch,obj2,NULL,TO_CHAR);
	    return;
	}
    	act("You draw $p from your right scabbard.",ch,obj,NULL,TO_CHAR);
    	act("$n draws $p from $s right scabbard.",ch,obj,NULL,TO_ROOM);
    }
    else
    {
	scabbard = WEAR_SCABBARD_L;
	worn = WEAR_HOLD;
	if ( (obj = get_eq_char(ch,scabbard)) == NULL )
	{
	    send_to_char("Your left scabbard is empty.\n\r",ch);
	    return;
	}
	else if ( (obj2 = get_eq_char(ch,WEAR_HOLD)) != NULL)
	{
	    act("You already have $p in your left hand.",ch,obj2,NULL,TO_CHAR);
	    return;
	}
    	act("You draw $p from your left scabbard.",ch,obj,NULL,TO_CHAR);
    	act("$n draws $p from $s left scabbard.",ch,obj,NULL,TO_ROOM);
    }
    obj->wear_loc = -1;
    equip_char(ch,obj,worn);
    return;
}

void do_special( CHAR_DATA *ch, char *argument )
{
    char bname[MAX_INPUT_LENGTH];
    char bshort[MAX_INPUT_LENGTH];
    char blong[MAX_INPUT_LENGTH];
    char *kav;
    int dice = number_range(1,3);
    OBJ_DATA *obj;

    obj = create_object(get_obj_index( OBJ_VNUM_PROTOPLASM ), 0);

    kav = special_item_name( obj );

    switch ( dice )
    {
    default:
	sprintf(bname,"%s ring", kav);
	sprintf(bshort,"a %s ring", kav);
	sprintf(blong,"A %s ring lies here.", kav);
	obj->wear_flags = ITEM_WEAR_FINGER + ITEM_TAKE;
	break;
    case 1:
	sprintf(bname,"%s ring", kav);
	sprintf(bshort,"a %s ring", kav);
	sprintf(blong,"A %s ring lies here.", kav);
	obj->wear_flags = ITEM_WEAR_FINGER + ITEM_TAKE;
	break;
    case 2:
	sprintf(bname,"%s necklace", kav);
	sprintf(bshort,"a %s necklace", kav);
	sprintf(blong,"A %s necklace lies here.", kav);
	obj->wear_flags = ITEM_WEAR_NECK + ITEM_TAKE;
	break;
    case 3:
	sprintf(bname,"%s plate", kav);
	sprintf(bshort,"a suit of %s platemail", kav);
	sprintf(blong,"A suit of %s platemail lies here.", kav);
	obj->wear_flags = ITEM_WEAR_BODY + ITEM_TAKE;
	break;
    }

    if (obj->wear_flags == 513 || obj->wear_flags == 8193 || 
	obj->wear_flags == 16385)
    {
	obj->item_type = ITEM_WEAPON;
    	obj->value[1] = 10;
    	obj->value[2] = 20;
    	obj->value[3] = number_range(1,12);
    }
    else
    {
	obj->item_type = ITEM_ARMOR;
    	obj->value[0] = 15;
    }

    obj->level = 50;
    obj->cost = 100000;

    if (obj->questmaker != NULL) free_string(obj->questmaker);
    obj->questmaker = str_dup(ch->name);

    free_string( obj->name );
    obj->name = str_dup( bname );

    free_string( obj->short_descr );
    obj->short_descr = str_dup( bshort );

    free_string( obj->description );
    obj->description = str_dup( blong );

    obj_to_char(obj,ch);
    return;
}

char *special_item_name( OBJ_DATA *obj )
{
    static char buf[MAX_INPUT_LENGTH];
    int dice = number_range(1,4);
    switch ( dice )
    {
    default:
	strcpy(buf,"golden");
	break;
    case 1:
	strcpy(buf,"golden");
	break;
    case 2:
	strcpy(buf,"silver");
	break;
    case 3:
	strcpy(buf,"brass");
	break;
    case 4:
	strcpy(buf,"copper");
	break;
    }
    return buf;
}





/***************************************************************************
 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
 *                                                                         *
 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
 *  Chastain, Michael Quan, and Mitchell Tse.                              *
 *                                                                         *
 *  In order to use any part of this Merc Diku Mud, you must comply with   *
 *  both the original Diku license in 'license.doc' as well the Merc       *
 *  license in 'license.txt'.  In particular, you may not remove either of *
 *  these copyright notices.                                               *
 *                                                                         *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 ***************************************************************************/

#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"



/*
 * Local functions.
 */
ROOM_INDEX_DATA *	find_location	args( ( CHAR_DATA *ch, char *arg ) );
void			call_all	args( ( CHAR_DATA *ch ) );
char			buf		[MAX_STRING_LENGTH];
char			arg		[MAX_INPUT_LENGTH];

void do_setdisciplines(CHAR_DATA *ch, char *argument)
{
    CHAR_DATA *victim;
    char arg1[MAX_STRING_LENGTH];
    char arg2[MAX_STRING_LENGTH];
    char arg3[MAX_STRING_LENGTH];
    int val;
    int i;

    argument = one_argument(argument, arg1);
    argument = one_argument(argument, arg2);
    argument = one_argument(argument, arg3);

    if (arg1[0] == '\0')
    {
	send_to_char("Set whose disciplines?\n\r",ch);
	return;
    }

    if ((victim = get_char_world(ch, arg1)) == NULL)
    {
	send_to_char("They aren't here.\n\r",ch);
	return;
    }

    val = atoi(arg3);

    if (val < -2 || val > 10)
    {
	send_to_char("Values between -2 and 10 please.\n\r",ch);
	return;
    }

    if (!str_cmp(arg2, "all"))
    {
	for (i = 0; i < MAX_DISCIPLINES; i++)
	    victim->power[i] = val;
	send_to_char("All disciplines set.\n\r",ch);
	return;
    }

    for (i = 0; i < MAX_DISCIPLINES; i++)
    {
	if (!str_prefix(arg2, discipline[i]))
	{
	    send_to_char("Discipline set.\n\r",ch);
	    victim->power[i] = val;
	    return;
	}
    }
    send_to_char("No such discipline.\n\r",ch);
}

void do_showquest( CHAR_DATA *ch, char *argument )
{
    OBJ_DATA *obj2;
    char buf[MAX_STRING_LENGTH];
    static const sh_int quest_selection[] = 
    {
	 102,
	 9201, 9225,  605, 1329, 2276, 5112, 6513, 6517, 6519, 5001,
	 5005, 5011, 5012, 5013, 2902, 1352, 2348, 2361, 3005, 5011,
	 5012, 5013, 2902, 1352, 2348, 2361, 3005,  300,  303,  307,
	 7216, 1100,  100,30315, 5110, 6001, 3050,  301, 5230,30302,
	  663, 7303, 2915, 2275, 8600, 8601, 8602, 8603, 5030, 9321,
	 6010, 1304, 1307, 1332, 1333, 1342, 1356, 1361, 2304, 2322,
	 2331, 2382, 8003, 8005, 5300, 5302, 5309, 5310, 5311, 4000,
	  601,  664,  900,  906,  923,  311, 7203, 7206, 1101, 5214,
	 5223, 5228, 2804, 1612, 5207, 9302, 5301, 5224, 7801, 9313,
	 6304, 2003, 3425, 3423, 608,  1109,30319, 8903, 9317, 9307,
	 4050,  911, 2204, 4100, 3428,  310, 5113, 3402, 5319, 6512,
	 5114,  913,30316, 2106, 8007, 6601, 2333, 3610, 2015, 5022,
	 1394, 2202, 1401, 6005, 1614,  647, 1388, 9311, 3604, 4701,
	30325, 6106, 2003, 7190, 9322, 1384, 3412, 2342, 1374, 2210,
	 2332, 2901, 7200, 7824, 3410, 2013, 1510, 8306, 3414, 2005
    };

    int i = 1;

    for ( i = 1; i < 150; i++ )
    {
      if ( (obj2 = create_object(get_obj_index( quest_selection[i]),0 )) == NULL )
        break;
      sprintf(buf, "%s\n",obj2->short_descr );
      append_file(ch, QUEST_TXT, buf);
//    stc(buf,ch);
      extract_obj(obj2);
    }
    return;
}

void do_resetarea(CHAR_DATA *ch, char *argument)
{
    send_to_char("You patiently twiddle your thumbs, waiting for the reset.\n\r",ch);
    send_to_char("Oh fuck this, you MAKE it reset!\n\r",ch);
    area_update();
}

void do_tick(CHAR_DATA *ch, char *argument)
{
    send_to_char("TICK!  Now wasn't that fun for you.\n\r",ch);
    weather_update();
    char_update();
    obj_update();
    area_update();
    room_update();
}

void do_form(CHAR_DATA *ch, char *argument)
{
    char buf[MAX_STRING_LENGTH];

    if (argument[0]=='\0')
    {
	send_to_char("Change your form to resemble what?\n\r",ch);
	return;
    }

    if (!str_cmp(argument, "Trace")) 
    {
	send_to_char("Hmmm... not a good idea really.\n\r", ch);
	return;
    } 

    sprintf(buf, "%s's form blurs and shifts to resemble %s.",
			ch->name,
			argument);
    act(buf,ch,NULL,NULL,TO_ROOM);
    set_pc_name(ch, argument);
    send_to_char("Your form blurs and shifts to resemble ",ch);
    send_to_char(argument,ch);
    send_to_char(".\n\r",ch);
    set_enter_room_text(ch, "");
}

/*
void do_reseteq( CHAR_DATA *ch, char *argument )
{
do_forceauto(ch,"rem all");
do_forceauto(ch,"drop all");
do_purge(ch,"");
do_autosave(ch,"");
send_to_char("Your eq has been wiped ",ch);
return;
}
*/
void do_wizhelp( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    int cmd;
    int col;
 
    col = 0;
    for ( cmd = 0; cmd_table[cmd].name[0] != '\0'; cmd++ )
    {
        if ( cmd_table[cmd].level > LEVEL_HERO
        &&   cmd_table[cmd].level <= get_trust( ch ) )
	{
	    sprintf( buf, "%-12s", cmd_table[cmd].name );
	    send_to_char( buf, ch );
	    if ( ++col % 6 == 0 )
		send_to_char( "\n\r", ch );
	}
    }
 
    if ( col % 6 != 0 )
	send_to_char( "\n\r", ch );
    return;
}


void do_testarm( CHAR_DATA *ch, char *argument )
{
   SET_BIT(ch->newbits, THIRD_HAND);
   SET_BIT(ch->newbits, FOURTH_HAND);
   stc("Ohh. You grow some arms.\n\r",ch);
   return;
}
void do_noarm( CHAR_DATA *ch, char *argument )
{
CHAR_DATA *victim;
char arg1[100];

one_argument(argument, arg1);

  if ((victim = get_char_world(ch, arg1)) == NULL) {
    stc("They are not here.\r\n", ch);
    return;
  }

	
  if (!IS_SET(victim->newbits, THIRD_HAND) && !IS_SET(victim->newbits,
      FOURTH_HAND)) {
    stc("They do not have any extra arms.\r\n", ch);
    return;
   } else {
    if (IS_SET(victim->newbits, THIRD_HAND) &&
!IS_CLASS(ch, CLASS_DEMON)) {
     REMOVE_BIT(victim->newbits, THIRD_HAND);
     stc("Third arm removed.\r\n", ch);}
 
    if (IS_SET(victim->newbits, FOURTH_HAND) && !IS_CLASS(ch,
CLASS_DEMON))
{    REMOVE_BIT(victim->newbits, FOURTH_HAND);
    stc("Fourth arm removed.\r\n", ch);
 }   
}
 return; 
} 

void do_bamfin( CHAR_DATA *ch, char *argument )
{
    if ( !IS_NPC(ch) )
    {
	smash_tilde( argument );
	free_string( ch->pcdata->bamfin );
	ch->pcdata->bamfin = str_dup( argument );
	send_to_char( "Ok.\n\r", ch );
    }
    return;
}



void do_bamfout( CHAR_DATA *ch, char *argument )
{
    if ( !IS_NPC(ch) )
    {
	smash_tilde( argument );
	free_string( ch->pcdata->bamfout );
	ch->pcdata->bamfout = str_dup( argument );
	send_to_char( "Ok.\n\r", ch );
    }
    return;
}

void do_godless( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];

    one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if ( arg[0] == '\0')
    {
	send_to_char( "Do you wish to switch it ON or OFF?\n\r", ch );
	return;
    }

    if ( ( (ch->level > 3)
	|| (ch->level < 2)
	|| (ch->trust > 3) )
	&& !IS_SET(ch->act, PLR_GODLESS))
    {
	send_to_char( "Sorry, you must be level 3.\n\r", ch );
	return;
    }

    if (IS_SET(ch->act, PLR_GODLESS) && !str_cmp(arg,"off"))
    {
	REMOVE_BIT(ch->act, PLR_GODLESS);
	send_to_char("You now obey the gods.\n\r", ch);
	sprintf(buf,"%s now follows the whims of the gods.",ch->name);
	do_info(ch,buf);
    }
    else if (!IS_SET(ch->act, PLR_GODLESS) && !str_cmp(arg,"off")) {
	send_to_char("But you already obey the gods!\n\r", ch);
	return;}
    else if (!IS_SET(ch->act, PLR_GODLESS) && !str_cmp(arg,"on"))
    {
	SET_BIT(ch->act, PLR_GODLESS);
	send_to_char("You no longer obey the gods.\n\r", ch);
	sprintf(buf,"%s has rejected the gods.",ch->name);
	do_info(ch,buf);
    }
    else if (IS_SET(ch->act, PLR_GODLESS) && !str_cmp(arg,"on")) {
	send_to_char("But you have already rejected the gods!\n\r", ch);
	return;}
    else
	send_to_char( "Do you wish to switch it ON or OFF?\n\r", ch );
    return;
}

void do_astat( CHAR_DATA *ch, char *argument )
{
     if( arena == FIGHT_OPEN )
         send_to_char("Arena is [CLEAR]\n\r",ch);

     if( arena == FIGHT_START )
         send_to_char("A challenge has been started.\n\r",ch);

     if( arena == FIGHT_BUSY )
         send_to_char("Arena is [BUSY]\n\r",ch);

     if( arena == FIGHT_LOCK )
         send_to_char("Arena is [LOCKED]\n\r",ch);

     return;
}

void do_aclear( CHAR_DATA *ch, char *argument )
{
     
       arena = FIGHT_OPEN;
       send_to_char("Arena now set [CLEARED]\n\r",ch);
       return;
       sprintf(buf,"[Arena] The arena has been opened.\n\r");
{
 DESCRIPTOR_DATA *d;    
 for ( d = descriptor_list; d; d = d->next )
  {
     if( d->connected == CON_PLAYING)
     {
        send_to_char( buf, d->character );
     }
  }
}
     }

void do_abusy( CHAR_DATA *ch, char *argument )
{
       arena = FIGHT_BUSY;
       send_to_char("Arena now set [BUSY]\n\r",ch);
       sprintf(buf,"[Arena] The arena is now busy.\n\r");
{
 DESCRIPTOR_DATA *d;
 for ( d = descriptor_list; d; d = d->next )
  {
     if( d->connected == CON_PLAYING)
     {
        send_to_char( buf, d->character );
     }
  }
    }
     }

void do_alock( CHAR_DATA *ch, char *argument )
{
     
       arena = FIGHT_LOCK;
       send_to_char("Arena now set [LOCKED]\n\r",ch);
       sprintf(buf,"[Arena] The arena has been locked.\n\r");
 {
   DESCRIPTOR_DATA *d;    
 for ( d = descriptor_list; d; d = d->next )
  {
     if( d->connected == CON_PLAYING)
     {
        send_to_char( buf, d->character );
     }
  }
       
 }
}


void do_nosummon( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];

    one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if ( arg[0] == '\0')
    {
	send_to_char( "Do you wish to switch summon ON or OFF?\n\r", ch );
	return;
    }

    if (IS_IMMUNE(ch, IMM_SUMMON) && !str_cmp(arg,"off"))
    {
	REMOVE_BIT(ch->immune, IMM_SUMMON);
	send_to_char("You now cant be the target of summon and portal.\n\r", ch);
    }
    else if (!IS_IMMUNE(ch, IMM_SUMMON) && !str_cmp(arg,"off")) {
	send_to_char("But it is already off!\n\r", ch);
	return;}
    else if (!IS_IMMUNE(ch, IMM_SUMMON) && !str_cmp(arg,"on"))
    {
	SET_BIT(ch->immune, IMM_SUMMON);
	send_to_char("You now can be the target of summon and portal.\n\r", ch);
    }
    else if (IS_IMMUNE(ch, IMM_SUMMON) && !str_cmp(arg,"on")) {
	send_to_char("But it is already on!\n\r", ch);
	return;}
    else
	send_to_char( "Do you wish to switch it ON or OFF?\n\r", ch );
    return;
}

void do_transport( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];

    one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if ( arg[0] == '\0')
    {
	send_to_char( "Do you wish to switch transport ON or OFF?\n\r", ch );
	return;
    }

    if (IS_IMMUNE(ch, IMM_TRANSPORT) && !str_cmp(arg,"off"))
    {
	REMOVE_BIT(ch->immune, IMM_TRANSPORT);
	send_to_char("You can no longer be the target of transport spells.\n\r", ch);
    }
    else if (!IS_IMMUNE(ch, IMM_TRANSPORT) && !str_cmp(arg,"off")) {
	send_to_char("But it is already off!\n\r", ch);
	return;}
    else if (!IS_IMMUNE(ch, IMM_TRANSPORT) && !str_cmp(arg,"on"))
    {
	SET_BIT(ch->immune, IMM_TRANSPORT);
	send_to_char("You can now be the target of transport spells.\n\r", ch);
    }
    else if (IS_IMMUNE(ch, IMM_TRANSPORT) && !str_cmp(arg,"on")) {
	send_to_char("But it is already on!\n\r", ch);
	return;}
    else
	send_to_char( "Do you wish to switch it ON or OFF?\n\r", ch );
    return;
}

void do_watcher( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;

    one_argument( argument, arg );

    if (IS_NPC(ch) || !IS_SET(ch->act, PLR_WATCHER)
	|| (ch->level > 6)
	|| (ch->level < 2)
	|| (ch->trust > 0) )
    {
	send_to_char( "Huh?\n\r", ch );
	return;
    }

    if ( arg[0] == '\0' )
    {
	do_users(ch,"");
	return;
    }

    if ( ( victim = get_char_world( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if (ch == victim)
    {
	send_to_char( "Not on yourself.\n\r", ch );
	return;
    }

    if ( IS_NPC(victim) )
    {
	send_to_char( "Not on NPC's.\n\r", ch );
	return;
    }

    if ( victim->desc->snoop_by != NULL )
    {
	send_to_char( "You better not, they are being snooped.\n\r", ch );
	return;
    }

    SET_BIT(victim->act, PLR_WATCHER);
    act( "$n has made you a watcher.", ch, NULL, victim, TO_VICT );
    act( "You make $N a watcher.", ch, NULL, victim, TO_CHAR );
    return;
}



void do_deny( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    char buf[MAX_STRING_LENGTH];

    sprintf(buf,"%s: Deny %s",ch->name,argument);
    if (ch->level < NO_WATCH) do_watching(ch,buf);

    one_argument( argument, arg );
    if ( arg[0] == '\0' )
    {
	send_to_char( "Deny whom?\n\r", ch );
	return;
    }

    if ( ( victim = get_char_world( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( IS_NPC(victim) )
    {
	send_to_char( "Not on NPC's.\n\r", ch );
	return;
    }

    if (IS_SET(victim->act, PLR_GODLESS) && get_trust(ch) < NO_GODLESS
        && !IS_SET(ch->extra , EXTRA_ANTI_GODLESS))
    {
	send_to_char( "You failed.\n\r", ch );
	return;
    }

    if ( get_trust( victim ) >= get_trust( ch ) )
    {
	send_to_char( "You failed.\n\r", ch );
	return;
    }

    SET_BIT(victim->act, PLR_DENY);
    send_to_char( "You are denied access!\n\r", victim );
    send_to_char( "OK.\n\r", ch );
    do_quit( victim, "" );

    return;
}



void do_disconnect( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    DESCRIPTOR_DATA *d;
    CHAR_DATA *victim;

    sprintf(buf,"%s: Disconnect %s",ch->name,argument);
    if (ch->level < NO_WATCH) do_watching(ch,buf);

    one_argument( argument, arg );
    if ( arg[0] == '\0' )
    {
	send_to_char( "Disconnect whom?\n\r", ch );
	return;
    }

    if ( ( victim = get_char_world( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( victim->desc == NULL )
    {
	act( "$N doesn't have a descriptor.", ch, NULL, victim, TO_CHAR );
	return;
    }

    if (IS_SET(victim->act, PLR_GODLESS) && get_trust(ch) < NO_GODLESS
        && !IS_SET(ch->extra , EXTRA_ANTI_GODLESS))
    {
	send_to_char( "You failed.\n\r", ch );
	return;
    }

    for ( d = descriptor_list; d != NULL; d = d->next )
    {
	if ( d == victim->desc )
	{
	    close_socket( d );
	    send_to_char( "Ok.\n\r", ch );
	    return;
	}
    }

    bug( "Do_disconnect: desc not found.", 0 );
    send_to_char( "Descriptor not found!\n\r", ch );
    return;
}


/*
void do_howl( CHAR_DATA *ch, char *argument )
{
    DESCRIPTOR_DATA *d;
    CHAR_DATA *vch;
    char buf [MAX_STRING_LENGTH];
    
    if (IS_NPC(ch)) return;
    if (!IS_CLASS(ch, CLASS_WEREWOLF) && !IS_POLYAFF(ch, POLY_WOLF))
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }
    if ( argument[0] == '\0' )
    {
	send_to_char("What do you wish to howl?\n\r",ch);
	return;
    }
    if (IS_SET(ch->deaf, CHANNEL_HOWL))
    {
	send_to_char("But you're not even on the channel!\n\r",ch);
	return;
    }

    for ( d = descriptor_list; d != NULL; d = d->next )
    {
	if ( d->connected != CON_PLAYING ) continue;
	if ( (vch = d->character) == NULL ) continue;
	if ( IS_SET(vch->deaf, CHANNEL_HOWL) ) continue;
	if ( vch == ch )
	    act("You howl '$T'.", ch, NULL, argument, TO_CHAR);
	else if (!IS_NPC(vch) && (IS_POLYAFF(ch, POLY_WOLF) ||
	    IS_CLASS(vch, CLASS_WEREWOLF) || IS_IMMORTAL(vch)))
	{
	    sprintf(buf,"$n howls '%s'.", argument);
	    act(buf, ch, NULL, vch, TO_VICT);
	}
	else if ( vch->in_room == ch->in_room )
	    act("$n throws back $s head and howls loudly.", ch, NULL, vch, TO_VICT);
	else if ( vch->in_room->area == ch->in_room->area )
	    act("You hear a loud howl from nearby.", ch, NULL, vch, TO_VICT);
	else
	    act("You hear a loud howl in the distance.", ch, NULL, vch, TO_VICT);
    }

    return;
}
*/
void do_info( CHAR_DATA *ch, char *argument )
{
    DESCRIPTOR_DATA *d;
    
    if ( argument[0] == '\0' )
    {
	return;
    }

    if (!IS_NPC(ch) && IS_IMMORTAL(ch) && IS_SET(ch->act,PLR_WIZINVIS))
	return;

    for ( d = descriptor_list; d != NULL; d = d->next )
    {
	if ( d->connected == CON_PLAYING && 
		!IS_SET(d->character->deaf, CHANNEL_INFO) )
	{
	    send_to_char( "#6Info ->#n ",d->character );
	    send_to_char( argument, d->character );
	    send_to_char( "\n\r",   d->character );
	}
    }

    return;
}

void do_watching( CHAR_DATA *ch, char *argument )
{
    DESCRIPTOR_DATA *d;
    
    if ( argument[0] == '\0' )
    {
	return;
    }

    for ( d = descriptor_list; d != NULL; d = d->next )
    {
	if ( d->connected == CON_PLAYING && 
	    IS_SET(d->character->act, PLR_WATCHER) &&
	    !IS_SET(d->character->deaf, CHANNEL_INFO) )
	{
	    send_to_char( "Monitor -> ",d->character );
	    send_to_char( argument, d->character );
	    send_to_char( "\n\r",   d->character );
	}
    }

    return;
}

void logchan( char *argument )
{
    CHAR_DATA *ch;
    DESCRIPTOR_DATA *d;
    
    if ( argument[0] == '\0' )
    {
	return;
    }

    for ( d = descriptor_list; d != NULL; d = d->next )
    {
	if ( ( ch = d->character ) == NULL ) continue;
	if ( (d->connected == CON_PLAYING) && IS_JUDGE(ch) && 
	    !IS_SET(ch->deaf,CHANNEL_LOG) )
	{
	    send_to_char( "[", ch );
	    send_to_char( argument, ch );
	    send_to_char( "]\n\r",  ch );
	}
    }

    return;
}

void do_echo( CHAR_DATA *ch, char *argument )
{
    DESCRIPTOR_DATA *d;
    char buf[MAX_STRING_LENGTH];

    sprintf(buf,"%s: Echo %s",ch->name,argument);
    if (ch->level < NO_WATCH) do_watching(ch,buf);
    
    if ( argument[0] == '\0' )
    {
	send_to_char( "Echo what?\n\r", ch );
	return;
    }

    for ( d = descriptor_list; d != NULL; d = d->next )
    {
	if ( d->connected == CON_PLAYING )
	{
	    send_to_char( argument, d->character );
/*	    send_to_char( "\n\r",   d->character );	*/
	}
    }

    return;
}



void do_recho( CHAR_DATA *ch, char *argument )
{
    DESCRIPTOR_DATA *d;
    char buf[MAX_STRING_LENGTH];

    sprintf(buf,"%s: Recho %s",ch->name,argument);
    if (ch->level < NO_WATCH) do_watching(ch,buf);
    
    if ( argument[0] == '\0' )
    {
	send_to_char( "Recho what?\n\r", ch );
	return;
    }

    for ( d = descriptor_list; d != NULL; d = d->next )
    {
	if ( d->connected == CON_PLAYING
	&&   d->character->in_room == ch->in_room )
	{
	    send_to_char( argument, d->character );
	    send_to_char( "\n\r",   d->character );
	}
    }

    return;
}



ROOM_INDEX_DATA *find_location( CHAR_DATA *ch, char *arg )
{
    CHAR_DATA *victim;
    OBJ_DATA *obj;

    if ( is_number(arg) && atoi(arg) != 30008 )
	return get_room_index( atoi( arg ) );

    if ( ( victim = get_char_world( ch, arg ) ) != NULL )
	return victim->in_room;

    if ( ( obj = get_obj_world( ch, arg ) ) != NULL && obj->in_room != NULL)
	return obj->in_room;

    if ( obj != NULL && obj->carried_by != NULL && obj->carried_by->in_room != NULL)
	return obj->carried_by->in_room;

    if ( obj != NULL && obj->in_obj != NULL && obj->in_obj->in_room != NULL)
	return obj->in_obj->in_room;

    if ( obj != NULL && obj->in_obj != NULL && obj->in_obj->carried_by && obj->in_obj->carried_by->in_room != NULL)
	return obj->in_obj->carried_by->in_room;

    return NULL;
}



void do_transfer( CHAR_DATA *ch, char *argument )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    ROOM_INDEX_DATA *location;
    DESCRIPTOR_DATA *d;
    CHAR_DATA *victim;
    CHAR_DATA *mount;

    sprintf(buf,"%s: Transfer %s",ch->name,argument);
    if (ch->level < NO_WATCH) do_watching(ch,buf);

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if ( arg1[0] == '\0' )
    {
	send_to_char( "Transfer whom (and where)?\n\r", ch );
	return;
    }

    if ( !str_cmp( arg1, "all" ) )
    {
	for ( d = descriptor_list; d != NULL; d = d->next )
	{
	    if ( d->connected == CON_PLAYING
	    &&   d->character != ch
	    &&   d->character->in_room != NULL
	    &&   can_see( ch, d->character ) )
	    {
		char buf[MAX_STRING_LENGTH];
		sprintf( buf, "%s %s", d->character->name, arg2 );
		if (!IS_NPC(d->character))
		{
		    	if (IS_SET(d->character->act, PLR_GODLESS) && get_trust(ch) < NO_GODLESS
        			&& !IS_SET(ch->extra , EXTRA_ANTI_GODLESS))
				continue;
		}
		do_transfer( ch, buf );
	    }
	}
	return;
    }

    /*
     * Thanks to Grodyn for the optional location parameter.
     */
    if ( arg2[0] == '\0' )
    {
	location = ch->in_room;
    }
    else
    {
	if ( ( location = find_location( ch, arg2 ) ) == NULL )
	{
	    send_to_char( "No such location.\n\r", ch );
	    return;
	}

	if ( room_is_private( location ) )
	{
	    send_to_char( "That room is private right now.\n\r", ch );
	    return;
	}
    }

    if ( ( victim = get_char_world( ch, arg1 ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( victim->in_room == NULL )
    {
	send_to_char( "They are in limbo.\n\r", ch );
	return;
    }

    if (IS_SET(victim->act, PLR_GODLESS) && get_trust(ch) < NO_GODLESS
        && !IS_SET(ch->extra , EXTRA_ANTI_GODLESS))
    {
	send_to_char( "You failed.\n\r", ch );
	return;
    }

    if ( victim->fighting != NULL )
	stop_fighting( victim, TRUE );
    act( "$n disappears in a mushroom cloud.", victim, NULL, NULL, TO_ROOM );
    char_from_room( victim );
    char_to_room( victim, location );
    act( "$n arrives from a puff of smoke.", victim, NULL, NULL, TO_ROOM );
    if ( ch != victim )
	act( "$n has transferred you.", ch, NULL, victim, TO_VICT );
    do_look( victim, "auto" );
    send_to_char( "Ok.\n\r", ch );
    if ( (mount = victim->mount) == NULL) return;
    char_from_room( mount );
    char_to_room( mount, get_room_index(victim->in_room->vnum) );
    if ( ch != mount )
	act( "$n has transferred you.", ch, NULL, mount, TO_VICT );
    do_look( mount, "auto" );
}



void do_at( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    ROOM_INDEX_DATA *location;
    ROOM_INDEX_DATA *original;
    CHAR_DATA *wch;
    
    sprintf(buf,"%s: At %s",ch->name,argument);
    if (ch->level < NO_WATCH) do_watching(ch,buf);

    argument = one_argument( argument, arg );

    if ( arg[0] == '\0' || argument[0] == '\0' )
    {
	send_to_char( "At where what?\n\r", ch );
	return;
    }

    if ( ( location = find_location( ch, arg ) ) == NULL )
    {
	send_to_char( "No such location.\n\r", ch );
	return;
    }

    if ( room_is_private( location ) )
    {
	send_to_char( "That room is private right now.\n\r", ch );
	return;
    }

    original = ch->in_room;
    char_from_room( ch );
    char_to_room( ch, location );
    interpret( ch, argument );

    /*
     * See if 'ch' still exists before continuing!
     * Handles 'at XXXX quit' case.
     */
    for ( wch = char_list; wch != NULL; wch = wch->next )
    {
	if ( wch == ch )
	{
	    char_from_room( ch );
	    char_to_room( ch, original );
	    break;
	}
    }

    return;
}



void do_goto( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    ROOM_INDEX_DATA *location;
    ROOM_INDEX_DATA *in_room;

    one_argument( argument, arg );
    if ( arg[0] == '\0' )
    {
	send_to_char( "Goto where?\n\r", ch );
	return;
    }

    if ( ( location = find_location( ch, arg ) ) == NULL )
    {
	stc("No such location.\n\r",ch);
	return;
    }

    in_room = ch->in_room;
    if ( ch->fighting )
	stop_fighting( ch, TRUE );

    if ( !IS_SET(ch->act, PLR_WIZINVIS) )
	act( "$n $T", ch, NULL,
	    (ch->pcdata && ch->pcdata->bamfout[0] != '\0')
	    ? ch->pcdata->bamfout : "leaves in a swirling mist.",  TO_ROOM );
    char_from_room( ch );
    char_to_room( ch, location );

    if ( !IS_SET(ch->act, PLR_WIZINVIS) )
	act("$n $T", ch, NULL,
	    (ch->pcdata && ch->pcdata->bamfin[0] != '\0')
	    ? ch->pcdata->bamfin : "appears in a swirling mist.", TO_ROOM );

    do_look( ch, "auto" );

    if ( ch->in_room == in_room )
      return;

    return;
}



void do_rstat( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    ROOM_INDEX_DATA *location;
    OBJ_DATA *obj;
    CHAR_DATA *rch;
    int door;

    one_argument( argument, arg );
    location = ( arg[0] == '\0' ) ? ch->in_room : find_location( ch, arg );
    if ( location == NULL )
    {
	send_to_char( "No such location.\n\r", ch );
	return;
    }

    if ( ch->in_room != location && room_is_private( location ) )
    {
	send_to_char( "That room is private right now.\n\r", ch );
	return;
    }

    sprintf( buf, "Name: '%s.'\n\rArea: '%s'.\n\r",
	location->name,
	location->area->name );
    send_to_char( buf, ch );

    sprintf( buf,
	"Vnum: %d.  Sector: %d.  Light: %d.\n\r",
	location->vnum,
	location->sector_type,
	location->light );
    send_to_char( buf, ch );

    sprintf( buf,
	"Room flags: %d.\n\rDescription:\n\r%s",
	location->room_flags,
	location->description );
    send_to_char( buf, ch );

    if ( location->extra_descr != NULL )
    {
	EXTRA_DESCR_DATA *ed;

	send_to_char( "Extra description keywords: '", ch );
	for ( ed = location->extra_descr; ed; ed = ed->next )
	{
	    send_to_char( ed->keyword, ch );
	    if ( ed->next != NULL )
		send_to_char( " ", ch );
	}
	send_to_char( "'.\n\r", ch );
    }

    send_to_char( "Characters:", ch );
    for ( rch = location->people; rch; rch = rch->next_in_room )
    {
	send_to_char( " ", ch );
	one_argument( rch->name, buf );
	send_to_char( buf, ch );
    }

    send_to_char( ".\n\rObjects:   ", ch );
    for ( obj = location->contents; obj; obj = obj->next_content )
    {
	send_to_char( " ", ch );
	one_argument( obj->name, buf );
	send_to_char( buf, ch );
    }
    send_to_char( ".\n\r", ch );

    for ( door = 0; door <= 5; door++ )
    {
	EXIT_DATA *pexit;

	if ( ( pexit = location->exit[door] ) != NULL )
	{
	    sprintf( buf,
		"Door: %d.  To: %d.  Key: %d.  Exit flags: %d.\n\rKeyword: '%s'.  Description: %s",

		door,
		pexit->to_room != NULL ? pexit->to_room->vnum : 0,
	    	pexit->key,
	    	pexit->exit_info,
	    	pexit->keyword,
	    	pexit->description[0] != '\0'
		    ? pexit->description : "(none).\n\r" );
	    send_to_char( buf, ch );
	}
    }

    return;
}



void do_ostat( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    char nm1[40];
    char nm2[40];
    AFFECT_DATA *paf;
    OBJ_DATA *obj;

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char( "Ostat what?\n\r", ch );
	return;
    }

    if ( ( obj = get_obj_world( ch, arg ) ) == NULL )
    {
	send_to_char( "Nothing like that in hell, earth, or heaven.\n\r", ch );
	return;
    }

    if (obj->questmaker != NULL && strlen(obj->questmaker) > 1)
	sprintf(nm1,obj->questmaker); else sprintf(nm1,"None");
    if (obj->questowner != NULL && strlen(obj->questowner) > 1)
	sprintf(nm2,obj->questowner); else sprintf(nm2,"None");

    sprintf( buf, "Name: %s.\n\r",
	obj->name );
    send_to_char( buf, ch );

    sprintf( buf, "Vnum: %d.  Type: %s.\n\r",
	obj->pIndexData->vnum, item_type_name( obj ) );
    send_to_char( buf, ch );

    sprintf( buf, "Short description: %s.\n\rLong description: %s\n\r",
	obj->short_descr, obj->description );
    send_to_char( buf, ch );

    sprintf( buf, "Object creator: %s.  Object owner: %s.  Quest points: %d.\n\r", nm1, nm2, obj->points );
    send_to_char( buf, ch );
    if (obj->quest != 0)
    {
    	send_to_char( "Quest selections:", ch );
    	if (IS_SET(obj->quest,QUEST_STR)) send_to_char(" Str",ch);
    	if (IS_SET(obj->quest,QUEST_DEX)) send_to_char(" Dex",ch);
    	if (IS_SET(obj->quest,QUEST_INT)) send_to_char(" Int",ch);
    	if (IS_SET(obj->quest,QUEST_WIS)) send_to_char(" Wis",ch);
    	if (IS_SET(obj->quest,QUEST_CON)) send_to_char(" Con",ch);
    	if (IS_SET(obj->quest,QUEST_HIT)) send_to_char(" Hp",ch);
    	if (IS_SET(obj->quest,QUEST_MANA)) send_to_char(" Mana",ch);
    	if (IS_SET(obj->quest,QUEST_MOVE)) send_to_char(" Move",ch);
    	if (IS_SET(obj->quest,QUEST_HITROLL)) send_to_char(" Hit",ch);
    	if (IS_SET(obj->quest,QUEST_DAMROLL)) send_to_char(" Dam",ch);
    	if (IS_SET(obj->quest,QUEST_AC)) send_to_char(" Ac",ch);
    	send_to_char( ".\n\r", ch );
    }
    sprintf( buf, "Wear bits: %d.  Extra bits: %s.\n\r",
	obj->wear_flags, extra_bit_name( obj->extra_flags ) );
    send_to_char( buf, ch );

    sprintf( buf, "Weight: %d/%d.\n\r",
	obj->weight, get_obj_weight( obj ) );
    send_to_char( buf, ch );

    sprintf( buf, "Cost: %d.  Timer: %d.  Level: %d.\n\r",
	obj->cost, obj->timer, obj->level );
    send_to_char( buf, ch );

    sprintf( buf,
	"In room: %d.  In object: %s.  Carried by: %s.  Wear_loc: %d.\n\r",
	obj->in_room    == NULL    ?        0 : obj->in_room->vnum,
	obj->in_obj     == NULL    ? "(none)" : obj->in_obj->short_descr,
	obj->carried_by == NULL    ? "(none)" : obj->carried_by->name,
	obj->wear_loc );
    send_to_char( buf, ch );
    
    sprintf( buf, "Values: %d %d %d %d.\n\r",
	obj->value[0], obj->value[1], obj->value[2], obj->value[3] );
    send_to_char( buf, ch );

    if ( obj->extra_descr != NULL || obj->pIndexData->extra_descr != NULL )
    {
	EXTRA_DESCR_DATA *ed;

	send_to_char( "Extra description keywords: '", ch );

	for ( ed = obj->extra_descr; ed != NULL; ed = ed->next )
	{
	    send_to_char( ed->keyword, ch );
	    if ( ed->next != NULL )
		send_to_char( " ", ch );
	}

	for ( ed = obj->pIndexData->extra_descr; ed != NULL; ed = ed->next )
	{
	    send_to_char( ed->keyword, ch );
	    if ( ed->next != NULL )
		send_to_char( " ", ch );
	}

	send_to_char( "'.\n\r", ch );
    }

    for ( paf = obj->affected; paf != NULL; paf = paf->next )
    {
	sprintf( buf, "Affects %s by %d.\n\r",
	    affect_loc_name( paf->location ), paf->modifier );
	send_to_char( buf, ch );
    }

    for ( paf = obj->pIndexData->affected; paf != NULL; paf = paf->next )
    {
	sprintf( buf, "Affects %s by %d.\n\r",
	    affect_loc_name( paf->location ), paf->modifier );
	send_to_char( buf, ch );
    }

    return;
}



void do_mstat( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    AFFECT_DATA *paf;
    CHAR_DATA *victim;

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char( "Mstat whom?\n\r", ch );
	return;
    }

    if ( ( victim = get_char_world( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if (IS_SET(victim->act, PLR_GODLESS) && get_trust(ch) < NO_GODLESS
        && !IS_SET(ch->extra , EXTRA_ANTI_GODLESS))
    {
	send_to_char( "You failed.\n\r", ch );
	return;
    }

    sprintf( buf, "Name: %s.\n\r",
	victim->name );
    send_to_char( buf, ch );

    sprintf( buf, "Vnum: %d.  Sex: %s.  Room: %d.\n\r",
	IS_NPC(victim) ? victim->pIndexData->vnum : 0,
	victim->sex == SEX_MALE    ? "male"   :
	victim->sex == SEX_FEMALE  ? "female" : "neutral",
	victim->in_room == NULL    ?        0 : victim->in_room->vnum
	);
    send_to_char( buf, ch );

    sprintf( buf, "Str: %d.  Int: %d.  Wis: %d.  Dex: %d.  Con: %d.\n\r",
	get_curr_str(victim),
	get_curr_int(victim),
	get_curr_wis(victim),
	get_curr_dex(victim),
	get_curr_con(victim) );
    send_to_char( buf, ch );

    sprintf( buf, "Hp: %d/%d.  Mana: %d/%d.  Move: %d/%d.  Primal: %d.\n\r",
	victim->hit,         victim->max_hit,
	victim->mana,        victim->max_mana,
	victim->move,        victim->max_move,
	victim->practice );
    send_to_char( buf, ch );
	
    sprintf( buf,
	"Lv: %d.  Align: %d.  AC: %d.  Gold: %d.  Exp: %d.\n\r",
	victim->level,       victim->alignment,
	char_ac(victim),     victim->gold,         victim->exp );
    send_to_char( buf, ch );

    sprintf( buf, "Hitroll: %d.  Damroll: %d.  Position: %d.  Wimpy: %d.\n\r",
	char_hitroll(victim), char_damroll(victim),
	victim->position,    victim->wimpy );
    send_to_char( buf, ch );
	
    sprintf( buf, "Fighting: %s.\n\r",
	victim->fighting ? victim->fighting->name : "(none)" );
    send_to_char( buf, ch );

    if ( !IS_NPC(victim) )
    {
	sprintf( buf,
	    "Thirst: %d.  Full: %d.  Drunk: %d.  Saving throw: %d.\n\r",
	    victim->pcdata->condition[COND_THIRST],
	    victim->pcdata->condition[COND_FULL],
	    victim->pcdata->condition[COND_DRUNK],
	    victim->saving_throw );
	send_to_char( buf, ch );

	if (IS_CLASS(victim, CLASS_VAMPIRE) || IS_CLASS(victim, CLASS_WEREWOLF))
	{
	    sprintf( buf, "Rage: %d. ", victim->rage);
	    send_to_char( buf, ch );
	    if (IS_CLASS(victim, CLASS_VAMPIRE))
	    {
		sprintf( buf, "Beast: %d. ", victim->beast);
		send_to_char( buf, ch );
		sprintf( buf, "Blood: %d.", victim->pcdata->condition[COND_THIRST]);
		send_to_char( buf, ch );
	    }
	    send_to_char( "\n\r", ch );
	}

	if (IS_CLASS(victim, CLASS_DEMON) || IS_SET(victim->special, SPC_CHAMPION))
	{
	    if (IS_SET(victim->special, SPC_CHAMPION))
	    {
		if (strlen(victim->lord) > 1) sprintf( buf, "Lord: %s. ", victim->lord);
		else sprintf( buf, "Lord: None. ");
		send_to_char( buf, ch );
	    }
	    sprintf( buf, "Demonic armor: %d pieces. ", victim->pcdata->stats[DEMON_POWER]);
	    send_to_char( buf, ch );
	    sprintf( buf, "Power: %d (%d).",
		victim->pcdata->stats[DEMON_CURRENT], victim->pcdata->stats[DEMON_TOTAL]);
	    send_to_char( buf, ch );
	    send_to_char( "\n\r", ch );
	}
    }

    sprintf( buf, "Carry number: %d.  Carry weight: %d.\n\r",
	victim->carry_number, victim->carry_weight );
    send_to_char( buf, ch );

    sprintf( buf, "Age: %d.  Played: %d.  Timer: %d.  Act: %d.\n\r",
	get_age( victim ), (int) victim->played, victim->timer, victim->act );
    send_to_char( buf, ch );

    sprintf( buf, "Master: %s.  Leader: %s.  Affected by: %s.\n\r",
	victim->master      ? victim->master->name   : "(none)",
	victim->leader      ? victim->leader->name   : "(none)",
	affect_bit_name( victim->affected_by ) );
    send_to_char( buf, ch );

    if ( !IS_NPC( victim ) )    /* OLC */
    {
        sprintf( buf, "Security: %d.\n\r", victim->pcdata->security );
	send_to_char( buf, ch );
    }


    sprintf( buf, "Short description: %s.\n\rLong  description: %s",
	victim->short_descr,
	victim->long_descr[0] != '\0' ? victim->long_descr : "(none).\n\r" );
    send_to_char( buf, ch );

    if ( IS_NPC(victim) && victim->spec_fun != 0 )
	send_to_char( "Mobile has spec fun.\n\r", ch );


    for ( paf = victim->affected; paf != NULL; paf = paf->next )
    {
	sprintf( buf,
	    "Spell: '%s' modifies %s by %d for %d hours with bits %s.\n\r",
	    skill_table[(int) paf->type].name,
	    affect_loc_name( paf->location ),
	    paf->modifier,
	    paf->duration,
	    affect_bit_name( paf->bitvector )
	    );
	send_to_char( buf, ch );
    }

    return;
}



void do_mfind( CHAR_DATA *ch, char *argument )
{
    extern int top_mob_index;
    char buf[MAX_STRING_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    MOB_INDEX_DATA *pMobIndex;
    int vnum;
    int nMatch;
    bool fAll;
    bool found;

    one_argument( argument, arg );
    if ( arg[0] == '\0' )
    {
	send_to_char( "Mfind whom?\n\r", ch );
	return;
    }

    fAll	= !str_cmp( arg, "all" );
    found	= FALSE;
    nMatch	= 0;

    /*
     * Yeah, so iterating over all vnum's takes 10,000 loops.
     * Get_mob_index is fast, and I don't feel like threading another link.
     * Do you?
     * -- Furey
     */
    for ( vnum = 0; nMatch < top_mob_index; vnum++ )
    {
	if ( ( pMobIndex = get_mob_index( vnum ) ) != NULL )
	{
	    nMatch++;
	    if ( fAll || is_name( arg, pMobIndex->player_name ) )
	    {
		found = TRUE;
		sprintf( buf, "[%5d] %s\n\r",
		    pMobIndex->vnum, capitalize( pMobIndex->short_descr ) );
		send_to_char( buf, ch );
	    }
	}
    }

    if ( !found )
	send_to_char( "Nothing like that in hell, earth, or heaven.\n\r", ch );

    return;
}



void do_ofind( CHAR_DATA *ch, char *argument )
{
    extern int top_obj_index;
    char buf[MAX_STRING_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    OBJ_INDEX_DATA *pObjIndex;
    int vnum;
    int nMatch;
    bool fAll;
    bool found;

    one_argument( argument, arg );
    if ( arg[0] == '\0' )
    {
	send_to_char( "Ofind what?\n\r", ch );
	return;
    }

    fAll	= !str_cmp( arg, "all" );
    found	= FALSE;
    nMatch	= 0;

    /*
     * Yeah, so iterating over all vnum's takes 10,000 loops.
     * Get_obj_index is fast, and I don't feel like threading another link.
     * Do you?
     * -- Furey
     */
    for ( vnum = 0; nMatch < top_obj_index; vnum++ )
    {
	if ( ( pObjIndex = get_obj_index( vnum ) ) != NULL )
	{
	    nMatch++;
	    if ( fAll || is_name( arg, pObjIndex->name ) )
	    {
		found = TRUE;
		sprintf( buf, "[%5d] %s\n\r",
		    pObjIndex->vnum, capitalize( pObjIndex->short_descr ) );
		send_to_char( buf, ch );
	    }
	}
    }

    if ( !found )
	send_to_char( "Nothing like that in hell, earth, or heaven.\n\r", ch );

    return;
}



void do_mwhere( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    bool found;

    one_argument( argument, arg );
    if ( arg[0] == '\0' )
    {
	send_to_char( "Mwhere whom?\n\r", ch );
	return;
    }

    /* Had problems when lots of gremlins existed - KaVir
    if ( !str_cmp( arg, "gremlin" ) )
    {
	send_to_char( "Sorry, but in the interest of mud stability you cannot do that.\n\r", ch );
	return;
    }
    */

    found = FALSE;
    for ( victim = char_list; victim != NULL; victim = victim->next )
    {
	if ( IS_NPC(victim)
	&&   victim->in_room != NULL
	&&   is_name( arg, victim->name ) )
	{
	    found = TRUE;
	    sprintf( buf, "[%5d] %-28s [%5d] %s\n\r",
		victim->pIndexData->vnum,
		victim->short_descr,
		victim->in_room->vnum,
		victim->in_room->name );
	    send_to_char( buf, ch );
	}
    }

    if ( !found )
	act( "You didn't find any $T.", ch, NULL, arg, TO_CHAR );

    return;
}



void do_reboo( CHAR_DATA *ch, char *argument )
{
    send_to_char( "If you want to REBOOT, spell it out.\n\r", ch );
    return;
}



void do_reboot( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    extern bool merc_down;
    sprintf( buf, "\033[1;24r\033[2JReboot by %s.", ch->name );
    do_echo( ch, buf );
    do_forceauto(ch,"call all");
    do_asave(ch,"changed");
    call_all(ch);
    do_forceauto(ch,"save");
    do_autosave(ch,"");
    merc_down = TRUE;
    return;
}


void do_shutdow( CHAR_DATA *ch, char *argument )
{
    send_to_char( "If you want to SHUTDOWN, spell it out.\n\r", ch );
    return;
}



void do_shutdown( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    extern bool merc_down;
    sprintf( buf, "Shutdown by %s.", ch->name );
    append_file( ch, SHUTDOWN_FILE, buf );
    strcat( buf, "\n\r" );
    do_echo( ch, buf );
    do_asave(ch,"changed");
    do_forceauto(ch,"save");
    do_autosave(ch,"");
    merc_down = TRUE;
    return;
}



void do_snoop( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    DESCRIPTOR_DATA *d;
    CHAR_DATA *victim;

    sprintf(buf,"%s: Snoop %s",ch->name,argument);
    if (ch->level < NO_WATCH) do_watching(ch,buf);

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char( "Snoop whom?\n\r", ch );
	return;
    }

    if ( ( victim = get_char_world( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( victim->desc == NULL )
    {
	send_to_char( "No descriptor to snoop.\n\r", ch );
	return;
    }

    if ( victim == ch )
    {
	send_to_char( "Cancelling all snoops.\n\r", ch );
	for ( d = descriptor_list; d != NULL; d = d->next )
	{
	    if ( d->snoop_by == ch->desc )
		d->snoop_by = NULL;
	}
	return;
    }

    if ( victim->desc->snoop_by != NULL )
    {
	send_to_char( "Busy already.\n\r", ch );
	return;
    }

    if (IS_SET(victim->act, PLR_GODLESS) && get_trust(ch) < NO_GODLESS
        && !IS_SET(ch->extra , EXTRA_ANTI_GODLESS))
    {
	send_to_char( "You failed.\n\r", ch );
	return;
    }

    if (IS_SET(victim->act, PLR_WATCHER))
    {
	send_to_char( "Busy already.\n\r", ch );
	return;
    }

    if ( get_trust( victim ) >= get_trust( ch ) )
    {
	send_to_char( "You failed.\n\r", ch );
	return;
    }

    if ( ch->desc != NULL )
    {
	for ( d = ch->desc->snoop_by; d != NULL; d = d->snoop_by )
	{
	    if ( d->character == victim || d->original == victim )
	    {
		send_to_char( "No snoop loops.\n\r", ch );
		return;
	    }
	}
    }

    victim->desc->snoop_by = ch->desc;
    send_to_char( "Ok.\n\r", ch );
    return;
}



void do_oswitch( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    OBJ_DATA *obj;
    CHAR_DATA *mount;

    sprintf(buf,"%s: Oswitch %s",ch->name,argument);
    if (ch->level < NO_WATCH) do_watching(ch,buf);

    one_argument( argument, arg );
    
    if ( IS_NPC(ch) )
	return;
    
    if ( arg[0] == '\0' )
    {
	send_to_char( "Switch into what?\n\r", ch );
	return;
    }

    if ( IS_EXTRA(ch, EXTRA_OSWITCH) || IS_HEAD(ch,LOST_HEAD) )
    {
	send_to_char( "You are already oswitched.\n\r", ch );
	return;
    }

    if ( IS_AFFECTED(ch, AFF_POLYMORPH) )
    {
	send_to_char( "Not while polymorphed.\n\r", ch );
	return;
    }

    if ( IS_NPC(ch) || IS_EXTRA(ch,EXTRA_SWITCH) )
    {
	send_to_char( "Not while switched.\n\r", ch );
	return;
    }

    if ( ( obj = get_obj_world( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( obj->chobj != NULL )
    {
	send_to_char( "Object in use.\n\r", ch );
	return;
    }

    if ( (mount = ch->mount) != NULL) do_dismount(ch,"");
    obj->chobj = ch;
    ch->pcdata->chobj = obj;
    SET_BIT(ch->affected_by, AFF_POLYMORPH);
    SET_BIT(ch->extra, EXTRA_OSWITCH);
    free_string(ch->morph);
    ch->morph = str_dup(obj->short_descr);
    send_to_char( "Ok.\n\r", ch );
    return;
}



void do_oreturn( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    OBJ_DATA *obj;

    sprintf(buf,"%s: Oreturn",ch->name);
    if (ch->level < NO_WATCH) do_watching(ch,buf);

    one_argument( argument, arg );
    
    if ( IS_NPC(ch) )
	return;
    
    if ( !IS_EXTRA(ch, EXTRA_OSWITCH) && !IS_HEAD(ch,LOST_HEAD) )
    {
	send_to_char( "You are not oswitched.\n\r", ch );
	return;
    }
    if ( ( obj = ch->pcdata->chobj ) != NULL ) obj->chobj = NULL;
    ch->pcdata->chobj = NULL;
    REMOVE_BIT(ch->affected_by, AFF_POLYMORPH);
    REMOVE_BIT(ch->extra, EXTRA_OSWITCH);
    if (IS_HEAD(ch,LOST_HEAD)) REMOVE_BIT(ch->loc_hp[0], LOST_HEAD);
    free_string(ch->morph);
    ch->morph = str_dup("");
    char_from_room(ch);
    char_to_room(ch,get_room_index(ROOM_VNUM_ALTAR));
    send_to_char( "Ok.\n\r", ch );
    return;
}



void do_switch( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    CHAR_DATA *victim;

    sprintf(buf,"%s: Switch %s",ch->name,argument);
    if (ch->level < NO_WATCH) do_watching(ch,buf);

    one_argument( argument, arg );
    
    if ( arg[0] == '\0' )
    {
	send_to_char( "Switch into whom?\n\r", ch );
	return;
    }

    if ( ch->desc == NULL )
	return;

    if ( ch->desc->original != NULL )
    {
	send_to_char( "You are already switched.\n\r", ch );
	return;
    }

    if ( ( victim = get_char_world( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( victim == ch )
    {
	send_to_char( "Ok.\n\r", ch );
	return;
    }

    if ( victim->desc != NULL )
    {
	send_to_char( "Character in use.\n\r", ch );
	return;
    }

    if ( !IS_NPC(victim))
    {
	send_to_char( "Only on NPC's.\n\r", ch );
	return;
    }

    SET_BIT(ch->extra, EXTRA_SWITCH);
    ch->desc->character = victim;
    ch->desc->original  = ch;
    victim->desc        = ch->desc;
    ch->desc            = NULL;
    send_to_char( "Ok.\n\r", victim );
    return;
}



void do_return( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];

    sprintf(buf,"%s: Return %s",ch->name,argument);
    if (ch->level < NO_WATCH) do_watching(ch,buf);

    if ( ch->desc == NULL )
	return;

    if ( ch->desc->original == NULL )
    {
	send_to_char( "You aren't switched.\n\r", ch );
	return;
    }

    send_to_char( "You return to your original body.\n\r", ch );
    REMOVE_BIT(ch->desc->original->extra, EXTRA_SWITCH);
    ch->desc->character       = ch->desc->original;
    ch->desc->original        = NULL;
    ch->desc->character->desc = ch->desc; 
    ch->desc                  = NULL;
    return;
}



void do_mload( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    MOB_INDEX_DATA *pMobIndex;
    CHAR_DATA *victim;

    sprintf(buf,"%s: Mload %s",ch->name,argument);
    if (ch->level < NO_WATCH && ch->trust > 3) do_watching(ch,buf);
    
    one_argument( argument, arg );

    if ( arg[0] == '\0' || !is_number(arg) )
    {
	send_to_char( "Syntax: mload <vnum>.\n\r", ch );
	return;
    }

    if ( ( pMobIndex = get_mob_index( atoi( arg ) ) ) == NULL )
    {
	send_to_char( "No mob has that vnum.\n\r", ch );
	return;
    }

    victim = create_mobile( pMobIndex );
    char_to_room( victim, ch->in_room );
    act( "$n has created $N!", ch, NULL, victim, TO_ROOM );
    act( "You have created $N!", ch, NULL, victim, TO_CHAR );
    return;
}


/*
void do_pload( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    char name[40];
    DESCRIPTOR_DATA *d;
    bool fOld;

    sprintf(buf,"%s: Pload %s",ch->name,argument);
    if (ch->level < NO_WATCH && ch->trust > 3) do_watching(ch,buf);
    
    one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if ( arg[0] == '\0' || is_number(arg) )
    {
	send_to_char( "Syntax: pload <name>.\n\r", ch );
	return;
    }

    if (!str_cmp(ch->name,arg))
    {
	send_to_char( "But you are already that character!\n\r", ch );
	return;
    }

    if (!(ch->pload == NULL || strlen(ch->pload) < 3))
    {
	send_to_char( "But you are already in another form!\n\r", ch );
	return;
    }

    d = ch->desc;

    sprintf(buf,"You transform into %s.\n\r",capitalize(arg));
    send_to_char(buf,ch);
    sprintf(buf,"$n transforms into %s.",capitalize(arg));
    act(buf,ch,NULL,NULL,TO_ROOM);

    sprintf(name,ch->name);
    save_char_obj(ch);

    if (ch != NULL && ch->desc != NULL)
	extract_char(ch,TRUE);
    else if (ch != NULL)
	extract_char(ch,TRUE);
    if (ch->desc) ch->desc->character = NULL;

    ch->next = char_list;
    char_list = ch;

    fOld = load_char_obj(d, capitalize(arg));
    if (ch->in_room != NULL)
    	char_to_room(ch,ch->in_room);
    else
    	char_to_room(ch,get_room_index(3001));
    free_string(ch->pload);
    ch->pload = str_dup(name);
    return;
}




void do_preturn( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    DESCRIPTOR_DATA *d;
    bool fOld;

    if (IS_NPC(ch)) {send_to_char("Huh?\n\r",ch);return;}

    if (ch->pload == NULL) {send_to_char("Huh?\n\r",ch);return;}
    sprintf(arg,ch->pload);
    if (strlen(arg) < 3 || strlen(arg) > 8) 
	{send_to_char("Huh?\n\r",ch);return;}

    if (!str_cmp(ch->name,arg)) {send_to_char("Huh?\n\r",ch);return;}

    d = ch->desc;

    sprintf(buf,"You transform back into %s.\n\r",capitalize(ch->pload));
    send_to_char(buf,ch);
    sprintf(buf,"$n transforms back into %s.",capitalize(ch->pload));
    act(buf,ch,NULL,NULL,TO_ROOM);
    save_char_obj(ch);

    if (ch != NULL && ch->desc != NULL)
	extract_char(ch,TRUE);
    else if (ch != NULL)
	extract_char(ch,TRUE);
    if (ch->desc) ch->desc->character = NULL;
*
    ch->next = char_list;
    char_list = ch;
*
    fOld = load_char_obj(d, capitalize(arg));
    if (ch->in_room != NULL)
    	char_to_room(ch,ch->in_room);
    else
    	char_to_room(ch,get_room_index(3001));
    free_string(ch->pload);
    ch->pload = str_dup("");
    return;
}

*/

void do_pload( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    DESCRIPTOR_DATA *d;
    ROOM_INDEX_DATA *in_room;
    bool fOld;

    if ( IS_NPC(ch) || ch->desc == NULL || ch->in_room == NULL ) return;

    if ( argument[0] == '\0' )
    {
	send_to_char( "Syntax: pload <name>.\n\r", ch );
	return;
    }

    if (!check_parse_name( argument ))
    {
	send_to_char( "Thats an illegal name.\n\r", ch );
	return;
    }

    if ( !char_exists(FALSE,argument) )
    {
	send_to_char( "That player doesn't exist.\n\r", ch );
	return;
    }

    sprintf(buf,"%s: Pload %s",ch->name,argument);
    if (ch->level < NO_WATCH && ch->trust > 3) do_watching(ch,buf);
    
    argument[0] = UPPER(argument[0]);

    sprintf(buf,"You transform into %s.\n\r",argument);
    send_to_char(buf,ch);
    sprintf(buf,"$n transforms into %s.",argument);
    act(buf,ch,NULL,NULL,TO_ROOM);

    d = ch->desc;
    do_autosave(ch,"");
    in_room = ch->in_room;
    extract_char(ch, TRUE);
    d->character = NULL;
    fOld = load_char_obj( d, argument );
    ch   = d->character;
    ch->next = char_list;
    char_list = ch;
    char_to_room(ch,in_room);
    return;
}



void do_preturn( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    DESCRIPTOR_DATA *d;
    bool fOld;

    if (IS_NPC(ch)) {send_to_char("Huh?\n\r",ch);return;}

    if (ch->pload == NULL) {send_to_char("Huh?\n\r",ch);return;}
    sprintf(arg,ch->pload);
    if (strlen(arg) < 3 || strlen(arg) > 8) 
	{send_to_char("Huh?\n\r",ch);return;}

    if (!str_cmp(ch->name,arg)) {send_to_char("Huh?\n\r",ch);return;}

    d = ch->desc;

    sprintf(buf,"You transform back into %s.\n\r",capitalize(ch->pload));
    send_to_char(buf,ch);
    sprintf(buf,"$n transforms back into %s.",capitalize(ch->pload));
    act(buf,ch,NULL,NULL,TO_ROOM);
    do_autosave(ch,"");
    if (ch != NULL && ch->desc != NULL)
	extract_char(ch,TRUE);
    else if (ch != NULL)
	extract_char(ch,TRUE);
    if (ch->desc) ch->desc->character = NULL;
/*
    ch->next = char_list;
    char_list = ch;
*/
    fOld = load_char_obj(d, capitalize(arg));
    if (ch->in_room != NULL)
    	char_to_room(ch,ch->in_room);
    else
    	char_to_room(ch,get_room_index(3001));
    free_string(ch->pload);
    ch->pload = str_dup("");
    return;
}


void do_oload( CHAR_DATA *ch, char *argument )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    OBJ_INDEX_DATA *pObjIndex;
    OBJ_DATA *obj;
    int level;

    if (IS_NPC(ch)) {send_to_char("Not while switched.\n\r",ch); return;}

    sprintf(buf,"%s: Oload %s",ch->name,argument);
    if (ch->level < NO_WATCH && ch->trust > 3) do_watching(ch,buf);
 
    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );
 
    if ( arg1[0] == '\0' || !is_number( arg1 ) )
    {
        send_to_char( "Syntax: oload <vnum> <level>.\n\r", ch );
        return;
    }
 
    if ( arg2[0] == '\0' )
    {
	level = get_trust( ch );
    }
    else
    {
	/*
	 * New feature from Alander.
	 */
        if ( !is_number( arg2 ) )
        {
	    send_to_char( "Syntax: oload <vnum> <level>.\n\r", ch );
	    return;
        }
        level = atoi( arg2 );
	if ( level < 0 || level > get_trust( ch ) )
        {
	    send_to_char( "Limited to your trust level.\n\r", ch );
	    return;
        }
    }

    if ( ( pObjIndex = get_obj_index( atoi( arg1 ) ) ) == NULL )
    {
	send_to_char( "No object has that vnum.\n\r", ch );
	return;
    }

    obj = create_object( pObjIndex, level );
    if ( CAN_WEAR(obj, ITEM_TAKE) )
    {
	obj_to_char( obj, ch );
	act( "$p appears in $n's hands!", ch, obj, NULL, TO_ROOM );
    }
    else
    {
	obj_to_room( obj, ch->in_room );
	act( "$n has created $p!", ch, obj, NULL, TO_ROOM );
    }
    act( "You create $p.", ch, obj, NULL, TO_CHAR );
    if (obj->questmaker != NULL) free_string(obj->questmaker);
    obj->questmaker = str_dup(ch->name);
    return;
}



void do_purge( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    CHAR_DATA *mount;
    OBJ_DATA *obj;

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	/* 'purge' */
	CHAR_DATA *vnext;
	OBJ_DATA  *obj_next;

	for ( victim = ch->in_room->people; victim != NULL; victim = vnext )
	{
	    vnext = victim->next_in_room;
	    if (IS_NPC(victim) && victim->desc == NULL && (mount = victim->mount) == NULL)
		extract_char( victim, TRUE );
	}

	for ( obj = ch->in_room->contents; obj != NULL; obj = obj_next )
	{
	    obj_next = obj->next_content;
	if (obj->item_type != ITEM_KINGDOM_POWER)
	    extract_obj( obj );
	}

	act( "$n purges the room!", ch, NULL, NULL, TO_ROOM);
	send_to_char( "Ok.\n\r", ch );
	return;
    }

    if ( ( victim = get_char_world( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( !IS_NPC(victim) )
    {
	send_to_char( "Not on PC's.\n\r", ch );
	return;
    }
    if ( victim->desc != NULL )
    {
	send_to_char( "Not on switched players.\n\r", ch );
	return;
    }

    act( "$n purges $N.", ch, NULL, victim, TO_NOTVICT );
    extract_char( victim, TRUE );
    return;
}



void do_trust( CHAR_DATA *ch, char *argument )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    CHAR_DATA *victim;
    int level;

    sprintf(buf,"%s: Trust %s",ch->name,argument);
    if (ch->level < NO_WATCH) do_watching(ch,buf);

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if ( arg1[0] == '\0' || arg2[0] == '\0' )
    {
	send_to_char( "Syntax: trust <char> <trust>.\n\r", ch );
	send_to_char( "Trust being one of: None, Builder, Questmaker, Enforcer, Judge, or Highjudge.\n\r", ch );
	return;
    }

    if ( ( victim = get_char_world( ch, arg1 ) ) == NULL )
    {
	send_to_char( "That player is not here.\n\r", ch);
	return;
    }

         if ( !str_cmp( arg2, "none"       ) ) level = 0;
    else if ( !str_cmp( arg2, "builder"    ) ) level = 7;
    else if ( !str_cmp( arg2, "questmaker" ) ) level = 8;
    else if ( !str_cmp( arg2, "enforcer"   ) ) level = 9;
    else if ( !str_cmp( arg2, "judge"      ) ) level = 10;
    else if ( !str_cmp( arg2, "highjudge"  ) ) level = 11;
    else
    {
	send_to_char( "Please enter: None, Builder, Questmaker, Enforcer, Judge, or Highjudge.\n\r", ch );
	return;
    }

    if ( level >= get_trust( ch ) )
    {
	send_to_char( "Limited to below your trust.\n\r", ch );
	return;
    }
    send_to_char("Ok.\n\r",ch);
    victim->trust = level;
    return;
}



void do_restore( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    CHAR_DATA *victim;
    DESCRIPTOR_DATA *d;

    sprintf(buf,"%s: Restore %s",ch->name,argument);
    if (ch->level < NO_WATCH) do_watching(ch,buf);

    one_argument( argument, arg );
    if ( arg[0] == '\0' )
    {
	send_to_char( "Restore whom?\n\r", ch );
	return;
    }

    if ( get_trust(ch) >=  MAX_LEVEL - 2 && !str_cmp(arg,"all"))
    {
    /* cure all */
    	
        for (d = descriptor_list; d != NULL; d = d->next)
        {
	    victim = d->character;

	    if (victim == NULL || IS_NPC(victim))
		continue;
                
          
            {
		affect_strip(victim,gsn_drowfire);
		affect_strip(victim,gsn_poison);
		affect_strip(victim,gsn_blindness);
		affect_strip(victim,gsn_sleep);
		affect_strip(victim,gsn_curse);
            
		victim->hit 	= victim->max_hit;
		victim->mana	= victim->max_mana;
		victim->move	= victim->max_move;
		update_pos( victim);
		if (victim->in_room != NULL)
		    act("$n has restored you.",ch,NULL,victim,TO_VICT);
	    }
        }
	send_to_char("All active players restored.\n\r",ch);
	return;
    }



    if ( ( victim = get_char_world( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if (IS_SET(victim->act, PLR_GODLESS) && get_trust(ch) < NO_GODLESS
        && !IS_SET(ch->extra , EXTRA_ANTI_GODLESS))
    {
	send_to_char( "You failed.\n\r", ch );
	return;
    }

    victim->hit  = victim->max_hit;
    victim->mana = victim->max_mana;
    victim->move = victim->max_move;
    victim->loc_hp[0] = 0;
    victim->loc_hp[1] = 0;
    victim->loc_hp[2] = 0;
    victim->loc_hp[3] = 0;
    victim->loc_hp[4] = 0;
    victim->loc_hp[5] = 0;
    victim->loc_hp[6] = 0;
    update_pos( victim );
    act( "$n has restored you.", ch, NULL, victim, TO_VICT );
    send_to_char( "Ok.\n\r", ch );
    return;
}



void do_freeze( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    CHAR_DATA *victim;

    sprintf(buf,"%s: Freeze %s",ch->name,argument);
    if (ch->level < NO_WATCH) do_watching(ch,buf);

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char( "Freeze whom?\n\r", ch );
	return;
    }

    if ( ( victim = get_char_world( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( IS_NPC(victim) )
    {
	send_to_char( "Not on NPC's.\n\r", ch );
	return;
    }

    if (IS_SET(victim->act, PLR_GODLESS) && get_trust(ch) < NO_GODLESS
        && !IS_SET(ch->extra , EXTRA_ANTI_GODLESS))
    {
	send_to_char( "You failed.\n\r", ch );
	return;
    }

    if ( get_trust( victim ) >= get_trust( ch ) )
    {
	send_to_char( "You failed.\n\r", ch );
	return;
    }

    if ( IS_SET(victim->act, PLR_FREEZE) )
    {
	REMOVE_BIT(victim->act, PLR_FREEZE);
	send_to_char( "You can play again.\n\r", victim );
	send_to_char( "FREEZE removed.\n\r", ch );
    }
    else
    {
	SET_BIT(victim->act, PLR_FREEZE);
	send_to_char( "You can't do ANYthing!\n\r", victim );
	send_to_char( "FREEZE set.\n\r", ch );
    }

    save_char_obj( victim );

    return;
}



void do_log( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    CHAR_DATA *victim;

    sprintf(buf,"%s: Log %s",ch->name,argument);
    if (ch->level < NO_WATCH) do_watching(ch,buf);

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char( "Log whom?\n\r", ch );
	return;
    }

    if ( !str_cmp( arg, "all" ) )
    {
	if ( fLogAll )
	{
	    fLogAll = FALSE;
	    send_to_char( "Log ALL off.\n\r", ch );
	}
	else
	{
	    fLogAll = TRUE;
	    send_to_char( "Log ALL on.\n\r", ch );
	}
	return;
    }

    if ( ( victim = get_char_world( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( IS_NPC(victim) )
    {
	send_to_char( "Not on NPC's.\n\r", ch );
	return;
    }

    /*
     * No level check, gods can log anyone.
     */
    if ( IS_SET(victim->act, PLR_LOG) )
    {
	REMOVE_BIT(victim->act, PLR_LOG);
	send_to_char( "LOG removed.\n\r", ch );
    }
    else
    {
	SET_BIT(victim->act, PLR_LOG);
	send_to_char( "LOG set.\n\r", ch );
    }

    return;
}



void do_noemote( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    CHAR_DATA *victim;

    sprintf(buf,"%s: Noemote %s",ch->name,argument);
    if (ch->level < NO_WATCH) do_watching(ch,buf);

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char( "Noemote whom?\n\r", ch );
	return;
    }

    if ( ( victim = get_char_world( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( IS_NPC(victim) )
    {
	send_to_char( "Not on NPC's.\n\r", ch );
	return;
    }

    if ( get_trust( victim ) >= get_trust( ch ) )
    {
	send_to_char( "You failed.\n\r", ch );
	return;
    }


    return;
}



void do_notell( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    CHAR_DATA *victim;

    sprintf(buf,"%s: Notell %s",ch->name,argument);
    if (ch->level < NO_WATCH) do_watching(ch,buf);

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char( "Notell whom?", ch );
	return;
    }

    if ( ( victim = get_char_world( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( IS_NPC(victim) )
    {
	send_to_char( "Not on NPC's.\n\r", ch );
	return;
    }

    if ( get_trust( victim ) >= get_trust( ch ) )
    {
	send_to_char( "You failed.\n\r", ch );
	return;
    }

    if (IS_SET(victim->act, PLR_GODLESS) && get_trust(ch) < NO_GODLESS
        && !IS_SET(ch->extra , EXTRA_ANTI_GODLESS))
    {
	send_to_char( "You failed.\n\r", ch );
	return;
    }

    if ( IS_SET(victim->act, PLR_NO_TELL) )
    {
	REMOVE_BIT(victim->act, PLR_NO_TELL);
	send_to_char( "You can tell again.\n\r", victim );
	send_to_char( "NO_TELL removed.\n\r", ch );
    }
    else
    {
	SET_BIT(victim->act, PLR_NO_TELL);
	send_to_char( "You can't tell!\n\r", victim );
	send_to_char( "NO_TELL set.\n\r", ch );
    }

    return;
}


void do_undeny( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    	char *oldname;
	CHAR_DATA *victim;
	DESCRIPTOR_DATA *d;
	ROOM_INDEX_DATA *in_room;

    sprintf(buf,"%s: Undeny %s",ch->name,argument);
    if (ch->level < NO_WATCH) do_watching(ch,buf);

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char( "Undeny whom?", ch );
	return;
    }

	if ((victim = get_char_world(ch, arg)) != NULL) {
	send_to_char("They are already online.\n\r", ch );
	return;}

    if (!char_exists(FALSE,arg))
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }
	oldname = str_dup(ch->pcdata->switchname);
	d = ch->desc;
	do_autosave(ch,"");
	in_room = ch->in_room;
	extract_char(ch, TRUE);
	d->character = NULL;
	load_char_obj(d, arg);
	ch = d->character;
	ch->next = char_list;
	char_list = ch;
	char_to_room(ch,in_room);    
	
 
    if ( IS_SET(ch->act, PLR_DENY) )
    {
	REMOVE_BIT(ch->act, PLR_DENY);
	send_to_char( "DENY removed.\n\r", ch );
    } else {
	send_to_char("They are not DENIED.\n\r", ch ); }

	d = ch->desc;
	do_autosave(ch,"");
	in_room = ch->in_room;
	extract_char(ch, TRUE);
	d->character = NULL;
	load_char_obj(d, oldname);
	ch = d->character;
	ch->next = char_list;
	char_list = ch;
	char_to_room(ch,in_room);    


    return;
}

void do_silence( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    CHAR_DATA *victim;

    sprintf(buf,"%s: Silence %s",ch->name,argument);
    if (ch->level < NO_WATCH) do_watching(ch,buf);

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char( "Silence whom?", ch );
	return;
    }

    if ( ( victim = get_char_world( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( IS_NPC(victim) )
    {
	send_to_char( "Not on NPC's.\n\r", ch );
	return;
    }

    if (IS_SET(victim->act, PLR_GODLESS) && get_trust(ch) < NO_GODLESS
        && !IS_SET(ch->extra , EXTRA_ANTI_GODLESS))
    {
	send_to_char( "You failed.\n\r", ch );
	return;
    }

    if ( get_trust( victim ) >= get_trust( ch ) )
    {
	send_to_char( "You failed.\n\r", ch );
	return;
    }

    if ( IS_SET(victim->act, PLR_SILENCE) )
    {
	REMOVE_BIT(victim->act, PLR_SILENCE);
	send_to_char( "You can use channels again.\n\r", victim );
	send_to_char( "SILENCE removed.\n\r", ch );
    }
    else
    {
	SET_BIT(victim->act, PLR_SILENCE);
	send_to_char( "You can't use channels!\n\r", victim );
	send_to_char( "SILENCE set.\n\r", ch );
    }

    return;
}



void do_peace( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *rch;
    char buf[MAX_STRING_LENGTH];

    sprintf(buf,"%s: Peace %s",ch->name,argument);
    if (ch->level < NO_WATCH) do_watching(ch,buf);

    for ( rch = ch->in_room->people; rch != NULL; rch = rch->next_in_room )
    {
	if ( rch->fighting != NULL )
	    stop_fighting( rch, TRUE );
    }

    send_to_char( "Ok.\n\r", ch );
    return;
}



BAN_DATA *		ban_free;
BAN_DATA *		ban_list;

void do_ban( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    char buf2[MAX_STRING_LENGTH];
    BAN_DATA *pban;

    sprintf(buf2,"%s: Ban %s",ch->name,argument);
    if (ch->level < NO_WATCH) do_watching(ch,buf);

    if ( IS_NPC(ch) )
	return;

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	strcpy( buf, "Banned sites:\n\r" );
	for ( pban = ban_list; pban != NULL; pban = pban->next )
	{
	    strcat( buf, pban->name );
	    strcat( buf, "\n\r" );
	}
	send_to_char( buf, ch );
	return;
    }

    for ( pban = ban_list; pban != NULL; pban = pban->next )
    {
	if ( !str_cmp( arg, pban->name ) )
	{
	    send_to_char( "That site is already banned!\n\r", ch );
	    return;
	}
    }

    if ( ban_free == NULL )
    {
	pban		= alloc_perm( sizeof(*pban) );
    }
    else
    {
	pban		= ban_free;
	ban_free	= ban_free->next;
    }

    pban->name	= str_dup( arg );
    pban->next	= ban_list;
    ban_list	= pban;
    send_to_char( "Ok.\n\r", ch );
	save_bans();
    return;
}



void do_allow( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    BAN_DATA *prev;
    BAN_DATA *curr;

    sprintf(buf,"%s: Allow %s",ch->name,argument);
    if (ch->level < NO_WATCH) do_watching(ch,buf);

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char( "Remove which site from the ban list?\n\r", ch );
	return;
    }

    prev = NULL;
    for ( curr = ban_list; curr != NULL; prev = curr, curr = curr->next )
    {
	if ( !str_cmp( arg, curr->name ) )
	{
	    if ( prev == NULL )
		ban_list   = ban_list->next;
	    else
		prev->next = curr->next;

	    free_string( curr->name );
	    curr->next	= ban_free;
	    ban_free	= curr;
	    send_to_char( "Ok.\n\r", ch );
	   save_bans();
	    return;
	}
    }

    send_to_char( "Site is not banned.\n\r", ch );
    return;
}



void do_wizlock( CHAR_DATA *ch, char *argument )
{
    extern bool wizlock;
    char buf[MAX_STRING_LENGTH];

    sprintf(buf,"%s: Wizlock %s",ch->name,argument);
    if (ch->level < NO_WATCH) do_watching(ch,buf);
    wizlock = !wizlock;

    if ( wizlock )
	send_to_char( "Game wizlocked.\n\r", ch );
    else
	send_to_char( "Game un-wizlocked.\n\r", ch );

    return;
}


void do_closemud( CHAR_DATA *ch, char *argument )
{
    extern bool wizlock;
    char buf[MAX_STRING_LENGTH];

    sprintf(buf,"%s: Wizlock %s",ch->name,argument);
    if (ch->level < NO_WATCH) do_watching(ch,buf);
    wizlock = !wizlock;

    if ( wizlock )
        send_to_char( "Game wizlocked.\n\r", ch );
    else
        send_to_char( "Game un-wizlocked.\n\r", ch );

    return;
}


void do_slookup( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    int sn;

    one_argument( argument, arg );
    if ( arg[0] == '\0' )
    {
	send_to_char( "Slookup what?\n\r", ch );
	return;
    }

    if ( !str_cmp( arg, "all" ) )
    {
	for ( sn = 0; sn < MAX_SKILL; sn++ )
	{
	    if ( skill_table[sn].name == NULL )
		break;
	    sprintf( buf, "Sn: %4d Slot: %4d Skill/spell: '%s'\n\r",
		sn, skill_table[sn].slot, skill_table[sn].name );
	    send_to_char( buf, ch );
	}
    }
    else
    {
	if ( ( sn = skill_lookup( arg ) ) < 0 )
	{
	    send_to_char( "No such skill or spell.\n\r", ch );
	    return;
	}

	sprintf( buf, "Sn: %4d Slot: %4d Skill/spell: '%s'\n\r",
	    sn, skill_table[sn].slot, skill_table[sn].name );
	send_to_char( buf, ch );
    }

    return;
}



void do_sset( CHAR_DATA *ch, char *argument )
{
    char arg1 [MAX_INPUT_LENGTH];
    char arg2 [MAX_INPUT_LENGTH];
    char arg3 [MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    CHAR_DATA *victim;
    int value;
    int sn;
    bool fAll;

    sprintf(buf,"%s: Sset %s",ch->name,argument);
    if (ch->level < NO_WATCH) do_watching(ch,buf);

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );
    argument = one_argument( argument, arg3 );

    if ( arg1[0] == '\0' || arg2[0] == '\0' || arg3[0] == '\0' )
    {
	send_to_char( "#7Syntax: sset <victim> <skill> <value>\n\r",	ch
);
	send_to_char( "#7or:     sset <victim> all     <value>\n\r",	ch
);
	send_to_char( "#3Skill being any skill or spell.\n\r",		ch
);
	return;
    }

    if ( ( victim = get_char_world( ch, arg1 ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( IS_NPC(victim) )
    {
	send_to_char( "Not on NPC's.\n\r", ch );
	return;
    }

    if (IS_SET(victim->act, PLR_GODLESS) && get_trust(ch) < NO_GODLESS
        && !IS_SET(ch->extra , EXTRA_ANTI_GODLESS))
    {
	send_to_char( "You failed.\n\r", ch );
	return;
    }

    fAll = !str_cmp( arg2, "all" );
    sn   = 0;
    if ( !fAll && ( sn = skill_lookup( arg2 ) ) < 0 )
    {
	send_to_char( "No such skill or spell.\n\r", ch );
	return;
    }

    /*
     * Snarf the value.
     */
    if ( !is_number( arg3 ) )
    {
	send_to_char( "Value must be numeric.\n\r", ch );
	return;
    }

    value = atoi( arg3 );
    if ( value < 0 || value > 100 )
    {
	send_to_char( "Value range is 0 to 100.\n\r", ch );
	return;
    }

    if ( fAll )
    {
	for ( sn = 0; sn < MAX_SKILL; sn++ )
	{
	    if ( skill_table[sn].name != NULL )
		victim->pcdata->learned[sn]	= value;
	}
    }
    else
    {
	victim->pcdata->learned[sn] = value;
    }

    send_to_char("Ok.\n\r",ch);
    return;
}


void do_mset( CHAR_DATA *ch, char *argument )
{
    char arg1 [MAX_INPUT_LENGTH];
    char arg2 [MAX_INPUT_LENGTH];
    char arg3 [MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    CHAR_DATA *victim;
    int value;

    sprintf(buf,"%s: Mset %s",ch->name,argument);
    if (ch->level < NO_WATCH) do_watching(ch,buf);

    smash_tilde( argument );
    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );
    strcpy( arg3, argument );

    if ( arg1[0] == '\0' || arg2[0] == '\0' || arg3[0] == '\0' )
    {
	send_to_char( "#7Syntax: mset <victim> <field>  <value>\n\r",	ch
);
	send_to_char( "#7or:     mset <victim> <string> <value>\n\r",	ch
);
	send_to_char( "\n\r",						ch );
	send_to_char( "#7Field being one of:\n\r",			ch
);
	send_to_char( "#3  str int wis dex con sex level exp\n\r",	ch
);
	send_to_char( "#3  gold hp mana move primal align\n\r",		ch
);
	send_to_char( "#3  thirst drunk full hit dam ac dp\n\r",ch );
	send_to_char( "#3  security\n\r\n\r",ch );
	send_to_char( "#7String being one of:\n\r",			ch
);
	send_to_char( "#3  name short long description title spec#n\n\r",
ch );
	return;
    }

    if ( ( victim = get_char_world( ch, arg1 ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if (IS_SET(victim->act, PLR_GODLESS) && get_trust(ch) < NO_GODLESS
        && !IS_SET(ch->extra , EXTRA_ANTI_GODLESS))
    {
	send_to_char( "You failed.\n\r", ch );
	return;
    }

    /*
     * Snarf the value (which need not be numeric).
     */
    value = is_number( arg3 ) ? atoi( arg3 ) : -1;

    /*
     * Set something.
     */
    if ( !str_cmp( arg2, "str" ) )
    {
	if ( IS_NPC(victim) )
	{
	    send_to_char( "Not on NPC's.\n\r", ch );
	    return;
	}

	if ( value < 3 || value > 18 )
	{
	    send_to_char( "Strength range is 3 to 18.\n\r", ch );
	    return;
	}

	if (IS_JUDGE(ch)) {
		victim->pcdata->perm_str = value;
		send_to_char("Ok.\n\r",ch);}
	else
		send_to_char( "Sorry, no can do...\n\r", ch );
	return;
    }

    if ( !str_cmp( arg2, "dp" ))
    {
	if ( IS_NPC(victim) )
	{
	    send_to_char( "Not on NPC's.\n\r",ch);
	    return;
	}

	if (!IS_CLASS(victim, CLASS_DEMON))
	{
	    send_to_char("Only on Demons.\n\r",ch);
	    return;
	}
	
	if ( value < 1 || value > 1000000 )
	{
	    send_to_char("Valid range is 1 to 1000000.\n\r",ch);
	    return;
	}

	victim->pcdata->stats[DEMON_CURRENT] = value;
	victim->pcdata->stats[DEMON_TOTAL]   = value;
	send_to_char("Ok.\n\r",ch);
	return;
    }

    if ( !str_cmp( arg2, "int" ) )
    {
	if ( IS_NPC(victim) )
	{
	    send_to_char( "Not on NPC's.\n\r", ch );
	    return;
	}

	if ( value < 3 || value > 18 )
	{
	    send_to_char( "Intelligence range is 3 to 18.\n\r", ch );
	    return;
	}

	if (IS_JUDGE(ch)) {
		victim->pcdata->perm_int = value;
		send_to_char("Ok.\n\r",ch);}
	else
		send_to_char( "Sorry, no can do...\n\r", ch );
	return;
    }

    if ( !str_cmp( arg2, "wis" ) )
    {
	if ( IS_NPC(victim) )
	{
	    send_to_char( "Not on NPC's.\n\r", ch );
	    return;
	}

	if ( value < 3 || value > 18 )
	{
	    send_to_char( "Wisdom range is 3 to 18.\n\r", ch );
	    return;
	}

	if (IS_JUDGE(ch)) {
		victim->pcdata->perm_wis = value;
		send_to_char("Ok.\n\r",ch);}
	else
		send_to_char( "Sorry, no can do...\n\r", ch );
	return;
    }

    if ( !str_cmp( arg2, "dex" ) )
    {
	if ( IS_NPC(victim) )
	{
	    send_to_char( "Not on NPC's.\n\r", ch );
	    return;
	}

	if ( value < 3 || value > 18 )
	{
	    send_to_char( "Dexterity range is 3 to 18.\n\r", ch );
	    return;
	}

	if (IS_JUDGE(ch)) {
		victim->pcdata->perm_dex = value;
		send_to_char("Ok.\n\r",ch);}
	else
		send_to_char( "Sorry, no can do...\n\r", ch );
	return;
    }

    if ( !str_cmp( arg2, "con" ) )
    {
	if ( IS_NPC(victim) )
	{
	    send_to_char( "Not on NPC's.\n\r", ch );
	    return;
	}

	if ( value < 3 || value > 18 )
	{
	    send_to_char( "Constitution range is 3 to 18.\n\r", ch );
	    return;
	}

	if (IS_JUDGE(ch)) {
		victim->pcdata->perm_con = value;
		send_to_char("Ok.\n\r",ch);}
	else
		send_to_char( "Sorry, no can do...\n\r", ch );
	return;
    }

    if ( !str_cmp( arg2, "sex" ) )
    {
	if ( value < 0 || value > 2 )
	{
	    send_to_char( "Sex range is 0 to 2.\n\r", ch );
	    return;
	}
	victim->sex = value;
	send_to_char("Ok.\n\r",ch);
	return;
    }

    if ( !str_cmp( arg2, "level" ) )
    {
	if ( IS_NPC(victim) && ( value < 1 || value > 250 ) )
	{
	    send_to_char( "Level range is 1 to 250 for mobs.\n\r", ch );
	    return;
	}
	else if (!IS_JUDGE(ch))
	{
	    send_to_char( "Sorry, no can do...\n\r", ch );
	    return;
	}
	     if ( !str_cmp( arg3, "mortal"     ) ) value = 2;
	else if ( !str_cmp( arg3, "avatar"     ) ) value = 3;
	else if ( !str_cmp( arg3, "apprentice" ) ) value = 4;
	else if ( !str_cmp( arg3, "mage"       ) ) value = 5;
        else if ( !str_cmp( arg3, "monk"       ) ) value = 6;          
	else if ( !str_cmp( arg3, "archmage"   ) ) value = 6;
	else if ( !str_cmp( arg3, "builder"    ) ) value = 7;
	else if ( !str_cmp( arg3, "questmaker" ) ) value = 8;
	else if ( !str_cmp( arg3, "enforcer"   ) ) value = 9;
	else if ( !str_cmp( arg3, "judge"      ) ) value = 10;
	else if ( !str_cmp( arg3, "highjudge"  ) ) value = 11;
	else if (!IS_NPC(victim))
	{
	    send_to_char( "Level should be one of the following:\n\rMortal, Avatar, Apprentice, Mage, Archmage, Builder, Questmaker, Enforcer,\n\rJudge, or Highjudge.\n\r", ch );
	    return;
	}
	
if (value >= ch->level && !IS_NPC(victim)) 
	    send_to_char( "Sorry, no can do...\n\r", ch );
	else {victim->level = value;  victim->trust = value;
send_to_char("Ok.\n\r",ch);}
	return;
    }

if ( !str_cmp( arg2, "hitroll" ) || !str_cmp(arg2, "hit" ) )
    {
	if ( !IS_NPC(victim) && ( value < 0 || value > 50 ) )
	{
	    send_to_char( "Hitroll range is 0 to 50.\n\r", ch );
	    return;
	}
	else if ( IS_NPC(victim) && ( value < 0 || value > 250 ) )
	{
	    send_to_char( "Hitroll range is 0 to 250.\n\r", ch );
	    return;
	}
	if (!IS_NPC(victim) && !IS_JUDGE(ch) && ch != victim)
	{
	    send_to_char( "Sorry, no can do...\n\r", ch );
	    return;
	}
	victim->hitroll = value;
	send_to_char("Ok.\n\r",ch);
	return;
    }

    if ( !str_cmp( arg2, "damroll" ) || !str_cmp( arg2, "dam" ) )
    {
	if ( !IS_NPC(victim) && ( value < 0 || value > 50 ) )
	{
	    send_to_char( "Damroll range is 0 to 50.\n\r", ch );
	    return;
	}
	else if ( IS_NPC(victim) && ( value < 0 || value > 250 ) )
	{
	    send_to_char( "Damroll range is 0 to 250.\n\r", ch );
	    return;
	}
	if (!IS_NPC(victim) && !IS_JUDGE(ch) && ch != victim)
	{
	    send_to_char( "Sorry, no can do...\n\r", ch );
	    return;
	}
	victim->damroll = value;
	send_to_char("Ok.\n\r",ch);
	return;
    }

if ( !str_cmp( arg2, "Xhitroll" ) || !str_cmp( arg2, "hit" ) )
    {
	if ( !IS_NPC(victim) && ( value < 0 || value > 50 ) )
	{
	    send_to_char( "Xhitroll range is 0 to 50.\n\r", ch );
	    return;
	}
	else if ( IS_NPC(victim) && ( value < 0 || value > 250 ) )
	{
	    send_to_char( "Xhitroll range is 0 to 250.\n\r", ch );
	    return;
	}
	if (!IS_NPC(victim) && !IS_JUDGE(ch) && ch != victim)
	{
	    send_to_char( "Sorry, no can do...\n\r", ch );
	    return;
	}
	victim->xhitroll = value;
	send_to_char("Ok.\n\r",ch);
	return;
    }

    if ( !str_cmp( arg2, "Xdamroll" ) || !str_cmp( arg2, "dam" ) )
    {
	if ( !IS_NPC(victim) && ( value < 0 || value > 50 ) )
	{
	    send_to_char( "Xdamroll range is 0 to 50.\n\r", ch );
	    return;
	}
	else if ( IS_NPC(victim) && ( value < 0 || value > 250 ) )
	{
	    send_to_char( "Xdamroll range is 0 to 250.\n\r", ch );
	    return;
	}
	if (!IS_NPC(victim) && !IS_JUDGE(ch) && ch != victim)
	{
	    send_to_char( "Sorry, no can do...\n\r", ch );
	    return;
	}
	victim->xdamroll = value;
	send_to_char("Ok.\n\r",ch);
	return;
    }

    if ( !str_cmp( arg2, "armor" ) || !str_cmp( arg2, "ac" ) )
    {
	if ( !IS_NPC(victim) && ( value < -200 || value > 200 ) )
	{
	    send_to_char( "Armor class range is -200 to 200.\n\r", ch );
	    return;
	}
	if (!IS_NPC(victim) && !IS_JUDGE(ch) && ch != victim)
	{
	    send_to_char( "Sorry, no can do...\n\r", ch );
	    return;
	}
	victim->armor = value;
	send_to_char("Ok.\n\r",ch);
	return;
    }

    if ( !str_cmp( arg2, "exp" ) )
    {
	if ( IS_NPC(victim) )
	{
	    send_to_char( "Not on NPC's.\n\r", ch );
	    return;
	}

	if ( value < 0 )
	{
	    send_to_char( "Exp must be at least 0.\n\r", ch );
	    return;
	}

	if ( value > 99000000 )
	{
	    send_to_char( "No more than 99000000 possible.\n\r", ch );
	    return;
	}

	if (IS_JUDGE(ch) || (ch == victim)) {
		victim->exp = value;
		send_to_char("Ok.\n\r",ch);}
	else
		send_to_char( "Sorry, no can do...\n\r", ch );
	return;
    }

    if ( !str_cmp( arg2, "gold" ) )
    {
	if (value > 100000 && !IS_JUDGE(ch))
		send_to_char("Don't be so damn greedy!\n\r",ch);
	else
		{victim->gold = value; send_to_char("Ok.\n\r",ch);}
	return;
    }

    if ( !str_cmp( arg2, "hp" ) )
    {
	if ( value < 1 || value > 30000 )
	{
	    send_to_char( "Hp range is 1 to 30,000 hit points.\n\r", ch );
	    return;
	}
	if (IS_JUDGE(ch) || (ch == victim) || (IS_NPC(victim)) ) {
		victim->max_hit = value;
		send_to_char("Ok.\n\r",ch);}
	else
	    send_to_char( "Sorry, no can do...\n\r", ch );
	return;
    }

    if ( !str_cmp( arg2, "mana" ) )
    {
	if ( value < 0 || value > 30000 )
	{
	    send_to_char( "Mana range is 0 to 30,000 mana points.\n\r", ch );
	    return;
	}
	if (IS_JUDGE(ch) || (ch == victim) || (IS_NPC(victim)) ) {
		victim->max_mana = value;
		send_to_char("Ok.\n\r",ch);}
	else
	    send_to_char( "Sorry, no can do...\n\r", ch );
	return;
    }

    if ( !str_cmp( arg2, "move" ) )
    {
	if ( value < 0 || value > 30000 )
	{
	    send_to_char( "Move range is 0 to 30,000 move points.\n\r", ch );
	    return;
	}
	if (IS_JUDGE(ch) || (ch == victim) || (IS_NPC(victim)) ) {
		victim->max_move = value;
		send_to_char("Ok.\n\r",ch);}
	else
	    send_to_char( "Sorry, no can do...\n\r", ch );
	return;
    }

    if ( !str_cmp( arg2, "primal" ) )
    {
	if ( value < 0 || value > 999 )
	{
	    send_to_char( "Primal range is 0 to 999.\n\r", ch );
	    return;
	}
	if (IS_JUDGE(ch) || (ch == victim)) {
		victim->practice = value;
		send_to_char("Ok.\n\r",ch);}
	else
	    send_to_char( "Sorry, no can do...\n\r", ch );
	return;
    }

    if ( !str_cmp( arg2, "align" ) )
    {
	if ( value < -1000 || value > 1000 )
	{
	    send_to_char( "Alignment range is -1000 to 1000.\n\r", ch );
	    return;
	}
	victim->alignment = value;
	send_to_char("Ok.\n\r",ch);
	return;
    }

    if ( !str_cmp( arg2, "thirst" ) )
    {
	if ( IS_NPC(victim) )
	{
	    send_to_char( "Not on NPC's.\n\r", ch );
	    return;
	}

	if ( value < 0 || value > 2000 )
	{
	    send_to_char( "Thirst range is 0 to 2000.\n\r", ch );
	    return;
	}

	victim->pcdata->condition[COND_THIRST] = value;
	send_to_char("Ok.\n\r",ch);
	return;
    }

    if ( !str_cmp( arg2, "drunk" ) )
    {
	if ( IS_NPC(victim) )
	{
	    send_to_char( "Not on NPC's.\n\r", ch );
	    return;
	}

	if ( value < 0 || value > 100 )
	{
	    send_to_char( "Drunk range is 0 to 100.\n\r", ch );
	    return;
	}

	victim->pcdata->condition[COND_DRUNK] = value;
	send_to_char("Ok.\n\r",ch);
	return;
    }

    if ( !str_cmp( arg2, "full" ) )
    {
	if ( IS_NPC(victim) )
	{
	    send_to_char( "Not on NPC's.\n\r", ch );
	    return;
	}

	if ( value < 0 || value > 100 )
	{
	    send_to_char( "Full range is 0 to 100.\n\r", ch );
	    return;
	}

	victim->pcdata->condition[COND_FULL] = value;
	send_to_char("Ok.\n\r",ch);
	return;
    }


    if ( !str_cmp( arg2, "name" ) )
    {
	if ( !IS_NPC(victim) )
	{
	    send_to_char( "Not on PC's.\n\r", ch );
	    return;
	}

	free_string( victim->name );
	victim->name = str_dup( arg3 );
	send_to_char("Ok.\n\r",ch);
	return;
    }

    if ( !str_cmp( arg2, "short" ) )
    {
	free_string( victim->short_descr );
	victim->short_descr = str_dup( arg3 );
	send_to_char("Ok.\n\r",ch);
	return;
    }

    if ( !str_cmp( arg2, "long" ) )
    {
	free_string( victim->long_descr );
	victim->long_descr = str_dup( arg3 );
	send_to_char("Ok.\n\r",ch);
	return;
    }

    if ( !str_cmp( arg2, "title" ) )
    {
	if ( IS_NPC(victim) )
	{
	    send_to_char( "Not on NPC's.\n\r", ch );
	    return;
	}

	set_title( victim, arg3 );
	send_to_char("Ok.\n\r",ch);
	return;
    }

    if ( !str_cmp( arg2, "spec" ) )
    {
	if ( !IS_NPC(victim) )
	{
	    send_to_char( "Not on PC's.\n\r", ch );
	    return;
	}

	if ( ( victim->spec_fun = spec_lookup( arg3 ) ) == 0 )
	{
	    send_to_char( "No such spec fun.\n\r", ch );
	    return;
	}

	send_to_char("Ok.\n\r",ch);
	return;
    }



    if ( !str_cmp( arg2, "status"   ) )
    {
	if ( IS_NPC( victim ) )
	return;

	if ( value > 50 || value < 0 )
	return;

	victim->race = value;
	return;
    }   

    if ( !str_cmp( arg2, "security" ) ) /* OLC */
    {
        if ( IS_NPC( victim ) )
        {
            send_to_char( "Not on NPC's.\n\r", ch );
            return;
        }
     
        if ( value > ch->pcdata->security || value < 0 )
        {
            if ( ch->pcdata->security != 0 )
            {
                sprintf( buf, "Valid security is 0-%d.\n\r",
                    ch->pcdata->security );
                send_to_char( buf, ch );
                send_to_char( buf, ch );
            }
            else
            {
                send_to_char( "Valid security is 0 only.\n\r", ch );
            }
            return;
        }
        victim->pcdata->security = value;
        return;
    }

 
    /*
     * Generate usage message.
     */

    do_mset( ch, "" );
    return;
}

void do_pack(CHAR_DATA *ch, char *argument)
{
  CHAR_DATA *victim;
  OBJ_DATA *obj;
  OBJ_DATA *obj2;
  char arg[MAX_STRING_LENGTH];
  one_argument(argument,arg);
  if (arg[0] == '\0')
  {send_to_char("Newbiepack Who?\n\r",ch);
  return;}
  if ((victim=get_char_world(ch,arg)) == NULL)
  {send_to_char("They arent here.\n\r",ch);
  return;}
  obj2 = create_object(get_obj_index(3032),0);
  obj  = create_object(get_obj_index(30334),0);
  obj_to_char(obj,victim);
  obj = NULL;
  obj  = create_object(get_obj_index(30335),0);
  obj = NULL;
  obj_to_char(obj,victim);

  obj  = create_object(get_obj_index(30336),0);
  obj_to_char(obj,victim);
  obj = NULL;
  obj  = create_object(get_obj_index(30337),0);
  obj_to_char(obj,victim);
  obj = NULL;
  obj  = create_object(get_obj_index(30338),0);
  obj_to_char(obj,victim);
  obj = NULL;
  obj  = create_object(get_obj_index(30339),0);
  obj_to_char(obj,victim);
  obj = NULL;
  obj  = create_object(get_obj_index(30339),0);
  obj_to_char(obj,victim);
  obj = NULL;
 
  obj  = create_object(get_obj_index(30340),0);
  obj_to_char(obj,victim);
  obj = NULL;
  obj  = create_object(get_obj_index(30341),0);
  obj_to_char(obj,victim);
  obj = NULL;
  obj  = create_object(get_obj_index(30342),0);
  obj_to_char(obj,victim);
  obj = NULL;
  obj  = create_object(get_obj_index(30342),0);
  obj_to_char(obj,victim);
  obj = NULL;
 
  obj  = create_object(get_obj_index(30343),0);
  obj_to_char(obj,victim);
  obj = NULL;
  obj  = create_object(get_obj_index(30343),0);
  obj_to_char(obj,victim);
  obj = NULL;
  obj  = create_object(get_obj_index(30344),0);
  obj_to_char(obj,victim);

  obj = NULL;
  obj  = create_object(get_obj_index(30345),0);
  obj_to_char(obj,victim);
 
  obj_to_char(obj2,victim);
  send_to_char(
 "Tons of stuff appears in your hands in a blast of flames.\n\r",victim);
  send_to_char("You newbiepack them.\n\r",ch);
  return;
  }
 
 

void do_oset( CHAR_DATA *ch, char *argument )
{
    char arg1 [MAX_INPUT_LENGTH];
    char arg2 [MAX_INPUT_LENGTH];
    char arg3 [MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    CHAR_DATA *victim;
    OBJ_DATA *obj;
    OBJ_DATA *morph;
    OBJ_INDEX_DATA *pObjIndex;
    int value;

    if (IS_NPC(ch)) {send_to_char("Not while switched.\n\r",ch); return;}

    sprintf(buf,"%s: Oset %s",ch->name,argument);
    if (ch->level < NO_WATCH) do_watching(ch,buf);

    smash_tilde( argument );
    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );
    strcpy( arg3, argument );

    if ( arg1[0] == '\0' || arg2[0] == '\0' || arg3[0] == '\0' )
    {
	send_to_char( "#7Syntax: oset <object> <field>  <value>\n\r",	ch
);
	send_to_char( "#7or:     oset <object> <string> <value>\n\r",	ch
);
	send_to_char( "#7or:     oset <object> <affect> <value>\n\r",	ch
);
	send_to_char( "\n\r",						ch );
	send_to_char( "#7Field being one of:\n\r",			ch
);
	send_to_char( "#3  value0 value1 value2 value3\n\r",		ch
);
	send_to_char( "#3  level weight cost timer morph\n\r",		ch
);
	send_to_char( "\n\r",						ch );
	send_to_char( "#7String being one of:\n\r",			ch
);
	send_to_char( "#3  name short long ed type extra wear owner\n\r",
ch );
	send_to_char( "\n\r",						ch );
	send_to_char( "#7Affect being one of:\n\r",			ch
);
	send_to_char( "#3  str dex int wis con\n\r",			ch
);
	send_to_char( "#3  hit dam ac hp mana move\n\r",
ch );
	stc("  #3attackgood\n\r",ch);
	return;
    }

    if ( ( obj = get_obj_world( ch, arg1 ) ) == NULL )
    {
	send_to_char( "Nothing like that in hell, earth, or heaven.\n\r", ch );
	return;
    }

    if (obj->carried_by != NULL && !IS_NPC(obj->carried_by) &&
	IS_SET(obj->carried_by->act, PLR_GODLESS) && get_trust(ch) < NO_GODLESS
        && !IS_SET(ch->extra , EXTRA_ANTI_GODLESS))
    {
	send_to_char( "You failed.\n\r", ch );
	return;
    }

    if (!IS_JUDGE(ch) && (obj->questmaker == NULL || str_cmp(ch->name,obj->questmaker)))
    {
	send_to_char("You don't have permission to change that item.\n\r", ch);
	return;
    }

    /*
     * Snarf the value (which need not be numeric).
     */
    value = atoi( arg3 );

    /*
     * Set something.
     */
    if ( !str_cmp( arg2, "value0" ) || !str_cmp( arg2, "v0" ) )
    {
	if (obj->item_type == ITEM_WEAPON && !IS_JUDGE(ch)) {
		send_to_char("You are not authorised to create spell weapons.\n\r", ch);
		return;}
	else if (obj->item_type == ITEM_QUEST) {
		send_to_char("You cannot change a quest tokens value with oset.\n\r", ch);
		return;}
	else if (obj->item_type == ITEM_ARMOR && value > 15)
		obj->value[0] = 15;
	else
		obj->value[0] = value;
	send_to_char("Ok.\n\r",ch);
    	if (obj->questmaker != NULL) free_string(obj->questmaker);
    	obj->questmaker = str_dup(ch->name);
	return;
    }

    if ( !str_cmp( arg2, "value1" ) || !str_cmp( arg2, "v1" ) )
    {
	if (obj->item_type == ITEM_WEAPON && value > 10)
		obj->value[1] = 10;
	else
		obj->value[1] = value;
	send_to_char("Ok.\n\r",ch);
    	if (obj->questmaker != NULL) free_string(obj->questmaker);
    	obj->questmaker = str_dup(ch->name);
	return;
    }

    if ( !str_cmp( arg2, "value2" ) || !str_cmp( arg2, "v2" ) )
    {
	if (obj->item_type == ITEM_WEAPON && value > 20)
		obj->value[2] = 20;
	else
		obj->value[2] = value;
	send_to_char("Ok.\n\r",ch);
    	if (obj->questmaker != NULL) free_string(obj->questmaker);
    	obj->questmaker = str_dup(ch->name);
	return;
    }

    if ( !str_cmp( arg2, "value3" ) || !str_cmp( arg2, "v3" ) )
    {
	if (obj->item_type == ITEM_ARMOR && !IS_JUDGE(ch))
		send_to_char("You are not authorised to create spell armour.\n\r", ch);
	else
		{obj->value[3] = value; send_to_char("Ok.\n\r",ch);}
    	if (obj->questmaker != NULL) free_string(obj->questmaker);
    	obj->questmaker = str_dup(ch->name);
	return;
    }

    if ( !str_cmp( arg2, "morph" ) )
    {
	int mnum;
	if ( IS_SET(obj->spectype, SITEM_MORPH) )
    	{
	    send_to_char( "This item can already morph.\n\r", ch );
	    return;
    	}
    	if ( ( pObjIndex = get_obj_index( value ) ) == NULL )
    	{
	    send_to_char( "No object has that vnum.\n\r", ch );
	    return;
    	}
    	morph = create_object( pObjIndex, obj->level );
    	if ( !CAN_WEAR(morph, ITEM_TAKE) )
	    SET_BIT(morph->wear_flags, ITEM_TAKE);
	if ( !IS_SET(obj->spectype, SITEM_MORPH) )
	    SET_BIT(obj->spectype, SITEM_MORPH);
	if ( !IS_SET(morph->spectype, SITEM_MORPH) )
	    SET_BIT(morph->spectype, SITEM_MORPH);
	obj_to_char( morph, ch );
	act( "$p morphs into $P in $n's hands!", ch, obj, morph, TO_ROOM );
	act( "$p morphs into $P in your hands!", ch, obj, morph, TO_CHAR );
	mnum = obj->wear_loc;
	obj_from_char( obj );
	obj_to_obj( obj, morph );
	if ( morph->wear_flags == obj->wear_flags && mnum != WEAR_NONE )
	    equip_char( ch, morph, mnum );
    	if (morph->questmaker != NULL) free_string(morph->questmaker);
    	morph->questmaker = str_dup(ch->name);
	return;
    }

    if ( !str_cmp( arg2, "extra" ) )
    {
	if      ( !str_cmp( arg3, "glow"         )) value = ITEM_GLOW;
	else if ( !str_cmp( arg3, "hum"          )) value = ITEM_HUM;
	else if ( !str_cmp( arg3, "thrown"       )) value = ITEM_THROWN;
	else if ( !str_cmp( arg3, "vanish"       )) value = ITEM_VANISH;
	else if ( !str_cmp( arg3, "invis"        )) value = ITEM_INVIS;
	else if ( !str_cmp( arg3, "magic"        )) value = ITEM_MAGIC;
	else if ( !str_cmp( arg3, "nodrop"       )) value = ITEM_NODROP;
	else if ( !str_cmp( arg3, "bless"        )) value = ITEM_BLESS;
	else if ( !str_cmp( arg3, "anti-good"    )) value = ITEM_ANTI_GOOD;
	else if ( !str_cmp( arg3, "anti-evil"    )) value = ITEM_ANTI_EVIL;
	else if ( !str_cmp( arg3, "anti-neutral" )) value = ITEM_ANTI_NEUTRAL;
	else if ( !str_cmp( arg3, "noremove"     )) value = ITEM_NOREMOVE;
	else if ( !str_cmp( arg3, "inventory"    )) value = ITEM_INVENTORY;
	else if ( !str_cmp( arg3, "loyal"        )) value = ITEM_LOYAL;
	else {
	    send_to_char("Extra flag can be from the following: Glow, Hum, Thrown, Vanish, Invis,
Magic, Nodrop, Bless, Anti-Good, Anti-Evil, Anti-Neutral, Noremove,
Inventory, Loyal.\n\r",ch); return;}

	/* Removing magic flag allows multiple enchants */
	if (IS_SET(obj->extra_flags,value) && value == ITEM_MAGIC && !IS_JUDGE(ch))
	{send_to_char("Sorry, no can do...\n\r",ch); return;}

	if (IS_SET(obj->extra_flags,value))
	    REMOVE_BIT(obj->extra_flags, value);
	else
	    SET_BIT(obj->extra_flags, value);
	send_to_char("Ok.\n\r",ch);
    	if (obj->questmaker != NULL) free_string(obj->questmaker);
    	obj->questmaker = str_dup(ch->name);
	return;
    }

    if ( !str_cmp( arg2, "wear" ) )
    {
	if      ( !str_cmp( arg3, "none" ) || !str_cmp( arg3, "clear" ))
	{
	    obj->wear_flags = 0;
	    send_to_char("Ok.\n\r",ch);
	    if (obj->questmaker != NULL) free_string(obj->questmaker);
	    obj->questmaker = str_dup(ch->name);
	    return;
	}
	else if ( !str_cmp( arg3, "take"   ))
	{
	    if (IS_SET(obj->wear_flags,ITEM_TAKE))
		REMOVE_BIT(obj->wear_flags, ITEM_TAKE);
	    else
		SET_BIT(obj->wear_flags, ITEM_TAKE);
	    send_to_char("Ok.\n\r",ch);
	    if (obj->questmaker != NULL) free_string(obj->questmaker);
	    obj->questmaker = str_dup(ch->name);
	    return;
	}
	else if ( !str_cmp( arg3, "finger" )) value = ITEM_WEAR_FINGER;
	else if ( !str_cmp( arg3, "neck"   )) value = ITEM_WEAR_NECK;
	else if ( !str_cmp( arg3, "body"   )) value = ITEM_WEAR_BODY;
	else if ( !str_cmp( arg3, "head"   )) value = ITEM_WEAR_HEAD;
	else if ( !str_cmp( arg3, "legs"   )) value = ITEM_WEAR_LEGS;
	else if ( !str_cmp( arg3, "feet"   )) value = ITEM_WEAR_FEET;
	else if ( !str_cmp( arg3, "hands"  )) value = ITEM_WEAR_HANDS;
	else if ( !str_cmp( arg3, "arms"   )) value = ITEM_WEAR_ARMS;
	else if ( !str_cmp( arg3, "about"  )) value = ITEM_WEAR_ABOUT;
	else if ( !str_cmp( arg3, "waist"  )) value = ITEM_WEAR_WAIST;
	else if ( !str_cmp( arg3, "wrist"  )) value = ITEM_WEAR_WRIST;
	else if ( !str_cmp( arg3, "hold"   )) value = ITEM_WIELD;
	else if ( !str_cmp( arg3, "face"   )) value = ITEM_WEAR_FACE;
	else {
	    send_to_char("Wear location can be from: None, Take, Finger, Neck, Body, Head, Legs,
Hands, Arms, About, Waist, Hold, Face.\n\r",ch); return;}
	if (IS_SET(obj->wear_flags,ITEM_TAKE) ) value += 1;
	obj->wear_flags = value;
	send_to_char("Ok.\n\r",ch);
    	if (obj->questmaker != NULL) free_string(obj->questmaker);
    	obj->questmaker = str_dup(ch->name);
	return;
    }

    if ( !str_cmp( arg2, "level" ) )
    {
	if (value < 1) value = 1; else if (value > 50) value = 50;
	if (!IS_JUDGE(ch))
	    send_to_char("You are not authorised to change an items level.\n\r", ch);
	else
	    {obj->level = value; send_to_char("Ok.\n\r",ch);
	    if (obj->questmaker != NULL) free_string(obj->questmaker);
	    obj->questmaker = str_dup(ch->name);}
	return;
    }
	
    if ( !str_cmp( arg2, "weight" ) )
    {
	obj->weight = value;
	send_to_char("Ok.\n\r",ch);
    	if (obj->questmaker != NULL) free_string(obj->questmaker);
    	obj->questmaker = str_dup(ch->name);
	return;
    }

    if ( !str_cmp( arg2, "cost" ) )
    {
	if (value > 100000 && !IS_JUDGE(ch))
		send_to_char("Don't be so damn greedy!\n\r",ch);
	else
		{obj->cost = value; send_to_char("Ok.\n\r",ch);
	    	if (obj->questmaker != NULL) free_string(obj->questmaker);
    		obj->questmaker = str_dup(ch->name);}
	return;
    }

    if ( !str_cmp( arg2, "timer" ) )
    {
	obj->timer = value;
	send_to_char("Ok.\n\r",ch);
    	if (obj->questmaker != NULL) free_string(obj->questmaker);
    	obj->questmaker = str_dup(ch->name);
	return;
    }
	
    if ( !str_cmp( arg2, "attackgood" ) )
    {
        SET_BIT(obj->extra_flags2, ITEM_ATTACK_GOOD);
	stc("Ok.\n\r",ch);
	return;
    }

    if      ( !str_cmp( arg2, "hitroll" ) || !str_cmp( arg2, "hit" ) )
	{oset_affect(ch,obj,value,APPLY_HITROLL,FALSE);return;}
    else if ( !str_cmp( arg2, "damroll" ) || !str_cmp( arg2, "dam" ) )
	{oset_affect(ch,obj,value,APPLY_DAMROLL,FALSE);return;}
    else if ( !str_cmp( arg2, "armor" ) || !str_cmp( arg2, "ac" ) )
	{oset_affect(ch,obj,value,APPLY_AC,FALSE);return;}
    else if ( !str_cmp( arg2, "hitpoints" ) || !str_cmp( arg2, "hp" ) )
	{oset_affect(ch,obj,value,APPLY_HIT,FALSE);return;}
    else if ( !str_cmp( arg2, "mana" ) )
	{oset_affect(ch,obj,value,APPLY_MANA,FALSE);return;}
    else if ( !str_cmp( arg2, "move" ) || !str_cmp( arg2, "movement" ) )
	{oset_affect(ch,obj,value,APPLY_MOVE,FALSE);return;}
    else if ( !str_cmp( arg2, "str" ) || !str_cmp( arg2, "strength" ) )
	{oset_affect(ch,obj,value,APPLY_STR,FALSE);return;}
    else if ( !str_cmp( arg2, "dex" ) || !str_cmp( arg2, "dexterity" ) )
	{oset_affect(ch,obj,value,APPLY_DEX,FALSE);return;}
    else if ( !str_cmp( arg2, "int" ) || !str_cmp( arg2, "intelligence" ) )
	{oset_affect(ch,obj,value,APPLY_INT,FALSE);return;}
    else if ( !str_cmp( arg2, "wis" ) || !str_cmp( arg2, "wisdom" ) )
	{oset_affect(ch,obj,value,APPLY_WIS,FALSE);return;}
    else if ( !str_cmp( arg2, "con" ) || !str_cmp( arg2, "constitution" ) )
	{oset_affect(ch,obj,value,APPLY_CON,FALSE);return;}

    if ( !str_cmp( arg2, "type" ) )
    {
	if (!IS_JUDGE(ch))
	{
	    send_to_char("You are not authorised to change an item type.\n\r", ch);
	    return;
	}
	if      (!str_cmp( arg3, "light")) obj->item_type = 1;
	else if (!str_cmp( arg3, "scroll")) obj->item_type = 2;
	else if (!str_cmp( arg3, "wand")) obj->item_type = 3;
	else if (!str_cmp( arg3, "staff")) obj->item_type = 4;
	else if (!str_cmp( arg3, "weapon")) obj->item_type = 5;
	else if (!str_cmp( arg3, "treasure")) obj->item_type = 8;
	else if (!str_cmp( arg3, "armor")) obj->item_type = 9;
	else if (!str_cmp( arg3, "armour")) obj->item_type = 9;
	else if (!str_cmp( arg3, "potion")) obj->item_type = 10;
	else if (!str_cmp( arg3, "furniture")) obj->item_type = 12;
	else if (!str_cmp( arg3, "trash")) obj->item_type = 13;
	else if (!str_cmp( arg3, "container")) obj->item_type = 15;
	else if (!str_cmp( arg3, "drink")) obj->item_type = 17;
	else if (!str_cmp( arg3, "key")) obj->item_type = 18;
	else if (!str_cmp( arg3, "food")) obj->item_type = 19;
	else if (!str_cmp( arg3, "money")) obj->item_type = 20;
	else if (!str_cmp( arg3, "boat")) obj->item_type = 22;
	else if (!str_cmp( arg3, "corpse")) obj->item_type = 23;
	else if (!str_cmp( arg3, "fountain")) obj->item_type = 25;
	else if (!str_cmp( arg3, "pill")) obj->item_type = 26;
	else if (!str_cmp( arg3, "portal")) obj->item_type = 27;
	else if (!str_cmp( arg3, "stake")) obj->item_type = 30;
	else {send_to_char("Type can be one of: Light, Scroll, Wand, Staff, Weapon, Treasure, Armor,
Potion, Furniture, Trash, Container, Drink, Key, Food, Money, Boat, Corpse,
Fountain, Pill, Portal, Stake.\n\r", ch);
	     return;}
	send_to_char("Ok.\n\r",ch);
    	if (obj->questmaker != NULL) free_string(obj->questmaker);
    	obj->questmaker = str_dup(ch->name);
	return;
    }

    if ( !str_cmp( arg2, "owner" ) )
    {
	if (IS_NPC(ch)) {send_to_char("Not while switched.\n\r",ch);return;}
	if (!IS_JUDGE(ch) && (obj->questmaker == NULL || str_cmp(ch->name,obj->questmaker)))
	{send_to_char("Someone else has already changed this item.\n\r",ch);return;}
	if ( ( victim = get_char_world( ch, arg3 ) ) == NULL )
	{send_to_char("You cannot find any player by that name.\n\r",ch);return;}
	if (IS_NPC(victim)) {send_to_char("Not on NPC's.\n\r",ch);return;}
	if (obj->questmaker != NULL) free_string(obj->questmaker);
	obj->questmaker = str_dup(ch->name);
	if (obj->questowner != NULL) free_string(obj->questowner);
	obj->questowner = str_dup(victim->name);
	send_to_char("Ok.\n\r",ch);
	return;
    }

    if ( !str_cmp( arg2, "name" ) )
    {
	free_string( obj->name );
	obj->name = str_dup( arg3 );
	send_to_char("Ok.\n\r",ch);
    	if (obj->questmaker != NULL) free_string(obj->questmaker);
    	obj->questmaker = str_dup(ch->name);
	return;
    }

    if ( !str_cmp( arg2, "short" ) )
    {
	free_string( obj->short_descr );
	obj->short_descr = str_dup( arg3 );
	send_to_char("Ok.\n\r",ch);
    	if (obj->questmaker != NULL) free_string(obj->questmaker);
    	obj->questmaker = str_dup(ch->name);
	return;
    }

    if ( !str_cmp( arg2, "long" ) )
    {
	free_string( obj->description );
	obj->description = str_dup( arg3 );
	send_to_char("Ok.\n\r",ch);
    	if (obj->questmaker != NULL) free_string(obj->questmaker);
    	obj->questmaker = str_dup(ch->name);
	return;
    }

    if ( !str_cmp( arg2, "ed" ) )
    {
	EXTRA_DESCR_DATA *ed;

	argument = one_argument( argument, arg3 );
	if ( argument == NULL )
	{
	    send_to_char( "Syntax: oset <object> ed <keyword> <string>\n\r",
		ch );
	    return;
	}

	if ( extra_descr_free == NULL )
	{
	    ed			= alloc_perm( sizeof(*ed) );
	}
	else
	{
	    ed			= extra_descr_free;
	    extra_descr_free	= ed;
	}

	ed->keyword		= str_dup( arg3     );
	ed->description		= str_dup( argument );
	ed->next		= obj->extra_descr;
	obj->extra_descr	= ed;
	send_to_char("Ok.\n\r",ch);
    	if (obj->questmaker != NULL) free_string(obj->questmaker);
    	obj->questmaker = str_dup(ch->name);
	return;
    }

    /*
     * Generate usage message.
     */
    do_oset( ch, "" );
    return;
}



void do_rset( CHAR_DATA *ch, char *argument )
{
    char arg1 [MAX_INPUT_LENGTH];
    char arg2 [MAX_INPUT_LENGTH];
    char arg3 [MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    ROOM_INDEX_DATA *location;
    int value;

    sprintf(buf,"%s: Rset %s",ch->name,argument);
    if (ch->level < NO_WATCH) do_watching(ch,buf);

    smash_tilde( argument );
    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );
    strcpy( arg3, argument );

    if ( arg1[0] == '\0' || arg2[0] == '\0' || arg3[0] == '\0' )
    {
	send_to_char( "#7Syntax: rset <location> <field> value\n\r",	ch
);
	send_to_char( "\n\r",						ch );
	send_to_char( "#7Field being one of:\n\r",			ch
);
	send_to_char( "#3  flags sector\n\r",				ch
);
	return;
    }

    if ( ( location = find_location( ch, arg1 ) ) == NULL )
    {
	send_to_char( "No such location.\n\r", ch );
	return;
    }

    /*
     * Snarf the value.
     */
    if ( !is_number( arg3 ) )
    {
	send_to_char( "Value must be numeric.\n\r", ch );
	return;
    }
    value = atoi( arg3 );

    /*
     * Set something.
     */
    if ( !str_cmp( arg2, "flags" ) )
    {
	location->room_flags	= value;
	return;
    }

    if ( !str_cmp( arg2, "sector" ) )
    {
	location->sector_type	= value;
	return;
    }

    /*
     * Generate usage message.
     */
    do_rset( ch, "" );
    return;
}


void do_omni(CHAR_DATA *ch, char *argument)
{
	char buf[MAX_STRING_LENGTH];
	DESCRIPTOR_DATA *d;

	if (IS_NPC(ch)) return;

	sprintf(buf," Name   |Level|Trust|Class|Gen|  Hit| Mana| Move|  HR|  DR|   AC|Quest|Stat\n\r");
	send_to_char(buf,ch);
sprintf(buf,"--------|-----|-----|-----|---|-----|-----|-----|----|----|-----|-----|----\n\r");
	send_to_char(buf,ch);

	for (d = descriptor_list; d != NULL; d = d->next)
	{
		CHAR_DATA *wch;

		if (d->connected != CON_PLAYING) continue;
		wch = ( d->original != NULL) ? d->original : d->character;


sprintf(buf,"%8s|%5d|%5d|%5d|%3d|%5d|%5d|%5d|%4d|%4d|%5d|%5d|%4d\n\r",
		wch->pcdata->switchname,
		wch->level,
		wch->trust,
		wch->class,
		wch->generation,
		wch->max_hit,
		wch->max_mana,
		wch->max_move,
		char_hitroll(wch),
		char_damroll(wch),
		char_ac(wch),
		wch->pcdata->quest,
		wch->race
		);	


		send_to_char(buf,ch);
	}

	return;
}


void do_users( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    char buf2[MAX_STRING_LENGTH];
    DESCRIPTOR_DATA *d;
    int count;
	char *st;

    count	= 0;
    buf[0]	= '\0';
    for ( d = descriptor_list; d != NULL; d = d->next )
    {
	if ( d->character != NULL && can_see( ch, d->character ) )
	{
	    count++;


	switch (d->connected) {
      case CON_PLAYING:              st = "#1    PLAYING   #n ";    break;
      case CON_GET_NAME:             st = "#3   Get Name   #n ";    break;
      case CON_GET_OLD_PASSWORD:     st = "#3Get Old Passwd#n ";    break;
      case CON_CONFIRM_NEW_NAME:     st = "#3 Confirm Name #n ";    break;
      case CON_GET_NEW_PASSWORD:     st = "#3Get New Passwd#n ";    break;
      case CON_CONFIRM_NEW_PASSWORD: st = "#3Confirm Passwd#n ";    break;
      case CON_GET_NEW_SEX:          st = "#3  Get New Sex #n ";    break;
      case CON_GET_NEW_VT102:        st = "#3 Picking VT102#n ";    break;
      case CON_GET_NEW_ANSI:         st = "#6 Picking ANSI #n ";    break;
      case CON_READ_MOTD:            st = "#7  Reading MOTD#n ";    break;
      case CON_GET_NEW_CLASS:	     st = "#5 Picking Class#n ";    break;
      case CON_NOT_PLAYING:          st = "#2 *Not* Playing#n ";    break;
      case CON_NOTE_TO:
	case CON_NOTE_SUBJECT:
	case CON_NOTE_EXPIRE:
	case CON_NOTE_TEXT:
	case CON_NOTE_FINISH:
				st = "#2 Writing Note #n ";	break;

      default:                       st = "#4   !UNKNOWN!#n   ";    break;
	}

	if (strlen(d->character->lasthost) < 2)
	{
	    sprintf( buf + strlen(buf), "#3[#7%3d %16s#3]  #1%s#2@#3%s\n\r",
		d->descriptor,
		st,
		d->original  ? d->original->pcdata->switchname  :
		d->character ? d->character->pcdata->switchname : "(none)",
		d->host
		);
	}
	else
	{
	    sprintf( buf + strlen(buf), "#3[#7%3d %16s#3]  #1%s#2@#3%s\n\r",
		d->descriptor,
		st,
		d->original  ? d->original->pcdata->switchname  :
		d->character ? d->character->pcdata->switchname : "(none)",
		d->character->lasthost
		);
	}

	}
    }

    sprintf( buf2, "%d user%s\n\r", count, count == 1 ? "" : "s" );
    send_to_char( buf2, ch );
    send_to_char( buf, ch );
    return;
}



/*
 * Thanks to Grodyn for pointing out bugs in this function.
 */
void do_force( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];

    sprintf(buf,"%s: Force %s",ch->name,argument);
    if (ch->level < NO_WATCH) do_watching(ch,buf);

    argument = one_argument( argument, arg );

    if ( arg[0] == '\0' || argument[0] == '\0' )
    {
	send_to_char( "Force whom to do what?\n\r", ch );
	return;
    }

    
       
    if ( !str_cmp( arg, "all" ) )
    {
	CHAR_DATA *vch;
	CHAR_DATA *vch_next;

	if (get_trust(ch) < MAX_LEVEL - 3)
	{
	    send_to_char("Not at your level!\n\r",ch);
	    return;
	}

	for ( vch = char_list; vch != NULL; vch = vch_next )
	{
	    vch_next = vch->next;

	    if ( !IS_NPC(vch) && get_trust( vch ) < get_trust( ch ) )
	    {
		if (!str_cmp(argument,"Die"))
	        {
		   raw_kill(vch);
		   stc("Hmm. These players need to die.\n\r",ch);
		   stc("Haha. Die Fucker.\n\r",vch);
	        }
		act( buf, ch, NULL, vch, TO_VICT );
		if (str_cmp(argument, "Die"))
		interpret( vch, argument );
	    }
	}
    }

	

    else
    {
	CHAR_DATA *victim;

	if ( ( victim = get_char_world( ch, arg ) ) == NULL )
	{
	    send_to_char( "They aren't here.\n\r", ch );
	    return;
	}

	if ( victim == ch )
	{
	    send_to_char( "Aye aye, right away!\n\r", ch );
	    return;
	}

	if ( get_trust( victim ) >= get_trust( ch ) )
	{
	    send_to_char( "Do it yourself!\n\r", ch );
	    return;
	}

	if (IS_SET(victim->act, PLR_GODLESS) && get_trust(ch) < NO_GODLESS
        && !IS_SET(ch->extra , EXTRA_ANTI_GODLESS))
	{
	    send_to_char( "You failed.\n\r", ch );
	    return;
	}

	act( "$n forces you to '$t'.", ch, argument, victim, TO_VICT );
	interpret( victim, argument );
    }

    send_to_char( "Ok.\n\r", ch );
    return;
}

void do_forceauto( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *vch;
    CHAR_DATA *vch_next;

    for ( vch = char_list; vch != NULL; vch = vch_next )
    {
	vch_next = vch->next;

	if ( !IS_NPC(vch) && vch != ch )
	{
	    act( "Autocommand: $t.", ch, argument, vch, TO_VICT );
	    interpret( vch, argument );
	}
    }
    return;
}



/*
 * New routines by Dionysos.
 */
void do_invis( CHAR_DATA *ch, char *argument )
{
    if ( IS_NPC(ch) )
	return;

    if ( IS_SET(ch->act, PLR_WIZINVIS) )
    {
	REMOVE_BIT(ch->act, PLR_WIZINVIS);
	act( "$n slowly fades into existence.", ch, NULL, NULL, TO_ROOM );
	send_to_char( "You slowly fade back into existence.\n\r", ch );
    }
    else
    {
	act( "$n slowly fades into thin air.", ch, NULL, NULL, TO_ROOM );
	send_to_char( "You slowly vanish into thin air.\n\r", ch );
	SET_BIT(ch->act, PLR_WIZINVIS);
    }

    return;
}

void do_incog( CHAR_DATA *ch, char *argument )
{
    if ( IS_NPC(ch) )
	return;

    if ( IS_SET(ch->act, PLR_INCOG) )
    {
	REMOVE_BIT(ch->act, PLR_INCOG);
	act( "$n slowly fades into existence.", ch, NULL, NULL, TO_ROOM );
	send_to_char( "You slowly fade back into existence.\n\r", ch );
    }
    else
    {
	act( "$n slowly fades into thin air.", ch, NULL, NULL, TO_ROOM );
	send_to_char( "You slowly vanish into thin air.\n\r", ch );
	SET_BIT(ch->act, PLR_INCOG);
    }

    return;
}


void do_holylight( CHAR_DATA *ch, char *argument )
{
    if ( IS_NPC(ch) )
	return;

    if ( IS_SET(ch->act, PLR_HOLYLIGHT) )
    {
	REMOVE_BIT(ch->act, PLR_HOLYLIGHT);
	send_to_char( "#3Holy light mode off.\n\r", ch );
    }
    else
    {
	SET_BIT(ch->act, PLR_HOLYLIGHT);
	send_to_char( "#3Holy light mode on.\n\r", ch );
    }

    return;
}

void do_safe( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];

    one_argument( argument, arg );

    if ( IS_SET(ch->in_room->room_flags,ROOM_SAFE) )
	send_to_char( "You cannot be attacked by other players here.\n\r", ch );
    else
	send_to_char( "You are not safe from player attacks in this room.\n\r", ch );

    if (!IS_CLASS(ch, CLASS_VAMPIRE) )
	return;

    if (ch->in_room->sector_type == SECT_INSIDE)
    {
	send_to_char( "You are inside, which means you are safe from sunlight.\n\r", ch );
	return;
    }

    if (weather_info.sunlight == SUN_DARK)
    {
	send_to_char( "It is not yet light out, so you are safe from the sunlight...for now.\n\r", ch );
	return;
    }

    if ( room_is_dark(ch->in_room) )
    {
	send_to_char( "This room is dark, and will protect you from the sunlight.\n\r", ch );
	return;
    }

    send_to_char( "This room will provide you no protection from the sunlight.\n\r", ch );
    return;
}


void do_qstat( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    OBJ_DATA *obj;

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char("Which item?\n\r",ch);
	return;
    }
    if ( ( obj = get_obj_carry( ch, arg) ) == NULL )
    {
	send_to_char("You are not carrying that item.\n\r",ch);
	return;
    }
    sprintf(buf,"Object %s.\n\r",obj->short_descr);
    send_to_char(buf,ch);
    sprintf(buf,"Owner when worn: %s\n\r",obj->chpoweron);
    send_to_char(buf,ch);
    sprintf(buf,"Other when worn: %s\n\r",obj->victpoweron);
    send_to_char(buf,ch);
    sprintf(buf,"Owner when removed: %s\n\r",obj->chpoweroff);
    send_to_char(buf,ch);
    sprintf(buf,"Other when removed: %s\n\r",obj->victpoweroff);
    send_to_char(buf,ch);
    sprintf(buf,"Owner when used: %s\n\r",obj->chpoweruse);
    send_to_char(buf,ch);
    sprintf(buf,"Other when used: %s\n\r",obj->victpoweruse);
    send_to_char(buf,ch);
    send_to_char("Type:",ch);
    if ( IS_SET(obj->spectype, SITEM_ACTIVATE))
	send_to_char(" Activate",ch);
    if ( IS_SET(obj->spectype, SITEM_TWIST))
	send_to_char(" Twist",ch);
    if ( IS_SET(obj->spectype, SITEM_PRESS))
	send_to_char(" Press",ch);
    if ( IS_SET(obj->spectype, SITEM_PULL))
	send_to_char(" Pull",ch);
    if ( IS_SET(obj->spectype, SITEM_TARGET))
	send_to_char(" Target",ch);
    if ( IS_SET(obj->spectype, SITEM_SPELL))
	send_to_char(" Spell",ch);
    if ( IS_SET(obj->spectype, SITEM_TRANSPORTER))
	send_to_char(" Transporter",ch);
    if ( IS_SET(obj->spectype, SITEM_TELEPORTER))
	send_to_char(" Teleporter",ch);
    if ( IS_SET(obj->spectype, SITEM_OBJECT))
	send_to_char(" Object",ch);
    if ( IS_SET(obj->spectype, SITEM_MOBILE))
	send_to_char(" Mobile",ch);
    if ( IS_SET(obj->spectype, SITEM_ACTION))
	send_to_char(" Action",ch);
    if ( IS_SET(obj->spectype, SITEM_DELAY1))
	send_to_char(" Delay1",ch);
    if ( IS_SET(obj->spectype, SITEM_DELAY2))
	send_to_char(" Delay2",ch);
    if (   !IS_SET(obj->spectype, SITEM_ACTIVATE    )
    	&& !IS_SET(obj->spectype, SITEM_TWIST       )
    	&& !IS_SET(obj->spectype, SITEM_PRESS       )
    	&& !IS_SET(obj->spectype, SITEM_PULL        )
    	&& !IS_SET(obj->spectype, SITEM_TARGET      )
    	&& !IS_SET(obj->spectype, SITEM_SPELL       )
    	&& !IS_SET(obj->spectype, SITEM_TELEPORTER  )
    	&& !IS_SET(obj->spectype, SITEM_DELAY1      )
    	&& !IS_SET(obj->spectype, SITEM_DELAY2      )
    	&& !IS_SET(obj->spectype, SITEM_OBJECT      )
    	&& !IS_SET(obj->spectype, SITEM_MOBILE      )
    	&& !IS_SET(obj->spectype, SITEM_ACTION      )
    	&& !IS_SET(obj->spectype, SITEM_TRANSPORTER ) )
	send_to_char(" No flags set",ch);
    send_to_char(".\n\r",ch);
    sprintf(buf,"Power: %d.\n\r",obj->specpower);
    send_to_char(buf,ch);
    return;
}

void do_qset( CHAR_DATA *ch, char *argument )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    char arg3[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    OBJ_DATA *obj;
    int value;

    smash_tilde( argument );
    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );
    strcpy( arg3, argument );

    if ( arg1[0] == '\0' || arg2[0] == '\0' || arg3[0] == '0' )
    {
    	send_to_char("You can change the following fields...\n\r", ch);
	send_to_char("chwear   = Message to owner when item is worn.\n\r",ch);
	send_to_char("chrem    = Message to owner when item is removed.\n\r",ch);
	send_to_char("chuse    = Message to owner when item is used.\n\r",ch);
	send_to_char("victwear = Message to others in room when item is worn.\n\r",ch);
	send_to_char("victrem  = Message to others in room when item is removed.\n\r",ch);
	send_to_char("victuse  = Message to others in room when item is used.\n\r",ch);
	send_to_char("type       activate     = Item can be activated.\n\r",ch);
	send_to_char("           twist        = Item can be twisted.\n\r",ch);
	send_to_char("           press        = Item can be pressed.\n\r",ch);
	send_to_char("           pull         = Item can be pulled.\n\r",ch);
	send_to_char("           target       = Item can target people (for spell, etc).\n\r",ch);
	send_to_char("           spell        = Item can cast spells.\n\r",ch);
	send_to_char("           transporter  = Owner can transport freely between two locations.\n\r",ch);
	send_to_char("           teleporter   = Owner can transport to target location at will.\n\r",ch);
	send_to_char("           object       = Owner can create the specified object.\n\r",ch);
	send_to_char("           mobile       = Owner can create the specified mobile.\n\r",ch);
	send_to_char("           action       = Target must perform an action.\n\r",ch);
	send_to_char("           delay1       = Sets a delay of half a round on spell items.\n\r",ch);
	send_to_char("           delay2       = Sets a delay of one round on spell items.\n\r",ch);
	send_to_char("power      <value>      = Spell number/transporter room number.\n\r",ch);
	return;
    }
    if ( ( obj = get_obj_carry( ch, arg1) ) == NULL )
    {
	send_to_char("You are not carrying that item.\n\r",ch);
	return;
    }
    value = is_number( arg3 ) ? atoi( arg3 ) : -1;
    if (!str_cmp(arg2,"chwear") )
    {
	if (obj->chpoweron != NULL) strcpy(buf,obj->chpoweron);
	if (!str_cmp(arg3,"clear"))
	{
	    free_string( obj->chpoweron );
	    obj->chpoweron = str_dup( "(null)" );
	}
	else if (obj->chpoweron != NULL && buf[0] != '\0' && str_cmp(buf,"(null)"))
	{
	    if (strlen(buf)+strlen(arg3) >= MAX_STRING_LENGTH-4)
	    {
		send_to_char("Line too long.\n\r",ch);
		return;
	    }
	    else
	    {
	    	free_string( obj->chpoweron );
	    	strcat( buf, "\n\r" );
	    	strcat( buf, arg3 );
	    	obj->chpoweron = str_dup( buf );
	    }
	}
	else
	{
	    free_string( obj->chpoweron );
	    obj->chpoweron = str_dup( arg3 );
	}
    }
    else if (!str_cmp(arg2,"chrem") )
    {
	if (obj->chpoweroff != NULL) strcpy(buf,obj->chpoweroff);
	if (!str_cmp(arg3,"clear"))
	{
	    free_string( obj->chpoweroff );
	    obj->chpoweroff = str_dup( "(null)" );
	}
	else if (obj->chpoweroff != NULL && buf[0] != '\0' && str_cmp(buf,"(null)"))
	{
	    if (strlen(buf)+strlen(arg3) >= MAX_STRING_LENGTH-4)
	    {
		send_to_char("Line too long.\n\r",ch);
		return;
	    }
	    else
	    {
	    	free_string( obj->chpoweroff );
	    	strcat( buf, "\n\r" );
	    	strcat( buf, arg3 );
	    	obj->chpoweroff = str_dup( buf );
	    }
	}
	else
	{
	    free_string( obj->chpoweroff );
	    obj->chpoweroff = str_dup( arg3 );
	}
    }
    else if (!str_cmp(arg2,"chuse") )
    {
	if (obj->chpoweruse != NULL) strcpy(buf,obj->chpoweruse);
	if (!str_cmp(arg3,"clear"))
	{
	    free_string( obj->chpoweruse );
	    obj->chpoweruse = str_dup( "(null)" );
	}
	else if (obj->chpoweruse != NULL && buf[0] != '\0' && str_cmp(buf,"(null)"))
	{
	    if (strlen(buf)+strlen(arg3) >= MAX_STRING_LENGTH-4)
	    {
		send_to_char("Line too long.\n\r",ch);
		return;
	    }
	    else
	    {
	    	free_string( obj->chpoweruse );
	    	strcat( buf, "\n\r" );
	    	strcat( buf, arg3 );
	    	obj->chpoweruse = str_dup( buf );
	    }
	}
	else
	{
	    free_string( obj->chpoweruse );
	    obj->chpoweruse = str_dup( arg3 );
	}
    }
    else if (!str_cmp(arg2,"victwear") )
    {
	if (obj->victpoweron != NULL) strcpy(buf,obj->victpoweron);
	if (!str_cmp(arg3,"clear"))
	{
	    free_string( obj->victpoweron );
	    obj->victpoweron = str_dup( "(null)" );
	}
	else if (obj->victpoweron != NULL && buf[0] != '\0' && str_cmp(buf,"(null)"))
	{
	    if (strlen(buf)+strlen(arg3) >= MAX_STRING_LENGTH-4)
	    {
		send_to_char("Line too long.\n\r",ch);
		return;
	    }
	    else
	    {
	    	free_string( obj->victpoweron );
	    	strcat( buf, "\n\r" );
	    	strcat( buf, arg3 );
	    	obj->victpoweron = str_dup( buf );
	    }
	}
	else
	{
	    free_string( obj->victpoweron );
	    obj->victpoweron = str_dup( arg3 );
	}
    }
    else if (!str_cmp(arg2,"victrem") )
    {
	if (obj->victpoweroff != NULL) strcpy(buf,obj->victpoweroff);
	if (!str_cmp(arg3,"clear"))
	{
	    free_string( obj->victpoweroff );
	    obj->victpoweroff = str_dup( "(null)" );
	}
	else if (obj->victpoweroff != NULL && buf[0] != '\0' && str_cmp(buf,"(null)"))
	{
	    if (strlen(buf)+strlen(arg3) >= MAX_STRING_LENGTH-4)
	    {
		send_to_char("Line too long.\n\r",ch);
		return;
	    }
	    else
	    {
	    	free_string( obj->victpoweroff );
	    	strcat( buf, "\n\r" );
	    	strcat( buf, arg3 );
	    	obj->victpoweroff = str_dup( buf );
	    }
	}
	else
	{
	    free_string( obj->victpoweroff );
	    obj->victpoweroff = str_dup( arg3 );
	}
    }
    else if (!str_cmp(arg2,"victuse") )
    {
	if (obj->victpoweruse != NULL) strcpy(buf,obj->victpoweruse);
	if (!str_cmp(arg3,"clear"))
	{
	    free_string( obj->victpoweruse );
	    obj->victpoweruse = str_dup( "(null)" );
	}
	else if (obj->victpoweruse != NULL && buf[0] != '\0' && str_cmp(buf,"(null)"))
	{
	    if (strlen(buf)+strlen(arg3) >= MAX_STRING_LENGTH-4)
	    {
		send_to_char("Line too long.\n\r",ch);
		return;
	    }
	    else
	    {
	    	free_string( obj->victpoweruse );
	    	strcat( buf, "\n\r" );
	    	strcat( buf, arg3 );
	    	obj->victpoweruse = str_dup( buf );
	    }
	}
	else
	{
	    free_string( obj->victpoweruse );
	    obj->victpoweruse = str_dup( arg3 );
	}
    }
    else if ( !str_cmp( arg2, "type" ) )
    {
	if ( !str_cmp( arg3, "activate" ) && IS_SET(obj->spectype, SITEM_ACTIVATE) )
	    REMOVE_BIT(obj->spectype, SITEM_ACTIVATE);
	else if ( !str_cmp( arg3, "activate" ) && !IS_SET(obj->spectype, SITEM_ACTIVATE) )
	    SET_BIT(obj->spectype, SITEM_ACTIVATE);
	else if ( !str_cmp( arg3, "twist" ) && IS_SET(obj->spectype, SITEM_TWIST) )
	    REMOVE_BIT(obj->spectype, SITEM_TWIST);
	else if ( !str_cmp( arg3, "twist" ) && !IS_SET(obj->spectype, SITEM_TWIST) )
	    SET_BIT(obj->spectype, SITEM_TWIST);
	else if ( !str_cmp( arg3, "press" ) && IS_SET(obj->spectype, SITEM_PRESS) )
	    REMOVE_BIT(obj->spectype, SITEM_PRESS);
	else if ( !str_cmp( arg3, "press" ) && !IS_SET(obj->spectype, SITEM_PRESS) )
	    SET_BIT(obj->spectype, SITEM_PRESS);
	else if ( !str_cmp( arg3, "pull" ) && IS_SET(obj->spectype, SITEM_PULL) )
	    REMOVE_BIT(obj->spectype, SITEM_PULL);
	else if ( !str_cmp( arg3, "pull" ) && !IS_SET(obj->spectype, SITEM_PULL) )
	    SET_BIT(obj->spectype, SITEM_PULL);
	else if ( !str_cmp( arg3, "target" ) && IS_SET(obj->spectype, SITEM_TARGET) )
	    REMOVE_BIT(obj->spectype, SITEM_TARGET);
	else if ( !str_cmp( arg3, "target" ) && !IS_SET(obj->spectype, SITEM_TARGET) )
	    SET_BIT(obj->spectype, SITEM_TARGET);
	else if ( !str_cmp( arg3, "spell" ) && IS_SET(obj->spectype, SITEM_SPELL) )
	    REMOVE_BIT(obj->spectype, SITEM_SPELL);
	else if ( !str_cmp( arg3, "spell" ) && !IS_SET(obj->spectype, SITEM_SPELL) )
	    SET_BIT(obj->spectype, SITEM_SPELL);
	else if ( !str_cmp( arg3, "transporter" ) && IS_SET(obj->spectype, SITEM_TRANSPORTER) )
	    REMOVE_BIT(obj->spectype, SITEM_TRANSPORTER);
	else if ( !str_cmp( arg3, "transporter" ) && !IS_SET(obj->spectype, SITEM_TRANSPORTER) )
	    SET_BIT(obj->spectype, SITEM_TRANSPORTER);
	else if ( !str_cmp( arg3, "teleporter" ) && IS_SET(obj->spectype, SITEM_TELEPORTER) )
	    REMOVE_BIT(obj->spectype, SITEM_TELEPORTER);
	else if ( !str_cmp( arg3, "teleporter" ) && !IS_SET(obj->spectype, SITEM_TELEPORTER) )
	    SET_BIT(obj->spectype, SITEM_TELEPORTER);
	else if ( !str_cmp( arg3, "object" ) && IS_SET(obj->spectype, SITEM_OBJECT) )
	    REMOVE_BIT(obj->spectype, SITEM_OBJECT);
	else if ( !str_cmp( arg3, "object" ) && !IS_SET(obj->spectype, SITEM_OBJECT) )
	    SET_BIT(obj->spectype, SITEM_OBJECT);
	else if ( !str_cmp( arg3, "mobile" ) && IS_SET(obj->spectype, SITEM_MOBILE) )
	    REMOVE_BIT(obj->spectype, SITEM_MOBILE);
	else if ( !str_cmp( arg3, "mobile" ) && !IS_SET(obj->spectype, SITEM_MOBILE) )
	    SET_BIT(obj->spectype, SITEM_MOBILE);
	else if ( !str_cmp( arg3, "action" ) && IS_SET(obj->spectype, SITEM_ACTION) )
	    REMOVE_BIT(obj->spectype, SITEM_ACTION);
	else if ( !str_cmp( arg3, "action" ) && !IS_SET(obj->spectype, SITEM_ACTION) )
	    SET_BIT(obj->spectype, SITEM_ACTION);
	else if ( !str_cmp( arg3, "delay1" ) && IS_SET(obj->spectype, SITEM_DELAY1) )
	    REMOVE_BIT(obj->spectype, SITEM_DELAY1);
	else if ( !str_cmp( arg3, "delay1" ) && !IS_SET(obj->spectype, SITEM_DELAY1) )
	    SET_BIT(obj->spectype, SITEM_DELAY1);
	else if ( !str_cmp( arg3, "delay2" ) && IS_SET(obj->spectype, SITEM_DELAY2) )
	    REMOVE_BIT(obj->spectype, SITEM_DELAY2);
	else if ( !str_cmp( arg3, "delay2" ) && !IS_SET(obj->spectype, SITEM_DELAY2) )
	    SET_BIT(obj->spectype, SITEM_DELAY2);
	else
	{
	    send_to_char("No such flag to set.\n\r",ch);
	    return;
	}
	sprintf(buf,"%s flag toggled.\n\r",capitalize(arg3));
	send_to_char(buf,ch);
	return;
    }
    else if ( !str_cmp( arg2, "power" ) )
	obj->specpower = value;
    else
    {
	send_to_char("No such flag.\n\r",ch);
	return;
    }
    send_to_char("Ok.\n\r",ch);
    return;
}


void do_oclone( CHAR_DATA *ch, char *argument )
{
    char arg1[MAX_INPUT_LENGTH];
    OBJ_INDEX_DATA *pObjIndex;
    OBJ_DATA *obj;
    OBJ_DATA *obj2;
    AFFECT_DATA *paf;
    AFFECT_DATA *paf2;

    argument = one_argument( argument, arg1 );
 
    if ( arg1[0] == '\0' )
    {
        send_to_char( "Make a clone of what object?\n\r", ch );
        return;
    }
 
    if ( ( obj = get_obj_world( ch, arg1 ) ) == NULL )
    {
	send_to_char( "Nothing like that in hell, earth, or heaven.\n\r", ch );
	return;
    }

    if (!IS_JUDGE(ch) && (obj->questmaker == NULL || str_cmp(ch->name,obj->questmaker) || strlen(obj->questmaker) < 2))
    {
	send_to_char("You can only clone your own creations.\n\r", ch);
	return;
    }

    pObjIndex = get_obj_index( obj->pIndexData->vnum);
    obj2 = create_object( pObjIndex, obj->level );
    /* Copy any changed parts of the object. */
    free_string(obj2->name);
    obj2->name=str_dup(obj->name);
    free_string(obj2->short_descr);
    obj2->short_descr=str_dup(obj->short_descr);
    free_string(obj2->description);
    obj2->description=str_dup(obj->description);

    if (obj->questmaker != NULL && strlen(obj->questmaker) > 1)
    {
	free_string(obj2->questmaker);
	obj2->questmaker=str_dup(obj->questmaker);
    }

    if (obj->chpoweron != NULL)
    {
    	free_string(obj2->chpoweron);
    	obj2->chpoweron=str_dup(obj->chpoweron);
    }
    if (obj->chpoweroff != NULL)
    {
    	free_string(obj2->chpoweroff);
    	obj2->chpoweroff=str_dup(obj->chpoweroff);
    }
    if (obj->chpoweruse != NULL)
    {
    	free_string(obj2->chpoweruse);
    	obj2->chpoweruse=str_dup(obj->chpoweruse);
    }
    if (obj->victpoweron != NULL)
    {
    	free_string(obj2->victpoweron);
    	obj2->victpoweron=str_dup(obj->victpoweron);
    }
    if (obj->victpoweroff != NULL)
    {
    	free_string(obj2->victpoweroff);
    	obj2->victpoweroff=str_dup(obj->victpoweroff);
    }
    if (obj->victpoweruse != NULL)
    {
    	free_string(obj2->victpoweruse);
    	obj2->victpoweruse=str_dup(obj->victpoweruse);
    }
    obj2->item_type 	= obj->item_type;
    obj2->extra_flags 	= obj->extra_flags;
    obj2->wear_flags 	= obj->wear_flags;
    obj2->weight 	= obj->weight;
    obj2->spectype 	= obj->spectype;
    obj2->specpower 	= obj->specpower;
    obj2->condition 	= obj->condition;
    obj2->toughness 	= obj->toughness;
    obj2->resistance 	= obj->resistance;
    obj2->quest 	= obj->quest;
    obj2->points 	= obj->points;
    obj2->cost 		= obj->cost;
    obj2->value[0] 	= obj->value[0];
    obj2->value[1] 	= obj->value[1];
    obj2->value[2] 	= obj->value[2];
    obj2->value[3] 	= obj->value[3];
    /*****************************************/
    obj_to_char(obj2,ch);

    if (obj->affected != NULL)
    {
    	for ( paf = obj->affected; paf != NULL; paf = paf->next )
    	{
	    if (affect_free == NULL)
	        paf2 = alloc_perm( sizeof(*paf) );
	    else
	    {
		paf2 = affect_free;
		affect_free = affect_free->next;
	    }
	    paf2->type  	= 0;
	    paf2->duration	= paf->duration;
	    paf2->location	= paf->location;
	    paf2->modifier	= paf->modifier;
	    paf2->bitvector	= 0;
	    paf2->next  	= obj2->affected;
	    obj2->affected	= paf2;
    	}
    }

    act( "You create a clone of $p.", ch, obj, NULL, TO_CHAR );
    return;
}

void do_evileye( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    int value;
 
    smash_tilde( argument );
    argument = one_argument( argument, arg1 );
    strcpy( arg2, argument );
 
    if (ch->power[DISC_DAEM_DISC] < 2)
    {
	stc("You must obtain a level two Mastery of Discord.\n\r",ch);
	return;
    }

    if ( arg1[0] == '\0' || arg2[0] == '\0' )
    {
        send_to_char( "Format is: evileye <option> <value>\n\r", ch );
        send_to_char( "Option ACTION is a text string action performed by you or the viewer.\n\r", ch );
        send_to_char( "Option MESSAGE is a text string shown to the person looking at you.\n\r", ch );
        send_to_char( "Option TOGGLE has values: spell, self, other.\n\r\n\r", ch );
	if ( ch->poweraction != NULL) {
	    sprintf(buf,"Current action: %s.\n\r",ch->poweraction);
	    send_to_char(buf,ch);}
	if ( ch->powertype != NULL) {
	    sprintf(buf,"Current message: %s.\n\r",ch->powertype);
	    send_to_char(buf,ch);}
	send_to_char("Current flags:",ch);
	if (IS_SET(ch->spectype,EYE_SPELL)) send_to_char(" Spell",ch);
	if (IS_SET(ch->spectype,EYE_SELFACTION)) send_to_char(" Self",ch);
	if (IS_SET(ch->spectype,EYE_ACTION)) send_to_char(" Other",ch);
	if (!IS_SET(ch->spectype,EYE_SPELL) &&
	    !IS_SET(ch->spectype,EYE_SELFACTION) &&
	    !IS_SET(ch->spectype,EYE_ACTION)) send_to_char(" None",ch);
	send_to_char(".\n\r",ch);
        return;
    }
    value = is_number( arg2 ) ? atoi( arg2 ) : -1;
    if ( !str_cmp( arg1, "action" ) )
    {
	free_string( ch->poweraction );
	ch->poweraction = str_dup( arg2 );
	return;
    }
    else if ( !str_cmp( arg1, "message" ) )
    {
	free_string( ch->powertype );
	ch->powertype = str_dup( arg2 );
	return;
    }
    else if ( !str_cmp( arg1, "toggle" ) )
    {
	if ( !str_cmp( arg2, "spell" ) && IS_SET(ch->spectype,EYE_SPELL))
	    REMOVE_BIT(ch->spectype,EYE_SPELL);
	else if ( !str_cmp( arg2, "spell" ) && !IS_SET(ch->spectype,EYE_SPELL))
	    SET_BIT(ch->spectype,EYE_SPELL);
	else if ( !str_cmp( arg2, "self" ) && IS_SET(ch->spectype,EYE_SELFACTION))
	    REMOVE_BIT(ch->spectype,EYE_SELFACTION);
	else if ( !str_cmp( arg2, "self" ) && !IS_SET(ch->spectype,EYE_SELFACTION))
	    SET_BIT(ch->spectype,EYE_SELFACTION);
	else if ( !str_cmp( arg2, "other" ) && IS_SET(ch->spectype,EYE_ACTION))
	    REMOVE_BIT(ch->spectype,EYE_ACTION);
	else if ( !str_cmp( arg2, "other" ) && !IS_SET(ch->spectype,EYE_ACTION))
	    SET_BIT(ch->spectype,EYE_ACTION);
	else {
	    send_to_char("TOGGLE flag should be one of: spell, self, other.\n\r",ch);
	    return;}
	sprintf(buf,"%s flag toggled.\n\r",capitalize(arg2));
	send_to_char(buf,ch);
	return;
    }
    else
    {
        send_to_char( "Format is: evileye <option> <value>\n\r", ch );
        send_to_char( "Option ACTION is a text string action performed by you or the viewer.\n\r", ch );
        send_to_char( "Option MESSAGE is a text string shown to the person looking at you.\n\r", ch );
        send_to_char( "Option TOGGLE has values: spell, self, other.\n\r\n\r", ch );
	if ( ch->poweraction != NULL) {
	    sprintf(buf,"Current action: %s.\n\r",ch->poweraction);
	    send_to_char(buf,ch);}
	if ( ch->powertype != NULL) {
	    sprintf(buf,"Current message: %s.\n\r",ch->powertype);
	    send_to_char(buf,ch);}
	send_to_char("Current flags:",ch);
	if (IS_SET(ch->spectype,EYE_SPELL)) send_to_char(" Spell",ch);
	if (IS_SET(ch->spectype,EYE_SELFACTION)) send_to_char(" Self",ch);
	if (IS_SET(ch->spectype,EYE_ACTION)) send_to_char(" Other",ch);
	if (!IS_SET(ch->spectype,EYE_SPELL) &&
	    !IS_SET(ch->spectype,EYE_SELFACTION) &&
	    !IS_SET(ch->spectype,EYE_ACTION)) send_to_char(" None",ch);
	send_to_char(".\n\r",ch);
    }
    return;
}

void do_clearvam( CHAR_DATA *ch, char *argument )
{
    if ( ch->trust < 8 )
    	send_to_char( "Huh?\n\r", ch );
    else
    	send_to_char( "If you want to CLEARVAMP, spell it out.\n\r", ch );
    return;
}


void do_clearvamp( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;

    char arg[MAX_INPUT_LENGTH];

    one_argument( argument, arg );

    if ( arg[0] == '\0' || is_number(arg) )
    {
	send_to_char( "Clear who's clan?\n\r", ch );
	return;
    }

    if ( ( victim = get_char_world( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( IS_NPC(victim) )
    {
	send_to_char( "Not on NPC's.\n\r", ch );
	return;
    }

    if (IS_SET(victim->act, PLR_GODLESS) && get_trust(ch) < NO_GODLESS
        && !IS_SET(ch->extra , EXTRA_ANTI_GODLESS))
    {
	send_to_char( "You failed.\n\r", ch );
	return;
    }

    if (IS_CLASS(victim,CLASS_VAMPIRE)) {
    do_mortalvamp(victim,"");
    free_string(victim->lord);
    victim->lord     = str_dup( "" );
    victim->generation     = 0;
    victim->pcdata->stats[UNI_AFF]     = 0;
    victim->pcdata->stats[UNI_CURRENT] = -1;

    REMOVE_BIT(victim->special, SPC_SIRE);
    REMOVE_BIT(victim->special, SPC_ANARCH);
    victim->rage = 0;
    victim->pcdata->rank = AGE_CHILDE;

    send_to_char( "Ok.\n\r", ch );
    return;

}

    if (IS_CLASS(victim,CLASS_WEREWOLF)) {
    free_string(victim->lord);
    victim->lord     = str_dup( "" );
    victim->generation     = 0;
    victim->pcdata->stats[UNI_AFF]     = 0;
    victim->pcdata->stats[UNI_CURRENT] = -1;
    victim->siltol = 0;
    victim->power[DISC_WERE_WOLF] = 0;
    victim->power[DISC_WERE_HAWK] = 0;
    victim->power[DISC_WERE_OWL] = 0;
    victim->power[DISC_WERE_BEAR] = 0;
    victim->power[DISC_WERE_SPID] = 0;
    victim->power[DISC_WERE_BOAR] = 0;
    victim->power[DISC_WERE_MANT] = 0;
    victim->power[DISC_WERE_LYNX] = 0;

    REMOVE_BIT(victim->special, SPC_SIRE);
    REMOVE_BIT(victim->special, SPC_ANARCH);
    REMOVE_BIT(victim->class, CLASS_WEREWOLF);


    send_to_char( "Ok.\n\r", ch );
    return;}
}

void do_artifact( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    OBJ_DATA *obj;
    OBJ_DATA *in_obj;
    bool found;

    if (IS_NPC(ch)) {send_to_char("Not while switched.\n\r",ch); return;}

    found = FALSE;
    for ( obj = object_list; obj != NULL; obj = obj->next )
    {
	if ( !IS_SET(obj->quest, QUEST_ARTIFACT) ) continue;

	found = TRUE;

	for ( in_obj = obj; in_obj->in_obj != NULL; in_obj = in_obj->in_obj )
	    ;

	if ( in_obj->carried_by != NULL )
	{
	    sprintf( buf, "%s carried by %s.\n\r",
		obj->short_descr, PERS(in_obj->carried_by, ch) );
	}
	else
	{
	    sprintf( buf, "%s in %s.\n\r",
		obj->short_descr, in_obj->in_room == NULL ? "somewhere" : in_obj->in_room->name );
	}

	buf[0] = UPPER(buf[0]);
	send_to_char( buf, ch );
    }

    if ( !found )
	send_to_char( "There are no artifacts in the game.\n\r", ch );

    return;
}

void do_locate( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    OBJ_DATA *obj;
    OBJ_DATA *in_obj;
    bool found;

    if (IS_NPC(ch)) {send_to_char("Not while switched.\n\r",ch); return;}

    found = FALSE;
    for ( obj = object_list; obj != NULL; obj = obj->next )
    {
	if ( !can_see_obj( ch, obj ) || obj->questowner == NULL || 
	    strlen(obj->questowner) < 2 || str_cmp( ch->pcdata->switchname, obj->questowner ))
	    continue;

	found = TRUE;

	for ( in_obj = obj; in_obj->in_obj != NULL; in_obj = in_obj->in_obj )
	    ;

	if ( in_obj->carried_by != NULL )
	{
	    sprintf( buf, "%s carried by %s.\n\r",
		obj->short_descr, PERS(in_obj->carried_by, ch) );
	}
	else
	{
	    sprintf( buf, "%s in %s.\n\r",
		obj->short_descr, in_obj->in_room == NULL
		    ? "somewhere" : in_obj->in_room->name );
	}

	buf[0] = UPPER(buf[0]);
	send_to_char( buf, ch );
    }

    if ( !found )
	send_to_char( "You cannot locate any items belonging to you.\n\r", ch );

    return;
}

void do_claim( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;

    one_argument( argument, arg );

    if (IS_NPC(ch)) {send_to_char("Not while switched.\n\r",ch); return;}

    if ( ch->exp < 500 ) {send_to_char("It costs 500 exp to claim ownership of an item.\n\r",ch); return;}

    if ( arg[0] == '\0' )
    {
	send_to_char( "What object do you wish to claim ownership of?\n\r", ch );
	return;
    }

    if ( ( obj = get_obj_carry(ch, arg) ) == NULL )
	{send_to_char("You are not carrying that item.\n\r",ch); return;}

    if (obj->item_type == ITEM_QUEST || obj->item_type == ITEM_AMMO ||
        obj->item_type == ITEM_EGG   || obj->item_type == ITEM_VOODOO ||
        obj->item_type == ITEM_MONEY || obj->item_type == ITEM_TREASURE ||
        obj->item_type == ITEM_PAGE  || IS_SET(obj->quest, QUEST_ARTIFACT))
    {
	send_to_char( "You cannot claim that item.\n\r", ch );
	return;
    }
/*    
if (!IS_SET(obj->spectype, SITEM_ADAMANTITE) &&
        !IS_SET(obj->spectype, SITEM_COPPER) &&
        !IS_SET(obj->spectype, SITEM_IRON) &&
        !IS_SET(obj->spectype, SITEM_STEEL))
{
send_to_char("You can only claim items forged from a rare metal.\n\r",ch);
return;
}
*/
 else if (obj->chobj != NULL && !IS_NPC(obj->chobj) &&
	obj->chobj->pcdata->obj_vnum != 0)
    {
	send_to_char( "You cannot claim that item.\n\r", ch );
	return;
    }

    if ( obj->questowner != NULL && strlen(obj->questowner) > 1 )
    {
	if (!str_cmp(ch->pcdata->switchname,obj->questowner))
	    send_to_char("But you already own it!\n\r",ch);
	else
	    send_to_char("Someone else has already claimed ownership to it.\n\r",ch);
	return;
    }

    ch->exp -= 500;
    if (obj->questowner != NULL) free_string(obj->questowner);
    obj->questowner = str_dup(ch->pcdata->switchname);
    act("You are now the owner of $p.",ch,obj,NULL,TO_CHAR);
    act("$n is now the owner of $p.",ch,obj,NULL,TO_ROOM);
    return;
}

void do_gift( CHAR_DATA *ch, char *argument )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;
    CHAR_DATA *victim;

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if (IS_NPC(ch)) {send_to_char("Not while switched.\n\r",ch); return;}

    if ( ch->exp < 500 ) {send_to_char("It costs 500 exp to make a gift of an item.\n\r",ch); return;}

    if ( arg1[0] == '\0' || arg2[0] == '\0' )
    {
	send_to_char( "Make a gift of which object to whom?\n\r", ch );
	return;
    }

    if ( ( obj = get_obj_carry(ch, arg1) ) == NULL )
	{send_to_char("You are not carrying that item.\n\r",ch); return;}
    if ( ( victim = get_char_room( ch, arg2 ) ) == NULL )
	{send_to_char("Nobody here by that name.\n\r",ch); return;}

    if ( IS_NPC(victim) )
    {
	send_to_char("Not on NPC's.\n\r",ch);
	return;
    }
    if ( obj->questowner == NULL || strlen(obj->questowner) < 2 )
    {
	send_to_char("That item has not yet been claimed.\n\r",ch);
	return;
    }
    if (str_cmp(ch->pcdata->switchname,obj->questowner))
    {
	send_to_char("But you don't own it!\n\r",ch);
	return;
    }
    ch->exp -= 500;
    if (obj->questowner != NULL) free_string(obj->questowner);
    obj->questowner = str_dup(victim->pcdata->switchname);
    act("You grant ownership of $p to $N.",ch,obj,victim,TO_CHAR);
    act("$n grants ownership of $p to $N.",ch,obj,victim,TO_NOTVICT);
    act("$n grants ownership of $p to you.",ch,obj,victim,TO_VICT);
    return;
}

void do_create( CHAR_DATA *ch, char *argument )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    OBJ_INDEX_DATA *pObjIndex;
    OBJ_DATA *obj;
    int itemtype = 13;
    int level;

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );
 
    if ( arg1[0] == '\0' )               itemtype = ITEM_TRASH;
    else if (!str_cmp(arg1,"light"    )) itemtype = ITEM_LIGHT;
    else if (!str_cmp(arg1,"scroll"   )) itemtype = ITEM_SCROLL;
    else if (!str_cmp(arg1,"wand"     )) itemtype = ITEM_WAND;
    else if (!str_cmp(arg1,"staff"    )) itemtype = ITEM_STAFF;
    else if (!str_cmp(arg1,"weapon"   )) itemtype = ITEM_WEAPON;
    else if (!str_cmp(arg1,"treasure" )) itemtype = ITEM_TREASURE;
    else if (!str_cmp(arg1,"armor"    )) itemtype = ITEM_ARMOR;
    else if (!str_cmp(arg1,"armour"   )) itemtype = ITEM_ARMOR;
    else if (!str_cmp(arg1,"potion"   )) itemtype = ITEM_POTION;
    else if (!str_cmp(arg1,"furniture")) itemtype = ITEM_FURNITURE;
    else if (!str_cmp(arg1,"trash"    )) itemtype = ITEM_TRASH;
    else if (!str_cmp(arg1,"container")) itemtype = ITEM_CONTAINER;
    else if (!str_cmp(arg1,"drink"    )) itemtype = ITEM_DRINK_CON;
    else if (!str_cmp(arg1,"key"      )) itemtype = ITEM_KEY;
    else if (!str_cmp(arg1,"food"     )) itemtype = ITEM_FOOD;
    else if (!str_cmp(arg1,"money"    )) itemtype = ITEM_MONEY;
    else if (!str_cmp(arg1,"boat"     )) itemtype = ITEM_BOAT;
    else if (!str_cmp(arg1,"corpse"   )) itemtype = ITEM_CORPSE_NPC;
    else if (!str_cmp(arg1,"fountain" )) itemtype = ITEM_FOUNTAIN;
    else if (!str_cmp(arg1,"pill"     )) itemtype = ITEM_PILL;
    else if (!str_cmp(arg1,"portal"   )) itemtype = ITEM_PORTAL;
    else if (!str_cmp(arg1,"egg"      )) itemtype = ITEM_EGG;
    else if (!str_cmp(arg1,"stake"    )) itemtype = ITEM_STAKE;
    else if (!str_cmp(arg1,"missile"  )) itemtype = ITEM_MISSILE;
    else                                 itemtype = ITEM_TRASH;

    if ( arg2[0] == '\0' || !is_number( arg2 ) )
    {
	level = 0;
    }
    else
    {
        level = atoi( arg2 );
	if ( level < 1 || level > 50 )
        {
	    send_to_char( "Level should be within range 1 to 50.\n\r", ch );
	    return;
        }
    }

    if ( ( pObjIndex = get_obj_index( OBJ_VNUM_PROTOPLASM ) ) == NULL )
    {
	send_to_char( "Error...missing object, please inform KaVir.\n\r", ch );
	return;
    }

    obj = create_object( pObjIndex, level );
    obj->level = level;
    obj->item_type = itemtype;
    obj_to_char(obj,ch);
    if (obj->questmaker != NULL) free_string(obj->questmaker);
    obj->questmaker = str_dup(ch->name);

    act( "You reach up into the air and draw out a ball of protoplasm.", ch, obj, NULL, TO_CHAR );
    act( "$n reaches up into the air and draws out a ball of protoplasm.", ch, obj, NULL, TO_ROOM );
    return;
}

void do_dtoken( CHAR_DATA *ch, char *argument )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    OBJ_INDEX_DATA *pObjIndex;
    OBJ_DATA *obj;
    CHAR_DATA *victim;
    int value;

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

if ( !IS_NPC(ch) && IS_CLASS(ch, CLASS_DROW) ) 
	return;
 
    if ( IS_NPC(ch) || (ch->pcdata->stats[DEMON_CURRENT] < 1 && !IS_CREATOR(ch)) )
    {
	send_to_char("You are unable to make a demonic token.\n\r",ch);
	return;
    }

    else if ( arg1[0] == '\0' || !is_number( arg1 ) )
    {
	send_to_char("Please specify a value for the demonic token.\n\r",ch);
	return;
    }
    else
    {
        value = atoi( arg1 );
	if ( value < 1 || value > 150 )
        {
	    send_to_char( "Demonic tokens should have a value between 1 and 150.\n\r", ch );
	    return;
        }
	else if ( value > ch->pcdata->stats[DEMON_CURRENT] && !IS_CREATOR(ch) )
        {
	    sprintf(buf,"You only have %d demon points left to put into tokens.\n\r",ch->pcdata->stats[DEMON_CURRENT]);
	    send_to_char( buf, ch );
	    return;
        }
    }

    victim = get_char_room( ch, arg2 );

    if ( ( pObjIndex = get_obj_index( OBJ_VNUM_PROTOPLASM ) ) == NULL )
    {
	send_to_char( "Error...missing object, please inform KaVir.\n\r", ch );
	return;
    }

    ch->pcdata->stats[DEMON_CURRENT] -= value;
    if (ch->pcdata->stats[DEMON_CURRENT] < 0)
      ch->pcdata->stats[DEMON_CURRENT] = 0;
    obj = create_object( pObjIndex, value );
    obj->value[0] = value;
    obj->level = 1;
    obj->cost = value*1000;
    obj->item_type = ITEM_DTOKEN;
    obj_to_char(obj,ch);
    if (obj->questmaker != NULL) free_string(obj->questmaker);
    obj->questmaker = str_dup(ch->name);
    free_string( obj->name );
    obj->name = str_dup( "demonic token" );
    sprintf(buf,"a %d point demonic token",value);
    free_string( obj->short_descr );
    obj->short_descr = str_dup( buf );
    sprintf(buf,"A %d point demonic token lies on the floor.",value);
    free_string( obj->description );
    obj->description = str_dup( buf );
    if (victim != NULL && victim != ch)
    {
    	act( "You pull $p out of $N's ass.", ch, obj, victim, TO_CHAR );
    	act( "$n pulls $p out of $s ass.", ch, obj, victim, TO_NOTVICT );
    	act( "$n pulls $p out of $N's ass.", ch, obj, victim, TO_VICT );
    }
    else
    { 
    	act( "You grin wickedly and produce $p.", ch, obj, NULL, TO_CHAR );
    	act( "$n grins wickedly as $e produces $p.", ch, obj, NULL, TO_ROOM );
    }
    return;
}

void do_token( CHAR_DATA *ch, char *argument )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    OBJ_INDEX_DATA *pObjIndex;
    OBJ_DATA *obj;
    CHAR_DATA *victim;
    int value;

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );
 
    if ( IS_NPC(ch) || (ch->pcdata->quest < 1 && !IS_JUDGE(ch)) )
    {
	send_to_char("You are unable to make a quest token.\n\r",ch);
	return;
    }
    else if ( arg1[0] == '\0' || !is_number( arg1 ) )
    {
	send_to_char("Please specify a value for the quest token.\n\r",ch);
	return;
    }
    else
    {
        value = atoi( arg1 );
	if ( value < 1 || value > 100 )
        {
	    send_to_char( "Quest token should have a value between 1 and 50.\n\r", ch );
	    return;
        }
	else if ( value > ch->pcdata->quest && !IS_JUDGE(ch) )
        {
	    sprintf(buf,"You only have %d quest points left to put into tokens.\n\r",ch->pcdata->quest);
	    send_to_char( buf, ch );
	    return;
        }
    }

    victim = get_char_room( ch, arg2 );

    if ( ( pObjIndex = get_obj_index( OBJ_VNUM_PROTOPLASM ) ) == NULL )
    {
	send_to_char( "Error...missing object, please inform Trace.\n\r",
ch );
	return;
    }

    ch->pcdata->quest -= value;
    if (ch->pcdata->quest < 0) ch->pcdata->quest = 0;
    obj = create_object( pObjIndex, value );
    obj->value[0] = value;
    obj->level = 1;
    obj->cost = value*1000;
    obj->item_type = ITEM_QUEST;
    obj_to_char(obj,ch);
    if (obj->questmaker != NULL) free_string(obj->questmaker);
    obj->questmaker = str_dup(ch->name);
    free_string( obj->name );
    obj->name = str_dup( "quest token" );
    sprintf(buf,"a %d point quest token",value);
    free_string( obj->short_descr );
    obj->short_descr = str_dup( buf );
    sprintf(buf,"A %d point quest token lies on the floor.",value);
    free_string( obj->description );
    obj->description = str_dup( buf );
    if (victim != NULL && victim != ch)
    {
    	act( "You reach behind $N's ear and produce $p.", ch, obj, victim, TO_CHAR );
    	act( "$n reaches behind $N's ear and produces $p.", ch, obj, victim, TO_NOTVICT );
    	act( "$n reaches behind your ear and produces $p.", ch, obj, victim, TO_VICT );
    }
    else
    {
    	act( "You snap your fingers and reveal $p.", ch, obj, NULL, TO_CHAR );
    	act( "$n snaps $s fingers and reveals $p.", ch, obj, NULL, TO_ROOM );
    }
    return;
}



void do_qtrust( CHAR_DATA *ch, char *argument )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if ( arg1[0] == '\0' )
    {
	send_to_char( "Syntax: qtrust <char> <on/off>.\n\r", ch );
	return;
    }

    if ( arg2[0] == '\0' )
    {
	send_to_char( "Do you wish to set qtrust ON or OFF?\n\r", ch );
	return;
    }

    if ( ( victim = get_char_room( ch, arg1 ) ) == NULL )
    {
	send_to_char( "That player is not here.\n\r", ch);
	return;
    }

    if (str_cmp(arg2,"on") && str_cmp(arg2,"off"))
    {
	send_to_char( "Do you want to set their qtrust ON or OFF?\n\r", ch);
	return;
    }
    if (!str_cmp(arg2,"off"))
    {
	if (!IS_EXTRA(victim, EXTRA_TRUSTED))
	{
	    send_to_char("Their qtrust is already off.\n\r",ch);
	    return;
	}
	REMOVE_BIT(victim->extra, EXTRA_TRUSTED);
	send_to_char("Quest trust OFF.\n\r",ch);
	send_to_char("You are no longer quest trusted.\n\r",victim);
	return;
    }
    else if (!str_cmp(arg2,"on"))
    {
	if (IS_EXTRA(victim, EXTRA_TRUSTED))
	{
	    send_to_char("Their qtrust is already on.\n\r",ch);
	    return;
	}
	SET_BIT(victim->extra, EXTRA_TRUSTED);
	send_to_char("Quest trust ON.\n\r",ch);
	send_to_char("You are now quest trusted.\n\r",victim);
	return;
    }
    return;
}

/*
void do_ntrust( CHAR_DATA *ch, char *argument )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if ( arg1[0] == '\0' )
    {
	send_to_char( "Syntax: ntrust <char> <on/off>.\n\r", ch );
	return;
    }

    if ( arg2[0] == '\0' )
    {
	send_to_char( "Do you wish to set ntrust ON or OFF?\n\r", ch );
	return;
    }

    if ( ( victim = get_char_room( ch, arg1 ) ) == NULL )
    {
	send_to_char( "That player is not here.\n\r", ch);
	return;
    }

    if (str_cmp(arg2,"on") && str_cmp(arg2,"off"))
    {
	send_to_char( "Do you want to set their ntrust ON or OFF?\n\r",ch);
	return;
    }
    if (!str_cmp(arg2,"off"))
    {
	if (!IS_EXTRA(victim, EXTRA_TRUSTED))
	{
	    send_to_char("Their ntrust is already off.\n\r",ch);
	    return;
	}
	REMOVE_BIT(victim->extra, EXTRA_NOTE_TRUST);
	send_to_char("Note trust OFF.\n\r",ch);
	send_to_char("You are no longer note trusted.\n\r",victim);
	return;
    }
    else if (!str_cmp(arg2,"on"))
    {
	if (IS_EXTRA(victim, EXTRA_NOTE_TRUST))
	{
	    send_to_char("Their ntrust is already on.\n\r",ch);
	    return;
	}
	SET_BIT(victim->extra, EXTRA_NOTE_TRUST);
	send_to_char("Note trust ON.\n\r",ch);
	send_to_char("You are now note trusted.\n\r",victim);
	return;
    }
    return;
}
*/
void do_mclear( CHAR_DATA *ch, char *argument )
{
    OBJ_DATA *obj;
    OBJ_DATA *obj_next;
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;

    argument = one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char( "Syntax: mclear <char>.\n\r", ch );
	return;
    }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "That player is not here.\n\r", ch);
	return;
    }

    if (IS_NPC(victim))
    {
	send_to_char( "Not on NPC's.\n\r", ch);
	return;
    }

    if (IS_SET(victim->act, PLR_GODLESS) && get_trust(ch) < NO_GODLESS
        && !IS_SET(ch->extra , EXTRA_ANTI_GODLESS))
    {
	send_to_char( "You failed.\n\r", ch );
	return;
    }

    for ( obj = victim->carrying; obj != NULL; obj = obj_next )
    {
	obj_next = obj->next_content;
	if ( obj->wear_loc != WEAR_NONE ) 
	{obj_from_char(obj); obj_to_char(obj,victim);}
    }
    while ( victim->affected )
	affect_remove( victim, victim->affected );
    if (IS_AFFECTED(victim,AFF_POLYMORPH) && IS_AFFECTED(victim,AFF_ETHEREAL))
    {
    	victim->affected_by	= AFF_POLYMORPH + AFF_ETHEREAL;
    }
    else if (IS_AFFECTED(victim,AFF_POLYMORPH))
    	victim->affected_by	= AFF_POLYMORPH;
    else if (IS_AFFECTED(victim,AFF_ETHEREAL))
    	victim->affected_by	= AFF_ETHEREAL;
    else
    	victim->affected_by	= 0;
    victim->armor	 = 100;
    victim->hit		 = UMAX( 1, victim->hit  );
    victim->mana	 = UMAX( 1, victim->mana );
    victim->move	 = UMAX( 1, victim->move );
    victim->hitroll	 = 0;
    victim->damroll	 = 0;
    victim->saving_throw = 0;
    victim->pcdata->mod_str = 0;
    victim->pcdata->mod_int = 0;
    victim->pcdata->mod_wis = 0;
    victim->pcdata->mod_dex = 0;
    victim->pcdata->mod_con = 0;
    victim->pcdata->followers = 0;
    save_char_obj( victim );
    send_to_char("Your stats have been cleared.  Please rewear your equipment.\n\r",victim);
    send_to_char("Ok.\n\r",ch);
    return;
}

void do_clearstats( CHAR_DATA *ch, char *argument )
{
    OBJ_DATA *obj;
    OBJ_DATA *obj_next;
if (IS_NPC(ch)) return;
    if (ch->in_room == NULL || ch->in_room->vnum != 3054)
    {
	send_to_char("You can only clear your stats at the Temple Altar of Midgaard.\n\r",ch);
	return;
    }

    for ( obj = ch->carrying; obj != NULL; obj = obj_next )
    {
	obj_next = obj->next_content;
	if ( obj->wear_loc != WEAR_NONE ) 
	{obj_from_char(obj); obj_to_char(obj,ch);}
    }
    while ( ch->affected )
	affect_remove( ch, ch->affected );
    if (IS_AFFECTED(ch,AFF_POLYMORPH) && IS_AFFECTED(ch,AFF_ETHEREAL))
    {
    	ch->affected_by	 = AFF_POLYMORPH + AFF_ETHEREAL;
    }
    else if (IS_AFFECTED(ch,AFF_POLYMORPH))
    	ch->affected_by	 = AFF_POLYMORPH;
    else if (IS_AFFECTED(ch,AFF_ETHEREAL))
    	ch->affected_by	 = AFF_ETHEREAL;
    else
    	ch->affected_by	 = 0;
    ch->armor		 = 100;
    ch->hit		 = UMAX( 1, ch->hit  );
    ch->mana		 = UMAX( 1, ch->mana );
    ch->move		 = UMAX( 1, ch->move );
    ch->hitroll		 = 0;
    ch->damroll		 = 0;
    ch->saving_throw	 = 0;
    ch->pcdata->mod_str	 = 0;
    ch->pcdata->mod_int	 = 0;
    ch->pcdata->mod_wis	 = 0;
    ch->pcdata->mod_dex	 = 0;
    ch->pcdata->mod_con	 = 0;
    save_char_obj( ch );
    send_to_char("Your stats have been cleared.  Please rewear your equipment.\n\r",ch);
    return;
}

void do_otransfer( CHAR_DATA *ch, char *argument )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;
    CHAR_DATA *victim;
    ROOM_INDEX_DATA *chroom;
    ROOM_INDEX_DATA *objroom;

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );
 
    if ( arg1[0] == '\0' )
    {
        send_to_char( "Otransfer which object?\n\r", ch );
        return;
    }

    if ( arg2[0] == '\0' ) victim = ch;
    else if ( ( victim = get_char_world( ch, arg2 ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( ( obj = get_obj_world( ch, arg1 ) ) == NULL )
    {
	send_to_char( "Nothing like that in hell, earth, or heaven.\n\r", ch );
	return;
    }

    if (!IS_JUDGE(ch) && (obj->questmaker == NULL || 
	str_cmp(ch->name,obj->questmaker) || strlen(obj->questmaker) < 2))
    {
	send_to_char("You don't have permission to otransfer that item.\n\r", ch);
	return;
    }

    if (obj->carried_by != NULL)
    {
	if (!IS_NPC(obj->carried_by) && IS_SET(obj->carried_by->act,PLR_GODLESS) && get_trust(ch) < NO_GODLESS
        && !IS_SET(ch->extra , EXTRA_ANTI_GODLESS))
	{
	    send_to_char("You failed.\n\r",ch);
	    act("$p flickers briefly with energy.",obj->carried_by,obj,NULL,TO_CHAR);
	    return;
	}
	act("$p vanishes from your hands in an explosion of energy.",obj->carried_by,obj,NULL,TO_CHAR);
	act("$p vanishes from $n's hands in an explosion of energy.",obj->carried_by,obj,NULL,TO_ROOM);
	obj_from_char(obj);
    }
    else if (obj->in_obj     != NULL) obj_from_obj(obj);
    else if (obj->in_room != NULL)
    {
    	chroom = ch->in_room;
    	objroom = obj->in_room;
    	char_from_room(ch);
    	char_to_room(ch,objroom);
    	act("$p vanishes from the ground in an explosion of energy.",ch,obj,NULL,TO_ROOM);
	if (chroom == objroom) act("$p vanishes from the ground in an explosion of energy.",ch,obj,NULL,TO_CHAR);
    	char_from_room(ch);
    	char_to_room(ch,chroom);
	obj_from_room(obj);
    }
    else
    {
	send_to_char( "You were unable to get it.\n\r", ch );
	return;
    }
    obj_to_char(obj,victim);
    act("$p appears in your hands in an explosion of energy.",victim,obj,NULL,TO_CHAR);
    act("$p appears in $n's hands in an explosion of energy.",victim,obj,NULL,TO_ROOM);
    return;
}

void bind_char( CHAR_DATA *ch )
{
    OBJ_DATA *obj;
    OBJ_INDEX_DATA *pObjIndex;
    ROOM_INDEX_DATA *location;

    if ( IS_NPC(ch) || ch->pcdata->obj_vnum < 1 )
	return;

    if ( ( pObjIndex = get_obj_index( ch->pcdata->obj_vnum ) ) == NULL )
	return;

    if ( ch->in_room == NULL || ch->in_room->vnum == ROOM_VNUM_IN_OBJECT )
    {
	location = get_room_index(ROOM_VNUM_ALTAR);
    	char_from_room(ch);
    	char_to_room(ch,location);
    }
    else location = ch->in_room;

    obj = create_object( pObjIndex, 50 );
    obj_to_room(obj,location);
    obj->chobj = ch;
    ch->pcdata->chobj = obj;
    SET_BIT(ch->affected_by, AFF_POLYMORPH);
    SET_BIT(ch->extra, EXTRA_OSWITCH);
    free_string(ch->morph);
    ch->morph = str_dup(obj->short_descr);
    send_to_char( "You reform yourself.\n\r", ch );
    act("$p fades into existance on the floor.",ch,obj,NULL,TO_ROOM);
    do_look(ch,"auto");
    return;
}

void do_bind( CHAR_DATA *ch, char *argument )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;
    CHAR_DATA *victim;

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if ( arg1[0] == '\0' || arg2[0] == '\0' )
    {
	send_to_char( "Syntax: bind <player> <object>\n\r", ch );
	return;
    }

    if ( ( victim = get_char_room( ch, arg1 ) ) == NULL )
    {
	send_to_char( "That player is not here.\n\r", ch);
	return;
    }
    if (ch == victim)
    {
	send_to_char( "You can't do this to yourself.\n\r", ch);
	return;
    }
    if (IS_NPC(victim))
    {
	send_to_char( "Not on NPC's.\n\r", ch);
	return;
    }
    else if (IS_AFFECTED(victim,AFF_POLYMORPH))
    {
	send_to_char( "You cannot do this while they are polymorphed.\n\r", ch);
	return;
    }
    else if (IS_IMMORTAL(victim))
    {
	send_to_char( "Only on mortals or avatars.\n\r", ch);
	return;
    }
    else if (IS_SET(victim->act, PLR_GODLESS) && get_trust(ch) < NO_GODLESS
        && !IS_SET(ch->extra , EXTRA_ANTI_GODLESS))
    {
	send_to_char( "You failed.\n\r", ch );
	return;
    }
    if ( ( obj = get_obj_carry( ch, arg2) ) == NULL )
    {
	send_to_char("You are not carrying that item.\n\r",ch);
	return;
    }
    if (obj->questmaker != NULL && strlen(obj->questmaker) > 1)
    {
	send_to_char("You cannot bind someone into a modified item.\n\r",ch);
	return;
    }
    if (obj->chobj != NULL)
    {
	send_to_char( "That item already has someone bound in it.\n\r", ch);
	return;
    }
    send_to_char("Ok.\n\r",ch);
    act("$n transforms into a white vapour and pours into $p.",victim,obj,NULL,TO_ROOM);
    act("You transform into a white vapour and pour into $p.",victim,obj,NULL,TO_CHAR);
    victim->pcdata->obj_vnum = obj->pIndexData->vnum;
    obj->chobj = victim;
    victim->pcdata->chobj = obj;
    SET_BIT(victim->affected_by, AFF_POLYMORPH);
    SET_BIT(victim->extra, EXTRA_OSWITCH);
    free_string(victim->morph);
    victim->morph = str_dup(obj->short_descr);
    return;
}

void do_release( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;
    CHAR_DATA *victim;

    argument = one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char( "Syntax: release <object>\n\r", ch );
	return;
    }

    if ( ( obj = get_obj_carry( ch, arg) ) == NULL )
    {
	send_to_char("You are not carrying that item.\n\r",ch);
	return;
    }
    if ( (victim = obj->chobj) == NULL)
    {
	send_to_char( "There is nobody bound in that item.\n\r", ch);
	return;
    }
    send_to_char("Ok.\n\r",ch);
    victim->pcdata->obj_vnum = 0;
    obj->chobj = NULL;
    victim->pcdata->chobj = NULL;
    REMOVE_BIT(victim->affected_by, AFF_POLYMORPH);
    REMOVE_BIT(victim->extra, EXTRA_OSWITCH);
    free_string(victim->morph);
    victim->morph = str_dup("");
    act("A white vapour pours out of $p and forms into $n.",victim,obj,NULL,TO_ROOM);
    act("Your spirit floats out of $p and reforms its body.",victim,obj,NULL,TO_CHAR);
    return;
}


void do_morph( CHAR_DATA *ch, char *argument )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;
    OBJ_DATA *morph;
    int mnum;

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if ( arg1[0] == '\0' )
    {
	send_to_char( "Syntax: morph <object> <form>\n\r", ch );
	return;
    }

    if ( ( obj = get_obj_wear( ch, arg1) ) == NULL )
    {
    	if ( ( obj = get_obj_carry( ch, arg1) ) == NULL )
	{
	    send_to_char("You are not carrying that item.\n\r",ch);
	    return;
	}
    }

    if ( !IS_SET(obj->spectype, SITEM_MORPH) )
    {
	send_to_char("That item cannot morph.\n\r",ch);
	return;
    }

    if ( arg2[0] == '\0' )
    {
	act("$p can morph into the following forms:",ch,obj,NULL,TO_CHAR);
	show_list_to_char( obj->contains, ch, TRUE, TRUE );
	return;
    }

    if ( ( morph = get_obj_list( ch, arg2, obj->contains ) ) == NULL )
    {
	send_to_char("It cannot assume that form.\n\r",ch);
	return;
    }
    obj_from_obj( morph );
    obj_to_char( morph, ch );
    act( "$p morphs into $P in $n's hands!", ch, obj, morph, TO_ROOM );
    act( "$p morphs into $P in your hands!", ch, obj, morph, TO_CHAR );
    mnum = obj->wear_loc;
    obj_from_char( obj );
    obj_to_obj( obj, morph );
    if ( morph->wear_flags == obj->wear_flags && mnum != WEAR_NONE )
	equip_char( ch, morph, mnum );
    return;
}

void do_clannum(CHAR_DATA *ch, char *argument) {

	CHAR_DATA *victim;
	char arg1[MAX_STRING_LENGTH];
	char arg2[MAX_STRING_LENGTH];
	int value;

	if (IS_NPC(ch)) return;

	argument = one_argument(argument, arg1);
	argument = one_argument(argument, arg2);


	if (arg1[0] == '\0' || arg2[0] == '\0') {
	send_to_char("#7Syntax:  clannum [char] [number]\n\r#7Set who to what clan?\n\r", ch );
       	return;}

	value = is_number(arg2) ? atoi(arg2) : -1;

	if ((victim = get_char_world(ch,arg1)) == NULL) {
	send_to_char("They are not here.\n\r", ch );
	return;}

	if (IS_NPC(victim)) {
	send_to_char("Not on NPCs.\n\r", ch );
	return;}

	if (value < 0 || value > MAX_KINGDOM) {
	send_to_char("That is an invalid number.\n\r", ch );
	return;}

	victim->pcdata->kingdom = value;
	send_to_char("Clannum changed.\n\r", ch );
	if (IS_SET(victim->special, SPC_PRINCE))
	REMOVE_BIT(victim->special, SPC_PRINCE);
	send_to_char("Your clan has been changed.\n\r", victim);
	save_char_obj(victim);
	return;
}
	

void do_clanset(CHAR_DATA *ch, char *argument) {

	char arg1[MAX_STRING_LENGTH];
	char arg2[MAX_STRING_LENGTH];
	int value;
	char *arg3;

	smash_tilde(argument);
	argument = one_argument(argument, arg1);
	argument = one_argument(argument, arg2);
	arg3 = argument;

	if (IS_NPC(ch)) return;

	if (arg1[0] == '\0' || arg2[0] == '\0' || arg3[0] == '\0') {

	send_to_char("Syntax:  clanset [clannum] [thing] [value]\n\r\n\r", ch );
	send_to_char("things:  name, whoname, leader, recall, altar\n\r\n\r", ch );
	return;}

	value = is_number(arg1) ? atoi(arg1) : -1;

	if (value < 0 || value > MAX_KINGDOM) {
	send_to_char("That is an invalid clan number.\n\r", ch );
	return;}

	if (!str_cmp(arg2,"name")) {
	free_string(king_table[value].name); 
	king_table[value].name = str_dup(arg3);}
	else if (!str_cmp(arg2,"whoname")) {
	free_string(king_table[value].who_name);
	king_table[value].who_name = str_dup(arg3);}
	else if (!str_cmp(arg2,"leader")) {
	free_string(king_table[value].leader_name);
	king_table[value].leader_name = str_dup(arg3);}
	else if (!str_cmp(arg2,"recall") &&  atoi(arg3) >= 0 ) {
	king_table[value].recall = atoi(arg3);}
	else if (!str_cmp(arg2,"altar") && atoi(arg3) >= 0) {
	king_table[value].altar = atoi(arg3);}
	else 
		send_to_char("Nothing set.\n\r", ch );

	send_to_char("Done.\n\r", ch );
	save_kingdoms();
	return;
}

void do_playerlist( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    CHAR_DATA *gch;


    if (IS_NPC(ch)) return;

    sprintf( buf, "Current player stats:\n\r");
    send_to_char( buf, ch );
    send_to_char("[      Name      ] [   Hp/Max  ] [ Mana/Max  ] [ Move/Max  ] [  Exp  ] [W Arena L] [W Wrestling L]\n\r", ch );
    for ( gch = char_list; gch != NULL; gch = gch->next )
    {
        if ( IS_NPC(gch) ) continue;
        if ( !IS_NPC(gch) )
        {
            sprintf( buf,
            "[%-16s] [%-5d/%-5d] [%-5d/%-5d] [%-5d/%-5d] [%7d] [%-3d   %-3d] [%-5d     %-3d]\n\r",
                capitalize( gch->name ),

		gch->hit,gch->max_hit,gch->mana,gch->max_mana,gch->move,gch->max_move,gch->exp,
		gch->pcdata->awins,gch->pcdata->alosses,gch->pcdata->wwins,gch->pcdata->wlosses);
                send_to_char( buf, ch );
        }
    }
    return;
}





#include <types.h>


#else


#include <sys/types.h>


#include <sys/time.h>


#endif


#include <stdio.h>


#include <string.h>


#include <stdlib.h>


#include <ctype.h>


#include <time.h>


#include "merc.h"





DECLARE_DO_FUN(do_look     );


int	arena;





/*=======================================================================*


 * function: do_challenge                                                *


 * purpose: sends initial arena match query                              *


 * written by: Doug Araya (whiplash@tft.nacs.net) 6-10-96                *


 *=======================================================================*/


void do_challenge(CHAR_DATA *ch, char *argument)


{


  CHAR_DATA *victim; 


  char buf[MAX_STRING_LENGTH]; 


  DESCRIPTOR_DATA *d;








/* == First make all invalid checks == */


 if(IS_NPC(ch))


  return; 





 if( arena == FIGHT_START )


  {


  send_to_char("Sorry, some one else has already started a challenge, please try later.\n\r",ch);


  return;


  }





 if( arena == FIGHT_BUSY )


  {


  send_to_char("Sorry, there is a fight in progress, please wait a few moments.\n\r",ch);


  return; 


  }





 if( arena == FIGHT_LOCK )


  {


  send_to_char("Sorry, the arena is currently locked from use.\n\r",ch);


  return;


  }





 if(IS_SET(ch->act,PLR_CHALLENGED))


  {


  send_to_char("You have already been challenged, either AGREE or DECLINE first.\n\r",ch);


  return; 


  }





 if(ch->hit < ch->max_hit)


  {


  send_to_char("You must be fully healed to fight in the arena.\n\r",ch);


  return;


  }








 if(argument[0] == '\0')


  {


  send_to_char("You must specify whom you wish to challenge.\n\r",ch);


  return;


  }





 if((victim = get_char_world(ch,argument)) == NULL)


  {


  send_to_char("They are not playing.\n\r",ch);


  return;


  }











 if(IS_NPC(victim) || IS_IMMORTAL(victim) || victim == ch )


  {


  send_to_char("You cannot challenge NPC's or yourself.\n\r",ch);


  return;


  }








 if(IS_SET(victim->act,PLR_CHALLENGER))


  {


  send_to_char("They have already challenged someone else.\n\r",ch);


  return;


  }





 if(victim->fighting != NULL )


  {


  send_to_char("That person is engaged in battle right now.\n\r",ch); 


  return; 


  }





 if(victim->hit < victim->max_hit)


  {


  send_to_char("That player is not healthy enough to fight right now.\n\r",ch);


  return;


  }








 if ( victim->desc == NULL )


  {


  send_to_char("That player is linkdead at the moment, try them later.\n\r",ch);


  return;


  }








/* == Now for the challenge == */


 ch->challenged = victim;


 SET_BIT(ch->act,PLR_CHALLENGER);


 victim->challenger = ch;


 SET_BIT(victim->act,PLR_CHALLENGED);


 arena = FIGHT_START;


 send_to_char("Challenge has been sent\n\r",ch);


 act("$n has challenged you to a death match.",ch,NULL,victim,TO_VICT);


 sprintf(buf,"[Arena] %s has challenged %s to a duel.\n\r",


         ch->name, victim->name);


 for ( d = descriptor_list; d; d = d->next )


  {


    if( d->connected == CON_PLAYING)


     {


	ADD_COLOUR(ch,buf,L_RED);


        send_to_char( buf, d->character );


     }


  }


 sprintf(buf,"type: AGREE %s to meet the challenge.\n\r",ch->name);


 send_to_char(buf,victim);


 sprintf(buf,"type: DECLINE %s to chicken out.\n\r",ch->name); 


 send_to_char(buf,victim);


 return;


}





/*=======================================================================*


 * function: do_accept                                                   *


 * purpose: to accept the arena match, and move the players to the arena *


 * written by: Doug Araya (whiplash@tft.nacs.net) 6-10-96                *


 *=======================================================================*/


void do_agree(CHAR_DATA *ch, char *argument)


{





 float odd1, odd2;


 float lvl1, lvl2;


 DESCRIPTOR_DATA *d;


 CHAR_DATA *victim; 


 char buf1[MAX_STRING_LENGTH]; 


 char buf2[MAX_STRING_LENGTH];


 char buf3[MAX_STRING_LENGTH];


 int char_room; 


 int vict_room; 





 /*== the room VNUM's for our arena.are ==*/


 /* we use 1051 thru 1066 for a 4x4 arena */


 char_room = number_range(50,68);


 vict_room = number_range(50,68);





/* == first make all invalid checks == */


 if(IS_NPC(ch))


 return;





 if( !IS_SET(ch->act,PLR_CHALLENGED) )


  {


  send_to_char("You have not been challenged.\n\r",ch);


  return;


  }





 if( arena == FIGHT_BUSY )


  {


  send_to_char("Sorry, there is a fight in progress, please wait a few moments.\n\r",ch);


  return;


  }





 if( arena == FIGHT_LOCK )


  {


  send_to_char("Sorry, the arena is currently locked from use.\n\r",ch);


  return;


  }





 if(argument[0]=='\0')


  {


  send_to_char("You must specify whose challenge you wish to accept.\n\r",ch);


  return;


  }





 if((victim = get_char_world(ch,argument)) == NULL)


  {


  send_to_char("They aren't logged in!\n\r",ch);


  return;


  }





 if(victim == ch)


  {


  send_to_char("You haven't challenged yourself!\n\r",ch);


  return;


  }





 if(!IS_SET(victim->act,PLR_CHALLENGER) || victim != ch->challenger )


  {


  send_to_char("That player hasn't challenged you!\n\r",ch); 


  return; 


  }





/* == now get to business == */


send_to_char("You have accepted the challenge!\n\r",ch);


act("$n accepts your challenge!",ch,NULL,victim,TO_VICT);


/* == announce the upcoming event == */


lvl1 = ch->hit;


lvl2 = victim->hit;


odd1 = ( lvl1 / lvl2 );


odd2 = ( lvl2 / lvl1 );


sprintf(buf1,


"[Arena] %s (%d wins) (%d losses) Payoff odds %f\n\r",


 victim->name,victim->pcdata->awins,victim->pcdata->alosses, odd1 );


sprintf(buf2,


"[Arena] %s (%d wins) (%d losses) Payoff odds %f\n\r", 


 ch->name,ch->pcdata->awins,ch->pcdata->alosses, odd2 ); 


strcpy(buf3,


"[Arena] To wager on the fight, type: bet (amount) (player name)\n\r");


for ( d = descriptor_list; d; d = d->next )


  {


     if( d->connected == CON_PLAYING)


     {


	ADD_COLOUR(ch,buf1,L_RED);


	ADD_COLOUR(ch,buf2,L_RED);


	ADD_COLOUR(ch,buf3,L_RED);


        send_to_char( buf1, d->character );


        send_to_char( buf2, d->character );


        send_to_char( buf3, d->character );


        d->character->gladiator = NULL;


     }


  }


/* == now move them both to an arena for the fun == */


send_to_char("You make your way into the arena.\n\r",ch);


char_from_room(ch); 


char_to_room(ch,get_room_index(char_room));


do_look(ch, "auto");


send_to_char("You make your way to the arena.\n\r",victim); 


char_from_room(victim); 


char_to_room(victim,get_room_index(vict_room)); 


do_look(victim, "auto");


arena = FIGHT_BUSY; 


return; 


}





/*=======================================================================*


 * function: do_decline                                                  *


 * purpose: to chicken out from a sent arena challenge                   *


 * written by: Doug Araya (whiplash@tft.nacs.net) 6-10-96                *


 *=======================================================================*/


void do_decline(CHAR_DATA *ch, char *argument )


{


  CHAR_DATA *victim; 


  char buf[MAX_STRING_LENGTH];


  DESCRIPTOR_DATA *d;








/*== make all invalid checks == */


  if(IS_NPC(ch))


   return;





 if( !IS_SET(ch->act,PLR_CHALLENGED) )


  {


  send_to_char("You have not been challenged.\n\r",ch);


  return;


  }





 if(argument[0]=='\0')


  {


  send_to_char("You must specify whose challenge you wish to decline.\n\r",ch);


  return;


  }


  


 if((victim = get_char_world(ch,argument)) == NULL)


  {


  send_to_char("They aren't logged in!\n\r",ch);


  return;


  }





 if(!IS_SET(victim->act,PLR_CHALLENGER) || victim != ch->challenger )


  {


  send_to_char("That player hasn't challenged you.\n\r",ch);


  return;


  }





 if(victim == ch)


 return; 





/*== now actually decline == */


victim->challenged = NULL;


REMOVE_BIT(victim->act,PLR_CHALLENGER); 


ch->challenger = NULL;


REMOVE_BIT(ch->act,PLR_CHALLENGED);


arena = FIGHT_OPEN;


send_to_char("Challenge declined!\n\r",ch);


act("$n has declined your challenge.",ch,NULL,victim,TO_VICT);


sprintf(buf,"[Arena] %s has declined %s's challenge.\n\r",


        ch->name, victim->name);


 for ( d = descriptor_list; d; d = d->next )


  {


     if( d->connected == CON_PLAYING)


     {


	ADD_COLOUR(ch,buf,L_RED);


        send_to_char( buf, d->character );


     }


  }





return;


}





/*======================================================================*


 * function: do_bet                                                     *


 * purpose: to allow players to wager on the outcome of arena battles   *


 * written by: Doug Araya (whiplash@tft.nacs.net) 6-10-96               *


 *======================================================================*/


void do_bet(CHAR_DATA *ch, char *argument)


 {


 char arg[MAX_INPUT_LENGTH]; 


 char buf[MAX_STRING_LENGTH]; 


 CHAR_DATA *fighter; 


 int wager; 





 argument = one_argument(argument, arg); 





 if(argument[0] == '\0' || !is_number(arg))


  {


  send_to_char("Syntax: BET [amount] [player]\n\r",ch); 


  return;


  }





 if(ch->gladiator != NULL)


  {


  send_to_char("You have already placed a bet on this fight.\n\r",ch);


  return;


  }





/*== disable the actual fighters from betting ==*/


 if(IS_SET(ch->act,PLR_CHALLENGER) || IS_SET(ch->act,PLR_CHALLENGED))


  {


  send_to_char("You can't bet on this battle.\n\r",ch); 


  return; 


  }





 fighter = get_char_world(ch,argument);





/*== make sure the choice is valid ==*/





 if( fighter == NULL )


  {


  send_to_char("That player is not logged in.\n\r",ch);


  return;


  }





 if( IS_NPC(fighter) )


  {


  send_to_char("Why bet on a mob? They aren't fighting...\n\r",ch);


  return;


  }





 if( !IS_SET(fighter->in_room->room_flags,ROOM_ARENA) )


  {


  send_to_char("That player is not in the arena.\n\r",ch); 


  return; 


  }





/*== do away with the negative number trickery ==*/


 if(!str_prefix("-",arg))


  {


  send_to_char("Error: Invalid argument!\n\r",ch); 


  return; 


  }





 wager   = atoi(arg);





 if(wager > 5000 || wager < 1)


  {


  send_to_char("Wager range is between 1 and 50\n\r",ch);


  return; 


  }





/*== make sure they have the cash ==*/


 if(wager > ch->exp)


  {


  send_to_char("You don't have that much qps to wager!\n\r",ch); 


  return; 


  }





/*== now set the info ==*/


ch->gladiator = fighter;


ch->pcdata->plr_wager = wager;


sprintf(buf,"You have placed a %d exp wager on %s\n\r",


        wager,fighter->name);


send_to_char(buf,ch);


return; 


}





i3
******************************************************************
 *  File: bit.c                                                            *
 *                                                                         *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 *                                                                         *
 *  This code was written by Jason Dinkel and inspired by Russ Taylor,     *
 *  and has been used here for OLC - OLC would not be what it is without   *
 *  all the previous coders who released their source code.                *
 *                                                                         *
 ***************************************************************************/
/*
 The code below uses a table lookup system that is based on suggestions
 from Russ Taylor.  There are many routines in handler.c that would benefit
 with the use of tables.  You may consider simplifying your code base by
 implementing a system like below with such functions. -Jason Dinkel
*/



#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"



struct flag_stat_type
{
    const struct flag_type *structure;
    bool stat;
};



/*****************************************************************************
 Name:		flag_stat_table
 Purpose:	This table catagorizes the tables following the lookup
 		functions below into stats and flags.  Flags can be toggled
 		but stats can only be assigned.  Update this table when a
 		new set of flags is installed.
 ****************************************************************************/
const struct flag_stat_type flag_stat_table[] =
{
/*  {	structure		stat	}, */
    {	area_flags,		FALSE	},
    {   sex_flags,		TRUE	},
    {   exit_flags,		FALSE	},
    {   door_resets,		TRUE	},
    {   room_flags,		FALSE	},
    {   sector_flags,		TRUE	},
    {   type_flags,		TRUE	},
    {   extra_flags,		FALSE	},
    {   wear_flags,		FALSE	},
    {   act_flags,		FALSE	},
    {   affect_flags,		FALSE	},
    {   apply_flags,		TRUE	},
    {   wear_loc_flags,		TRUE	},
    {   wear_loc_strings,	TRUE	},
    {   weapon_flags,		TRUE	},
    {   container_flags,	FALSE	},
    {   liquid_flags,		TRUE	},

    {   0,			0	}
};
    


/*****************************************************************************
 Name:		is_stat( table )
 Purpose:	Returns TRUE if the table is a stat table and FALSE if flag.
 Called by:	flag_value and flag_string.
 Note:		This function is local and used only in bit.c.
 ****************************************************************************/
bool is_stat( const struct flag_type *flag_table )
{
    int flag;

    for (flag = 0; flag_stat_table[flag].structure; flag++)
    {
	if ( flag_stat_table[flag].structure == flag_table
	  && flag_stat_table[flag].stat )
	    return TRUE;
    }
    return FALSE;
}



/*
 * This function is Russ Taylor's creation.  Thanks Russ!
 * All code copyright (C) Russ Taylor, permission to use and/or distribute
 * has NOT been granted.  Use only in this OLC package has been granted.
 */
/*****************************************************************************
 Name:		flag_lookup( flag, table )
 Purpose:	Returns the value of a single, settable flag from the table.
 Called by:	flag_value and flag_string.
 Note:		This function is local and used only in bit.c.
 ****************************************************************************/
int flag_lookup(const char *name, const struct flag_type *flag_table)
{
    int flag;
 
    for (flag = 0; *flag_table[flag].name; flag++)	/* OLC 1.1b */
    {
        if ( !str_cmp( name, flag_table[flag].name )
          && flag_table[flag].settable )
            return flag_table[flag].bit;
    }
 
    return NO_FLAG;
}



/*****************************************************************************
 Name:		flag_value( table, flag )
 Purpose:	Returns the value of the flags entered.  Multi-flags accepted.
 Called by:	olc.c and olc_act.c.
 ****************************************************************************/
int flag_value( const struct flag_type *flag_table, char *argument)
{
    char word[MAX_INPUT_LENGTH];
    int  bit;
    int  marked = 0;
    bool found = FALSE;

    if ( is_stat( flag_table ) )
    {
	one_argument( argument, word );

	if ( ( bit = flag_lookup( word, flag_table ) ) != NO_FLAG )
	    return bit;
	else
	    return NO_FLAG;
    }

    /*
     * Accept multiple flags.
     */
    for (; ;)
    {
        argument = one_argument( argument, word );

        if ( word[0] == '\0' )
	    break;

        if ( ( bit = flag_lookup( word, flag_table ) ) != NO_FLAG )
        {
            SET_BIT( marked, bit );
            found = TRUE;
        }
    }

    if ( found )
	return marked;
    else
	return NO_FLAG;
}



/*****************************************************************************
 Name:		flag_string( table, flags/stat )
 Purpose:	Returns string with name(s) of the flags or stat entered.
 Called by:	act_olc.c, olc.c, and olc_save.c.
 ****************************************************************************/
char *flag_string( const struct flag_type *flag_table, int bits )
{
    static char buf[512];
    int  flag;

    buf[0] = '\0';

    for (flag = 0; *flag_table[flag].name; flag++)	/* OLC 1.1b */
    {
	if ( !is_stat( flag_table ) && IS_SET(bits, flag_table[flag].bit) )
	{
	    strcat( buf, " " );
	    strcat( buf, flag_table[flag].name );
	}
	else
	if ( flag_table[flag].bit == bits )
	{
	    strcat( buf, " " );
	    strcat( buf, flag_table[flag].name );
	    break;
	}
    }
    return (buf[0] != '\0') ? buf+1 : "none";
}



const struct flag_type area_flags[] =
{
    {	"none",			AREA_NONE,		FALSE	},
    {	"changed",		AREA_CHANGED,		FALSE	},
    {	"added",		AREA_ADDED,		FALSE	},
    {	"loading",		AREA_LOADING,		FALSE	},
    {	"verbose",		AREA_VERBOSE,		FALSE	},
    {	"",			0,			0	}
};



const struct flag_type sex_flags[] =
{
    {	"male",			SEX_MALE,		TRUE	},
    {	"female",		SEX_FEMALE,		TRUE	},
    {	"neutral",		SEX_NEUTRAL,		TRUE	},
    {	"",			0,			0	}
};



const struct flag_type exit_flags[] =
{
    {   "door",			EX_ISDOOR,		TRUE    },
    {	"closed",		EX_CLOSED,		TRUE	},
    {	"locked",		EX_LOCKED,		TRUE	},
    {	"pickproof",		EX_PICKPROOF,		TRUE	},
    { 	"ice_wall",		EX_ICE_WALL,		TRUE	},
    { 	"fire_wall",		EX_FIRE_WALL,		TRUE	},
    { 	"sword_wall",		EX_SWORD_WALL,		TRUE	},
    { 	"prismatic_wall",	EX_PRISMATIC_WALL,	TRUE	},
    { 	"iron_wall",		EX_IRON_WALL,		TRUE	},
    { 	"mushroom_wall",	EX_MUSHROOM_WALL,	TRUE	},
    { 	"caltrop_wall",		EX_CALTROP_WALL,	TRUE	},
    { 	"ash_wall",		EX_ASH_WALL,		TRUE	},
    { 	"warding",		EX_WARDING,		TRUE	},
    {	"",			0,			0	}
};



const struct flag_type door_resets[] =
{
    {	"open and unlocked",	0,		TRUE	},
    {	"closed and unlocked",	1,		TRUE	},
    {	"closed and locked",	2,		TRUE	},
    {	"",			0,		0	}
};



const struct flag_type room_flags[] =
{
    {	"dark",			ROOM_DARK,		TRUE	},
    {	"no_mob",		ROOM_NO_MOB,		TRUE	},
    {	"indoors",		ROOM_INDOORS,		TRUE	},
    {	"private",		ROOM_PRIVATE,		TRUE	},
    {	"safe",			ROOM_SAFE,		TRUE	},
    {	"solitary",		ROOM_SOLITARY,		TRUE	},
    {	"pet_shop",		ROOM_PET_SHOP,		TRUE	},
    {	"no_recall",		ROOM_NO_RECALL,		TRUE	},
    {	"no_otrans",		ROOM_NO_OTRANS,		TRUE	},
    { 	"no_teleport",		ROOM_NO_TELEPORT,	TRUE	},
    {  	"total_darkness",	ROOM_TOTAL_DARKNESS,	TRUE	},
    { 	"blade_barrier",	ROOM_BLADE_BARRIER,	TRUE	},
    { 	"arena",		ROOM_ARENA,		TRUE	},
    { 	"flaming",		ROOM_FLAMING,		TRUE	},
    {   "silence",		ROOM_SILENCE,		TRUE	},
    {	"",			0,			0	}
};



const struct flag_type sector_flags[] =
{
    {	"inside",	SECT_INSIDE,		TRUE	},
    {	"city",		SECT_CITY,		TRUE	},
    {	"field",	SECT_FIELD,		TRUE	},
    {	"forest",	SECT_FOREST,		TRUE	},
    {	"hills",	SECT_HILLS,		TRUE	},
    {	"mountain",	SECT_MOUNTAIN,		TRUE	},
    {	"swim",		SECT_WATER_SWIM,	TRUE	},
    {	"noswim",	SECT_WATER_NOSWIM,	TRUE	},
    {	"air",		SECT_AIR,		TRUE	},
    {	"desert",	SECT_DESERT,		TRUE	},
    {	"",		0,			0	}
};



const struct flag_type type_flags[] =
{
    {	"light",		ITEM_LIGHT,		TRUE	},
    {	"scroll",		ITEM_SCROLL,		TRUE	},
    {	"wand",			ITEM_WAND,		TRUE	},
    {	"staff",		ITEM_STAFF,		TRUE	},
    {	"weapon",		ITEM_WEAPON,		TRUE	},
    {	"treasure",		ITEM_TREASURE,		TRUE	},
    {	"armor",		ITEM_ARMOR,		TRUE	},
    {	"potion",		ITEM_POTION,		TRUE	},
    {	"furniture",		ITEM_FURNITURE,		TRUE	},
    {	"trash",		ITEM_TRASH,		TRUE	},
    {	"container",		ITEM_CONTAINER,		TRUE	},
    {	"drink-container",	ITEM_DRINK_CON,		TRUE	},
    {	"key",			ITEM_KEY,		TRUE	},
    {	"food",			ITEM_FOOD,		TRUE	},
    {	"money",		ITEM_MONEY,		TRUE	},
    {	"boat",			ITEM_BOAT,		TRUE	},
    {	"npc corpse",		ITEM_CORPSE_NPC,	TRUE	},
    {	"pc corpse",		ITEM_CORPSE_PC,		FALSE	},
    {	"fountain",		ITEM_FOUNTAIN,		TRUE	},
    {	"pill",			ITEM_PILL,		TRUE	},
    { 	"portal",		ITEM_PORTAL,		TRUE	},
    {	"egg",			ITEM_EGG,		TRUE	},
    {	"voodoo",		ITEM_VOODOO,		TRUE	},
    {	"stake",		ITEM_STAKE,		TRUE	},
    { 	"missile",		ITEM_MISSILE,		TRUE	},
    {	"ammo",			ITEM_AMMO,		TRUE	},
    { 	"quest",		ITEM_QUEST,		TRUE	},
    {	"questcard",		ITEM_QUESTCARD,		TRUE	},
    {	"questmachine",		ITEM_QUESTMACHINE,	TRUE	},
    { 	"symbol",		ITEM_SYMBOL,		TRUE	},
    {   "book",			ITEM_BOOK,		TRUE	},
    {	"page",			ITEM_PAGE,		TRUE	},
    {	"tool",			ITEM_TOOL,		TRUE	},
    {	"wall",			ITEM_WALL,		TRUE	},
    {	"copper",		ITEM_COPPER,		TRUE	},
    {	"iron",			ITEM_IRON,		TRUE	},
    {	"steel",		ITEM_STEEL,		TRUE	},
    { 	"adamantite",		ITEM_ADAMANTITE,	TRUE	},
    {   "gemstone",		ITEM_GEMSTONE,		TRUE	},
    {	"hilt",			ITEM_HILT,		TRUE	},
    {   "kingdom",		ITEM_KINGDOM_POWER,	TRUE	},
    {	"",			0,			0	}
};


const struct flag_type extra_flags[] =
{
    {	"glow",			ITEM_GLOW,		TRUE	},
    {	"hum",			ITEM_HUM,		TRUE	},
    {	"thrown",		ITEM_THROWN,		TRUE	},
    {	"keep",			ITEM_KEEP,		TRUE	},
    {	"vanish",		ITEM_VANISH,		TRUE	},
    {	"invis",		ITEM_INVIS,		TRUE	},
    {	"magic",		ITEM_MAGIC,		TRUE	},
    {	"nodrop",		ITEM_NODROP,		TRUE	},
    {	"bless",		ITEM_BLESS,		TRUE	},
    {	"anti-good",		ITEM_ANTI_GOOD,		TRUE	},
    {	"anti-evil",		ITEM_ANTI_EVIL,		TRUE	},
    {	"anti-neutral",		ITEM_ANTI_NEUTRAL,	TRUE	},
    {	"noremove",		ITEM_NOREMOVE,		TRUE	},
    {	"inventory",		ITEM_INVENTORY,		TRUE	},
    {	"shadowplane",		ITEM_SHADOWPLANE,	TRUE	},
    { 	"loyal",		ITEM_LOYAL,		TRUE	},
    {	"",			0,			0	}
};



const struct flag_type wear_flags[] =
{
    {	"take",			ITEM_TAKE,		TRUE	},
    {	"finger",		ITEM_WEAR_FINGER,	TRUE	},
    {	"neck",			ITEM_WEAR_NECK,		TRUE	},
    {	"body",			ITEM_WEAR_BODY,		TRUE	},
    {	"head",			ITEM_WEAR_HEAD,		TRUE	},
    {	"legs",			ITEM_WEAR_LEGS,		TRUE	},
    {	"feet",			ITEM_WEAR_FEET,		TRUE	},
    {	"hands",		ITEM_WEAR_HANDS,	TRUE	},
    {	"arms",			ITEM_WEAR_ARMS,		TRUE	},
    {	"shield",		ITEM_WEAR_SHIELD,	TRUE	},
    {	"about",		ITEM_WEAR_ABOUT,	TRUE	},
    {	"waist",		ITEM_WEAR_WAIST,	TRUE	},
    {	"wrist",		ITEM_WEAR_WRIST,	TRUE	},
    {	"wield",		ITEM_WIELD,		TRUE	},
    {	"hold",			ITEM_HOLD,		TRUE	},
    {	"face",			ITEM_WEAR_FACE,		TRUE	},
    {	"",			0,			0	}
};



const struct flag_type act_flags[] =
{
    {	"npc",			ACT_IS_NPC,		FALSE	},
    {	"sentinel",		ACT_SENTINEL,		TRUE	},
    {	"scavenger",		ACT_SCAVENGER,		TRUE	},
    {	"aggressive",		ACT_AGGRESSIVE,		TRUE	},
    {	"stay_area",		ACT_STAY_AREA,		TRUE	},
    {	"wimpy",		ACT_WIMPY,		TRUE	},
    {	"pet",			ACT_PET,		TRUE	},
    {	"train",		ACT_TRAIN,		TRUE	},
    {	"practice",		ACT_PRACTICE,		TRUE	},
    {	"mount",		ACT_MOUNT,		TRUE	},
    {	"no_parts",		ACT_NOPARTS,		TRUE	},
    {	"no_exp",		ACT_NOEXP,		TRUE	},
    {   "no_autokill",		ACT_NOAUTOKILL,		TRUE	},
    {	"",			0,			0	}
};



const struct flag_type affect_flags[] =
{
    {	"blind",		AFF_BLIND,		TRUE	},
    {	"invisible",		AFF_INVISIBLE,		TRUE	},
    {	"detect-evil",		AFF_DETECT_EVIL,	TRUE	},
    {	"detect-invis",		AFF_DETECT_INVIS,	TRUE	},
    {	"detect-magic",		AFF_DETECT_MAGIC,	TRUE	},
    {	"detect-hidden",	AFF_DETECT_HIDDEN,	TRUE	},
    {	"shadowplane",		AFF_SHADOWPLANE,	TRUE	},
    {	"sanctuary",		AFF_SANCTUARY,		TRUE	},
    {	"faerie-fire",		AFF_FAERIE_FIRE,	TRUE	},
    {	"infrared",		AFF_INFRARED,		TRUE	},
    {	"curse",		AFF_CURSE,		TRUE	},
    {	"flaming",		AFF_FLAMING,		TRUE	},
    {	"poison",		AFF_POISON,		TRUE	},
    {	"protect",		AFF_PROTECT,		TRUE	},
    {	"ethereal",		AFF_ETHEREAL,		TRUE	},
    {	"sneak",		AFF_SNEAK,		TRUE	},
    {	"hide",			AFF_HIDE,		TRUE	},
    {	"sleep",		AFF_SLEEP,		TRUE	},
    {	"charm",		AFF_CHARM,		TRUE	},
    {	"flying",		AFF_FLYING,		TRUE	},
    {	"pass-door",		AFF_PASS_DOOR,		TRUE	},
    {	"polymorph",		AFF_POLYMORPH,		FALSE	},
    {	"shadowsight",		AFF_SHADOWSIGHT,	TRUE	},
    {	"web",			AFF_WEBBED,		TRUE	},
    {	"tendrils",		AFF_TENDRILS,		TRUE	},
    {	"drowfire",		AFF_DROWFIRE,		TRUE	},
    {	"zuloform",		AFF_ZULOFORM,		FALSE	},
    {	"peace",		AFF_PEACE,		TRUE	},
    {	"infirmity",		AFF_INFIRMITY,		TRUE	},
    {	"shift",		AFF_SHIFT,		FALSE	},
    {	"",			0,			0	}
};


/*
 * Used when adding an affect to tell where it goes.
 * See addaffect and delaffect in act_olc.c
 */
const struct flag_type apply_flags[] =
{
    {	"none",			APPLY_NONE,		TRUE	},
    {	"strength",		APPLY_STR,		TRUE	},
    {	"dexterity",		APPLY_DEX,		TRUE	},
    {	"intelligence",		APPLY_INT,		TRUE	},
    {	"wisdom",		APPLY_WIS,		TRUE	},
    {	"constitution",		APPLY_CON,		TRUE	},
    {	"sex",			APPLY_SEX,		TRUE	},
    {	"class",		APPLY_CLASS,		TRUE	},
    {	"level",		APPLY_LEVEL,		TRUE	},
    {	"age",			APPLY_AGE,		TRUE	},
    {	"height",		APPLY_HEIGHT,		TRUE	},
    {	"weight",		APPLY_WEIGHT,		TRUE	},
    {	"mana",			APPLY_MANA,		TRUE	},
    {	"hp",			APPLY_HIT,		TRUE	},
    {	"move",			APPLY_MOVE,		TRUE	},
    {	"gold",			APPLY_GOLD,		TRUE	},
    {	"experience",		APPLY_EXP,		TRUE	},
    {	"ac",			APPLY_AC,		TRUE	},
    {	"hitroll",		APPLY_HITROLL,		TRUE	},
    {	"damroll",		APPLY_DAMROLL,		TRUE	},
    {	"saving-para",		APPLY_SAVING_PARA,	TRUE	},
    {	"saving-rod",		APPLY_SAVING_ROD,	TRUE	},
    {	"saving-petri",		APPLY_SAVING_PETRI,	TRUE	},
    {	"saving-breath",	APPLY_SAVING_BREATH,	TRUE	},
    {	"saving-spell",		APPLY_SAVING_SPELL,	TRUE	},
    {	"polymorph",		APPLY_POLY,		TRUE	},
    {	"",			0,			0	}
};



/*
 * What is seen.
 */
const struct flag_type wear_loc_strings[] =
{
    {	"in the inventory",	WEAR_NONE,	TRUE	},
    {	"as a light",		WEAR_LIGHT,	TRUE	},
    {	"on the left finger",	WEAR_FINGER_L,	TRUE	},
    {	"on the right finger",	WEAR_FINGER_R,	TRUE	},
    {	"around the neck (1)",	WEAR_NECK_1,	TRUE	},
    {	"around the neck (2)",	WEAR_NECK_2,	TRUE	},
    {	"on the body",		WEAR_BODY,	TRUE	},
    {	"over the head",	WEAR_HEAD,	TRUE	},
    {	"on the legs",		WEAR_LEGS,	TRUE	},
    {	"on the feet",		WEAR_FEET,	TRUE	},
    {	"on the hands",		WEAR_HANDS,	TRUE	},
    {	"on the arms",		WEAR_ARMS,	TRUE	},
    {	"about the body",	WEAR_ABOUT,	TRUE	},
    {	"around the waist",	WEAR_WAIST,	TRUE	},
    {	"on the left wrist",	WEAR_WRIST_L,	TRUE	},
    {	"on the right wrist",	WEAR_WRIST_R,	TRUE	},
    {	"on the face",		WEAR_FACE,	TRUE	},
    {	"as a shield",		WEAR_SHIELD,	TRUE	},
    {	"first hand",		WEAR_WIELD,	TRUE	},
    {	"second hand",		WEAR_HOLD,	TRUE	},
    {	"third hand",		WEAR_THIRD,	TRUE	},
    {	"fourth hand",		WEAR_FOURTH,	TRUE	},
    {	"left scabbard",	WEAR_SCABBARD_L,TRUE	},
    {	"right scabbard",	WEAR_SCABBARD_R,TRUE	},
    {	"",			0			}
};


/*
 * What is typed.
 * Neck2 should not be settable for loaded mobiles.
 */
const struct flag_type wear_loc_flags[] =
{
    {	"none",		WEAR_NONE,	TRUE	},
    {	"light",	WEAR_LIGHT,	TRUE	},
    {	"lfinger",	WEAR_FINGER_L,	TRUE	},
    {	"rfinger",	WEAR_FINGER_R,	TRUE	},
    {	"neck",		WEAR_NECK_1,	TRUE	},
    {	"body",		WEAR_BODY,	TRUE	},
    {	"head",		WEAR_HEAD,	TRUE	},
    {	"legs",		WEAR_LEGS,	TRUE	},
    {	"feet",		WEAR_FEET,	TRUE	},
    {	"hands",	WEAR_HANDS,	TRUE	},
    {	"arms",		WEAR_ARMS,	TRUE	},
    {	"shield",	WEAR_SHIELD,	TRUE	},
    {	"about",	WEAR_ABOUT,	TRUE	},
    {	"waist",	WEAR_WAIST,	TRUE	},
    {	"lwrist",	WEAR_WRIST_L,	TRUE	},
    {	"rwrist",	WEAR_WRIST_R,	TRUE	},
    {	"wielded",	WEAR_WIELD,	TRUE	},
    {	"hold",		WEAR_HOLD,	TRUE	},
    {	"face",		WEAR_FACE,	TRUE	},
    {	"",		0,		0	}
};



const struct flag_type weapon_flags[] =
{
    {	"hit",		0,	TRUE	},
    {	"slice",	1,	TRUE	},
    {	"stab",		2,	TRUE	},
    {	"slash",	3,	TRUE	},
    {	"whip",		4,	TRUE	},
    {	"claw",		5,	TRUE	},
    {	"blast",	6,	TRUE	},
    {	"pound",	7,	TRUE	},
    {	"crush",	8,	TRUE	},
    {	"grep",		9,	TRUE	},
    {	"bite",		10,	TRUE	},
    {	"pierce",	11,	TRUE	},
    {	"suck",		12,	TRUE	},
    {	"",		0,	0	}
};


const struct flag_type container_flags[] =
{
    {	"closeable",		1,		TRUE	},
    {	"pickproof",		2,		TRUE	},
    {	"closed",		4,		TRUE	},
    {	"locked",		8,		TRUE	},
    {	"",			0,		0	}
};



const struct flag_type liquid_flags[] =
{
    {	"water",		0,	TRUE	},
    {	"beer",			1,	TRUE	},
    {	"wine",			2,	TRUE	},
    {	"ale",			3,	TRUE	},
    {	"dark-ale",		4,	TRUE	},
    {	"whisky",		5,	TRUE	},
    {	"lemonade",		6,	TRUE	},
    {	"firebreather",		7,	TRUE	},
    {	"local-specialty",	8,	TRUE	},
    {	"slime-mold-juice",	9,	TRUE	},
    {	"milk",			10,	TRUE	},
    {	"tea",			11,	TRUE	},
    {	"coffee",		12,	TRUE	},
    {	"blood",		13,	TRUE	},
    {	"salt-water",		14,	TRUE	},
    {	"cola",			15,	TRUE	},
    {	"",			0,	0	}
};



******************
 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
 *                                                                         *
 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
 *  Chastain, Michael Quan, and Mitchell Tse.                              *
 *                                                                         *
 *  In order to use any part of this Merc Diku Mud, you must comply with   *
 *  both the original Diku license in 'license.doc' as well the Merc       *
 *  license in 'license.txt'.  In particular, you may not remove either of *
 *  these copyright notices.                                               *
 *                                                                         *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 ***************************************************************************/

#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"


/*
 
 Note Board system, (c) 1995-96 Erwin S. Andreasen, erwin@pip.dknet.dk
 =====================================================================
 
 Basically, the notes are split up into several boards. The boards do not
 exist physically, they can be read anywhere and in any position.
 
 Each of the note boards has its own file. Each of the boards can have its own
 "rights": who can read/write.
 
 Each character has an extra field added, namele the timestamp of the last note
 read by him/her on a certain board.
 
 The note entering system is changed too, making it more interactive. When
 entering a note, a character is put AFK and into a special CON_ state.
 Everything typed goes into the note.
 
 For the immortals it is possible to purge notes based on age. An Archive
 options is available which moves the notes older than X days into a special
 board. The file of this board should then be moved into some other directory
 during e.g. the startup script and perhaps renamed depending on date.
 
 Note that write_level MUST be >= read_level or else there will be strange
 output in certain functions.
 
 Board DEFAULT_BOARD must be at least readable by *everyone*.
 
*/ 

#define L_SUP (MAX_LEVEL - 1) /* if not already defined */


BOARD_DATA boards[MAX_BOARD] =
{

{ "General",  	"General discussion",            0,     2,     "all", DEF_INCLUDE,21, NULL, FALSE },
{ "Ideas",	  	"Suggestion for improvement",	 0,     2,     "all", DEF_NORMAL, 30, NULL, FALSE }, 
{ "Announce", 	"Announcements from Immortals",  0,     8, "all", DEF_NORMAL, 60, NULL, FALSE },
{ "Bugs",	  	"Typos, bugs, errors",		     2,     2, "imm", DEF_INCLUDE, 60, NULL, FALSE },
{ "Personal", 	"Personal messages",			 0,     2,     "all", DEF_EXCLUDE,14, NULL, FALSE },
{ "Immortal",	"Immortal Board",		8,	8, "imm", DEF_INCLUDE, 60, NULL, FALSE}  
};

/* The prompt that the character is given after finishing a note with ~ or END */
const char * szFinishPrompt = "(" BOLD "C" NO_COLOR ")ontinue, (" BOLD "V" NO_COLOR ")iew, (" BOLD "P" NO_COLOR ")ost or (" BOLD "F" NO_COLOR ")orget it?";

long last_note_stamp = 0; /* To generate unique timestamps on notes */

#define BOARD_NOACCESS -1
#define BOARD_NOTFOUND -1

static bool next_board (CHAR_DATA *ch);


/* recycle a note */
void free_note (NOTE_DATA *note)
{
	if (note->sender)
		free_string (note->sender);
	if (note->to_list)
		free_string (note->to_list);
	if (note->subject)
		free_string (note->subject);
	if (note->date) /* was note->datestamp for some reason */
		free_string (note->date);
	if (note->text)
		free_string (note->text);
		
	note->next = note_free;
	note_free = note;	
}

/* allocate memory for a new note or recycle */
NOTE_DATA *new_note ()
{
	NOTE_DATA *note;
	
	if (note_free)
	{
		note = note_free;
		note_free = note_free->next;
	}
	else
		note = alloc_mem (sizeof(NOTE_DATA));

	/* Zero all the field - Envy does not gurantee zeroed memory */	
	note->next = NULL;
	note->sender = NULL;		
	note->expire = 0;
	note->to_list = NULL;
	note->subject = NULL;
	note->date = NULL;
	note->date_stamp = 0;
	note->text = NULL;
	
	return note;
}

/* append this note to the given file */
static void append_note (FILE *fp, NOTE_DATA *note)
{
	fprintf (fp, "Sender  %s~\n", note->sender);
	fprintf (fp, "Date    %s~\n", note->date);
	fprintf (fp, "Stamp   %ld\n", note->date_stamp);
	fprintf (fp, "Expire  %ld\n", note->expire);
	fprintf (fp, "To      %s~\n", note->to_list);
	fprintf (fp, "Subject %s~\n", note->subject);
	fprintf (fp, "Text\n%s~\n\n", note->text);
}

/* Save a note in a given board */
void finish_note (BOARD_DATA *board, NOTE_DATA *note)
{
	FILE *fp;
	NOTE_DATA *p;
	char filename[200];
	
	/* The following is done in order to generate unique date_stamps */

	if (last_note_stamp >= current_time)
		note->date_stamp = ++last_note_stamp;
	else
	{
	    note->date_stamp = current_time;
	    last_note_stamp = current_time;
	}
	
	if (board->note_first) /* are there any notes in there now? */
	{
		for (p = board->note_first; p->next; p = p->next )
			; /* empty */
		
		p->next = note;
	}
	else /* nope. empty list. */
		board->note_first = note;

	/* append note to note file */		
	
	sprintf (filename, "%s%s", NOTE_DIR, board->short_name);
	
	fp = fopen (filename, "a");
	if (!fp)
	{
		bug ("Could not open one of the note files in append mode",0);
		board->changed = TRUE; /* set it to TRUE hope it will be OK later? */
		return;
	}
	
	append_note (fp, note);
	fclose (fp);
}

/* Find the number of a board */
int board_number (const BOARD_DATA *board)
{
	int i;
	
	for (i = 0; i < MAX_BOARD; i++)
		if (board == &boards[i])
			return i;

	return -1;
}

/* Find a board number based on  a string */
int board_lookup (const char *name)
{
	int i;
	
	for (i = 0; i < MAX_BOARD; i++)
		if (!str_cmp (boards[i].short_name, name))
			return i;

	return -1;
}

/* Remove list from the list. Do not free note */
static void unlink_note (BOARD_DATA *board, NOTE_DATA *note)
{
	NOTE_DATA *p;
	
	if (board->note_first == note)
		board->note_first = note->next;
	else
	{
		for (p = board->note_first; p && p->next != note; p = p->next);
		if (!p)
			bug ("unlink_note: could not find note.",0);
		else
			p->next = note->next;
	}
}

/* Find the nth note on a board. Return NULL if ch has no access to that note */
static NOTE_DATA* find_note (CHAR_DATA *ch, BOARD_DATA *board, int num)
{
	int count = 0;
	NOTE_DATA *p;
	
	for (p = board->note_first; p ; p = p->next)
			if (++count == num)
				break;
	
	if ( (count == num) && is_note_to (ch, p))
		return p;
	else
		return NULL;
	
}

/* save a single board */
static void save_board (BOARD_DATA *board)
{
	FILE *fp;
	char filename[200];
	char buf[200];
	NOTE_DATA *note;
	
	sprintf (filename, "%s%s", NOTE_DIR, board->short_name);
	
	fp = fopen (filename, "w");
	if (!fp)
	{
		sprintf (buf, "Error writing to: %s", filename);
		bug (buf, 0);
	}
	else
	{
		for (note = board->note_first; note ; note = note->next)
			append_note (fp, note);
			
		fclose (fp);
	}
}

/* Show one not to a character */
static void show_note_to_char (CHAR_DATA *ch, NOTE_DATA *note, int num)
{
	char buf[4*MAX_STRING_LENGTH];

	/* Ugly colors ? */	
	sprintf (buf,
			 "[" BOLD "%4d" NO_COLOR "] " BOLD YELLOW "%s" NO_COLOR ": " GREEN "%s" NO_COLOR "\n\r"
	         BOLD YELLOW "Date" NO_COLOR ":  %s\n\r"
			 BOLD YELLOW "To" NO_COLOR ":    %s\n\r"
	         GREEN "===========================================================================" NO_COLOR "\n\r"
	         "%s\n\r",
	         num, note->sender, note->subject,
	         note->date,
	         note->to_list,
	         note->text);

	send_to_char (buf,ch);	         
}

/* Save changed boards */
void save_notes ()
{
	int i;
	 
	for (i = 0; i < MAX_BOARD; i++)
		if (boards[i].changed) /* only save changed boards */
			save_board (&boards[i]);
}

/* Load a single board */
static void load_board (BOARD_DATA *board)
{
	FILE *fp, *fp_archive;
	NOTE_DATA *last_note;
	char filename[200];
	
	sprintf (filename, "%s%s", NOTE_DIR, board->short_name);
	
	fp = fopen (filename, "r");
	
	/* Silently return */
	if (!fp)
		return;		
		
	/* Start note fetching. copy of db.c:load_notes() */

    last_note = NULL;

    for ( ; ; )
    {
        NOTE_DATA *pnote;
        char letter;

        do
        {
            letter = getc( fp );
            if ( feof(fp) )
            {
                fclose( fp );
                return;
            }
        }
        while ( isspace(letter) );
        ungetc( letter, fp );

        pnote             = alloc_perm( sizeof(*pnote) );

        if ( str_cmp( fread_word( fp ), "sender" ) )
            break;
        pnote->sender     = fread_string( fp );

        if ( str_cmp( fread_word( fp ), "date" ) )
            break;
        pnote->date       = fread_string( fp );

        if ( str_cmp( fread_word( fp ), "stamp" ) )
            break;
        pnote->date_stamp = fread_number( fp );

        if ( str_cmp( fread_word( fp ), "expire" ) )
            break;
        pnote->expire = fread_number( fp );

        if ( str_cmp( fread_word( fp ), "to" ) )
            break;
        pnote->to_list    = fread_string( fp );

        if ( str_cmp( fread_word( fp ), "subject" ) )
            break;
        pnote->subject    = fread_string( fp );

        if ( str_cmp( fread_word( fp ), "text" ) )
            break;
        pnote->text       = fread_string( fp );
        
        pnote->next = NULL; /* jic */
        
        /* Should this note be archived right now ? */
        
        if (pnote->expire < current_time)
        {
			char archive_name[200];

			sprintf (archive_name, "%s%s.old", NOTE_DIR, board->short_name);
			fp_archive = fopen (archive_name, "a");
			if (!fp_archive)
				bug ("Could not open archive boards for writing",0);
			else
			{
				append_note (fp_archive, pnote);
				fclose (fp_archive); /* it might be more efficient to close this later */
			}

			free_note (pnote);
			board->changed = TRUE;
			continue;
			
        }
        

        if ( board->note_first == NULL )
            board->note_first = pnote;
        else
            last_note->next     = pnote;

        last_note         = pnote;
    }

    bug( "Load_notes: bad key word.", 0 );
    return; /* just return */
}

/* Initialize structures. Load all boards. */
void load_boards ()
{
	int i;
	
	for (i = 0; i < MAX_BOARD; i++)
		load_board (&boards[i]);
}

/* Returns TRUE if the specified note is address to ch */
bool is_note_to (CHAR_DATA *ch, NOTE_DATA *note)
{
	if (!str_cmp (ch->pcdata->switchname, note->sender))
		return TRUE;
	
	if (is_full_name ("all", note->to_list))
		return TRUE;
		
	if (IS_IMMORTAL(ch) && ( 
		is_full_name ("imm", note->to_list) ||
		is_full_name ("imms", note->to_list) ||
		is_full_name ("immortal", note->to_list) ||
		is_full_name ("god", note->to_list) ||
		is_full_name ("gods", note->to_list) ||
		is_full_name ("immortals", note->to_list)))
		return TRUE;

	if ((get_trust(ch) == MAX_LEVEL) && (
		is_full_name ("imp", note->to_list) ||
		is_full_name ("imps", note->to_list) ||
		is_full_name ("implementor", note->to_list) ||
		is_full_name ("implementors", note->to_list)))
		return TRUE;
		
	if (is_full_name (ch->pcdata->switchname, note->to_list))
		return TRUE;

	/* Allow a note to e.g. 40 to send to characters level 40 and above */		
	if (is_number(note->to_list) && get_trust(ch) >= atoi(note->to_list))
		return TRUE;
		
	return FALSE;
}

/* Return the number of unread notes 'ch' has in 'board' */
/* Returns BOARD_NOACCESS if ch has no access to board */
int unread_notes (CHAR_DATA *ch, BOARD_DATA *board)
{
	NOTE_DATA *note;
	time_t last_read;
	int count = 0;
	
	if (board->read_level > get_trust(ch))
		return BOARD_NOACCESS;
		
	last_read = ch->pcdata->last_note[board_number(board)];
	
	for (note = board->note_first; note; note = note->next)
		if (is_note_to(ch, note) && ((long)last_read < (long)note->date_stamp))
			count++;
			
	return count;
}

/*
 * COMMANDS
 */

/* Start writing a note */
static void do_nwrite (CHAR_DATA *ch, char *argument)
{
	char *strtime;
	char buf[200];
	
	if (IS_NPC(ch)) /* NPC cannot post notes */
		return;

	if (ch->pcdata->board == NULL) {
	send_to_char("You're not on a board.\n\r", ch );
	return;}

	if (get_trust(ch) < ch->pcdata->board->write_level)
	{
		send_to_char ("You cannot post notes on this board.\n\r",ch);
		return;
	}
	
	/* continue previous note, if any text was written*/ 
	if (ch->pcdata->in_progress && (!ch->pcdata->in_progress->text))
	{
		send_to_char ("Note in progress cancelled because you did not manage to write any text \n\r"
		              "before losing link.\n\r\n\r",ch);
		free_note (ch->pcdata->in_progress);		              
		ch->pcdata->in_progress = NULL;
	}
	
	
	if (!ch->pcdata->in_progress)
	{
		ch->pcdata->in_progress = new_note();
		ch->pcdata->in_progress->sender = str_dup (ch->pcdata->switchname);

		/* convert to ascii. ctime returns a string which last character is \n, so remove that */	
		strtime = ctime (&current_time);
		strtime[strlen(strtime)-1] = '\0';
	
		ch->pcdata->in_progress->date = str_dup (strtime);
	}

	act (BOLD GREEN "$n starts writing a note." NO_COLOR , ch, NULL, NULL, TO_ROOM);
	
	/* Begin writing the note ! */
	sprintf (buf, "You are now %s a new note on the " BOLD "%s" NO_COLOR " board.\n\r"
	              "If you are using tintin, type #verbose to turn off alias expansion!\n\r\n\r",
	               ch->pcdata->in_progress->text ? "continuing" : "posting",
	               ch->pcdata->board->short_name);
	send_to_char (buf,ch);
	
	sprintf (buf, BOLD YELLOW "From" NO_COLOR ":    %s\n\r\n\r", ch->pcdata->switchname);
	send_to_char (buf,ch);

	if (!ch->pcdata->in_progress->text) /* Are we continuing an old note or not? */
	{
		switch (ch->pcdata->board->force_type)
		{
		case DEF_NORMAL:
			sprintf (buf, "If you press Return, default recipient \"" BOLD "%s" NO_COLOR "\" will be chosen.\n\r",
					  ch->pcdata->board->names);
			break;
		case DEF_INCLUDE:
			sprintf (buf, "The recipient list MUST include \"" BOLD "%s" NO_COLOR "\". If not, it will be added automatically.\n\r",
						   ch->pcdata->board->names);
			break;
	
		case DEF_EXCLUDE:
			sprintf (buf, "The recipient of this note must NOT include: \"" BOLD "%s" NO_COLOR "\".",
						   ch->pcdata->board->names);
	
			break;
		}			
		
		send_to_char (buf,ch);
		send_to_char ("\n\r" BOLD YELLOW "To" NO_COLOR ":      ",ch);
	
		ch->desc->connected = CON_NOTE_TO;
		/* nanny takes over from here */
		
	}
	else /* we are continuing, print out all the fields and the note so far*/
	{
		sprintf (buf, BOLD YELLOW "To" NO_COLOR ":      %s\n\r"
		              BOLD YELLOW "Expires" NO_COLOR ": %s\n\r"
		              BOLD YELLOW "Subject" NO_COLOR ": %s\n\r", 
		               ch->pcdata->in_progress->to_list,
		               ctime(&ch->pcdata->in_progress->expire),
		               ch->pcdata->in_progress->subject);
		send_to_char (buf,ch);
		send_to_char (BOLD GREEN "Your note so far:\n\r" NO_COLOR,ch);
		if (ch->pcdata->in_progress != NULL)
		send_to_char (ch->pcdata->in_progress->text,ch);
		
		send_to_char ("\n\rEnter text. Type " BOLD "~" NO_COLOR " or " BOLD "END" NO_COLOR " on an empty line to end note.\n\r"
		                    "=======================================================\n\r",ch);
		

		ch->desc->connected = CON_NOTE_TEXT;		            

	}
	
}


/* Read next note in current group. If no more notes, go to next board */
static void do_nread (CHAR_DATA *ch, char *argument)
{
	NOTE_DATA *p;
	int count = 0, number;
	time_t *last_note = &ch->pcdata->last_note[board_number(ch->pcdata->board)];
	
	if (!str_cmp(argument, "again"))
	{ /* read last note again */
	
	}
	else if (is_number (argument))
	{
		number = atoi(argument);
		
		for (p = ch->pcdata->board->note_first; p; p = p->next)
			if (++count == number)
				break;
		
		if (!p || !is_note_to(ch, p))
			send_to_char ("No such note.\n\r",ch);
		else
		{
			show_note_to_char (ch,p,count);
			*last_note =  UMAX (*last_note, p->date_stamp);
		}
	}
	else /* just next one */
	{
		char buf[200];
		
		count = 1;
	if (ch->pcdata->board == NULL) {
	send_to_char("You are not on a board.\n\r", ch );
	return;}
	if (ch->pcdata->board->note_first == NULL) {
	send_to_char("There are no notes.\n\r", ch );
	return;}

		for (p = ch->pcdata->board->note_first; p ; p = p->next, count++)
			if ((p->date_stamp > *last_note) && is_note_to(ch,p))
			{
				show_note_to_char (ch,p,count);
				/* Advance if new note is newer than the currently newest for that char */
				*last_note =  UMAX (*last_note, p->date_stamp);
				return;
			}
		
		send_to_char ("No new notes in this board.\n\r",ch);
		
		if (next_board (ch))
			sprintf (buf, "Changed to next board, %s.\n\r", ch->pcdata->board->short_name);
		else
			sprintf (buf, "There are no more boards.\n\r");			
			
		send_to_char (buf,ch);
	}
}

/* Remove a note */
static void do_nremove (CHAR_DATA *ch, char *argument)
{
	NOTE_DATA *p;
	
	if (!is_number(argument))
	{
		send_to_char ("Remove which note?\n\r",ch);
		return;
	}

	p = find_note (ch, ch->pcdata->board, atoi(argument));
	if (!p)
	{
		send_to_char ("No such note.\n\r",ch);
		return;
	}
	
	if (str_cmp(ch->pcdata->switchname,p->sender) || ch->level <
MAX_LEVEL-1)
	{
		send_to_char ("You are not authorized to remove this note.\n\r",ch);
		return;
	}
	
	unlink_note (ch->pcdata->board,p);
	free_note (p);
	send_to_char ("Note removed!\n\r",ch);
	
	save_board(ch->pcdata->board); /* save the board */
}


/* List all notes or if argument given, list N of the last notes */
/* Shows REAL note numbers! */
static void do_nlist (CHAR_DATA *ch, char *argument)
{
	int count= 0, show = 0, num = 0, has_shown = 0;
	time_t last_note;
	NOTE_DATA *p;
	char buf[MAX_STRING_LENGTH];
	
	
	if (is_number(argument))	 /* first, count the number of notes */
	{
		show = atoi(argument);
		
		for (p = ch->pcdata->board->note_first; p; p = p->next)
			if (is_note_to(ch,p))
				count++;
	}
	
	send_to_char (BOLD "Notes on this board:" NO_COLOR "\n\r"
	              RED "Num> Author        Subject" NO_COLOR "\n\r",ch);
	              
	last_note = ch->pcdata->last_note[board_number (ch->pcdata->board)];
	
	for (p = ch->pcdata->board->note_first; p ; p = p->next)
	{
		num++;
		if (is_note_to(ch,p))
		{
			has_shown++; /* note that we want to see X VISIBLE note, not just last X */
			if (!show || ((count-show) < has_shown))
			{
				sprintf (buf, BOLD "%3d" NO_COLOR ">" BLUE BOLD "%c" NO_COLOR YELLOW BOLD "%-13s" NO_COLOR YELLOW " %s" NO_COLOR " \n\r",
				               num, 
				               last_note < p->date_stamp ? '*' : ' ',
				               p->sender, p->subject);
				send_to_char (buf,ch);
			}
		}
				              
	}
}

/* catch up with some notes */
static void do_ncatchup (CHAR_DATA *ch, char *argument)
{
	NOTE_DATA *p;

	/* Find last note */	
	for (p = ch->pcdata->board->note_first; p && p->next; p = p->next);
	
	if (!p)
		send_to_char ("Alas, there are no notes in that board.\n\r",ch);
	else
	{
		ch->pcdata->last_note[board_number(ch->pcdata->board)] = p->date_stamp;
		send_to_char ("All mesages skipped.\n\r",ch);
	}
}

/* Dispatch function for backwards compatibility */
void do_note (CHAR_DATA *ch, char *argument)
{
	char arg[MAX_INPUT_LENGTH];

	if (IS_NPC(ch))
		return;
	
	argument = one_argument (argument, arg);
	
	if ((!arg[0]) || (!str_cmp(arg, "read"))) /* 'note' or 'note read X' */
		do_nread (ch, argument);
		
	else if (!str_cmp (arg, "list"))
		do_nlist (ch, argument);

	else if (!str_cmp (arg, "write"))
		do_nwrite (ch, argument);

	else if (!str_cmp (arg, "remove"))
		do_nremove (ch, argument);
		
	else if (!str_cmp (arg, "purge"))
		send_to_char ("Obsolete.\n\r",ch);
	
	else if (!str_cmp (arg, "archive"))
		send_to_char ("Obsolete.\n\r",ch);
	
	else if (!str_cmp (arg, "catchup"))
		do_ncatchup (ch, argument);
	else 
		do_help (ch, "note");
}

/* Show all accessible boards with their numbers of unread messages OR
   change board. New board name can be given as a number or as a name (e.g.
    board personal or board 4 */
void do_board (CHAR_DATA *ch, char *argument)
{
	int i, count, number;
	char buf[200];
	
	if (IS_NPC(ch))
		return;
	
	if (!argument[0]) /* show boards */
	{
		int unread;
		
		count = 1;
		send_to_char("\n\r", ch);
		send_to_char (BOLD RED "Num         Name Unread Description" NO_COLOR "\n\r"
		              RED "=== ============ ====== ===========" NO_COLOR "\n\r",ch);
		for (i = 0; i < MAX_BOARD; i++)
		{
			unread = unread_notes (ch,&boards[i]); /* how many unread notes? */
			if (unread != BOARD_NOACCESS)
			{ /* watch out for the non-portable &%c !!! */
				sprintf (buf, BOLD "%2d" NO_COLOR "> " GREEN BOLD "%12s" NO_COLOR " [%4d" NO_COLOR "] " YELLOW "%s" NO_COLOR "\n\r", 
				                   count, boards[i].short_name,
				                    unread, boards[i].long_name);
				send_to_char (buf,ch);	                    
				count++;
			} /* if has access */
			
		} /* for each board */
		if (ch->pcdata->board != NULL) {
		sprintf (buf, "\n\rYou current board is " BOLD "%s" NO_COLOR ".\n\r", ch->pcdata->board->short_name);
		send_to_char (buf,ch);

		/* Inform of rights */		
		if (ch->pcdata->board->read_level > get_trust(ch))
			send_to_char ("You cannot read nor write notes on this board.\n\r",ch);
		else if (ch->pcdata->board->write_level > get_trust(ch))
			send_to_char ("You can only read notes from this board.\n\r",ch);
		else
			send_to_char ("You can both read and write on this board.\n\r",ch);
		}
		send_to_char("\n\r",ch);
		return;			
	} /* if empty argument */
	
	/* Change board based on its number */
	if (is_number(argument))
	{
		count = 0;
		number = atoi(argument);
		for (i = 0; i < MAX_BOARD; i++)
			if (unread_notes(ch,&boards[i]) != BOARD_NOACCESS)		
				if (++count == number)
					break;
		
		if (count == number) /* found the board.. change to it */
		{
			ch->pcdata->board = &boards[i];
			sprintf (buf, "Current board changed to " BOLD "%s" NO_COLOR ". %s.\n\r",boards[i].short_name,
			              (get_trust(ch) < boards[i].write_level) 
			              ? "You can only read here" 
			              : "You can both read and write here");
			send_to_char (buf,ch);
		}			
		else /* so such board */
			send_to_char ("No such board.\n\r",ch);
			
		return;
	}

	/* Non-number given, find board with that name */
	
	for (i = 0; i < MAX_BOARD; i++)
		if (!str_cmp(boards[i].short_name, argument))
			break;
			
	if (i == MAX_BOARD)
	{
		send_to_char ("No such board.\n\r",ch);
		return;
	}

	/* Does ch have access to this board? */	
	if (unread_notes(ch,&boards[i]) == BOARD_NOACCESS)
	{
		send_to_char ("No such board.\n\r",ch);
		return;
	}
	
	ch->pcdata->board = &boards[i];
	sprintf (buf, "Current board changed to " BOLD "%s" NO_COLOR ". %s.\n\r",boards[i].short_name,
	              (get_trust(ch) < boards[i].write_level) 
	              ? "You can only read here" 
	              : "You can both read and write here");
	send_to_char (buf,ch);
}

/* Send a note to someone on the personal board */
void personal_message (const char *sender, const char *to, const char *subject, const int expire_days, const char *text)
{
	make_note ("Personal", sender, to, subject, expire_days, text);
}

void make_note (const char* board_name, const char *sender, const char *to, const char *subject, const int expire_days, const char *text)
{
	int board_index = board_lookup (board_name);
	BOARD_DATA *board;
	NOTE_DATA *note;
	char *strtime;
	
	if (board_index == BOARD_NOTFOUND)
	{
		bug ("make_note: board not found",0);
		return;
	}
	
	if (strlen(text) > MAX_NOTE_TEXT)
	{
		bug ("make_note: text too long (%d bytes)", strlen(text));
		return;
	}
	
	
	board = &boards [board_index];
	
	note = new_note(); /* allocate new note */
	
	note->sender = str_dup (sender);
	note->to_list = str_dup(to);
	note->subject = str_dup (subject);
	note->expire = current_time + expire_days * 60 * 60 * 24;
	note->text = str_dup (text);

	/* convert to ascii. ctime returns a string which last character is \n, so remove that */	
	strtime = ctime (&current_time);
	strtime[strlen(strtime)-1] = '\0';
	
	note->date = str_dup (strtime);
	
	finish_note (board, note);
	
}

/* tries to change to the next accessible board */
static bool next_board (CHAR_DATA *ch)
{
	int i = board_number (ch->pcdata->board) + 1;
	
	while ((i < MAX_BOARD) && (unread_notes(ch,&boards[i]) == BOARD_NOACCESS))
		i++;
		
	if (i == MAX_BOARD)
		return FALSE;
	else
	{
		ch->pcdata->board = &boards[i];
		return TRUE;
	}
}

void handle_con_note_to (DESCRIPTOR_DATA *d, char * argument)
{
	char buf [MAX_INPUT_LENGTH];
	CHAR_DATA *ch = d->character;

	if (!ch->pcdata->in_progress)
	{
		d->connected = CON_PLAYING;
		bug ("nanny: In CON_NOTE_TO, but no note in progress",0);
		return;
	}

	strcpy (buf, argument);
	smash_tilde (buf); /* change ~ to - as we save this field as a string later */

	switch (ch->pcdata->board->force_type)
	{
		case DEF_NORMAL: /* default field */
			if (!buf[0]) /* empty string? */
			{
				ch->pcdata->in_progress->to_list = str_dup (ch->pcdata->board->names);
				sprintf (buf, "Assumed default recipient: " BOLD "%s" NO_COLOR "\n\r", ch->pcdata->board->names);
				write_to_buffer (d, buf, 0);
			}
			else
				ch->pcdata->in_progress->to_list = str_dup (buf);
				
			break;
		
		case DEF_INCLUDE: /* forced default */
			if (!is_full_name (ch->pcdata->board->names, buf))
			{
				strcat (buf, " ");
				strcat (buf, ch->pcdata->board->names);
				ch->pcdata->in_progress->to_list = str_dup(buf);

				sprintf (buf, "\n\rYou did not specify %s as recipient, so it was automatically added.\n\r"
				         BOLD YELLOW "New To" NO_COLOR " :  %s\n\r",
						 ch->pcdata->board->names, ch->pcdata->in_progress->to_list);
				write_to_buffer (d, buf, 0);
			}
			else
				ch->pcdata->in_progress->to_list = str_dup (buf);
			break;
		
		case DEF_EXCLUDE: /* forced exclude */
			if (is_full_name (ch->pcdata->board->names, buf))
			{
				sprintf (buf, "You are not allowed to send notes to %s on this board. Try again.\n\r"
				         BOLD YELLOW "To" NO_COLOR ":      ", ch->pcdata->board->names);
				write_to_buffer (d, buf, 0);
				return; /* return from nanny, not changing to the next state! */
			}
			else
				ch->pcdata->in_progress->to_list = str_dup (buf);
			break;
		
	}		

	write_to_buffer (d, BOLD YELLOW "\n\rSubject" NO_COLOR ": ", 0);
	d->connected = CON_NOTE_SUBJECT;
}

void handle_con_note_subject (DESCRIPTOR_DATA *d, char * argument)
{
	char buf [MAX_INPUT_LENGTH];
	CHAR_DATA *ch = d->character;

	if (!ch->pcdata->in_progress)
	{
		d->connected = CON_PLAYING;
		bug ("nanny: In CON_NOTE_SUBJECT, but no note in progress",0);
		return;
	}

	strcpy (buf, argument);
	smash_tilde (buf); /* change ~ to - as we save this field as a string later */
	
	/* Do not allow empty subjects */
	
	if (!buf[0])		
	{
		write_to_buffer (d, "Please find a meaningful subject!\n\r",0);
		write_to_buffer (d, BOLD YELLOW "Subject" NO_COLOR ": ", 0);
	}
	else  if (strlen(buf)>60)
	{
		write_to_buffer (d, "No, no. This is just the Subject. You're note writing the note yet. Twit.\n\r",0);
	}
	else
	/* advance to next stage */
	{
		ch->pcdata->in_progress->subject = str_dup(buf);
		if (IS_IMMORTAL(ch)) /* immortals get to choose number of expire days */
		{
			sprintf (buf,"\n\rHow many days do you want this note to expire in?\n\r"
			             "Press Enter for default value for this board, " BOLD "%d" NO_COLOR " days.\n\r"
           				 BOLD YELLOW "Expire" NO_COLOR ":  ",
		                 ch->pcdata->board->purge_days);
			write_to_buffer (d, buf, 0);				               
			d->connected = CON_NOTE_EXPIRE;
		}
		else
		{
			ch->pcdata->in_progress->expire = 
				current_time + ch->pcdata->board->purge_days * 24L * 3600L;				
			sprintf (buf, "This note will expire %s\r",ctime(&ch->pcdata->in_progress->expire));
			write_to_buffer (d,buf,0);
			write_to_buffer (d, "\n\rEnter text. Type " BOLD "~" NO_COLOR " or " BOLD "END" NO_COLOR " on an empty line to end note.\n\r"
			                    "=======================================================\n\r",0);
			d->connected = CON_NOTE_TEXT;
		}
	}
}

void handle_con_note_expire(DESCRIPTOR_DATA *d, char * argument)
{
	CHAR_DATA *ch = d->character;
	char buf[MAX_STRING_LENGTH];
	time_t expire;
	int days;

	if (!ch->pcdata->in_progress)
	{
		d->connected = CON_PLAYING;
		bug ("nanny: In CON_NOTE_EXPIRE, but no note in progress",0);
		return;
	}
	
	/* Numeric argument. no tilde smashing */
	strcpy (buf, argument);
	if (!buf[0]) /* assume default expire */
		days = 	ch->pcdata->board->purge_days;
	else /* use this expire */
		if (!is_number(buf))
		{
			write_to_buffer (d,"Write the number of days!\n\r",0);
			write_to_buffer (d,BOLD YELLOW "Expire" NO_COLOR ":  ",0);
			return;
		}
		else
		{
			days = atoi (buf);
			if (days <= 0)
			{
				write_to_buffer (d, "This is a positive MUD. Use positive numbers only! :)\n\r",0);
				write_to_buffer (d, BOLD YELLOW "Expire" NO_COLOR ":  ",0);
				return;
			}
		}
			
	expire = current_time + (days*24L*3600L); /* 24 hours, 3600 seconds */

	ch->pcdata->in_progress->expire = expire;
	
	/* note that ctime returns XXX\n so we only need to add an \r */

	write_to_buffer (d, "\n\rEnter text. Type " BOLD "~" NO_COLOR " or " BOLD "END" NO_COLOR " on an empty line to end note.\n\r"
	                    "=======================================================\n\r",0);

	d->connected = CON_NOTE_TEXT;
}



void handle_con_note_text (DESCRIPTOR_DATA *d, char * argument)
{
	CHAR_DATA *ch = d->character;
	char buf[MAX_STRING_LENGTH];
	char letter[4*MAX_STRING_LENGTH];
	
	if (!ch->pcdata->in_progress)
	{
		d->connected = CON_PLAYING;
		bug ("nanny: In CON_NOTE_TEXT, but no note in progress",0);
		return;
	}

	/* First, check for EndOfNote marker */

	strcpy (buf, argument);
	if ((!str_cmp(buf, "~")) || (!str_cmp(buf, "END")))
	{
		write_to_buffer (d, "\n\r\n\r",0);
		write_to_buffer (d, szFinishPrompt, 0);
		write_to_buffer (d, "\n\r", 0);
		d->connected = CON_NOTE_FINISH;
		return;
	}
	
	smash_tilde (buf); /* smash it now */

	/* Check for too long lines. Do not allow lines longer than 80 chars */
	
	if (strlen (buf) > MAX_LINE_LENGTH)
	{
		write_to_buffer (d, "Too long line rejected. Do NOT go over 80 characters!\n\r",0);
		return;
	}
	
	/* Not end of note. Copy current text into temp buffer, add new line, and copy back */

	/* How would the system react to strcpy( , NULL) ? */		
	if (ch->pcdata->in_progress->text)
	{
		strcpy (letter, ch->pcdata->in_progress->text);
		free_string (ch->pcdata->in_progress->text);
		ch->pcdata->in_progress->text = NULL; /* be sure we don't free it twice */
	}
	else
		strcpy (letter, "");
		
	/* Check for overflow */
	
	if ((strlen(letter) + strlen (buf)) > MAX_NOTE_TEXT)
	{ /* Note too long, take appropriate steps */
		write_to_buffer (d, "Note too long!\n\r", 0);
		free_note (ch->pcdata->in_progress);
		ch->pcdata->in_progress = NULL;			/* important */
		d->connected = CON_PLAYING;
		return;			
	}
	
	/* Add new line to the buffer */
	
	strcat (letter, buf);
	strcat (letter, "\r\n"); /* new line. \r first to make note files better readable */

	/* allocate dynamically */		
	ch->pcdata->in_progress->text = str_dup (letter);
}

void handle_con_note_finish (DESCRIPTOR_DATA *d, char * argument)
{

	CHAR_DATA *ch = d->character;
	
		if (!ch->pcdata->in_progress)
		{
			d->connected = CON_PLAYING;
			bug ("nanny: In CON_NOTE_FINISH, but no note in progress",0);
			return;
		}
		
		switch (tolower(argument[0]))
		{
			case 'c': /* keep writing */
				write_to_buffer (d,"Continuing note...\n\r",0);
				d->connected = CON_NOTE_TEXT;
				break;

			case 'v': /* view note so far */
				if (ch->pcdata->in_progress->text)
				{
					write_to_buffer (d,GREEN "Text of your note so far:" NO_COLOR "\n\r",0);
					write_to_buffer (d, ch->pcdata->in_progress->text, 0);
				}
				else
					write_to_buffer (d,"You haven't written a thing!\n\r\n\r",0);
				write_to_buffer (d, szFinishPrompt, 0);
				write_to_buffer (d, "\n\r",0);
				break;

			case 'p': /* post note */
				finish_note (ch->pcdata->board, ch->pcdata->in_progress);
				write_to_buffer (d, "Note posted.\n\r",0);
				d->connected = CON_PLAYING;
				/* remove AFK status */
				ch->pcdata->in_progress = NULL;
				act (BOLD GREEN "$n finishes $s note." NO_COLOR , ch, NULL, NULL, TO_ROOM);
				break;
				
			case 'f':
				write_to_buffer (d, "Note cancelled!\n\r",0);
				free_note (ch->pcdata->in_progress);
				ch->pcdata->in_progress = NULL;
				d->connected = CON_PLAYING;
				/* remove afk status */
				break;
			
			default: /* invalid response */
				write_to_buffer (d, "Huh? Valid answers are:\n\r\n\r",0);
				write_to_buffer (d, szFinishPrompt, 0);
				write_to_buffer (d, "\n\r",0);
				
		}
}


  10420

*		       Online Building and Editing Module		    *
*****************************************************************************/

#include <sys/types.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "merc.h"

extern int top_ed;

EXTRA_DESCR_DATA *SetRExtra( ROOM_INDEX_DATA *room, char *keywords )
{
    EXTRA_DESCR_DATA *ed;
    
    for ( ed = room->first_extradesc; ed; ed = ed->next )
    {
	  if ( is_name( keywords, ed->keyword ) )
	    break;
    }
    if ( !ed )
    {
	CREATE( ed, EXTRA_DESCR_DATA, 1 );
	LINK( ed, room->first_extradesc, room->last_extradesc, next, prev
);
	ed->keyword	= STRALLOC( keywords );
	ed->description	= STRALLOC( "" );
	top_ed++;
    }
    return ed;
}

bool DelRExtra( ROOM_INDEX_DATA *room, char *keywords )
{
    EXTRA_DESCR_DATA *rmed;
    
    for ( rmed = room->first_extradesc; rmed; rmed = rmed->next )
    {
	  if ( is_name( keywords, rmed->keyword ) )
	    break;
    }
    if ( !rmed )
      return FALSE;
    UNLINK( rmed, room->first_extradesc, room->last_extradesc, next, prev
);
    STRFREE( rmed->keyword );
    STRFREE( rmed->description );
    DISPOSE( rmed );
    top_ed--;
    return TRUE;
}

EXTRA_DESCR_DATA *SetOExtra( OBJ_DATA *obj, char *keywords )
{
    EXTRA_DESCR_DATA *ed;
    
    for ( ed = obj->first_extradesc; ed; ed = ed->next )
    {
	  if ( is_name( keywords, ed->keyword ) )
	    break;
    }
    if ( !ed )
    {
	CREATE( ed, EXTRA_DESCR_DATA, 1 );
	LINK( ed, obj->first_extradesc, obj->last_extradesc, next, prev );
	ed->keyword	= STRALLOC( keywords );
	ed->description	= STRALLOC( "" );
	top_ed++;
    }
    return ed;
}

bool DelOExtra( OBJ_DATA *obj, char *keywords )
{
    EXTRA_DESCR_DATA *rmed;
    
    for ( rmed = obj->first_extradesc; rmed; rmed = rmed->next )
    {
	  if ( is_name( keywords, rmed->keyword ) )
	    break;
    }
    if ( !rmed )
      return FALSE;
    UNLINK( rmed, obj->first_extradesc, obj->last_extradesc, next, prev );
    STRFREE( rmed->keyword );
    STRFREE( rmed->description );
    DISPOSE( rmed );
    top_ed--;
    return TRUE;
}

EXTRA_DESCR_DATA *SetOExtraProto( OBJ_INDEX_DATA *obj, char *keywords )
{
    EXTRA_DESCR_DATA *ed;
    
    for ( ed = obj->first_extradesc; ed; ed = ed->next )
    {
	  if ( is_name( keywords, ed->keyword ) )
	    break;
    }
    if ( !ed )
    {
	CREATE( ed, EXTRA_DESCR_DATA, 1 );
	LINK( ed, obj->first_extradesc, obj->last_extradesc, next, prev );
	ed->keyword	= STRALLOC( keywords );
	ed->description	= STRALLOC( "" );
	top_ed++;
    }
    return ed;
}

bool DelOExtraProto( OBJ_INDEX_DATA *obj, char *keywords )
{
    EXTRA_DESCR_DATA *rmed;
    
    for ( rmed = obj->first_extradesc; rmed; rmed = rmed->next )
    {
	  if ( is_name( keywords, rmed->keyword ) )
	    break;
    }
    if ( !rmed )
      return FALSE;
    UNLINK( rmed, obj->first_extradesc, obj->last_extradesc, next, prev );
    STRFREE( rmed->keyword );
    STRFREE( rmed->description );
    DISPOSE( rmed );
    top_ed--;
    return TRUE;
}


/*
 * Function to get the equivelant exit of DIR 0-MAXDIR out of linked list.
 * Made to allow old-style diku-merc exit functions to work.	-Thoric
 */
EXIT_DATA *get_exit( ROOM_INDEX_DATA *room, sh_int dir )
{
    EXIT_DATA *xit;

    if ( !room )
    {
	bug( "Get_exit: NULL room", 0 );
	return NULL;
    }

    for (xit = room->first_exit; xit; xit = xit->next )
       if ( xit->vdir == dir )
         return xit;
    return NULL;
}

/*
 * Function to get an exit, leading the the specified room
 */
EXIT_DATA *get_exit_to( ROOM_INDEX_DATA *room, sh_int dir, int vnum )
{
    EXIT_DATA *xit;

    if ( !room )
    {
	bug( "Get_exit: NULL room", 0 );
	return NULL;
    }

    for (xit = room->first_exit; xit; xit = xit->next )
       if ( xit->vdir == dir && xit->vnum == vnum )
         return xit;
    return NULL;
}

/*
 * Function to get the nth exit of a room			-Thoric
 */
EXIT_DATA *get_exit_num( ROOM_INDEX_DATA *room, sh_int count )
{
    EXIT_DATA *xit;
    int cnt;

    if ( !room )
    {
	bug( "Get_exit: NULL room", 0 );
	return NULL;
    }

    for (cnt = 0, xit = room->first_exit; xit; xit = xit->next )
       if ( ++cnt == count )
         return xit;
    return NULL;
}

/*
 * Returns value 0 - 9 based on directional text.
 */
int get_dir( char *txt )
{
    int edir;
    char c1,c2;

    c1 = txt[0];
    if ( c1 == '\0' )
      return 0;
    c2 = txt[1];
    edir = 0;
    switch ( c1 )
    {
	  case 'n':
	  switch ( c2 )
	  {
		    default:   edir = 0; break;	/* north */
	  }
	  break;    case '0':  edir = 0; break; /* north */
	  case 'e': case '1':  edir = 1; break; /* east  */
	  case 's':
	  switch ( c2 )
	  {
		    default:   edir = 2; break; /* south */
	  }
	  break;    case '2':  edir = 2; break; /* south */
	  case 'w': case '3':  edir = 3; break; /* west	 */
	  case 'u': case '4':  edir = 4; break; /* up	 */
	  case 'd': case '5':  edir = 5; break; /* down	 */
    }
    return edir;
}

char *  const   ex_flags [] = 
{ 
"isdoor", "closed", "locked", "pickproof" 
};

char *	const	r_flags	[] =
{
"dark", "no_otrans",
"nomob", "indoors",
"private", "safe",
"solitary", "petshop",
"norecall", "noteleport",
"totaldarkness",
"blade_barrier", "arena",
"flaming", "silence"
};

char *	const	o_flags	[] =
{
"glow", "hum", "thrown",
"keep", "vanish",
"invis", "magic",
"nodrop", "bless",
"antigood", "antievil",
"antineutral", "noremove",
"inventory", "loyal",
"shadowplane"
};


char *	const	w_flags	[] =
{
"take", "finger", "neck", "body", "head", "legs", "feet", "hands", "arms",
"shield", "about", "waist", "wrist", "wield", "hold", "face"
};

char *	const	o_types	[] =
{
"none", "light", "scroll", "wand", "staff", "weapon", 
"treasure", "armor", "potion", "furniture", "trash", "container",
"drinkcon", "key", "food", "money", "boat",
"corpse", "corpse_pc", "fountain", "pill", 
"portal", "egg",
"voodoo", "stake",
"missile", "ammo",
"quest", "questcard",
"symbol", "book",
"page", "tool",
"wall", "copper",
"iron", "steel",
"adamantite", "gemstone",
"hilt"
};

char *	const	a_types	[] =
{
"none", "strength", "dexterity", "intelligence", "wisdom", "constitution",
"sex", "class", "level", "age", "height", "weight", "mana", "hit", "move",
"gold", "experience", "armor", "hitroll", "damroll", "save_para",
"save_rod","save_petri", 
"save_breath",
"save_spell",
"poly"
};

char *	const	a_flags [] =
{
"blind", "invisible", "detect_evil", "detect_invis", "detect_magic",
"detect_hidden", "shadowplane", "sanctuary", "faerie_fire", "infrared",
"curse",
"flaming", "poison", "protect", "ethereal", "sneak", "hide", "sleep",
"charm", "flying", "pass_door", "polymorph", "shadowsight", "webbed",
"tendrils", "drowfire", "zuloform", "shift", "peace", "infirmity", 
"godbless", "totalblind",
"steelshield", "monkflaming" };
/*
char *	const	act_flags [] =
{
"npc", "sentinel", "scavenger", "aggressive", "stayarea", "wimpy", "pet",
"train", "practice", "mount", "noparts", "noexp", "prototype", "r1" };
*/

char *	const	plr_flags [] =
{
"npc", "autoexit", "autoloot", "autosac", "blank", "brief", "combine", 
"prompt", "telnet_ga", "holylight", "wizinvis", "ansi", "silence", 
"vt102", "incog", "notell", "log", "deny", "freeze", "godless", 
"watcher", "acid", "challenger","challendged", 
"r1", "r2"
};

char *	const	wear_locs [] =
{
"light", "finger1", "finger2", "neck1", "neck2", "body", "head", "legs",
"feet", "hands", "arms", "shield", "about", "waist", "wrist1", "wrist2",
"wield", "hold", "third", "fourth", "r1", "r2"
};


bool can_rmodify( CHAR_DATA *ch, ROOM_INDEX_DATA *room )
{
	if ( IS_NPC( ch ) )
	  return FALSE;
	if ( get_trust( ch ) >= MAX_LEVEL - 1 )
	  return TRUE;
	if ( !IS_SET( room->room_flags, ROOM_PROTOTYPE) )
	{
	  send_to_char( "You cannot modify this room.\n\r", ch );
	  return FALSE;
	}
	
	send_to_char( "That room is not in your allocated range.\n\r", ch
);
	return FALSE;
}

bool can_oedit( CHAR_DATA *ch, OBJ_INDEX_DATA *obj )
{
	
	if ( IS_NPC( ch ) )
	  return FALSE;
	if ( get_trust( ch ) >= MAX_LEVEL - 1 )
	  return TRUE;
	if ( !IS_OBJ_STAT( obj, ITEM_PROTOTYPE) )
	{
	  send_to_char( "You cannot modify this object.\n\r", ch );
	  return FALSE;
	}

	send_to_char( "That object is not in your allocated range.\n\r",
ch );
	return FALSE;
}


bool can_mmodify( CHAR_DATA *ch, CHAR_DATA *mob )
{

	if ( mob == ch )
	  return TRUE;

	if ( !IS_NPC( mob ) )
	{
	   if ( get_trust( ch ) >= MAX_LEVEL - 1 && get_trust(ch) > 
		get_trust( mob ) )
	     return TRUE;
	   else
	     send_to_char( "You can't do that.\n\r", ch );
	     return FALSE;
	}

	if ( IS_NPC( ch ) )
	  return FALSE;
	if ( get_trust( ch ) >= MAX_LEVEL - 1 )
	  return TRUE;
	if ( !IS_SET( mob->act, ACT_PROTOTYPE) )
	{
	  send_to_char( "You cannot modify this mobile.\n\r", ch );
	  return FALSE;
	}
	
	send_to_char( "That mobile is not in your allocated range.\n\r",
ch );
	return FALSE;
}

bool can_medit( CHAR_DATA *ch, MOB_INDEX_DATA *mob )
{
	if ( IS_NPC( ch ) )
	  return FALSE;
	if ( get_trust( ch ) >= MAX_LEVEL - 1 )
	  return TRUE;
	if ( !IS_SET( mob->act, ACT_PROTOTYPE) )
	{
	  send_to_char( "You cannot modify this mobile.\n\r", ch );
	  return FALSE;
	}

	send_to_char( "That mobile is not in your allocated range.\n\r",
ch );
	return FALSE;
}

int get_otype( char *type )
{
    int x;

    for ( x = 0; x < (sizeof(o_types) / sizeof(o_types[0]) ); x++ )
      if ( !str_cmp( type, o_types[x] ) )
        return x;
    return -1;
}


int get_wearloc( char *type )
{
    int x;
    
    for ( x = 0; x < MAX_WEAR; x++ )
      if ( !str_cmp( type, wear_locs[x] ) )
        return x;
    return -1;
}

int get_exflag( char *flag )
{
    int x;
    
    for ( x = 0; x <= MAX_EXFLAG; x++ )
      if ( !str_cmp( flag, ex_flags[x] ) )
        return x;
    return -1;
}

int get_rflag( char *flag )
{
    int x;
    
    for ( x = 0; x < 32; x++ )
      if ( !str_cmp( flag, r_flags[x] ) )
        return x;
    return -1;
}

int get_oflag( char *flag )
{
    int x;

    for ( x = 0; x < 32; x++ )
      if ( !str_cmp( flag, o_flags[x] ) )
        return x;
    return -1;
}

int get_wflag( char *flag )
{
    int x;

    for ( x = 0; x < 32; x++ )
      if ( !str_cmp( flag, w_flags[x] ) )
        return x;
    return -1;
}


int get_plrflag( char *flag )
{
    int x;

    for ( x = 0; x < 32; x++ )
      if ( !str_cmp( flag, plr_flags[x] ) )
        return x;
    return -1;
}


/*
 * Simple but nice and handle line editor.			-Thoric
 */
void edit_buffer( CHAR_DATA *ch, char *argument )
{
    DESCRIPTOR_DATA *d;
    EDITOR_DATA *edit;
    char cmd[MAX_INPUT_LENGTH];
    char buf[MAX_INPUT_LENGTH];
    sh_int x, line, max_buf_lines;
    bool save;

    if ( (d = ch->desc) == NULL )
    {
	send_to_char( "You have no descriptor.\n\r", ch );
	return;
    }

   if ( d->connected != CON_EDITING )
   {
	send_to_char( "You can't do that!\n\r", ch );
	bug( "Edit_buffer: d->connected != CON_EDITING", 0 );
	return;
   }
    
   if ( ch->substate <= SUB_PAUSE )
   {
	send_to_char( "You can't do that!\n\r", ch );
      sprintf(buf,"Edit_buffer: illegal ch->substate (%d)", ch->substate
);
      bug(buf,0);
	d->connected = CON_PLAYING;
	return;
   }
   
   if ( !ch->editor )
   {
	send_to_char( "You can't do that!\n\r", ch );
	bug( "Edit_buffer: null editor", 0 );
	d->connected = CON_PLAYING;
	return;
   }
   
   edit = ch->editor;
   save = FALSE;
   max_buf_lines = 24;

   if ( ch->substate == SUB_MPROG_EDIT || ch->substate == SUB_HELP_EDIT )
     max_buf_lines = 48;

   if ( argument[0] == '/' || argument[0] == '\\' )
   {
	one_argument( argument, cmd );
	if ( !str_cmp( cmd+1, "?" ) )
	{
	    send_to_char( "Editing
commands\n\r---------------------------------\n\r", ch );
	    send_to_char( "/l              list buffer\n\r",	ch );
	    send_to_char( "/c              clear buffer\n\r",	ch );
	    send_to_char( "/d [line]       delete line\n\r",	ch );
	    send_to_char( "/g <line>       goto line\n\r",	ch );
	    send_to_char( "/i <line>       insert line\n\r",	ch );
	    send_to_char( "/r <old> <new>  global replace\n\r",	ch );
	    send_to_char( "/a              abort editing\n\r",	ch );
	    if ( get_trust(ch) > MAX_LEVEL - 4 )
	      send_to_char( "/! <command>    execute command (do not use
another editing command)\n\r",  ch );
	    send_to_char( "/s              save buffer\n\r\n\r> ",ch );
	    return;
	}
	if ( !str_cmp( cmd+1, "c" ) )
	{
	    memset( edit, '\0', sizeof(EDITOR_DATA) );
	    edit->numlines = 0;
	    edit->on_line   = 0;
	    send_to_char( "Buffer cleared.\n\r> ", ch );
	    return;
	}
	if ( !str_cmp( cmd+1, "r" ) )
	{
	    char word1[MAX_INPUT_LENGTH];
	    char word2[MAX_INPUT_LENGTH];
	    char *sptr, *wptr, *lwptr;
	    int x, count, wordln, word2ln, lineln;

	    sptr = one_argument( argument, word1 );
	    sptr = one_argument( sptr, word1 );
	    sptr = one_argument( sptr, word2 );
	    if ( word1[0] == '\0' || word2[0] == '\0' )
	    {
		send_to_char( "Need word to replace, and replacement.\n\r>", ch );
		return;
	    }
	    if ( strcmp( word1, word2 ) == 0 )
	    {
		send_to_char( "Done.\n\r> ", ch );
		return;
	    }
	    count = 0;  wordln = strlen(word1);  word2ln = strlen(word2);
	    sprintf( buf, "Replacing all occurrences of %s with %s...\n\r", word1, word2 );
	     stc(buf, ch);
	    for ( x = edit->on_line; x < edit->numlines; x++ )
	    {
		lwptr = edit->line[x];
		while ( (wptr = strstr( lwptr, word1 )) != NULL )
		{
		    sptr = lwptr;
		    lwptr = wptr + wordln;
		    sprintf( buf, "%s%s", word2, wptr + wordln );
		    lineln = wptr - edit->line[x] - wordln;
		    ++count;
		    if ( strlen(buf) + lineln > 79 )
		    {
			lineln = UMAX(0, (79 - strlen(buf)));
			buf[lineln] = '\0';
			break;
		    }
		    else
			lineln = strlen(buf);
		    buf[lineln] = '\0';
		    strcpy( wptr, buf );
		}
	    }
	    sprintf( buf, "Found and replaced %d occurrence(s).\n\r> ", count );
		stc(buf, ch);
	    return;
	}

	if ( !str_cmp( cmd+1, "i" ) )
	{
	    if ( edit->numlines >= max_buf_lines )
		send_to_char( "Buffer is full.\n\r> ", ch );
	    else
	    {
		if ( argument[2] == ' ' )
		  line = atoi( argument + 2 ) - 1;
		else
		  line = edit->on_line;
		if ( line < 0 )
		  line = edit->on_line;
		if ( line < 0 || line > edit->numlines )
		  send_to_char( "Out of range.\n\r> ", ch );
		else
		{
		  for ( x = ++edit->numlines; x > line; x-- )
			strcpy( edit->line[x], edit->line[x-1] );
		  strcpy( edit->line[line], "" );
		  send_to_char( "Line inserted.\n\r> ", ch );
		}
 	    }
	    return;
	}
	if ( !str_cmp( cmd+1, "d" ) )
	{
	    if ( edit->numlines == 0 )
		send_to_char( "Buffer is empty.\n\r> ", ch );
	    else
	    {
		if ( argument[2] == ' ' )
		  line = atoi( argument + 2 ) - 1;
		else
		  line = edit->on_line;
		if ( line < 0 )
		  line = edit->on_line;
		if ( line < 0 || line > edit->numlines )
		  send_to_char( "Out of range.\n\r> ", ch );
		else
		{
		  if ( line == 0 && edit->numlines == 1 )
		  {
			memset( edit, '\0', sizeof(EDITOR_DATA) );
			edit->numlines = 0;
			edit->on_line   = 0;
			send_to_char( "Line deleted.\n\r> ", ch );
			return;
		  }
		  for ( x = line; x < (edit->numlines - 1); x++ )
			strcpy( edit->line[x], edit->line[x+1] );
		  strcpy( edit->line[edit->numlines--], "" );
		  if ( edit->on_line > edit->numlines )
		    edit->on_line = edit->numlines;
		  send_to_char( "Line deleted.\n\r> ", ch );
		}
 	    }
	    return;
	}
	if ( !str_cmp( cmd+1, "g" ) )
	{
	    if ( edit->numlines == 0 )
		send_to_char( "Buffer is empty.\n\r> ", ch );
	    else
	    {
		if ( argument[2] == ' ' )
		  line = atoi( argument + 2 ) - 1;
		else
		{
		    send_to_char( "Goto what line?\n\r> ", ch );
		    return;
		}
		if ( line < 0 )
		  line = edit->on_line;
		if ( line < 0 || line > edit->numlines )
		  send_to_char( "Out of range.\n\r> ", ch );
		else
		{
		  edit->on_line = line;
		  sprintf( buf, "(On line %d)\n\r> ", line+1 );
		  stc(buf,ch);
		}
 	    }
	    return;
	}
	if ( !str_cmp( cmd+1, "l" ) )
	{
	    if ( edit->numlines == 0 )
	      send_to_char( "Buffer is empty.\n\r> ", ch );
	    else
	    {
	      send_to_char( "------------------\n\r", ch );
	      for ( x = 0; x < edit->numlines; x++ )
	      {
	        sprintf( buf, "%2d> %s\n\r", x+1, edit->line[x] );
	        stc(buf, ch);
	      }
	      send_to_char( "------------------\n\r> ", ch );
	    }
	    return;
	}
	if ( !str_cmp( cmd+1, "a" ) )
	{
	    send_to_char( "\n\rAborting... ", ch );
	    stop_editing( ch );
	    return;
	}
	if ( get_trust(ch) > LEVEL_IMMORTAL && !str_cmp( cmd+1, "!" ) )
	{
	    int substate = ch->substate;

	    ch->substate = SUB_RESTRICTED;
	    interpret(ch, argument+3);
	    ch->substate = substate;
	    send_to_char( "\n\r> ", ch );
	    return;
	}/*
	if ( !str_cmp( cmd+1, "s" ) )
	{
	    d->connected = CON_PLAYING;
	    do_hedit(ch, "");
            if ( !ch->last_cmd )
              return;
            (*ch->last_cmd) ( ch, "" );
            return;
	}*/
   }

   if ( edit->size + strlen(argument) + 1 >= MAX_STRING_LENGTH - 1 )
	send_to_char( "You buffer is full.\n\r", ch );
   else
   {
	if ( strlen(argument) > 79 )
	{
	  strncpy( buf, argument, 79 );
	  buf[79] = 0; 
	  send_to_char( "(Long line trimmed)\n\r> ", ch );
	}
	else
	  strcpy( buf, argument );
	strcpy( edit->line[edit->on_line++], buf );
	if ( edit->on_line > edit->numlines )
	  edit->numlines++;
	if ( edit->numlines > max_buf_lines )
	{
	  edit->numlines = max_buf_lines;
	  send_to_char( "Buffer full.\n\r", ch );
	  save = TRUE;
	}
   }

   if ( save )
   {
      d->connected = CON_PLAYING;
            if ( !ch->last_cmd )
              return;
            (*ch->last_cmd) ( ch, "" );
            return;  
   }
   send_to_char( "> ", ch );
}

/*
 * Remove carriage returns from a line
 */
char *strip_cr( char *str )
{
    static char newstr[MAX_STRING_LENGTH];
    int i, j;

    for ( i=j=0; str[i] != '\0'; i++ )
	if ( str[i] != '\r' )
	{
	  newstr[j++] = str[i];	
	}
    newstr[j] = '\0';
    return newstr;
}

void smush_tilde( char *str )
{
    int len;
    char last;
    char *strptr;
    
    strptr = str;
    
    len  = strlen( str );
    if ( len )
      last = strptr[len-1];
    else
      last = '\0';

    for ( ; *str != '\0'; str++ )
    {
	if ( *str == '~' )
	    *str = '-';
    }
    if ( len )
      strptr[len-1] = last;

    return;
}

void start_editing( CHAR_DATA *ch, char *data )
{
	EDITOR_DATA *edit;
	sh_int lines, size, lpos;
	char c;
	
	if ( !ch->desc )
	{
	   bug( "Fatal: start_editing: no desc", 0 );
	   return;
	}
	if ( ch->substate == SUB_RESTRICTED )
	   bug( "NOT GOOD: start_editing: ch->substate == SUB_RESTRICTED", 0 );

	send_to_char( "Begin entering your text now (/? = help /s = save /c = clear /l = list)\n\r", ch );
	send_to_char( "-----------------------------------------------------------------------\n\r> ", ch );
	if ( ch->editor )
	  stop_editing( ch );
	
	CREATE( edit, EDITOR_DATA, 1 );
	edit->numlines = 0;
	edit->on_line  = 0;
	edit->size     = 0;
	size = 0;  lpos = 0;  lines = 0;
	if ( !data )
	    bug("editor: data is NULL!\n\r",0);
	else
	for ( ;; )
	{  
	   c = data[size++];
	   if ( c == '\0' )
	   {
		edit->line[lines][lpos] = '\0';
		break;
	   }
	   else
	   if ( c == '\r' );
	   else
	   if ( c == '\n' || lpos > 78)
	   {
		edit->line[lines][lpos] = '\0';
		lines++;
		lpos = 0;
	   }
	   else
	     edit->line[lines][lpos++] = c;
	   if ( lines >= 49 || size > 4096 )
	   {
		edit->line[lines][lpos] = '\0';
		break;
	   }	   
	}
	edit->numlines = lines;
	edit->size = size;
	edit->on_line = lines;
	ch->editor = edit;
	ch->desc->connected = CON_EDITING;
}

char *copy_buffer( CHAR_DATA *ch )
{
   char buf[MAX_STRING_LENGTH];
   char tmp[100];
   sh_int x, len;

   if ( !ch )
   {
	bug( "copy_buffer: null ch", 0 );
	return STRALLOC( "" );
   } 

   if ( !ch->editor )
   {
	bug( "copy_buffer: null editor", 0 );
	return STRALLOC( "" );
   }

   buf[0] = '\0';
   for ( x = 0; x < ch->editor->numlines; x++ )
   {
      strcpy( tmp, ch->editor->line[x] );
      smush_tilde( tmp );
      len = strlen(tmp);
      if ( tmp && tmp[len-1] == '~' )
        tmp[len-1] = '\0';
      else
        strcat( tmp, "\n\r" );
      strcat( buf, tmp );
   }
   return STRALLOC( buf );
}

void stop_editing( CHAR_DATA *ch )
{
    DISPOSE( ch->editor );
    ch->editor = NULL;
    send_to_char( "Done.\n\r", ch );
    ch->dest_buf  = NULL;
    ch->spare_ptr = NULL;
    ch->substate  = SUB_NONE;
    if ( !ch->desc )
    {
	bug( "Fatal: stop_editing: no desc", 0 );
	return;
    }
    ch->desc->connected = CON_PLAYING;
}


/*
 * Moved into a separate function so it can be used for other things
 * ie: online help editing				-Thoric
 */
HELP_DATA *get_help( CHAR_DATA *ch, char *argument )
{
    char argall[MAX_INPUT_LENGTH];
    char argone[MAX_INPUT_LENGTH];
    char argnew[MAX_INPUT_LENGTH];
    HELP_DATA *pHelp;
    int lev;

    if ( argument[0] == '\0' )
	argument = "summary";

    if ( isdigit(argument[0]) )
    {
	lev = number_argument( argument, argnew );
	argument = argnew;
    }
    else
	lev = -2;
    /*
     * Tricky argument handling so 'help a b' doesn't match a.
     */
    argall[0] = '\0';
    while ( argument[0] != '\0' )
    {
	argument = one_argument( argument, argone );
	if ( argall[0] != '\0' )
	    strcat( argall, " " );
	strcat( argall, argone );
    }

    for ( pHelp = first_help; pHelp; pHelp = pHelp->next )
    {
	if ( pHelp->level > get_trust( ch ) )
	    continue;
	if ( lev != -2 && pHelp->level != lev )
	    continue;

	if ( is_name( argall, pHelp->keyword ) )
	    return pHelp;
    }

    return NULL;
}


/*
 * Now this is cleaner
 */
void do_help( CHAR_DATA *ch, char *argument )
{
    HELP_DATA *pHelp;

    if ( (pHelp = get_help( ch, argument )) == NULL )
    {
	send_to_char( "No help on that word.\n\r", ch );
	return;
    }

    if ( pHelp->level >= 0 && str_cmp( argument, "imotd" ) )
    {
	stc( pHelp->keyword, ch );
	stc( "\n\r", ch );
    }

    /*
     * Strip leading '.' to allow initial blanks.
     */
    if ( pHelp->text[0] == '.' )
	stc( pHelp->text+1, ch );
    else
	stc( pHelp->text, ch );
    return;
}

/*
 * Help editor							-Thoric
 *
void do_hedit( CHAR_DATA *ch, char *argument )
{
    HELP_DATA *pHelp;

    if ( !ch->desc )
    {
	send_to_char( "You have no descriptor.\n\r", ch );
	return;
    }

    switch( ch->substate )
    {
	default:
	  break;
	case SUB_HELP_EDIT:
	  if ( (pHelp = ch->dest_buf) == NULL )
	  {
		bug( "hedit: sub_help_edit: NULL ch->dest_buf", 0 );
		stop_editing( ch );
		return;
	  }
	  STRFREE( pHelp->text );
	  pHelp->text = copy_buffer( ch );
	  stop_editing( ch );
	  return;
    }
    if ( (pHelp = get_help( ch, argument )) == NULL )	
    {
	char argnew[MAX_INPUT_LENGTH];
	int lev;

	if ( isdigit(argument[0]) )
	{
	    lev = number_argument( argument, argnew );
	    argument = argnew;
	}
	else
	    lev = get_trust(ch);
	CREATE( pHelp, HELP_DATA, 1 );
	pHelp->keyword = STRALLOC( strupper(argument) );
	pHelp->text    = STRALLOC( "" );
	pHelp->level   = lev;
	add_help( pHelp );
    }
    ch->substate = SUB_HELP_EDIT;
    ch->dest_buf = pHelp;
    start_editing( ch, pHelp->text );
}
*/
/*
 * Stupid leading space muncher fix				-Thoric
 */
char *help_fix( char *text )
{
    char *fixed;

    if ( !text )
      return "";
    fixed = strip_cr(text);
    if ( fixed[0] == ' ' )
      fixed[0] = '.';
    return fixed;
}

void do_hset( CHAR_DATA *ch, char *argument )
{
    HELP_DATA *pHelp;
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];

    smash_tilde( argument );
    argument = one_argument( argument, arg1 );
    if ( arg1[0] == '\0' )
    {
	send_to_char( "Syntax: hset <field> [value] [help page]\n\r",	ch
);
	send_to_char( "\n\r",						ch
);
	send_to_char( "Field being one of:\n\r",			ch
);
	send_to_char( "  level keyword remove save\n\r",		ch
);
	return;
    }

    if ( !str_cmp( arg1, "save" ) )
    {
	FILE *fpout;

	rename( "help.are", "help.are.bak" );
	fclose( fpReserve );
	if ( ( fpout = fopen( "help.are", "w" ) ) == NULL )
	{
	   bug( "hset save: fopen", 0 );
	   perror( "help.are" );
	   fpReserve = fopen( NULL_FILE, "r" );
	   return;
	}
    
	fprintf( fpout, "#HELPS\n\n" );
	for ( pHelp = first_help; pHelp; pHelp = pHelp->next )
	    fprintf( fpout, "%d %s~\n%s~\n\n",
			pHelp->level, pHelp->keyword,
help_fix(pHelp->text) );

	fprintf( fpout, "0 $~\n\n\n#$\n" );
	fclose( fpout );
	fpReserve = fopen( NULL_FILE, "r" );
	send_to_char( "Saved.\n\r", ch );
	return;
    }
    if ( str_cmp( arg1, "remove" ) )
	argument = one_argument( argument, arg2 );

    if ( (pHelp = get_help( ch, argument )) == NULL )
    {
	send_to_char( "Cannot find help on that subject.\n\r", ch );
	return;
    }
    if ( !str_cmp( arg1, "remove" ) )
    {
	UNLINK( pHelp, first_help, last_help, next, prev );
	STRFREE( pHelp->text );
	STRFREE( pHelp->keyword );
	DISPOSE( pHelp );
	send_to_char( "Removed.\n\r", ch );
	return;
    }
    if ( !str_cmp( arg1, "level" ) )
    {
	pHelp->level = atoi( arg2 );
	send_to_char( "Done.\n\r", ch );
	return;
    }
    if ( !str_cmp( arg1, "keyword" ) )
    {
	STRFREE( pHelp->keyword );
	pHelp->keyword = STRALLOC( strupper(arg2) );
	send_to_char( "Done.\n\r", ch );
	return;
    }

    do_hset( ch, "" );
}

/*
 * Show help topics in a level range				-Thoric
 * Idea suggested by Gorog
 */
void do_hlist( CHAR_DATA *ch, char *argument )
{
    int min, max, minlimit, maxlimit, cnt;
    char arg[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    HELP_DATA *help;

    maxlimit = get_trust(ch);
    minlimit = maxlimit >= (MAX_LEVEL - 3) ? -1 : 0;
    argument = one_argument( argument, arg );
    if ( arg[0] != '\0' )
    {
	min = URANGE( minlimit, atoi(arg), maxlimit );
	if ( argument[0] != '\0' )
	    max = URANGE( min, atoi(argument), maxlimit );
	else
	    max = maxlimit;
    }
    else
    {
	min = minlimit;
	max = maxlimit;
    }
    sprintf( buf, "Help Topics in level range %d to %d:\n\r\n\r", min, max
);
	stc(buf,ch);
    for ( cnt = 0, help = first_help; help; help = help->next )
	if ( help->level >= min && help->level <= max )
	{
	    sprintf( buf, "  %3d %s\n\r", help->level, help->keyword );
	    stc(buf, ch);
	    ++cnt;
	}
    if ( cnt )
    {
	sprintf( buf, "\n\r%d pages found.\n\r", cnt );
	stc(buf,ch);
    }
    else
	send_to_char( "None found.\n\r", ch );
}





 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,
 *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
 *                                                                         *
 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
 *  Chastain, Michael Quan, and Mitchell Tse.                              *
 *                                                                         *
 *  In order to use any part of this Merc Diku Mud, you must comply with   *
 *  both the original Diku license in 'license.doc' as well the Merc       *
 *  license in 'license.txt'.  In particular, you may not remove either of *
 *  these copyright notices.                                               *
 *                                                                         *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 ***************************************************************************/

#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"

/*
 * Local functions.
 */

void	adv_spell_damage	args( ( CHAR_DATA *ch, OBJ_DATA *book, 
				OBJ_DATA *page, char *argument) );
void	adv_spell_affect	args( ( CHAR_DATA *ch, OBJ_DATA *book, 
				OBJ_DATA *page, char *argument) );
void	adv_spell_action	args( ( CHAR_DATA *ch, OBJ_DATA *book, 
				OBJ_DATA *page, char *argument) );
void	birth_write		args( ( CHAR_DATA *ch, char *argument ) );
bool	birth_ok		args( ( CHAR_DATA *ch, char *argument ) );

/* Need to get rid of those flames somehow - KaVir */


void do_devoursoul(CHAR_DATA *ch, char *argument)
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim; 
    char buf[MAX_STRING_LENGTH];
	
    argument = one_argument( argument, arg );
    
    if ( !IS_CLASS(ch, CLASS_DEMON))
	return;

    if ( arg[0] == '\0' )
    {
	send_to_char( "Whose soul do you wish to devour?\n\r", ch );
	return;
    }
    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }
    
    if (!IS_NEWFLAG(victim, AFF_ALLOW_DEMON))
    {
	stc("They have not released their soul, yet.\n\r",ch);
	return;
    }

    if ( victim->class > 0 || IS_NPC(victim))
    {
	send_to_char("You cannot wrench their soul from their deity.\n\r",ch);
	send_to_char("You feel a tugging at your soul.\n\r",victim);
	return;
    }


    victim->class = CLASS_DEMON;
    victim->generation = 1;

    set_learnable_disciplines(victim);

    set_form(victim,  0);
    victim->pcdata->perm_int -= 4;
    victim->alignment = -666;
    victim->hit = 1;
    victim->move = 1;
    save_char_obj(victim);
    save_char_obj(ch);
    sprintf(buf, "%s's soul has been devoured by %s.", victim->name, ch->name);
    do_info(ch,buf);

    /* Now demons actually have forms.  Kooky. */
    set_form(victim, FRM_LEMURE);
    look_name(victim);
    ch->hit = ch->max_hit;

    WAIT_STATE(ch, 10);
    WAIT_STATE(victim, 30);

    send_to_char("Plunging your hand deep within your victims chest, you rip out their\n\r",ch);
    send_to_char("soul, leaving a lifeless husk motionless at your feet. You have been\n\r",ch);
    send_to_char("rewarded by your diety by enrolling another follower.\n\r",ch);

    act("$N's vast demonic form towers over you.  With a mighty roar, $E
plunges $S\n\rscaly claw into your chest.  Blood sprays everywhere, and
you hear the eldritch\n\rmocking cry of conquest as your mortal
conciousness fades forever.", victim, NULL, ch, TO_CHAR);
    send_to_char("The demonic transformation *****TOTALLY DESTROYS***** you.\n\r",victim);
    send_to_char("That really did HURT!\n\r",victim);
    send_to_char("You have been KILLED!\n\r",victim);

    act("With a deafening roar, the great demon $N plunges $S claw into
$n's chest and rips out $s soul.  $n drops to the ground, lifeless.",
victim, NULL, ch, TO_NOTVICT);
}      


/*
void do_level( CHAR_DATA *ch, char *argument )
{
    char arg       [MAX_INPUT_LENGTH];
    char skill  [20];  
    char stance [20];
    one_argument( argument, arg );

    if (IS_NPC(ch)) return;  
    
    send_to_char("---------------------------=[#6 Weapon Levels#n ]=-------------------------------\n\r", ch);
    sprintf(skill,"Slice   : %-10d", ch->wpn[1]);
    send_to_char( skill, ch );
    sprintf(skill,"Stab     : %-10d", ch->wpn[2]);
    send_to_char( skill, ch );      
    sprintf(skill, "Slash  : %-10d", ch->wpn[3]);
    send_to_char( skill, ch );  
    sprintf(skill,"Whip : %-10d\n\r", ch->wpn[4]);
    send_to_char( skill, ch ); 
    sprintf(skill,"Claw    : %-10d", ch->wpn[5]);
    send_to_char( skill, ch );
    sprintf(skill,"Blast    : %-10d", ch->wpn[6]);
    send_to_char( skill, ch );
    sprintf(skill,"Pound  : %-10d", ch->wpn[7]);
    send_to_char( skill, ch );
    sprintf(skill,"Crush: %-10d\n\r", ch->wpn[8]);
    send_to_char( skill, ch );
    sprintf(skill,"Grep    : %-10d", ch->wpn[9]);
    send_to_char( skill, ch ); 
    sprintf(skill,"Bite     : %-10d", ch->wpn[10]);
    send_to_char( skill, ch );  
    sprintf(skill,"Pierce : %-10d", ch->wpn[11]);
    send_to_char( skill, ch );
    sprintf(skill,"Suck : %-10d\n\r", ch->wpn[12]);
    send_to_char( skill, ch );        
    sprintf(skill,"Unarmed : %-10d\n\r\n", ch->wpn[0]);
    send_to_char( skill, ch );    
    
    send_to_char("---------------------------=[#6 Stance Levels#n ]=--------------------------------\n\r",ch);
    sprintf(skill,"Viper  : %-10d", ch->stance[1]);
    send_to_char( skill, ch );
    sprintf(skill, "Crane   : %-10d", ch->stance[2]);
    send_to_char( skill, ch );
    sprintf(skill,  "Crab   : %-10d", ch->stance[3]);
    send_to_char( skill, ch );
    sprintf(skill,"Mongoose : %-10d\n\r", ch->stance[4]);
    send_to_char( skill, ch );
    sprintf(skill,"Bull   : %-10d", ch->stance[5]);
    send_to_char( skill, ch );
    sprintf(skill, "Mantis  : %-10d", ch->stance[6]);
    send_to_char( skill, ch );
    sprintf(skill,"Dragon : %-10d", ch->stance[7]);
    send_to_char( skill, ch );
    sprintf(skill,"Tiger    : %-10d\n\r", ch->stance[8]);
    send_to_char( skill, ch );
    sprintf(skill,"Monkey : %-10d", ch->stance[9]);
    send_to_char( skill, ch );
    sprintf(skill,"Swallow : %-10d", ch->stance[10]);
    send_to_char( skill, ch );
    sprintf(skill,"Kozudo : %-10d\n\r\n", ch->stance[12]);
    send_to_char( skill, ch );

    send_to_char("---------------------------=[#6 Spell Levels#n ]=---------------------------------\n\r", ch);
    sprintf(skill,"#5Purple#n : %-10d", ch->spl[0]);
    send_to_char( skill, ch );
    sprintf(skill,"#4Blue#n   : %-10d", ch->spl[2]);
    send_to_char( skill, ch );
    sprintf(skill,"#1Red#n : %-10d\n\r", ch->spl[1]);
    send_to_char( skill, ch );    
    sprintf(skill,"#2Green#n  : %-10d", ch->spl[3]);
    send_to_char( skill, ch );
    sprintf(skill, "#3Yellow#n : %-10d\n\r\n", ch->spl[4]);
    send_to_char( skill, ch );
    
    
    send_to_char("---------------------------=[#6 Misc. Things#n ]=---------------------------------\n\r", ch);
    sprintf(skill, "Recall Room : %d     ", ch->home);
    send_to_char( skill, ch );
    sprintf(skill, "Trust : %d\n\r", ch->trust);
    send_to_char( skill, ch );
 
     if ( ch->stance[11] == 1 )
      sprintf(stance, " Viper\n\r" );
     else if ( ch->stance[11] == 2 )
      sprintf(stance, " Crane\n\r" );
     else if ( ch->stance[11] == 3 )
      sprintf(stance, " Crab\n\r" );  
     else if ( ch->stance[11] == 4 )
      sprintf(stance, " Mongoose\n\r" );  
     else if ( ch->stance[11] == 5 )
      sprintf(stance, " Bull\n\r" );  
     else if ( ch->stance[11] == 6 )
      sprintf(stance, " Mantis\n\r" );  
     else if ( ch->stance[11] == 7 )
      sprintf(stance, " Dragon\n\r" );  
     else if ( ch->stance[11] == 8 )
      sprintf(stance, " Tiger\n\r" );  
     else if ( ch->stance[11] == 9 )
      sprintf(stance, " Monkey\n\r" );  
     else if ( ch->stance[11] == 10 )
      sprintf(stance, " Swallow\n\r" ); 
     else 
      sprintf(stance, " None\n\r" );
    
      sprintf(skill, "Autostance:  %s", stance);
      send_to_char( skill, ch );

	 send_to_char("\n---------------------------=[#6 Class Things#n ]=---------------------------------\n\r", ch);
    
    if ( IS_CLASS(ch, CLASS_DEMON) )
     send_to_char("You are a demon!\n\r", ch);
    if ( IS_CLASS(ch, CLASS_MAGE) )
     send_to_char("You are a mage!\n\r", ch);    
     if ( IS_CLASS(ch, CLASS_WEREWOLF) )
     send_to_char("You are a werewolf!\n\r", ch);
     if ( IS_CLASS(ch, CLASS_NINJA) )
     send_to_char("You are a ninja!\n\r", ch);
    if ( IS_CLASS(ch, CLASS_VAMPIRE) )
     send_to_char("You are a vampire!\n\r", ch);
    if ( IS_CLASS(ch, CLASS_HIGHLANDER) )
     send_to_char("You are a highlander!\n\r", ch);
    if ( IS_CLASS(ch, CLASS_DROW) )
     send_to_char("You are a drow!\n\r", ch);    
 
 if (IS_CLASS(ch, CLASS_VAMPIRE) )
 {

    sprintf(skill, "Generation : %d     ", ch->generation);
    send_to_char( skill, ch );	
	if (ch->pcdata->rank == AGE_METHUSELAH)
	  send_to_char("You are a Methuselah!\n\r",ch);
	else if (ch->pcdata->rank == AGE_ELDER)
	  send_to_char("You are an Elder!\n\r",ch);
	else if (ch->pcdata->rank == AGE_ANCILLA)
	  send_to_char("You are an Ancilla!\n\r",ch);
	else if (ch->pcdata->rank == AGE_NEONATE)
	  send_to_char("You are a Neonate!\n\r", ch);
	else
	  send_to_char("You are a Childe!\n\r", ch);
	if ( IS_SET(ch->special, SPC_PRINCE) )
	  send_to_char("You are a prince!\n\r", ch);
 }
 
 if (IS_CLASS(ch, CLASS_NINJA) )
 {
    sprintf(skill, "Generation : %d\n\r", ch->generation);
    send_to_char( skill, ch );	
	if ( IS_SET(ch->special, SPC_PRINCE) )
	  send_to_char("You can discipline people!\n\r", ch);
 }
 
 if (IS_CLASS(ch, CLASS_WEREWOLF) )
 {
    sprintf(skill, "Generation : %d\n\r", ch->generation);
    send_to_char( skill, ch );	
    if ( IS_SET(ch->special, SPC_SIRE) && ch->generation > 2 )
      send_to_char("You are able to spread the gift!\n\r", ch);
    if ( IS_SET(ch->special, SPC_PRINCE) && ch->generation > 2
)
	  send_to_char("You are a shaman!\n\r", ch);
 }
}
*/

void do_level( CHAR_DATA *ch, char *argument )
{
    char arg       [MAX_INPUT_LENGTH];
    char skill  [20];  
   /* char stance [20];*/
    one_argument( argument, arg );

    if (IS_NPC(ch)) return;  
    
    send_to_char("---------------------------=[#6Weapon Levels#n]=--------------------------------\n\r", ch);
    sprintf(skill,"Slice  : %-4d", ch->wpn[1]);
    send_to_char( skill, ch );
    sprintf(skill," Stab   : %-4d", ch->wpn[2]);
    send_to_char( skill, ch );      
    sprintf(skill," Slash  : %-4d", ch->wpn[3]);
    send_to_char( skill, ch );  
    sprintf(skill," Whip   : %-4d", ch->wpn[4]);
    send_to_char( skill, ch ); 
    sprintf(skill," Claw   : %-4d\n\r", ch->wpn[5]);
    send_to_char( skill, ch );
    sprintf(skill,"Blast  : %-4d", ch->wpn[6]);
    send_to_char( skill, ch );
    sprintf(skill," Pound  : %-4d", ch->wpn[7]);
    send_to_char( skill, ch );
    sprintf(skill," Crush  : %-4d", ch->wpn[8]);
    send_to_char( skill, ch );
    sprintf(skill," Grep   : %-4d", ch->wpn[9]);
    send_to_char( skill, ch ); 
    sprintf(skill," Bite   : %-4d\n\r", ch->wpn[10]);
    send_to_char( skill, ch );  
    sprintf(skill,"Pierce : %-4d", ch->wpn[11]);
    send_to_char( skill, ch );
    sprintf(skill," Suck   : %-4d", ch->wpn[12]);
    send_to_char( skill, ch );        
    sprintf(skill," Unarmed: %-4d\n\r\n", ch->wpn[0]);
    send_to_char( skill, ch );    
    
    send_to_char("---------------------------=[#6Stance Levels#n]=--------------------------------\n\r",ch);
    sprintf(skill,"Viper    : %-4d", ch->stance[1]);
    send_to_char( skill, ch );
    sprintf(skill, "Crane   : %-4d", ch->stance[2]);
    send_to_char( skill, ch );
    sprintf(skill,  "Crab   : %-4d", ch->stance[3]);
    send_to_char( skill, ch );
    sprintf(skill,"Mongoose : %-4d", ch->stance[4]);
    send_to_char( skill, ch );
    sprintf(skill,"Bull     : %-4d\n\r", ch->stance[5]);
    send_to_char( skill, ch );
    sprintf(skill, "Mantis   : %-4d", ch->stance[6]);
    send_to_char( skill, ch );
    sprintf(skill,"Dragon  : %-4d", ch->stance[7]);
    send_to_char( skill, ch );
    sprintf(skill,"Tiger  : %-4d", ch->stance[8]);
    send_to_char( skill, ch );
    sprintf(skill,"Monkey   : %-4d", ch->stance[9]);
    send_to_char( skill, ch );
    sprintf(skill,"Swallow  : %-4d\n\r", ch->stance[10]);
    send_to_char( skill, ch );
    sprintf(skill,"Kozudo   : %-10d\n\r\n", ch->stance[12]);
    send_to_char( skill, ch );
    
    send_to_char("---------------------------=[#6Spell Levels#n]=---------------------------------\n\r", ch);
    sprintf(skill,"#5Purple#n : %-4d", ch->spl[0]);
    send_to_char( skill, ch );
    sprintf(skill,"#4Blue#n : %-4d", ch->spl[2]);
    send_to_char( skill, ch );
    sprintf(skill,"#1Red#n : %-4d", ch->spl[1]);
    send_to_char( skill, ch );    
    sprintf(skill,"#2Green#n : %-4d", ch->spl[3]);
    send_to_char( skill, ch );
    sprintf(skill, "#3Yellow#n : %-4d\n\r\n", ch->spl[4]);
    send_to_char( skill, ch );
    
    
    send_to_char("---------------------------=[#6Misc. Things#n]=---------------------------------\n\r", ch);
    sprintf(skill, "Recall Room : %d     ", ch->home);
    send_to_char( skill, ch );
/*	 
     if ( ch->stance[11] == 1 )
      sprintf(stance, " Viper\n\r" );
     else if ( ch->stance[11] == 2 )
      sprintf(stance, " Crane\n\r" );
     else if ( ch->stance[11] == 3 )
      sprintf(stance, " Crab\n\r" );  
     else if ( ch->stance[11] == 4 )
      sprintf(stance, " Mongoose\n\r" );  
     else if ( ch->stance[11] == 5 )
      sprintf(stance, " Bull\n\r" );  
     else if ( ch->stance[11] == 6 )
      sprintf(stance, " Mantis\n\r" );  
     else if ( ch->stance[11] == 7 )
      sprintf(stance, " Dragon\n\r" );  
     else if ( ch->stance[11] == 8 )
      sprintf(stance, " Tiger\n\r" );  
     else if ( ch->stance[11] == 9 )
      sprintf(stance, " Monkey\n\r" );  
     else if ( ch->stance[11] == 10 )
      sprintf(stance, " Swallow\n\r" ); 
	else sprintf(stance, " None\n\r" );
    
      sprintf(skill, "Autostance:  %s", stance);
      send_to_char( skill, ch );*/

	 send_to_char("\n---------------------------=[#6Class Things#n]=---------------------------------\n\r", ch);
    
    if ( IS_CLASS(ch, CLASS_DEMON) )
     send_to_char("You are a demon!\n\r", ch);
    if ( IS_CLASS(ch, CLASS_MAGE) )
     send_to_char("You are a mage!\n\r", ch);    
     if ( IS_CLASS(ch, CLASS_WEREWOLF) )
     send_to_char("You are a werewolf!\n\r", ch);
     if ( IS_CLASS(ch, CLASS_NINJA) )
     send_to_char("You are a ninja!\n\r", ch);
    if ( IS_CLASS(ch, CLASS_VAMPIRE) )
     send_to_char("You are a vampire!\n\r", ch);
    if ( IS_CLASS(ch, CLASS_HIGHLANDER) )
     send_to_char("You are a highlander!\n\r", ch);
    if ( IS_CLASS(ch, CLASS_DROW) )
     send_to_char("You are a drow!\n\r", ch);    
 
 if (IS_CLASS(ch, CLASS_VAMPIRE) )
 {

    sprintf(skill, "Generation : %d     ", ch->generation);
    send_to_char( skill, ch );	
	if (ch->pcdata->rank == AGE_METHUSELAH)
	  send_to_char("You are a Methuselah!\n\r",ch);
	else if (ch->pcdata->rank == AGE_ELDER)
	  send_to_char("You are an Elder!\n\r",ch);
	else if (ch->pcdata->rank == AGE_ANCILLA)
	  send_to_char("You are an Ancilla!\n\r",ch);
	else if (ch->pcdata->rank == AGE_NEONATE)
	  send_to_char("You are a Neonate!\n\r", ch);
	else
	  send_to_char("You are a Childe!\n\r", ch);
	if ( IS_SET(ch->special, SPC_PRINCE) )
	  send_to_char("You are a prince!\n\r", ch);
 }
 
 if (IS_CLASS(ch, CLASS_NINJA) )
 {
    sprintf(skill, "Generation : %d\n\r", ch->generation);
    send_to_char( skill, ch );	
	if ( IS_SET(ch->special, SPC_PRINCE) )
	  send_to_char("You can discipline people!\n\r", ch);
 }
 
 if (IS_CLASS(ch, CLASS_WEREWOLF) )
 {
    sprintf(skill, "Generation : %d\n\r", ch->generation);
    send_to_char( skill, ch );	
    if ( IS_SET(ch->special, SPC_SIRE) && ch->generation > 2 )
      send_to_char("You are able to spread the gift!\n\r", ch);
    if ( IS_SET(ch->special, SPC_PRINCE) && ch->generation > 2
)
	  send_to_char("You are a shaman!\n\r", ch);
 }
}
/*
void do_autostance( CHAR_DATA *ch, char *argument )
{
	char arg       [MAX_INPUT_LENGTH];	
	int selection;
	
	one_argument( argument, arg );

    if (IS_NPC(ch)) return;  
	
    if (!str_cmp(arg,"none")    ) 
    {
    selection = STANCE_NONE;
	send_to_char("You're autostance has been removed.\n\r",ch);
	REMOVE_BIT(ch->extra, EXTRA_STANCE);
	}
    else if (!str_cmp(arg,"viper")   ) 
    {
    selection = STANCE_VIPER;
	send_to_char("Viper stance set.\n\r",ch);
	}
    else if (!str_cmp(arg,"crane")   ) 
    {
    selection = STANCE_CRANE;
	send_to_char("Crane stance set.\n\r",ch);
	}
    else if (!str_cmp(arg,"crab")    ) 
    {
    selection = STANCE_CRAB;
	send_to_char("Crab stance set.\n\r",ch);
	}
    else if (!str_cmp(arg,"mongoose")) 
    {
    selection = STANCE_MONGOOSE;
	send_to_char("Mongoose stance set.\n\r",ch);
	}
    else if (!str_cmp(arg,"bull")    ) 
    {
    selection = STANCE_BULL;
	send_to_char("Bull stance set.\n\r",ch);
	}
    else
    {
	if (!str_cmp(arg,"mantis") && ch->stance[STANCE_CRANE] >= 200 &&
	    ch->stance[STANCE_VIPER] >= 200)
	{
	    selection = STANCE_MANTIS;
	    send_to_char("Mantis stance set.\n\r",ch);
	}
	else if (!str_cmp(arg,"dragon") && ch->stance[STANCE_BULL] >= 200
&&
	    ch->stance[STANCE_CRAB] >= 200)
	{
	    selection = STANCE_DRAGON;
	    send_to_char("Dragon stance set.\n\r",ch);
	}
	else if (!str_cmp(arg,"tiger") && ch->stance[STANCE_BULL] >= 200
&&
	    ch->stance[STANCE_VIPER] >= 200)
	{
	    selection = STANCE_TIGER;
	    send_to_char("Tiger stance set.\n\r",ch);
	}
	else if (!str_cmp(arg,"monkey") && ch->stance[STANCE_CRANE] >= 200
&&
	    ch->stance[STANCE_MONGOOSE] >= 200)
	{
	    selection = STANCE_MONKEY;
	    send_to_char("Monkey stance set.\n\r",ch);
	}
	else if (!str_cmp(arg,"swallow") && ch->stance[STANCE_CRAB] >= 200
&&
	    ch->stance[STANCE_MONGOOSE] >= 200)
	{
	    selection = STANCE_SWALLOW;
	    send_to_char("Swallow  stance set.\n\r",ch);
	}
	else if (!str_cmp(arg,"kozudo") && ch->stance[STANCE_SWALLOW] >= 200
	&& ch->stance[STANCE_TIGER] >= 200 && ch->stance[STANCE_DRAGON] >= 200
	&& ch->stance[STANCE_MONKEY] >= 200 && ch->stance[STANCE_MANTIS] >= 200)
	{
	selection = STANCE_KOZUDO;
	send_to_char("Kozudo stance set.\n\r",ch);
	}
	else
	{
	    send_to_char("Syntax is: autostance <style>.\n\r",ch);
	    send_to_char("Autotance being one of: None, Viper, Crane,Crab, Mongoose, Bull.\n\r",ch);
	    send_to_char("      If you know them:  Mantis, Dragon, Tiger, Monkey, Swallow.\n\r",ch);
	    return;
	}
    }
    ch->stance[11] = selection;
    SET_BIT(ch->extra, EXTRA_STANCE);
    return;
}
*/



void do_smother( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char arg[MAX_INPUT_LENGTH];
    ROOM_INDEX_DATA *inroom;
    one_argument( argument, arg );
    if (IS_NPC( ch )) return;
    inroom=ch->in_room;
    if ( arg[0] == '\0' && !IS_SET(inroom->room_flags,ROOM_FLAMING))
    {
	send_to_char( "Smother whom?\n\r", ch );
	return;
    }
    
    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( ch == victim )
    {
	send_to_char( "You cannot smother yourself.\n\r", ch );
	return;
    }

    if (!IS_AFFECTED(victim, AFF_FLAMING))
    {
	send_to_char( "But they are not on fire!\n\r", ch );
	return;
    }

    if ( number_percent() > (ch->level) )
    {
	act( "You try to smother the flames around $N but fail!",  ch, NULL, victim, TO_CHAR    );
	act( "$n tries to smother the flames around you but fails!", ch, NULL, victim, TO_VICT    );
	act( "$n tries to smother the flames around $N but fails!",  ch, NULL, victim, TO_NOTVICT );
	if ( number_percent() > 98 && !IS_AFFECTED(ch,AFF_FLAMING) )
	{
	    act( "A spark of flame from $N's body sets you on fire!",  ch, NULL, victim, TO_CHAR    );
	    act( "A spark of flame from your body sets $n on fire!", ch, NULL, victim, TO_VICT    );
	    act( "A spark of flame from $N's body sets $n on fire!",  ch, NULL, victim, TO_NOTVICT );
	    SET_BIT(ch->affected_by, AFF_FLAMING);
	    do_humanity(ch,"");
	}
	return;
    }

    act( "You manage to smother the flames around $M!",  ch, NULL, victim, TO_CHAR    );
    act( "$n manages to smother the flames around you!", ch, NULL, victim, TO_VICT    );
    act( "$n manages to smother the flames around $N!",  ch, NULL, victim, TO_NOTVICT );
    REMOVE_BIT(victim->affected_by, AFF_FLAMING);
    do_humanity(ch,"");
    return;
}

void do_introduce( CHAR_DATA *ch, char *argument )
{
    char      arg [MAX_INPUT_LENGTH];
    char      buf [MAX_STRING_LENGTH];
    argument = one_argument( argument, arg );


    if (IS_NPC(ch)) return;

    if (IS_CLASS(ch, CLASS_VAMPIRE) && ch->generation > 0 && ch->generation < 14)
    {
      if ( ch->generation == 1 )
      {
	sprintf(buf,"My name is %s.  I am of the First Generation.  I am the Sire of all Kindred.\n\r", ch->name);
	do_say(ch,buf);
      }
      else if ( ch->generation == 2 )
      {
	sprintf(buf,"My name is %s.  I am of the Second Generation.  My
sire is Lobo.\n\r",ch->name );
	do_say(ch,buf);
      }
      else if ( ch->generation == 3 )
      {
	sprintf(buf,"My name is %s.  I am of the Third Generation.  My
sire is Lobo.\n\r",ch->name );
	do_say(ch, buf);
      }
      else if ( ch->generation > 3 )
      {
	sprintf(buf,"My name is %s.  I am of the %dth Generation.  My sire
is Lobo.\n\r",ch->name, ch->generation );
	do_say(ch,buf);
      }
      else return;
    }
    else if (IS_CLASS(ch, CLASS_WEREWOLF) && IS_HERO(ch) &&
        ch->generation > 0 && ch->generation < 7)
    {
	if ( ch->generation == 1 )
	{
	  sprintf(buf,"My name is %s.  I am the chosen champion of Gaia.\n\r",ch->name );
	  do_say(ch,buf);
	}
	else if ( ch->generation > 1 )
	{
	  sprintf(buf,"My name is %s.  I am the pup of Gaia.",ch->name );
	  do_say(ch,buf);
	}
        return;
    }
    else send_to_char("Huh?\n\r",ch);
    return;
}  


/* Loads of Vampire powers follow.  KaVir */
void do_coil( CHAR_DATA *ch, char *argument )
{
    if (IS_NPC(ch)) return;
    if (!IS_CLASS(ch, CLASS_VAMPIRE))
    {
      send_to_char("Huh?\n\r", ch);
      return;
    }
    if (ch->power[DISC_VAMP_SERP] < 8)
    {
      send_to_char("You require level 8 Serpentis to use Body Coil.\n\r", ch);
      return;
    }
    if (!IS_SET(ch->newbits, NEW_COIL))
    {
     send_to_char("You prepare to coil your victims.\n\r", ch);
     SET_BIT(ch->newbits, NEW_COIL);
     return;
    }
    else if (IS_SET(ch->newbits, NEW_COIL))
    {
     send_to_char("You stand down from your coil posture.\n\r", ch);
     REMOVE_BIT(ch->newbits, NEW_COIL);
     return;
    }
 return;
}

void do_tide( CHAR_DATA *ch, char *argument )
{
    if (IS_NPC(ch)) return;
    if (!IS_CLASS(ch, CLASS_VAMPIRE))
    {
      send_to_char("Huh?\n\r", ch);
      return;
    }
    if (ch->power[DISC_VAMP_THAU] < 5)
    {
      send_to_char("You require level 5 Thaumaturgy to use Tide of Vitae.\n\r", ch);
      return;
    }

    if (ch->practice < 10)
    {
     send_to_char("You require at least 10 primal to use Tide of Vitae.\n\r",ch);
     return;
    }

    if (IS_SET(ch->newbits, NEW_TIDE))
    {send_to_char("The tide is already with you.\n\r",ch); return;}
    SET_BIT(ch->newbits, NEW_TIDE);
    ch->practice -= 10;
    send_to_char("You feel a tide of vitae rush over you.\n\r",ch);
 
 
}

void do_flash( CHAR_DATA *ch, char *argument )
{
   char       buf[MAX_STRING_LENGTH];
 
    if (IS_NPC(ch)) return;
    if (!IS_CLASS(ch, CLASS_VAMPIRE))
    {
      send_to_char("Huh?\n\r", ch);
      return;
    }
    if (ch->power[DISC_VAMP_QUIE] < 9)
    {
      send_to_char("You require level 9 Quietus to use Flashing Speed.\n\r", ch);
      return;
    }
    if (IS_EXTRA(ch, EXTRA_FLASH))
    {
     send_to_char("You are already moving swiftly.\n\r", ch);
     return;
    }
    if (ch->pcdata->condition[COND_THIRST] < 200)
    {
     send_to_char("You have insufficient blood.\n\r",ch);
     return;
    }
    SET_BIT(ch->extra, EXTRA_FLASH);
    ch->power[DISC_VAMP_CELE] += 2;
    ch->pcdata->condition[COND_THIRST] -= 200;
    sprintf(buf, "%s starts moving with lightening speed.",ch->name);
    act(buf,ch,NULL,NULL,TO_ROOM);
    send_to_char("You start moving with lightening speed.\n\r",ch);
    return;
}
void do_death( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    ROOM_INDEX_DATA *inroom;
    inroom= ch->in_room;
 
    if (IS_NPC(ch)) return;
    if (!IS_CLASS(ch, CLASS_VAMPIRE))
    {
      send_to_char("Huh?\n\r", ch);
      return;
    }
    if (ch->power[DISC_VAMP_QUIE] < 5)
    {
      send_to_char("You require level 5 Quietus to use Silence of Death.\n\r", ch);
      return;
    }
    if (RTIMER(ch->in_room, RTIMER_SILENCE) != 0)
    {
     sprintf(buf,"The silence leaves the room.\n\r");
     act(buf,ch,NULL,NULL,TO_ROOM);
     send_to_char("The silence leaves the room.\n\r", ch);
     SET_RTIMER(ch->in_room, RTIMER_SILENCE, 0);
     return;
    }
    if (ch->pcdata->condition[COND_THIRST] < 300)
    {
     send_to_char("You have insufficient blood.\n\r", ch);
     return;
    }
    ch->pcdata->condition[COND_THIRST] -= 300;
    SET_RTIMER(inroom, RTIMER_SILENCE, 10);
    sprintf(buf,"A look of concentration passes over %s's face.\n\r", ch->name);
    act(buf,ch,NULL,NULL,TO_ROOM);
    send_to_char("A look of concentration passes over your face.\n\r",ch);
    sprintf(buf,"An eerie silence fills the room.\n\r");
    act(buf,ch,NULL,NULL,TO_ROOM);
    send_to_char(buf,ch);
    return;
}

void do_acid( CHAR_DATA *ch, char *argument )
{
    if (IS_NPC(ch)) return;
    if (!IS_CLASS(ch, CLASS_VAMPIRE))
    {
      send_to_char("Huh?\n\r", ch);
      return;
    }
    if (ch->power[DISC_VAMP_DOMI] < 4)
    {
      send_to_char("You require level 9 Vicissitude to use Acid Blood.\n\r", ch);
      return;
    }
    if (ch->pcdata->condition[COND_THIRST] < 500)
    {
     send_to_char("You have insufficient blood.\n\r", ch);
     return;
    }
    if (IS_SET(ch->act, PLR_ACID))
    {
     send_to_char("Your blood is already acid.\n\r",ch);
     return;
    }
    SET_BIT(ch->act, PLR_ACID);
    send_to_char("Your blood turns to a potent acid.\n\r", ch);
    return;
}

void do_retrn( CHAR_DATA *ch, char *argument )
{
    ROOM_INDEX_DATA *location;
 
    act( "$n raises $s arms to the sky.", ch, NULL, NULL, TO_ROOM );
    act( "Your raise your arms to the sky.", ch, NULL, NULL, TO_CHAR );
 
    if (IS_NPC(ch)) return;
 
    if (!IS_CLASS(ch, CLASS_VAMPIRE))
    {
	send_to_char( "Huh?\n\r", ch );
	return;
    }
    location = get_room_index(27000);
    if (ch->power[DISC_VAMP_OBFU] < 8)
    {
     send_to_char("You must obtain at least level 8 in Obuscate to Return to Caine.\n\r", ch);
     return;
    }
    if (ch->pcdata->condition[COND_THIRST] < 250)
    {
	send_to_char("You have insufficient blood.\n\r", ch);
        return;
    }
    if (ch->practice < 20)
    {
	send_to_char("You need 20 primal to use Return to Caine.\n\r", ch);
	return;
    }
    if ( ch->in_room == location )
	return;
    ch->pcdata->condition[COND_THIRST] -= 250;
    ch->practice -= 20;
    act( "$n disappears.", ch, NULL, NULL, TO_ROOM );
    char_from_room( ch );
    char_to_room( ch, location );
    act( "$n appears in the room.", ch, NULL, NULL, TO_ROOM );
    do_look( ch, "auto" );
    return;
}

void do_forget( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char      arg1[MAX_INPUT_LENGTH];
    char      arg2[MAX_INPUT_LENGTH];
 
 
    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );
 
    if (IS_NPC(ch)) return;
 
    if (!IS_CLASS(ch, CLASS_VAMPIRE))
    {
	send_to_char( "Huh?\n\r", ch );
	return;
    }
 
    if (ch->power[DISC_VAMP_DOMI] < 8)
    {
        send_to_char("You must obtain at least level 8 in Dominate to use Forgetful Mind.\n\r",ch);
	return;
    }
 
 
    if ( arg1[0] == '\0' )
    {
        send_to_char( "Force whom to forget what disc?\n\r", ch );
	return;
    }
    if ( ( victim = get_char_room( ch, arg1 ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }
    if (IS_NPC(victim))
    {
        send_to_char("Why use Forgetful Mind on a mob?\n\r", ch);
        return;
    }
    if (!IS_CLASS(victim, CLASS_VAMPIRE))
    {
        send_to_char("Only useful on vamps?\n\r", ch);
        return;
    }
 
 
    if ( IS_IMMORTAL(victim) && victim != ch )
    {
        send_to_char( "You can only use Forgetful Mind on Avatar's or lower.\n\r", ch );
	return;
    }
    if (ch->pcdata->condition[COND_THIRST] < 250)
    {
    send_to_char("You have insufficient blood.\n\r", ch);
    return;
    }
 
    if (ch->practice < 25)
    {
    send_to_char("You need 25 primal to use Forgetful Mind.\n\r", ch);
    return;
    }
 
    act("You close your eyes and concentrate on $N.", ch,NULL,victim,TO_CHAR);
    act("$n closes $s eyes and concentrates on you.", ch,NULL,victim,TO_VICT);
    act("$n closes $s eyes and cencentrates on $N.", ch,NULL,victim,TO_NOTVICT);
    ch->pcdata->condition[COND_THIRST] -= 250;
    ch->practice -= 25;
    WAIT_STATE(ch, 12);
    
 
    if ( number_percent() > 10)
    {
        send_to_char("You failed.\n\r",ch);
        return;
    }
 
    if ( !str_cmp(arg2,"animalism") )
    {
    victim->power[DISC_VAMP_ANIM] -= 1;
    act("Your mind becomes hazy about Animalism.", victim,NULL,NULL,TO_CHAR);
    act("$n blinks $s eyes for a moment.", victim,NULL,NULL,TO_ROOM);
    return;
    }
    if ( !str_cmp(arg2,"celerity") )
    {
    victim->power[DISC_VAMP_CELE] -= 1;
    act("Your mind becomes hazy about Celerity.", victim,NULL,NULL,TO_CHAR);
    act("$n blinks $s eyes for a moment.", victim,NULL,NULL,TO_ROOM);
    return;
    }
    if ( !str_cmp(arg2,"dominate") )
    {
    victim->power[DISC_VAMP_DOMI] -= 1;
    act("Your mind becomes hazy about Dominate.", victim,NULL,NULL,TO_CHAR);
    act("$n blinks $s eyes for a moment.", victim,NULL,NULL,TO_ROOM);
    return;
    }
    if ( !str_cmp(arg2,"fortitude") )
    {
    victim->power[DISC_VAMP_FORT] -= 1;
    act("Your mind becomes hazy about Fortitude.", victim,NULL,NULL,TO_CHAR);
    act("$n blinks $s eyes for a moment.", victim,NULL,NULL,TO_ROOM);
    return;
    }
    if ( !str_cmp(arg2,"auspex") )
    {
    victim->power[DISC_VAMP_AUSP] -= 1;
    act("Your mind becomes hazy about Auspex.", victim,NULL,NULL,TO_CHAR);
    act("$n blinks $s eyes for a moment.", victim,NULL,NULL,TO_ROOM);
    return;
    }
    if ( !str_cmp(arg2,"obfuscate") )
    {
    victim->power[DISC_VAMP_OBFU] -= 1;
    act("Your mind becomes hazy about Obfuscate.", victim,NULL,NULL,TO_CHAR);
    act("$n blinks $s eyes for a moment.", victim,NULL,NULL,TO_ROOM);
    return;
    }
    if ( !str_cmp(arg2,"obtenebration") )
    {
    victim->power[DISC_VAMP_OBTE] -= 1;
    act("Your mind becomes hazy about Obtenebration.", victim,NULL,NULL,TO_CHAR);
    act("$n blinks $s eyes for a moment.", victim,NULL,NULL,TO_ROOM);
    return;
    }
    if ( !str_cmp(arg2,"presence") )
    {
    victim->power[DISC_VAMP_PRES] -= 1;
    act("Your mind becomes hazy about Presence.", victim,NULL,NULL,TO_CHAR);
    act("$n blinks $s eyes for a moment.", victim,NULL,NULL,TO_ROOM);
    return;
    }
    if ( !str_cmp(arg2,"potence") )
    {
    victim->power[DISC_VAMP_POTE] -= 1;
    act("Your mind becomes hazy about Potence.", victim,NULL,NULL,TO_CHAR);
    act("$n blinks $s eyes for a moment.", victim,NULL,NULL,TO_ROOM);
    return;
    }
    if ( !str_cmp(arg2,"protean") )
    {
    victim->power[DISC_VAMP_PROT] -= 1;
    act("Your mind becomes hazy about Protean.", victim,NULL,NULL,TO_CHAR);
    act("$n blinks $s eyes for a moment.", victim,NULL,NULL,TO_ROOM);
    return;
    }
    if ( !str_cmp(arg2,"quietus") )
    {
    victim->power[DISC_VAMP_QUIE] -= 1;
    act("Your mind becomes hazy about Quietus.", victim,NULL,NULL,TO_CHAR);
    act("$n blinks $s eyes for a moment.", victim,NULL,NULL,TO_ROOM);
    return;
    }
    if ( !str_cmp(arg2,"serpentis") )
    {
    victim->power[DISC_VAMP_SERP] -= 1;
    act("Your mind becomes hazy about Serpentis.", victim,NULL,NULL,TO_CHAR);
    act("$n blinks $s eyes for a moment.", victim,NULL,NULL,TO_ROOM);
    return;
    }
    if ( !str_cmp(arg2,"thaumaturgy") )
    {
    victim->power[DISC_VAMP_THAU] -= 1;
    act("Your mind becomes hazy about Thaumaturgy.", victim,NULL,NULL,TO_CHAR);
    act("$n blinks $s eyes for a moment.", victim,NULL,NULL,TO_ROOM);
    return;
    }
    if ( !str_cmp(arg2,"vicissitude") )
    {
    victim->power[DISC_VAMP_VICI] -= 1;
    act("Your mind becomes hazy about Vicissitude.", victim,NULL,NULL,TO_CHAR);
    act("$n blinks $s eyes for a moment.", victim,NULL,NULL,TO_ROOM);
    return;
    }
 
return;
 
}
 
 

void do_rot( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char      arg [MAX_INPUT_LENGTH];
 
    argument = one_argument( argument, arg );
 
    if (IS_NPC(ch)) return;
 
    if (!IS_CLASS(ch, CLASS_VAMPIRE))
    {
	send_to_char( "Huh?\n\r", ch );
	return;
    }
 
    if (ch->power[DISC_VAMP_VICI] < 2)
    {
        send_to_char("You must obtain at level 2 in Thanatosis to use Putrefaction.\n\r",ch);
	return;
    }
 
 
    if ( arg[0] == '\0' )
    {
        send_to_char( "Who do you wish to use Putrefaction on?\n\r", ch );
	return;
    }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if (IS_NPC(victim))
    {
        send_to_char("Why use Putrefaction on a mob?\n\r", ch);
        return;
    }

    if ( IS_IMMORTAL(victim) && victim != ch )
    {
        send_to_char( "You can only use Putrefaction on Avatar's or lower.\n\r", ch );
	return;
    }

    if (is_safe(ch,victim) == TRUE) return;

    if (victim->hit < victim->max_hit)
    {
      send_to_char("They are hurt and suspicious.\n\r", ch);
      return;
    }
    act("You close your eyes and concentrate on $N.", ch,NULL,victim,TO_CHAR);
    act("$n closes $s eyes and concentrates on you.", ch,NULL,victim,TO_VICT);
    act("$n closes $s eyes and cencentrates on $N.", ch,NULL,victim,TO_NOTVICT);
    WAIT_STATE(ch, 12);
    if (number_percent( ) < 50)
    {
        send_to_char("You failed.\n\r",ch);
        return;
    }
 
    act("Your flesh begins to rot!", victim,NULL,NULL,TO_CHAR);
    act("$n's flesh begins to rot!", victim,NULL,NULL,TO_ROOM);
    SET_BIT(victim->extra, EXTRA_ROT);
    return;
}
 

void do_dragon (CHAR_DATA *ch, char *argument)
{
        CHAR_DATA *victim;
        char buf[MAX_STRING_LENGTH];
        int dam;
 
        if (IS_NPC(ch)) return;
        if (!IS_CLASS(ch, CLASS_VAMPIRE))
        {
         send_to_char("Huh?\n\r", ch);
         return;
        }
        if (ch->power[DISC_VAMP_VICI] < 8)
        {
         send_to_char("You must have at least level 8 Vicissitude to use Dragon Breath.\n\r",ch);
         return;
        }
        if ((victim = ch->fighting) == NULL)
	{
	send_to_char("You aren't fighting anyone.\n\r", ch);
	return;
	}
        if (!IS_EXTRA(ch,EXTRA_DRAGON))
        {
        send_to_char("You must be in Dragonform to use Dragonbreath.\n\r",ch);
        return;
        }
        if (ch->pcdata->condition[COND_THIRST] < 6)
        {
         send_to_char("You have insufficient blood.\n\r", ch);
         return;
        }
        WAIT_STATE(ch, 12);
        if (!IS_NPC(victim))
        {
         dam = ch->power[DISC_VAMP_VICI] * 50;
        }
        if (IS_NPC(victim))
        {
         dam = ch->power[DISC_VAMP_VICI] * 200;
        }
        ch->pcdata->condition[COND_THIRST] -= 6;
        if ((!IS_NPC(victim)) && IS_CLASS(victim, CLASS_VAMPIRE))
        {
         dam *= 1.5;
        }
        if ((!IS_NPC(victim)) && IS_CLASS(victim, CLASS_WEREWOLF))
        {
         if (ch->power[DISC_WERE_BOAR] > 2) dam *= 1.5;
        }
 
        if (dam <= 0)
          dam = 1;
sprintf(buf,"Your flame fries $N! [%d]\n\r",dam);
act(buf,ch,NULL,victim,TO_CHAR);
sprintf(buf,"$n's flame fries you! [%d]\n\r",dam);
act(buf,ch,NULL,victim,TO_VICT);
sprintf(buf,"$n's flame fries $N! [%d]\n\r",dam);
act(buf,ch,NULL,victim,TO_NOTVICT);
 

        victim->hit -= dam;
     if(!IS_AFFECTED(victim,AFF_FLAMING)) SET_BIT(victim->affected_by,AFF_FLAMING);
 
       return;
}         

void do_satan( CHAR_DATA *ch, char *argument )
{
    char buf [MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    AFFECT_DATA af;

    if (IS_NPC(ch)) return;
    if (!IS_CLASS(ch, CLASS_VAMPIRE))
    {
      send_to_char("Huh?\n\r", ch);
      return;
    }
    if (ch->power[DISC_VAMP_DAIM] < 10)
    {
      send_to_char("You require level 10 Daimoinon to use Call of Satan.\n\r", ch);
      return;
    }
 
    if (ch->pcdata->followers > 0)
    {
	send_to_char("Only one Satan can exist in this world.\n\r",ch);
	return;
    }
    if (ch->pcdata->condition[COND_THIRST] < 750)
    {
        send_to_char("You have insufficient blood.\n\r", ch);
	return;
    }
    ch->pcdata->condition[COND_THIRST] = ch->pcdata->condition[COND_THIRST] - 750;
    ch->pcdata->followers++;
 
    victim=create_mobile( get_mob_index( MOB_VNUM_SATAN ) );
    victim->level = 800;
    victim->hit = 30000;
    victim->max_hit = 30000;
    victim->hitroll = 1500;
    victim->damroll = 1500;
    victim->armor = 6000;
 
    strcpy(buf,"Lord of all Evil, Join me to crush those who oppose us!");
    do_say( ch, buf );
 
    send_to_char( "You hear a loud tremor and Satan appears before you.\n\r",ch );
    act( "The ground roars and $N bursts appears before $n.", ch, NULL, victim, TO_ROOM );
 
    char_to_room( victim, ch->in_room );
 
    add_follower( victim, ch );
    af.duration  = 666;
    af.location  = APPLY_NONE;
    af.modifier  = 0;
    af.bitvector = AFF_CHARM;
    affect_to_char( victim, &af );

    SET_BIT(victim->act, ACT_NOEXP);
    return;

}
 

void do_awe    ( CHAR_DATA *ch, char *argument )
{
	if (IS_NPC(ch)) return;
        if (!IS_CLASS(ch, CLASS_VAMPIRE))
	{
	  send_to_char("Huh?\n\r", ch);
          return;
        }
        if (ch->power[DISC_VAMP_PRES] < 1)
	{
	  send_to_char("You must obtain at least level 1 in Presence to you Awe.\n\r", ch);
	  return;
	}
        if (IS_EXTRA(ch, EXTRA_AWE))
	{
	  REMOVE_BIT(ch->extra, EXTRA_AWE);
	  send_to_char("You are no longer Awe Inspiring.\n\r", ch);
	  act("$n is no longer awe inspiring.", ch, NULL, NULL, TO_ROOM);
	  return;
	}
        SET_BIT(ch->extra, EXTRA_AWE);
	send_to_char("You are now Awe Inspiring.\n\r", ch);
	act("$n is now awe inspiring", ch, NULL, NULL, TO_ROOM);
        return;


}
void do_potency( CHAR_DATA *ch, char *argument )
{

	if (IS_NPC(ch)) return;
        if (!IS_CLASS(ch, CLASS_VAMPIRE))
        {
	  send_to_char("Huh?\n\r", ch);
	  return;
        }
        if (ch->power[DISC_VAMP_THAU] < 3)
	{ 
	  send_to_char("You must obtain at least level 3 in Thaumaturgy to use Blood Potency.\n\r", ch);
          return;
        }
        if (IS_EXTRA(ch, EXTRA_POTENCY))
        {
	  send_to_char("Your blood is already potent.\n\r", ch);
          return;
	}
	if (ch->pcdata->condition[COND_THIRST] < 300)
	{
	  send_to_char("You have insufficient blood.\n\r", ch);
	  return;
	}
        if (ch->generation == 3)
        {
	  send_to_char("Your blood is as potent as it can get.\n\r", ch);
	  return;
	}	
      
        ch->pcdata->condition[COND_THIRST] = ch->pcdata->condition[COND_THIRST] - 300;
	ch->generation = ch->generation - 1;
        SET_BIT(ch->extra, EXTRA_POTENCY);
        send_to_char("You feel your blood become more potent.\n\r", ch);
        return;

}


void do_plasma( CHAR_DATA *ch, char *argument )
{
    OBJ_DATA *obj;
    
     if ( IS_NPC(ch) )
	return;
 
    if (!IS_CLASS(ch, CLASS_VAMPIRE)) 
    {
	send_to_char("Huh?\n\r", ch);
	return;
    }

    if (ch->power[DISC_VAMP_VICI] < 5)
    {
       send_to_char("You must obtain at least level 5 in Vicissitude to use Plasma Form.\n\r", ch);
       return;
    }
 
save_char_obj(ch);

  if ((obj = create_object(get_obj_index( 30007),60)) == NULL)
    {
        send_to_char( "Error - Please inform Maser.\n\r", ch);
	return;
    }

    if ( IS_EXTRA(ch, EXTRA_PLASMA) )
    {
      ch->pcdata->obj_vnum = 0;
      REMOVE_BIT(ch->affected_by, AFF_POLYMORPH);
      REMOVE_BIT(ch->extra, EXTRA_OSWITCH);
      REMOVE_BIT(ch->extra, EXTRA_PLASMA);
      ch->pcdata->chobj = NULL;
      obj->chobj = NULL;
      free_string(ch->morph);
      ch->morph = str_dup("");
      act("$p transforms into $n.",ch,obj,NULL,TO_ROOM);
      act("Your reform your human body.",ch,obj,NULL,TO_CHAR);
      extract_obj( obj );
      return;
                
    }
    
    if ( IS_AFFECTED(ch, AFF_POLYMORPH) )
    {
	send_to_char( "Not while polymorphed.\n\r", ch );
	return;
    }
    act("$n transforms into $p and splashes to the ground.",ch,obj,NULL,TO_ROOM);
    act("You transform into $p and splashes to the ground.",ch,obj,NULL,TO_CHAR);
    ch->pcdata->obj_vnum = ch->pcdata->powers[VPOWER_OBJ_VNUM];
    obj->chobj = ch;
    ch->pcdata->chobj = obj;
    SET_BIT(ch->affected_by, AFF_POLYMORPH);
    SET_BIT(ch->extra, EXTRA_OSWITCH);
    SET_BIT(ch->extra, EXTRA_PLASMA);
    free_string(ch->morph);
    ch->morph = str_dup("a pool of blood");
    obj_to_room(obj,ch->in_room);
    return;
}
 
void do_taste( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char      buf [MAX_STRING_LENGTH];
    char      age [MAX_STRING_LENGTH];
    char      lin [MAX_STRING_LENGTH];
    char     lord [MAX_STRING_LENGTH];
    char      arg [MAX_INPUT_LENGTH];

    argument = one_argument (argument, arg );

    if (IS_NPC(ch)) return;
 
    if (!IS_CLASS(ch, CLASS_VAMPIRE))
    {
	send_to_char( "Huh?\n\r", ch );
	return;
    }
 
    if (ch->power[DISC_VAMP_THAU] < 1)
    {
        send_to_char("You must obtain at least level 1 in Thaumaturgy to use Taste of Blood.\n\r",ch);
	return;
    }
 
       if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if (!IS_CLASS(victim, CLASS_VAMPIRE))
    {
        send_to_char( "Only useful on vampire targets.\n\r",ch);
        return;
    }

    if (IS_NPC(victim))
    {
        send_to_char( "Only useful on vampire targets.\n\r",ch);
        return;
    }                               

sprintf(buf,"You examine $N's blood carefully.\n\r");
act(buf,ch,NULL,victim,TO_CHAR);
sprintf(buf,"$n examines your blood carefully.\n\r");
act(buf,ch,NULL,victim,TO_VICT);
sprintf(buf,"$n examines $N's blood carefully.\n\r");
act(buf,ch,NULL,victim,TO_NOTVICT);
 

send_to_char("\n\r",ch);
send_to_char("\n\r",victim);


if (victim->pcdata->rank == AGE_ANCILLA)         sprintf( age, "Ancilla");
else if (victim->pcdata->rank == AGE_CHILDE)     sprintf( age, "Childe");
else if (victim->pcdata->rank == AGE_NEONATE)    sprintf( age, "Neonate");
else if (victim->pcdata->rank == AGE_ELDER)      sprintf( age, "Elder");
else if (victim->pcdata->rank == AGE_METHUSELAH) sprintf( age, "Methuselah");
if (victim->lord == NULL) sprintf(lord, "None");
    else sprintf(lord, "%s",victim->lord);
    sprintf( lin,
"---------------------------------------------------------------------------\n\r");
send_to_char( lin,ch);
send_to_char(
"                              Vampire Status\n\r",ch);
send_to_char(lin,ch);
sprintf(buf,
"Generation:%d  Bloodpool:%d  Age:%s  Lord:%s\n\r",
victim->generation,victim->pcdata->condition[COND_THIRST],
age,lord);
send_to_char(buf,ch);
send_to_char(lin,ch);
send_to_char(
"                              Disciplines\n\r",ch);
send_to_char(lin,ch);
sprintf(buf,
"Animalism:    [%d]             Celerity:   [%d]             Fortitude: [%d]\n\r",
victim->power[DISC_VAMP_ANIM],
victim->power[DISC_VAMP_CELE],
victim->power[DISC_VAMP_FORT]);
send_to_char(buf,ch);
sprintf(buf,
"Obtenebration:[%d]             Presence:   [%d]             Quietus:   [%d]\n\r",
victim->power[DISC_VAMP_OBTE],
victim->power[DISC_VAMP_PRES],
victim->power[DISC_VAMP_QUIE]);
send_to_char(buf,ch);
sprintf(buf,
"Thaumaturgy:  [%d]             Auspex:     [%d]             Dominate:  [%d]\n\r",
victim->power[DISC_VAMP_THAU],
victim->power[DISC_VAMP_AUSP],
victim->power[DISC_VAMP_DOMI]);
send_to_char(buf,ch);
sprintf(buf,
"Obfuscate:    [%d]             Potence:    [%d]             Protean:   [%d]\n\r",
victim->power[DISC_VAMP_OBFU],
victim->power[DISC_VAMP_POTE],
victim->power[DISC_VAMP_PROT]);
send_to_char(buf,ch);
sprintf(buf,
"Serpentis:    [%d]             Vicissitude:[%d]             Daimoinon: [%d]\n\r",
victim->power[DISC_VAMP_SERP],
victim->power[DISC_VAMP_VICI],
victim->power[DISC_VAMP_DAIM]);
send_to_char(buf,ch);
send_to_char(lin,ch);
 
return;
}
 
 




void do_shadowstep( CHAR_DATA *ch, char *argument)
{
    CHAR_DATA *victim;
    char arg[MAX_INPUT_LENGTH];

    if ( IS_NPC(ch) )
	return;

    argument = one_argument (argument, arg);

    if (!IS_CLASS(ch, CLASS_VAMPIRE))
	{
         send_to_char("Huh?\n\r",ch);
	   return;
	}

    if (ch->power[DISC_VAMP_OBTE] < 4)
	{
           send_to_char("You must obtain at least level 4 in Obtenebration to use this power.\n\r",ch);
	   return;
	}

    if ( arg[0] == '\0' )
    {
	send_to_char( "Shadowstep to who?\n\r", ch );
	return;
    }

    if ( ( victim = get_char_world( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }
 
    if (!IS_IMMUNE(victim, IMM_SUMMON)) 
    {
    send_to_char("He doesnt want you near him!\n\r",ch);
    return;
    }

/*
    if (IS_NPC(victim))
    {
	send_to_char("Not to mobs!\n\r",ch);
	return;
    }
*/
    if (ch == victim)
    {
        send_to_char("But you're already at yourself!\n\r",ch);
	  return;
    }

    if (IS_NPC(victim) && (!room_is_dark(victim->in_room)))
    {
	send_to_char("You cant find a shadow in his room.\n\r",ch);
	return;
    }

    if (victim->in_room == ch->in_room)
    {
	send_to_char("But you're already there!\n\r",ch);
        return;
    }

    char_from_room(ch);
    char_to_room(ch,victim->in_room);
    act("You step into the shadows and appear before $N.", ch, NULL, victim, TO_CHAR);
    act("$n appears out of the shadows before $N.", ch, NULL, victim, TO_NOTVICT);
    act("$n appears from the shadows in front of you.", ch, NULL, victim, TO_VICT);
    do_look(ch,"auto");
    return;
}

void do_earthmeld( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    CHAR_DATA *mount;

    one_argument( argument, arg );
    
    if ( IS_NPC(ch) )
	return;

    if (!IS_CLASS(ch, CLASS_VAMPIRE))
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }

    if ( ch->power[DISC_VAMP_PROT] < 4 )
    {
        send_to_char("You must obtain at least level 4 Protean to use Earthmeld.\n\r",ch);
	return;
    }
    

    if ( IS_AFFECTED(ch, AFF_POLYMORPH) )
    {
	send_to_char( "Not while polymorphed.\n\r", ch );
	return;
    }

	if (has_timer(ch)) return;

    if ( IS_NPC(ch) || IS_EXTRA(ch,EXTRA_EARTHMELD) )
    {
            REMOVE_BIT(ch->affected_by, AFF_SHIFT);
            REMOVE_BIT(ch->extra, EXTRA_EARTHMELD);
            REMOVE_BIT(ch->act, PLR_WIZINVIS);
           if (IS_HEAD(ch,LOST_HEAD)) REMOVE_BIT(ch->loc_hp[0],LOST_HEAD);
            free_string(ch->morph);
            ch->morph = str_dup("");
            ch->level = 3;
            ch->trust = 3; 
           send_to_char( "You rise up from the ground.\n\r", ch );
            sprintf(buf, "%s rises up from the ground",ch->name);
            act(buf,ch,NULL,NULL,TO_ROOM);

            return;

    }

    if ( (mount = ch->mount) != NULL) do_dismount(ch,"");
    SET_BIT(ch->affected_by, AFF_SHIFT);
    SET_BIT(ch->extra, EXTRA_EARTHMELD);
    SET_BIT(ch->act, PLR_WIZINVIS);
    free_string(ch->morph);
    ch->morph = str_dup("Someone");
    ch->level = 4;
    ch->trust = 4;
    send_to_char( "You sink into the ground.\n\r", ch );
    sprintf(buf, "%s sinks into the ground.",ch->name);
    act(buf,ch,NULL,NULL,TO_ROOM);
    return;
}
/*
void do_burrow( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    CHAR_DATA *mount;

    
    if ( IS_NPC(ch) )
	return;

    if (!IS_CLASS(ch, CLASS_WEREWOLF))
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }

    if ( ch->power[DISC_WERE_BOAR] < 5 )
    {
        send_to_char("You must obtain at least level 5 boar to use burrow.\n\r",ch);
	return;
    }
    


    if ( IS_NPC(ch) || IS_EXTRA(ch,EXTRA_EARTHMELD) )
    {
            REMOVE_BIT(ch->affected_by, AFF_SHIFT);
            REMOVE_BIT(ch->extra, EXTRA_EARTHMELD);
            REMOVE_BIT(ch->act, PLR_WIZINVIS);
           if (IS_HEAD(ch,LOST_HEAD)) REMOVE_BIT(ch->loc_hp[0],LOST_HEAD);
            free_string(ch->morph);
            ch->morph = str_dup("");
            ch->level = 3;
            ch->trust = 3; 
           send_to_char( "You rise up from your burrow.\n\r", ch );
            sprintf(buf, "%s rises up from a hole",ch->name);
            act(buf,ch,NULL,NULL,TO_ROOM);

            return;

    }

    if ( (mount = ch->mount) != NULL) do_dismount(ch,"");
    SET_BIT(ch->affected_by, AFF_SHIFT);
    SET_BIT(ch->extra, EXTRA_EARTHMELD);
    SET_BIT(ch->act, PLR_WIZINVIS);
    free_string(ch->morph);
    ch->morph = str_dup("Someone");
    ch->level = 4;
    ch->trust = 4;
    send_to_char( "You burrow into the ground.\n\r", ch );
    sprintf(buf, "%s burrow into the ground.",ch->name);
    act(buf,ch,NULL,NULL,TO_ROOM);
    return;
}


void do_burrow( CHAR_DATA *ch, char *argument )
{
    char      arg [MAX_INPUT_LENGTH];
    CHAR_DATA *victim;

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if ( !IS_CLASS(ch, CLASS_WEREWOLF) )
 {
        send_to_char("Huh?\n\r",ch);
        return;
    }

    if ( ch->power[DISC_WERE_BOAR] < 5 )
    {
    send_to_char("You need the Boar totem to 5!\n\r", ch);
        return;
    }

    if ( arg[0] == '\0' )
    {
    send_to_char("Burrow to who?\n\r", ch);
    return;
    }
if ( ( victim = get_char_world( ch, arg ) ) == NULL )
    {
        send_to_char( "They are not here.\n\r", ch );
        return;
    }

    if ( IS_NPC(victim) )
    {
        send_to_char( "Not on NPC's.\n\r", ch );
        return;
    }

    if (IS_IMMUNE(victim, IMM_TRAVEL))
    {
        send_to_char("I don't think they want you to do that.\n\r",ch);
        return;
    }        

    if ( victim == ch )
    {
                send_to_char( "You cannot burrow to yourself.\n\r", ch);
                return;
        }
if ( victim->level != LEVEL_AVATAR || !IS_CLASS(victim, CLASS_WEREWOLF))
    {
        send_to_char( "Nothing happens.\n\r", ch );
        return;
    }

    if (victim->in_room == NULL)
    {
        send_to_char( "Nothing happens.\n\r", ch );
        return;
    }

    send_to_char("You burrow into the ground.\n\r",ch);
    act("$n burrows into the ground.",ch,NULL,NULL,TO_ROOM);
    char_from_room(ch);
    char_to_room(ch,victim->in_room);
do_look(ch,"");
    send_to_char("You burrow out of the ground.\n\r",ch);
    act("$n burrows out of the ground.",ch,NULL,NULL,TO_ROOM);
    return;
}
*/

void do_serenity( CHAR_DATA *ch, char *argument )
{
    if ( IS_NPC(ch) )
	return;
    if(!IS_CLASS(ch, CLASS_VAMPIRE))
    {
        send_to_char("huh?.\n\r",ch);
        return;
    }
    if (ch->power[DISC_VAMP_ANIM] < 2)
    {
        send_to_char("You must obtain at least level 2 in Animalism to use Song of Serenity.\n\r",ch);
	return;
    }



    if (IS_CLASS(ch, CLASS_VAMPIRE) && ch->beast < 1)
    {
	if ( ch->rage < 1 )
	{
	    send_to_char("Your beast doesn't control your actions.\n\r",ch);
	    return;
	}
        send_to_char("You chant a soft tune and pacify your inner beast.\n\r",ch);
        act("$n chants a soft tune and pacifies their inner beast.",ch,NULL,NULL,TO_ROOM);
	ch->rage = 0;
	if (IS_VAMPAFF(ch, VAM_NIGHTSIGHT)) do_nightsight(ch,"");
	if (IS_VAMPAFF(ch, VAM_FANGS)) do_fangs(ch,"");
	if (IS_VAMPAFF(ch, VAM_CLAWS)) do_claws(ch,"");
	WAIT_STATE(ch,12);
	return;
    }
    else 
    {
     send_to_char("Only those who achieve Golconda can sing the Song of Serenity.\n\r",ch);
     return;
    }
}

void do_theft( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char      arg [MAX_INPUT_LENGTH];
    char      buf [MAX_INPUT_LENGTH];
    int bloodpool;
	int blpr; /* Blood sucked storage variable. Shakti */

    argument = one_argument( argument, arg );

    if (ch->generation <= 0)
        ch->generation = 4;

    {
    if (IS_SET(ch->newbits, NEW_TIDE))
    bloodpool = (3000 / ch->generation);
    else bloodpool = (2000 / ch->generation);
    } 

    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch, CLASS_VAMPIRE))
    {
	send_to_char( "Huh?\n\r", ch );
	return;
    }

    if (ch->power[DISC_VAMP_THAU] < 4)
    {
        send_to_char("You must obtain at least level 4 in Thaumaturgy to use Theft of Vitae.\n\r",ch);
	return;
    }


    if ( arg[0] == '\0' )
    {
        send_to_char( "Steal blood from whom?\n\r", ch );
	return;
    }

    if (IS_AFFECTED(ch,AFF_POLYMORPH) && !IS_VAMPAFF(ch,VAM_DISGUISED))
    {
	send_to_char( "Not while polymorphed.\n\r", ch );
	return;
    }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }
	if (IS_NPC(victim) && IS_SET(victim->act, ACT_NOAUTOKILL)) {
	send_to_char("You can't do that to them.\n\r", ch );
	return;}

/*
    if ( IS_NPC(victim) ) 
    {
        send_to_char( "Lower life forms are immune to Theft of Vitae.\n\r", ch);
        return;
    }
*/
    if (!IS_NPC(victim) && victim->pcdata->condition[COND_THIRST] <= 0)
    {
        send_to_char( "There isn't enough blood to steal.\n\r", ch);
        return;
    }
    if (!IS_NPC(victim) && IS_IMMORTAL(victim) && victim != ch )
    {
        send_to_char( "You can only steal blood from Avatar's or lower.\n\r", ch );
	return;
    }
if (is_safe(ch,victim) == TRUE) return;

if (!IS_NPC(victim)) {
        sprintf(buf,"A stream of blood shoots from %s into your body.",victim->name);
	act(buf,ch,NULL,victim,TO_CHAR);
        sprintf(buf,"A stream of blood shoots from %s into %s.",victim->name,ch->name);
	act(buf,ch,NULL,victim,TO_ROOM);
        sprintf(buf,"A stream of blood shoots from your body into %s.",ch->name);
        act(buf,ch,NULL,victim,TO_VICT);
        } else {
        sprintf(buf,"A stream of blood shoots from %s into your body.",victim->short_descr);
	act(buf,ch,NULL,victim,TO_CHAR);
        sprintf(buf,"A stream of blood shoots from %s into %s.",victim->short_descr,ch->name);
	act(buf,ch,NULL,victim,TO_ROOM);
        sprintf(buf,"A stream of blood shoots from your body into %s.",ch->name);
        act(buf,ch,NULL,victim,TO_VICT);


	}
        ch->pcdata->condition[COND_THIRST] += number_range(10,15);
     
		
		if (IS_NPC(victim))
        {
/* Raw-killing it from one theft is stupid. Im going to use the primal        */
/* stat on the mobs for blood its quick, effective, and straightford, AND	  */
/* no new fields have to be added to the mob.Shakti 09/07/98				  */
			(blpr = number_range (30,40) );
			(victim->practice -=blpr);
            (ch->pcdata->condition[COND_THIRST] += blpr);
		if (victim->practice < 0) {
		sprintf(buf,"%s falls over dead.",victim->short_descr);
		act(buf,ch,NULL,victim,TO_ROOM);
		act(buf,ch,NULL,victim,TO_CHAR);
		raw_kill(victim);}		

		 if (ch->pcdata->condition[COND_THIRST] >= bloodpool /ch->generation)
             {
              ch->pcdata->condition[COND_THIRST] = bloodpool / ch->generation;
             }
	if (ch->fighting == NULL) set_fighting(ch,victim);

         return;
        }
        if (IS_SET(victim->act, PLR_ACID))
        {
        send_to_char("Their blood is a deadly acid!\n\r", ch);
        ch->hit -= 300;
        victim->pcdata->condition[COND_THIRST] -= 30;
        return;
        }

    if (!IS_NPC(victim)) 
{
victim->pcdata->condition[COND_THIRST] -=number_range(30,40);
}
    if (ch->pcdata->condition[COND_THIRST] >= bloodpool / ch->generation)
    {
       ch->pcdata->condition[COND_THIRST] = bloodpool /ch->generation;
    }

   if (victim->pcdata->condition[COND_THIRST] <= 0)
    {
       victim->pcdata->condition[COND_THIRST] = 0; 
    }
	if (ch->fighting == NULL) set_fighting(ch,victim);

   return;
}


void do_demonform( CHAR_DATA *ch, char *argument )
{
    char arg [MAX_INPUT_LENGTH];
    char buf [MAX_STRING_LENGTH]; 
    argument = one_argument( argument, arg ); 

    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch, CLASS_DEMON))
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }

    /*if (ch->power[DISC_VAMP_VICI] < 4)
    {
        send_to_char("You must obtain at least level 4 in Vicissitude to
use Zuloform.\n\r",ch);
	return;
    }*/
    
    
    if (!IS_DEMPOWER( ch, DEM_FORM) && IS_CLASS(ch,CLASS_DEMON))
    {
	send_to_char("You haven't been granted the gift of demonform.\n\r",ch);
	return;
    }
    

    /*if (IS_EXTRA(ch,EXTRA_DRAGON))
    {
    send_to_char("You cannot unzulo while a dragon.\n\r",ch);
    return;
    }*/
    
    if (IS_POLYAFF(ch, POLY_ZULOFORM))
    {   
        REMOVE_BIT(ch->polyaff, POLY_ZULOFORM);
        REMOVE_BIT(ch->affected_by, AFF_POLYMORPH);
        act( "You transform into human form.", ch, NULL, NULL, TO_CHAR );
        act( "$n's shrinks back into human form.", ch, NULL, NULL, TO_ROOM
);
     /*   ch->max_hit = ch->max_hit - 1500;
        ch->hit = ch->hit - 1500;
        if (ch->hit < 1) ch->hit = 1;
    */   
        ch->damroll = - 150;
        ch->hitroll = - 150; 
	clear_stats(ch);
	free_string( ch->morph );
        ch->morph = str_dup( "" );
        return;
    }
    else if (IS_AFFECTED(ch,AFF_POLYMORPH))
    {
send_to_char("You cant demon form when changed.\n\r",ch);
return;
}
  
  
    /*if ( ch->pcdata->condition[COND_THIRST] < 200 )
    	{
	    send_to_char("You have insufficient blood.\n\r",ch);
	    return;
    	}*/

        if (ch->stance[0] != -1) do_stance(ch,"");
	if (ch->mounted == IS_RIDING) do_dismount(ch,"");
    	/*ch->pcdata->condition[COND_THIRST] -= number_range(100,200);*/
        act( "You transform into a huge demon.", ch, NULL, NULL, TO_CHAR
);
        act( "$n's body grows and distorts into a huge demon.", ch, NULL,
NULL, TO_ROOM );
        /*
        clear_stats(ch);
    	if (ch->wpn[0] > 0)
    	{
	    ch->hitroll += (ch->wpn[0]);
	    ch->damroll += (ch->wpn[0]);
	    ch->armor   -= (ch->wpn[0] * 3);
    	}
        */
        ch->pcdata->mod_str = 15;
        ch->pcdata->mod_dex = 15;
        SET_BIT(ch->polyaff, POLY_ZULOFORM);
        SET_BIT(ch->affected_by, AFF_POLYMORPH);
        sprintf(buf, "%s the huge hulking demon", ch->name);
        free_string( ch->morph );
        ch->morph = str_dup( buf );
	/*ch->max_hit =  + 500;
	ch->hit = + 500;*/
	ch->damroll = + 350;
	ch->hitroll = + 350;
        return;
    }
  




void do_zuloform( CHAR_DATA *ch, char *argument )
{
    char arg [MAX_INPUT_LENGTH];
    char buf [MAX_STRING_LENGTH]; 
    argument = one_argument( argument, arg ); 

    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch, CLASS_VAMPIRE))
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }

    if (ch->power[DISC_VAMP_VICI] < 2)
    {
        send_to_char("You must obtain at least level 2 in Vicissitude to use Zuloform.\n\r",ch);
	return;
    }

    if (IS_EXTRA(ch,EXTRA_DRAGON))
    {
    send_to_char("You cannot unzulo while a dragon.\n\r",ch);
    return;
    }
    if (IS_POLYAFF(ch, POLY_ZULOFORM))
    {   
        REMOVE_BIT(ch->polyaff, POLY_ZULOFORM);
        REMOVE_BIT(ch->affected_by, AFF_POLYMORPH);
        act( "You transform into human form.", ch, NULL, NULL, TO_CHAR );
        act( "$n's shrinks back into human form.", ch, NULL, NULL, TO_ROOM );
        ch->max_hit = ch->max_hit - 1500;
        ch->hit = ch->hit - 1500;
        if (ch->hit < 1) ch->hit = 1;
        ch->damroll = ch->damroll / 1.4;
        ch->hitroll = ch->hitroll / 1.4; 
        free_string( ch->morph );
        ch->morph = str_dup( "" );
        return;
    }
    else if (IS_AFFECTED(ch,AFF_POLYMORPH))
    {
send_to_char("You cant zulo when changed.\n\r",ch);
return;
}
  
  
    if ( ch->pcdata->condition[COND_THIRST] < 200 )
    	{
	    send_to_char("You have insufficient blood.\n\r",ch);
	    return;
    	}

        if (ch->stance[0] != -1) do_stance(ch,"");
	if (ch->mounted == IS_RIDING) do_dismount(ch,"");
    	ch->pcdata->condition[COND_THIRST] -= number_range(100,200);
        act( "You transform into large beast.", ch, NULL, NULL, TO_CHAR );
        act( "$n's body grows and distorts into a large beast.", ch, NULL, NULL, TO_ROOM );
        /*
        clear_stats(ch);
    	if (ch->wpn[0] > 0)
    	{
	    ch->hitroll += (ch->wpn[0]);
	    ch->damroll += (ch->wpn[0]);
	    ch->armor   -= (ch->wpn[0] * 3);
    	}
        */
        ch->pcdata->mod_str = 15;
        ch->pcdata->mod_dex = 15;
        SET_BIT(ch->polyaff, POLY_ZULOFORM);
        SET_BIT(ch->affected_by, AFF_POLYMORPH);
        sprintf(buf, "A big black monster");
        free_string( ch->morph );
        ch->morph = str_dup( buf );
        ch->max_hit = ch->max_hit + 1500;
        ch->hit = ch->hit + 1500;
        ch->damroll = ch->damroll * 1.4;
        ch->hitroll = ch->hitroll * 1.4;
        return;
    }
  



void do_shift( CHAR_DATA *ch, char *argument )
{
    char arg [MAX_INPUT_LENGTH];
    int  toform = 0;

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch, CLASS_WEREWOLF))
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }

    if ( arg[0] == '\0' )
    {
	send_to_char( "You can shift between the following forms: Homid, Glabro, Crinos, Hispo, Lupus.\n\r", ch );
	return;
    }
    if      ( !str_cmp(arg,"homid" ) ) toform = 1;
    else if ( !str_cmp(arg,"glabro") ) toform = 2;
    else if ( !str_cmp(arg,"crinos") ) toform = 3;
    else if ( !str_cmp(arg,"hispo" ) ) toform = 4;
    else if ( !str_cmp(arg,"lupus" ) ) toform = 5;
    else
    {
	send_to_char( "You can shift between the following forms: Homid, Glabro, Crinos, Hispo, Lupus.\n\r", ch );
	return;
    }
    if ( ch->pcdata->stats[UNI_FORM0] < 1 || ch->pcdata->stats[UNI_FORM0] > 5) 
	ch->pcdata->stats[UNI_FORM0] = 1;
    if ( ch->pcdata->stats[UNI_FORM0] == toform )
    {
	send_to_char( "You are already in that form.\n\r", ch );
	return;
    }
    ch->pcdata->stats[UNI_FORM1] = toform;
    return;
}


void horn args((CHAR_DATA *ch));

/* claw and fang commands */

void declaw(CHAR_DATA *ch)
{
    if (!IS_VAMPAFF(ch, VAM_CLAWS)) return;

    send_to_char("You retract your claws.\n\r",ch);
    act("$n retracts $s claws.",ch, NULL, NULL, TO_ROOM);
    REMOVE_BIT(ch->pcdata->stats[UNI_AFF], VAM_CLAWS);
}

void dehorn(CHAR_DATA *ch)
{
    if (!IS_VAMPAFF(ch, VAM_HORNS)) return;

    send_to_char("Your horns burrow back into your skull.\n\r",ch);
    act("$n's horns retract into $s skull.",ch, NULL, NULL, TO_ROOM);
    REMOVE_BIT(ch->pcdata->stats[UNI_AFF], VAM_HORNS);
}

/*
void do_horns(CHAR_DATA *ch, char *argument)
{
  
 if (IS_CLASS(ch, CLASS_DEMON))
   {
	if (ch->power[DISC_DAEM_ATTA] < 4)
        {
	  stc("Huh?\n\r",ch);
          return;
	}
   }

   else
   {
	stc("Huh?\n\r",ch);
	return;
   }

    WAIT_STATE(ch, 8);
    if (IS_VAMPAFF(ch, VAM_HORNS)) dehorn(ch);
    else horn(ch);
}
*/
void horn(CHAR_DATA *ch)
{
    OBJ_DATA *obj;
  
    if (IS_VAMPAFF(ch, VAM_HORNS)) return;

    /* Only certain demons may use their horns */
    if (ch->power[DISC_DAEM_ATTA] < 4) return;

    send_to_char("Sharp horns grow out of your skull.\n\r",ch);
    act("Sharp horns grow out of $n's skull.",ch, NULL, NULL, TO_ROOM);

    if ( (obj = get_eq_char(ch, WEAR_HEAD)) != NULL) 
    { 
        act("Your horns shred $p.", ch, obj, NULL, TO_CHAR); 
        act("$n's horns shred $p.", ch, obj, NULL, TO_ROOM); 
        extract_obj(obj); 
    } 

    SET_BIT(ch->pcdata->stats[UNI_AFF], VAM_HORNS);
}

void defang(CHAR_DATA *ch)
{
    if (!IS_VAMPAFF(ch, VAM_FANGS)) return;

    send_to_char("Your fangs slide back into your gums.\n\r",ch);
    act("$n retracts $s fangs back into $s gums.",ch, NULL, NULL, TO_ROOM);
    REMOVE_BIT(ch->pcdata->stats[UNI_AFF], VAM_FANGS);
}

void do_claws(CHAR_DATA *ch, char *argument)
{
    if (ch->cur_form != 0 && !form_data[ch->cur_form].can_use_claws )
    {
	send_to_char("You cannot use your claws in this form.\n\r", ch);
	return;
    }
   if (IS_CLASS(ch, CLASS_WEREWOLF))
   {
	if (ch->power[DISC_WERE_WOLF] < 1)
      {
	    stc("Huh?\n\r",ch);
	    return;
	}
   }
	else if (IS_CLASS(ch, CLASS_DEMON) || IS_SET(ch->special, SPC_CHAMPION))
    {
	if (!IS_DEMPOWER( ch, DEM_CLAWS))
	{
	    send_to_char("You haven't been granted the gift of claws.\n\r",ch);
	    return;
	}
    }
   else if (IS_CLASS(ch, CLASS_VAMPIRE))
   {
	if (ch->power[DISC_VAMP_PROT] < 2)
	{
	    stc("Huh?\n\r",ch);
	    return;
	}
   }
   else
   {
	stc("Huh?\n\r",ch);
	return;
   }

   if (IS_VAMPAFF(ch, VAM_CLAWS))
   {
     if (IS_CLASS(ch, CLASS_VAMPIRE) || IS_CLASS(ch, CLASS_DEMON))
     {
	if (ch->rage >0)
	{    
	    send_to_char("You cannot retract your claws while the beast is within you.\n\r", ch);
	    return;
	}
     }
	send_to_char("You retract your claws.\n\r",ch);
	act("$n retracts $s claws.",ch, NULL, NULL, TO_ROOM);
	REMOVE_BIT(ch->pcdata->stats[UNI_AFF], VAM_CLAWS);
   }
   else
   {
	send_to_char("Wicked claws extend from your fingers.\n\r",ch);
	act("Long sharp claws extend from $n's fingers.",ch, NULL, NULL, TO_ROOM);
	remove_obj( ch, WEAR_WIELD, TRUE );
	remove_obj( ch, WEAR_HOLD, TRUE );
	remove_obj( ch, WEAR_THIRD, TRUE );
	remove_obj( ch, WEAR_FOURTH, TRUE );
	SET_BIT(ch->pcdata->stats[UNI_AFF], VAM_CLAWS);
   }
}

void do_fangs(CHAR_DATA *ch, char *argument)
{
    if (ch->cur_form != 0 && !form_data[ch->cur_form].can_use_claws )
    {
	send_to_char("You cannot use your fangs in this form.\n\r", ch);
	return;
    }

   if (IS_CLASS(ch, CLASS_WEREWOLF))
   {
	if (ch->power[DISC_WERE_WOLF] < 2)
        {
	    stc("Huh?\n\r",ch);
	    return;
	}
   }

	else if (IS_CLASS(ch, CLASS_DEMON) || IS_SET(ch->special, SPC_CHAMPION))
    {
	if (!IS_DEMPOWER( ch, DEM_FANGS))
	{
	    send_to_char("You haven't been granted the gift of fangs.\n\r",ch);
	    return;
	}
    }

   else if (!IS_CLASS(ch, CLASS_VAMPIRE))
   {
	stc("Huh?\n\r",ch);
	return;
   }

   if (IS_VAMPAFF(ch, VAM_FANGS))
   {
     if (IS_CLASS(ch, CLASS_VAMPIRE) || IS_CLASS(ch, CLASS_DEMON))
     {
	if (ch->rage >0)
	{    
	    send_to_char("You cannot retract your fangs while the beast is within you.\n\r", ch);
	    return;
	}
     }
	send_to_char("Your fangs slide back into your gums.\n\r",ch);
	act("$n retracts $s fangs back into $s gums.",ch, NULL, NULL, TO_ROOM);
	REMOVE_BIT(ch->pcdata->stats[UNI_AFF], VAM_FANGS);
   }
   else
   {
	send_to_char("Sharp fangs slide out of your gums.\n\r",ch);
	act("Sharp fangs slide out of $n's gums.",ch, NULL, NULL, TO_ROOM);
	SET_BIT(ch->pcdata->stats[UNI_AFF], VAM_FANGS);
   }
}

void do_nightsight( CHAR_DATA *ch, char *argument )
{
    char      arg [MAX_INPUT_LENGTH];

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if (IS_CLASS(ch, CLASS_WEREWOLF))
    {/*supposed to be < but changedd while gifts are out */
	if ( ch->gifts[METIS] > 3 )
	{
	    send_to_char("You haven't learned the Metis gift Eyes of the Cat.\n\r",ch);
	    return;
	}
    }
    else if (IS_CLASS(ch, CLASS_DEMON) || IS_SET(ch->special, SPC_CHAMPION))
    {
	if (!IS_DEMPOWER( ch, DEM_EYES))
	{
	    send_to_char("You haven't been granted the gift of nightsight.\n\r",ch);
	    return;
	}
    }
    else if (IS_CLASS(ch, CLASS_MONK) )
    {
	if ( ch->monkab[AWARE] < 1 )
	{
	    stc("You must obtain level one in Awareness to use Nightsight.\n\r",ch);
	    return;
        }
    }
    else if (!IS_CLASS(ch, CLASS_VAMPIRE) )
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }
    if (IS_CLASS(ch, CLASS_VAMPIRE) && ch->power[DISC_VAMP_PROT] < 1 &&
       ch->power[DISC_VAMP_OBTE] < 3) 
    {
        send_to_char("You must obtain at least level 1 in Protean or 3 in Obtenebration.\n\r",ch);
	return;
    }
    if (IS_CLASS(ch, CLASS_VAMPIRE) && ch->rage > 0)
    {
	send_to_char("Not while your beast is in control.\n\r",ch);
	return;
    }

    if (IS_VAMPAFF(ch,VAM_NIGHTSIGHT) )
    {
	send_to_char("The red glow in your eyes fades.\n\r",ch);
	act("The red glow in $n's eyes fades.", ch, NULL, NULL, TO_ROOM);
	REMOVE_BIT(ch->pcdata->stats[UNI_AFF], VAM_NIGHTSIGHT);
	return;
    }
    send_to_char("Your eyes start glowing red.\n\r",ch);
    act("$n's eyes start glowing red.", ch, NULL, NULL, TO_ROOM);
    SET_BIT(ch->pcdata->stats[UNI_AFF], VAM_NIGHTSIGHT);
    return;
}

void do_inconnu( CHAR_DATA *ch, char *argument )
{
    char      arg [MAX_INPUT_LENGTH];
    char      buf [MAX_INPUT_LENGTH];

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch, CLASS_VAMPIRE) )
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }


    if (ch->pcdata->rank == AGE_ELDER && ch->generation > 2)
    {
	send_to_char("You must be at least an Elder to become an Inconnu.\n\r",ch);
	return;
    }

    if (IS_SET(ch->special, SPC_INCONNU))
    {
	send_to_char("But you are already an Inconnu!\n\r",ch);
	return;
    }

    if (ch->exp < 1000000)
    {
	send_to_char("It costs 1000000 exp to become an Inconnu.\n\r",ch);
	return;
    }

    if (IS_SET(ch->special, SPC_ANARCH)) REMOVE_BIT(ch->special, SPC_ANARCH);
    ch->exp -= 1000000;
    send_to_char("You are now an Inconnu.\n\r",ch);
    sprintf(buf,"%s is now an Inconnu!",ch->name);
    do_info(ch,buf);
    SET_BIT(ch->special, SPC_INCONNU);
    return;
}

void do_shadowsight( CHAR_DATA *ch, char *argument )
{
    char      arg [MAX_INPUT_LENGTH];

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if (IS_CLASS(ch, CLASS_WEREWOLF) && ch->power[DISC_WERE_HAWK] < 2)
    {
	stc("Huh?\n\r",ch);
	return;
    }

    else if ( IS_CLASS(ch, CLASS_MONK) && ch->monkab[AWARE] < 2 )
    {
	stc("Huh?\n\r",ch);
	return;
    }

    else if ( IS_CLASS(ch, CLASS_VAMPIRE) && ch->power[DISC_VAMP_OBTE] < 2)
	{
	    send_to_char("Huh?\n\r",ch);
	    return;
	}
/*
        if (ch->power[DISC_VAMP_OBTE] < 2  )
	{
            send_to_char("You must obtain at least Level 2 Obtenebration to use Shadowsight.\n\r",ch);
	    return;
	}
*/
//    }
    if (IS_AFFECTED(ch,AFF_SHADOWSIGHT) )
    {
	send_to_char("You can no longer see between planes.\n\r",ch);
	REMOVE_BIT(ch->affected_by, AFF_SHADOWSIGHT);
	return;
    }
    if (IS_CLASS(ch, CLASS_VAMPIRE) && ch->pcdata->condition[COND_THIRST] < 10)
    {
	send_to_char("You have insufficient blood.\n\r",ch);
	return;
    }
    if (IS_CLASS(ch, CLASS_VAMPIRE))
	ch->pcdata->condition[COND_THIRST] -= number_range(5,10);
    send_to_char("You can now see between planes.\n\r",ch);
    SET_BIT(ch->affected_by, AFF_SHADOWSIGHT);
    return;
}

void do_bite( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char      arg [MAX_INPUT_LENGTH];
    char      buf [MAX_INPUT_LENGTH];
    int       clancount;
    bool      outcast = FALSE;

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch, CLASS_VAMPIRE))
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }

    clancount = 0;
    if (ch->power[DISC_VAMP_PROT] >= 1)       clancount = clancount + 1;
    if (ch->power[DISC_VAMP_CELE] >= 1)      clancount = clancount + 1;
    if (ch->power[DISC_VAMP_FORT] >= 1)     clancount = clancount + 1;
    if (ch->power[DISC_VAMP_POTE] >= 1)       clancount = clancount + 1;
    if (ch->power[DISC_VAMP_OBFU] >= 1)     clancount = clancount + 1;
    if (ch->power[DISC_VAMP_OBTE] >= 1) clancount = clancount + 1;
    if (ch->power[DISC_VAMP_SERP] >= 1)     clancount = clancount + 1;
    if (ch->power[DISC_VAMP_AUSP] >= 1)        clancount = clancount + 1;
    if (ch->power[DISC_VAMP_DOMI] >= 1)      clancount = clancount + 1;
    if (ch->power[DISC_VAMP_PRES] >= 1)      clancount = clancount + 1;
    if (ch->power[DISC_VAMP_VICI] >= 1)   clancount = clancount + 1;
    if (ch->power[DISC_VAMP_THAU] >= 1)          clancount = clancount + 1;
    if (ch->power[DISC_VAMP_ANIM] >= 1)        clancount = clancount + 1;
    if (ch->power[DISC_VAMP_QUIE] >= 1)       clancount = clancount + 1;

    if ( clancount < 3 )
    {
	send_to_char( "First you need to master 3 disciplines.\n\r", ch );
	return;
    }

    if ( arg[0] == '\0' )
    {
	send_to_char( "Bite whom?\n\r", ch );
	return;
    }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( IS_NPC(victim) )
    {
	send_to_char( "Not on NPC's.\n\r", ch );
	return;
    }

    if ( IS_IMMORTAL(victim) )
    {
	send_to_char( "Not on Immortal's.\n\r", ch );
	return;
    }

    if ( ch == victim )
    {
	send_to_char( "You cannot bite yourself.\n\r", ch );
	return;
    }

	if (victim->class != 0) {
	send_to_char("Not on them.\n\r", ch );
	return;}
    if ( victim->level != LEVEL_AVATAR && !IS_IMMORTAL(victim) )
    {
	send_to_char( "You can only bite avatars.\n\r", ch );
	return;
    }
    if (!IS_NEWFLAG(victim, AFF_ALLOW_VAMP))
    {
	stc("They are not a willing subject.\n\r",ch);
	return;
    }

    if (!IS_VAMPAFF(ch,VAM_FANGS))
    {
	send_to_char("First you better get your fangs out!\n\r",ch);
	return;
    }

    if (IS_VAMPAFF(ch,VAM_DISGUISED))
    {
	send_to_char("You must reveal your true nature to bite someone.\n\r",ch);
	return;
    }

    if (ch->exp < 1000)
    {
	send_to_char("You cannot afford the 1000 exp to create a childe.\n\r",ch);
	return;
    }

    if (ch->beast > 0)
	ch->beast += 1;
    ch->exp = ch->exp - 1000;
    act("You sink your teeth into $N.", ch, NULL, victim, TO_CHAR);
    act("$n sinks $s teeth into $N.", ch, NULL, victim, TO_NOTVICT);
    act("$n sinks $s teeth into your neck.", ch, NULL, victim, TO_VICT);
    victim->class=CLASS_VAMPIRE;
    set_learnable_disciplines(victim);

    if ( victim->generation != 0 && (victim->generation <= ( ch->generation = 13 ) ) ) 
    if ( victim->generation != 0 )
    {
	save_char_obj(ch);
	save_char_obj(victim);
	send_to_char( "Your vampiric status has been restored.\n\r", victim );
	return;
    }
    else outcast = TRUE;
    send_to_char( "You are now a vampire.\n\r", victim );    
    victim->generation = ch->generation = 13;
    free_string(victim->lord);
    if (ch->generation == 1)
	victim->lord=str_dup(ch->name);
    else
    {
	sprintf(buf,"%s %s",ch->lord,ch->name);
	victim->lord=str_dup(buf);
    }
    if (ch->generation != 1)
    {
    	if (victim->pcdata->stats[UNI_CURRENT] == -1) 
		victim->pcdata->stats[UNI_CURRENT] = victim->pcdata->stats[UNI_AFF];

	/* Remove hp bonus from fortitude */
	if (IS_VAMPPASS(victim,VAM_FORTITUDE) && !IS_VAMPAFF(victim,VAM_FORTITUDE))
	{
	    victim->max_hit = victim->max_hit - 50;
	    victim->hit = victim->hit - 50;
	    if (victim->hit < 1) victim->hit = 1;
	}

	/* Remove any old powers they might have */
	if (IS_VAMPPASS(victim,VAM_PROTEAN))
	{REMOVE_BIT(victim->pcdata->stats[UNI_CURRENT], VAM_PROTEAN);
	 REMOVE_BIT(victim->pcdata->stats[UNI_AFF], VAM_PROTEAN);}
	if (IS_VAMPPASS(victim,VAM_CELERITY))
	{REMOVE_BIT(victim->pcdata->stats[UNI_CURRENT], VAM_CELERITY);
	 REMOVE_BIT(victim->pcdata->stats[UNI_AFF], VAM_CELERITY);}
	if (IS_VAMPPASS(victim,VAM_FORTITUDE))
	{REMOVE_BIT(victim->pcdata->stats[UNI_CURRENT], VAM_FORTITUDE);
	 REMOVE_BIT(victim->pcdata->stats[UNI_AFF], VAM_FORTITUDE);}
	if (IS_VAMPPASS(victim,VAM_POTENCE))
	{REMOVE_BIT(victim->pcdata->stats[UNI_CURRENT], VAM_POTENCE);
	 REMOVE_BIT(victim->pcdata->stats[UNI_AFF], VAM_POTENCE);}
	if (IS_VAMPPASS(victim,VAM_OBFUSCATE))
	{REMOVE_BIT(victim->pcdata->stats[UNI_CURRENT], VAM_OBFUSCATE);
	 REMOVE_BIT(victim->pcdata->stats[UNI_AFF], VAM_OBFUSCATE);}
	if (IS_VAMPPASS(victim,VAM_OBTENEBRATION))
	{REMOVE_BIT(victim->pcdata->stats[UNI_CURRENT], VAM_OBTENEBRATION);
	 REMOVE_BIT(victim->pcdata->stats[UNI_AFF], VAM_OBTENEBRATION);}
	if (IS_VAMPPASS(victim,VAM_SERPENTIS))
	{REMOVE_BIT(victim->pcdata->stats[UNI_CURRENT], VAM_SERPENTIS);
	 REMOVE_BIT(victim->pcdata->stats[UNI_AFF], VAM_SERPENTIS);}
	if (IS_VAMPPASS(victim,VAM_AUSPEX))
	{REMOVE_BIT(victim->pcdata->stats[UNI_CURRENT], VAM_AUSPEX);
	 REMOVE_BIT(victim->pcdata->stats[UNI_AFF], VAM_AUSPEX);}
	if (IS_VAMPPASS(victim,VAM_DOMINATE))
	{REMOVE_BIT(victim->pcdata->stats[UNI_CURRENT], VAM_DOMINATE);
	 REMOVE_BIT(victim->pcdata->stats[UNI_AFF], VAM_DOMINATE);}
	if (IS_VAMPPASS(victim,VAM_PRESENCE))
	{REMOVE_BIT(victim->pcdata->stats[UNI_CURRENT], VAM_PRESENCE);
	 REMOVE_BIT(victim->pcdata->stats[UNI_AFF], VAM_PRESENCE);}
        if (IS_VAMPPASS(victim,VAM_VICISSITUDE))
        {REMOVE_BIT(victim->pcdata->stats[UNI_CURRENT], VAM_VICISSITUDE);
         REMOVE_BIT(victim->pcdata->stats[UNI_AFF], VAM_VICISSITUDE);}
        if (IS_VAMPPASS(victim,VAM_THAU))
        {REMOVE_BIT(victim->pcdata->stats[UNI_CURRENT], VAM_THAU);
         REMOVE_BIT(victim->pcdata->stats[UNI_AFF], VAM_THAU);}
        if (IS_VAMPPASS(victim,VAM_ANIMAL))
        {REMOVE_BIT(victim->pcdata->stats[UNI_CURRENT], VAM_ANIMAL);
         REMOVE_BIT(victim->pcdata->stats[UNI_AFF], VAM_ANIMAL);}
        if (IS_VAMPPASS(victim,VAM_QUIETUS))
        {REMOVE_BIT(victim->pcdata->stats[UNI_CURRENT], VAM_QUIETUS);
         REMOVE_BIT(victim->pcdata->stats[UNI_AFF], VAM_QUIETUS);}



	/* Give the vampire the base powers of their sire */
	if (IS_VAMPPASS(ch,VAM_FORTITUDE) && !IS_VAMPAFF(victim,VAM_FORTITUDE))
	{
	    victim->max_hit = victim->max_hit + 50;
	    victim->hit = victim->hit + 50;
	}
	if (IS_VAMPPASS(ch,VAM_PROTEAN))
	{SET_BIT(victim->pcdata->stats[UNI_CURRENT], VAM_PROTEAN);
	 SET_BIT(victim->pcdata->stats[UNI_AFF], VAM_PROTEAN);}
	if (IS_VAMPPASS(ch,VAM_CELERITY))
	{SET_BIT(victim->pcdata->stats[UNI_CURRENT], VAM_CELERITY);
	 SET_BIT(victim->pcdata->stats[UNI_AFF], VAM_CELERITY);}
	if (IS_VAMPPASS(ch,VAM_FORTITUDE))
	{SET_BIT(victim->pcdata->stats[UNI_CURRENT], VAM_FORTITUDE);
	 SET_BIT(victim->pcdata->stats[UNI_AFF], VAM_FORTITUDE);}
	if (IS_VAMPPASS(ch,VAM_POTENCE))
	{SET_BIT(victim->pcdata->stats[UNI_CURRENT], VAM_POTENCE);
	 SET_BIT(victim->pcdata->stats[UNI_AFF], VAM_POTENCE);}
	if (IS_VAMPPASS(ch,VAM_OBFUSCATE))
	{SET_BIT(victim->pcdata->stats[UNI_CURRENT], VAM_OBFUSCATE);
	 SET_BIT(victim->pcdata->stats[UNI_AFF], VAM_OBFUSCATE);}
	if (IS_VAMPPASS(ch,VAM_OBTENEBRATION))
	{SET_BIT(victim->pcdata->stats[UNI_CURRENT], VAM_OBTENEBRATION);
	 SET_BIT(victim->pcdata->stats[UNI_AFF], VAM_OBTENEBRATION);}
	if (IS_VAMPPASS(ch,VAM_SERPENTIS))
	{SET_BIT(victim->pcdata->stats[UNI_CURRENT], VAM_SERPENTIS);
	 SET_BIT(victim->pcdata->stats[UNI_AFF], VAM_SERPENTIS);}
	if (IS_VAMPPASS(ch,VAM_AUSPEX))
	{SET_BIT(victim->pcdata->stats[UNI_CURRENT], VAM_AUSPEX);
	 SET_BIT(victim->pcdata->stats[UNI_AFF], VAM_AUSPEX);}
	if (IS_VAMPPASS(ch,VAM_DOMINATE))
	{SET_BIT(victim->pcdata->stats[UNI_CURRENT], VAM_DOMINATE);
	 SET_BIT(victim->pcdata->stats[UNI_AFF], VAM_DOMINATE);}
	if (IS_VAMPPASS(ch,VAM_PRESENCE))
	{SET_BIT(victim->pcdata->stats[UNI_CURRENT], VAM_PRESENCE);
	 SET_BIT(victim->pcdata->stats[UNI_AFF], VAM_PRESENCE);}
        if (IS_VAMPPASS(ch,VAM_VICISSITUDE))
        {SET_BIT(victim->pcdata->stats[UNI_CURRENT], VAM_VICISSITUDE);
         SET_BIT(victim->pcdata->stats[UNI_AFF], VAM_VICISSITUDE);}
        if (IS_VAMPPASS(ch,VAM_THAU))
        {SET_BIT(victim->pcdata->stats[UNI_CURRENT], VAM_THAU);
         SET_BIT(victim->pcdata->stats[UNI_AFF], VAM_THAU);}
        if (IS_VAMPPASS(ch,VAM_ANIMAL))
        {SET_BIT(victim->pcdata->stats[UNI_CURRENT], VAM_ANIMAL);
         SET_BIT(victim->pcdata->stats[UNI_AFF], VAM_ANIMAL);}
        if (IS_VAMPPASS(ch,VAM_QUIETUS))
        {SET_BIT(victim->pcdata->stats[UNI_CURRENT], VAM_QUIETUS);
         SET_BIT(victim->pcdata->stats[UNI_AFF], VAM_QUIETUS);}



    }
    save_char_obj(ch);
    save_char_obj(victim);
    return;
}

void do_claw( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char      arg [MAX_INPUT_LENGTH];
    char      buf [MAX_INPUT_LENGTH];

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch, CLASS_WEREWOLF))
    {
	do_claws(ch,"");
	return;
    }
 
    if ( arg[0] == '\0' )
    {
	send_to_char( "Claw whom?\n\r", ch );
	return;
    }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( IS_NPC(victim) )
    {
	send_to_char( "Not on NPC's.\n\r", ch );
	return;
    }

    if ( ch == victim )
    {
	send_to_char( "You cannot claw yourself.\n\r", ch );
	return;
    }

	if (victim->class != 0) {
	send_to_char("Not on them.\n\r", ch );
	return;}

    if ( victim->level != LEVEL_AVATAR && !IS_IMMORTAL(victim) )
    {
	send_to_char( "You can only claw avatars.\n\r", ch );
	return;
    }


    if (!IS_NEWFLAG(victim, AFF_ALLOW_WERE))
    {
	stc("You are unable to infect your victim.\n\r",ch);
	return;
    }

    if (!IS_VAMPAFF(ch,VAM_CLAWS))
    {
	send_to_char("First you better get your claws out!\n\r",ch);
	return;
    }

    if (ch->exp < 10000)
    {
	send_to_char("You cannot afford the 10000 exp to pass on the gift.\n\r",ch);
	return;
    }

    ch->exp = ch->exp - 10000;
    if (ch->pcdata->stats[UNI_CURRENT] < 1) ch->pcdata->stats[UNI_CURRENT] = 1;
    else ch->pcdata->stats[UNI_CURRENT] += 1;
    if (IS_SET(ch->special,SPC_SIRE)) REMOVE_BIT(ch->special,SPC_SIRE);
    act("You plunge your claws into $N.", ch, NULL, victim, TO_CHAR);
    act("$n plunges $s claws into $N.", ch, NULL, victim, TO_NOTVICT);
    act("$n plunges $s claws into your chest.", ch, NULL, victim, TO_VICT);
    victim->class=CLASS_WEREWOLF;
    set_learnable_disciplines(victim);
    send_to_char( "You are now a werewolf.\n\r", victim );
    victim->generation = ch->generation + 1;
    free_string(victim->lord);
    if (ch->generation == 1)
	victim->lord=str_dup(ch->name);
    else
    {
	sprintf(buf,"%s %s",ch->lord,ch->name);
	victim->lord=str_dup(buf);
    }
    victim->pcdata->stats[UNI_AFF] = 0;
    victim->pcdata->stats[UNI_CURRENT] = 0;
    save_char_obj(ch);
    save_char_obj(victim);
    return;
}

void do_class( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char      arg1 [MAX_INPUT_LENGTH];
    char      arg2 [MAX_INPUT_LENGTH];
    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );
        
    if ( IS_NPC(ch) ) return;
    
    if ( arg1[0] == '\0' || arg2[0] == '\0' )
    {
	send_to_char( "Syntax: class <char> <class>.\n\r", ch );
	send_to_char("      Classes:\n\r", ch );
    send_to_char("None, ", ch);
    send_to_char("Demon, ", ch);
    send_to_char("Demon Lord , ", ch);
    send_to_char("Purple Mage, Blue Mage, Yellow Mage, Green Mage, Red Mage, ", ch);
    send_to_char("Werewolf, ", ch);
    send_to_char("Monk, ", ch);
    send_to_char("Vampire, ", ch);
    send_to_char("Drow, ", ch);
	return;
    }
    
    if ( ( victim = get_char_world( ch, arg1 ) ) == NULL )
    {
	send_to_char( "That player is not here.\n\r", ch);
	return;
    }

         if ( !str_cmp( arg2, "none"       ) ) 
    {
    /* Used to make sure the person has enough "stuff" to change */
	victim->pcdata->condition[COND_THIRST] = 10000;
	victim->move = 10000;
	victim->mana = 10000;

	victim->power[DISC_WERE_BEAR]   = 4;
        victim->power[DISC_WERE_LYNX]   = 4;
	victim->power[DISC_WERE_BOAR]   = 4;
	victim->power[DISC_WERE_OWL]    = 4;
	victim->power[DISC_WERE_SPID] = 4; 
	victim->power[DISC_WERE_WOLF]   = 4;
	victim->power[DISC_WERE_HAWK]   = 4;
	victim->power[DISC_WERE_MANT] = 4;

	if ( IS_CLASS(victim, CLASS_WEREWOLF)
	     || IS_CLASS(victim, CLASS_VAMPIRE) ) do_unwerewolf(victim,"");
	if (IS_VAMPAFF(victim,VAM_DISGUISED) ) do_mask(victim,"self");
    victim->pcdata->stats[UNI_FORM0] = 0;
 
/* All classes in general */   
    if (IS_VAMPAFF(victim,VAM_FANGS) )
    {
	 send_to_char("Your fangs slide back into your gums.\n\r",victim);
	 act("$N's fangs slide back into $s gums.", ch, NULL, victim, TO_ROOM);
	 REMOVE_BIT(victim->pcdata->stats[UNI_AFF], VAM_FANGS);
    }
    if (IS_CLASS(victim, CLASS_VAMPIRE) && IS_VAMPAFF(victim,VAM_CLAWS) ) 
	{
	    send_to_char("Your claws slide back under your nails.\n\r",victim);
	    act("$N's claws slide back under $s nails.", ch, NULL, victim, TO_ROOM);
	    REMOVE_BIT(victim->pcdata->stats[UNI_AFF], VAM_CLAWS);
	}
    else if (IS_CLASS(victim, CLASS_WEREWOLF) && IS_VAMPAFF(victim,VAM_CLAWS) ) 
    {
    	send_to_char("Your talons slide back into your fingers.\n\r",victim);
	    act("$N's talons slide back into $s fingers.",ch,NULL,victim,TO_ROOM);
    	REMOVE_BIT(victim->pcdata->stats[UNI_AFF], VAM_CLAWS);
    }

    if (IS_VAMPAFF(victim,VAM_NIGHTSIGHT) )
    {
	 send_to_char("The red glow in your eyes fades.\n\r",victim);
	 act("The red glow in $N's eyes fades.", ch, NULL, victim, TO_ROOM);
	 REMOVE_BIT(victim->pcdata->stats[UNI_AFF], VAM_NIGHTSIGHT);
    }
    if (IS_AFFECTED(victim,AFF_SHADOWSIGHT) )
    {
	 send_to_char("You can no longer see between planes.\n\r",victim);
	 REMOVE_BIT(victim->affected_by, AFF_SHADOWSIGHT);
    }
    
    if (IS_IMMUNE(victim,IMM_SHIELDED) )
    {
     send_to_char("You stop shielding your aura.\n\r",victim);
     REMOVE_BIT(victim->immune, IMM_SHIELDED);
    }
    
    if (IS_VAMPAFF(victim,VAM_DISGUISED) )
    {
     free_string( victim->morph );
     victim->morph = str_dup( victim->name );
     send_to_char("You transform into yourself.\n\r", victim);
     REMOVE_BIT(victim->pcdata->stats[UNI_AFF], VAM_DISGUISED);
    }
    
    if (IS_AFFECTED(victim,AFF_SHADOWPLANE) )
    {
     send_to_char("You fade back into the real world.\n\r",victim);
	 act("The shadows flicker and $N fades into existance.",ch,NULL,victim,TO_ROOM);
	 REMOVE_BIT(victim->affected_by,AFF_SHADOWPLANE);
	 do_look(ch,"auto");
	}
	
	if (IS_SET(victim->act, PLR_WIZINVIS) )
	{
	 REMOVE_BIT(victim->act, PLR_WIZINVIS);
	 send_to_char( "You slowly fade into existence.\n\r", victim );
	}
	
	if (IS_SET(victim->act, PLR_HOLYLIGHT) )
	{
	 REMOVE_BIT(victim->act, PLR_HOLYLIGHT);
	 send_to_char( "Your senses return to normal.\n\r", victim );
	}
	
/* Demon Stuff */
    if (IS_DEMAFF(victim,DEM_HORNS) && IS_CLASS(victim, CLASS_DEMON) )
    {
	 send_to_char("Your horns slide back into your head.\n\r",victim);
	 act("$N's horns slide back into $s head.", ch, NULL, victim, TO_ROOM);
	 REMOVE_BIT(victim->pcdata->powers[DPOWER_CURRENT], DEM_HORNS);
	}
	
	if (IS_DEMAFF(victim,DEM_HOOVES) && IS_CLASS(victim, CLASS_DEMON) )
    {
	 send_to_char("Your hooves transform into feet.\n\r",victim);
	 act("$N's hooves transform back into $s feet.", ch, NULL,victim,TO_ROOM);
	 REMOVE_BIT(victim->pcdata->powers[DPOWER_CURRENT], DEM_HOOVES);
    }
    
    if (IS_DEMAFF(victim,DEM_WINGS) && IS_CLASS(victim, CLASS_DEMON) )
    {
	if (IS_DEMAFF(victim,DEM_UNFOLDED) && IS_CLASS(victim, CLASS_DEMON) )
	{
	    send_to_char("Your wings fold up behind your back.\n\r",victim);
	    act("$N's wings fold up behind $s back.", ch, NULL, victim, TO_ROOM);
	    REMOVE_BIT(victim->pcdata->powers[DPOWER_CURRENT], DEM_UNFOLDED);
	}
	send_to_char("Your wings slide into your back.\n\r",victim);
	act("$N's wings slide into $s back.", ch, NULL, victim, TO_ROOM);
	REMOVE_BIT(victim->pcdata->powers[DPOWER_CURRENT], DEM_WINGS);
    }
    
	if ( IS_EXTRA(victim, EXTRA_OSWITCH) ) 
	{
	 do_humanform(victim,"");
	}
	
	REMOVE_BIT(victim->special, SPC_CHAMPION );
	REMOVE_BIT(victim->special, SPC_INCONNU );
	REMOVE_BIT(victim->special, SPC_ANARCH );
    REMOVE_BIT(victim->special, SPC_DEMON_LORD);
    REMOVE_BIT(victim->special, SPC_DROW_WAR );
    REMOVE_BIT(victim->special, SPC_DROW_MAG );
    REMOVE_BIT(victim->special, SPC_DROW_CLE );
	REMOVE_BIT(victim->affected_by, AFF_POLYMORPH);
	REMOVE_BIT(victim->pcdata->stats[UNI_AFF], VAM_CHANGED);
    REMOVE_BIT(victim->pcdata->powers[WOLF_POLYAFF], POLY_MIST);
	REMOVE_BIT(victim->affected_by, AFF_ETHEREAL);
	REMOVE_BIT(victim->pcdata->stats[UNI_AFF], VAM_FLYING);
	REMOVE_BIT(victim->pcdata->stats[UNI_AFF], VAM_SONIC);
	REMOVE_BIT(victim->pcdata->powers[WOLF_POLYAFF], POLY_BAT);
	REMOVE_BIT(victim->pcdata->powers[WOLF_POLYAFF], POLY_WOLF);
	
	victim->pcdata->powers[DPOWER_FLAGS] = 0;
  	victim->pcdata->stats[DEMON_TOTAL] = 0;
	victim->pcdata->stats[DEMON_CURRENT] = 0;
	victim->power[DISC_WERE_BEAR]   = 0;
    victim->power[DISC_WERE_LYNX]   = 0;
	victim->power[DISC_WERE_BOAR]   = 0;
	victim->power[DISC_WERE_OWL]    = 0;
	victim->power[DISC_WERE_SPID] = 0; 
	victim->power[DISC_WERE_WOLF]   = 0;
	victim->power[DISC_WERE_HAWK]   = 0;
	victim->pcdata->powers[1] = 0;
	victim->pcdata->condition[COND_THIRST] = 0;
	victim->move = victim->max_move;
	victim->mana = victim->max_mana;
	victim->hit = victim->max_hit;
	victim->pcdata->rank = 0;
	
	victim->rage = 0;
    free_string(victim->lord);
    victim->lord     = str_dup( "" );
    victim->generation     = 0;
    victim->pcdata->stats[UNI_AFF]     = 0;
    victim->pcdata->stats[UNI_CURRENT] = -1;
    victim->beast = 15;
    
    victim->class = 0;
    victim->trust = 0;
    victim->level = 2;
    send_to_char("You are classless now!\n\r", victim);
    }
    else if ( !str_cmp( arg2, "demon"      ) ) 
    {
    victim->class = CLASS_DEMON;
    set_learnable_disciplines(victim);
    send_to_char("You are now a demon!\n\r", victim);
    }
	else if (!str_cmp(arg2,"drow"	)){
	victim->class = CLASS_DROW;}
    else if ( !str_cmp( arg2, "dlord"      ) ) 
    {
    victim->class = 1;
    victim->level = 3;
    set_learnable_disciplines(victim);
    send_to_char("You are now a Demon Lord!\n\r", victim);
    }
    else if ( !str_cmp( arg2, "purplemage"     ) )
    {
    victim->class = 2;
    if ( victim->trust > 6 )
    {
    victim->trust = victim->trust;     
    }
    else
    {
    victim->trust = 6;
    }
    victim->level = 6;
    victim->pcdata->powers[MPOWER_RUNE0] = 0;
    victim->pcdata->powers[MPOWER_RUNE1] = 2047;
    victim->pcdata->powers[MPOWER_RUNE2] = 1023;
    victim->pcdata->powers[MPOWER_RUNE3] = 15;    
    send_to_char("You are now a purple mage!\n\r", victim);
    }
    else if ( !str_cmp( arg2, "redmage"     ) )
    {
    victim->class = 2;
    if ( victim->trust > 6 )
    {
      victim->trust=victim->trust;
    }
    else
    {
    victim->trust = 6;
    }
    victim->level = 6;
    victim->pcdata->powers[MPOWER_RUNE0] = 1;
    victim->pcdata->powers[MPOWER_RUNE1] = 2047;
    victim->pcdata->powers[MPOWER_RUNE2] = 1023;
    victim->pcdata->powers[MPOWER_RUNE3] = 15;    
    send_to_char("You are now a red mage!\n\r", victim);
    }
    else if ( !str_cmp( arg2, "yellowmage"     ) )
    {
    victim->class = 2;
    if ( victim->trust > 6 )
    {
    victim->trust=victim->trust;
    }
    else
    {
    victim->trust = 6;
    }
    victim->level = 6;
    victim->pcdata->powers[MPOWER_RUNE0] = 4;
    victim->pcdata->powers[MPOWER_RUNE1] = 2047;
    victim->pcdata->powers[MPOWER_RUNE2] = 1023;
    victim->pcdata->powers[MPOWER_RUNE3] = 15;    
    send_to_char("You are now a yellow mage!\n\r", victim);
    }
    else if ( !str_cmp( arg2, "bluemage"     ) )
    {
    victim->class = 2;
    if ( victim->trust > 6 )
    {
      victim->trust=victim->trust;
    }
    else
    {
    victim->trust = 6;
    }
    victim->level = 6;
    victim->pcdata->powers[MPOWER_RUNE0] = 2;
    victim->pcdata->powers[MPOWER_RUNE1] = 2047;
    victim->pcdata->powers[MPOWER_RUNE2] = 1023;
    victim->pcdata->powers[MPOWER_RUNE3] = 15;
    send_to_char("You are now a blue mage!\n\r", victim);
    }
    else if ( !str_cmp( arg2, "greenmage"     ) )
    {
    victim->class = 2;
    if ( victim->trust > 6 )
    {
    victim->trust=victim->trust;
    }
    else
    {
    victim->trust = 6;
    }
    victim->level = 6;
    victim->pcdata->powers[MPOWER_RUNE0] = 3;
    victim->pcdata->powers[MPOWER_RUNE1] = 2047;
    victim->pcdata->powers[MPOWER_RUNE2] = 1023;
    victim->pcdata->powers[MPOWER_RUNE3] = 15;
    send_to_char("You are now a green mage!\n\r", victim);
    }
    else if ( !str_cmp( arg2, "werewolf"   ) ) 
    {
    if (!str_cmp(ch->name, "Zaphonite") || !str_cmp(ch->name, "Lobo"))
    {
    victim->class = CLASS_WEREWOLF;
    victim->generation = 5;
    set_learnable_disciplines(victim);
    send_to_char("You are now a werewolf!\n\r", victim);
    }
    else
    {
	send_to_char("Sorry, werewolves are still being tested.\n\r",ch);
	return;
    }
    }
    else if ( !str_cmp( arg2,"cyborg"))
    {
    if (!str_cmp(ch->name,"Zaphonite") || !str_cmp(ch->name,"Lobo"))
    {
    victim->class = CLASS_CYBORG;
    victim->generation = 3;
    send_to_char("You are now a cyborg!\n\r",victim);
    }
    else
    {
	send_to_char("Sorry, cyborgs are stil being tested.\n\r",ch);
	return;
    }
    }
    else if ( !str_cmp( arg2, "vampire"    ) ) 
    {
    victim->class = CLASS_VAMPIRE;
    victim->generation = 13;
    victim->beast = 30;
    set_learnable_disciplines(victim);
    send_to_char("You are now a vampire!\n\r", victim);
    }
    else if ( !str_cmp( arg2, "highlander" ) ) 
    {
    victim->class = 16;
    victim->level = 3;
    send_to_char("You are now a highlander!\n\r", victim);
    }
    else if ( !str_cmp( arg2, "monk"      ) )
    {
     victim->class = CLASS_MONK;
     victim->level = 3;
     send_to_char("You are now a monk!\n\r", victim);
    }
 
    else if ( !str_cmp( arg2, "drow"       ) ) 
    {
    victim->class = 32;
    send_to_char("You are now a drow!\n\r", victim);
    }  
   else if ( !str_cmp( arg2, "ninja"       ) )
    {
    victim->class = 128;
    send_to_char("You are now a ninja!\n\r", victim);
    }
else
    {
	send_to_char( "Syntax: class <char> <class>.\n\r", ch );
	send_to_char("      Classes:\n\r", ch );
    send_to_char("None, ", ch);
    send_to_char("Demon, ", ch);
    send_to_char("Demon Lord , ", ch);
    send_to_char("Purple Mage, Blue Mage, Yellow Mage, \n\rGreen Mage, Red Mage, ", ch);
    send_to_char("Werewolf, ", ch);
    send_to_char("Vampire, ", ch);
    send_to_char("Monk, ", ch);
    send_to_char("Drow.\n\r",ch);
    send_to_char("Ninja.\n\r",ch);
	return;
    }
    send_to_char("Class Set.\n\r",ch);
    return;
}

void do_generation( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    int gen;
    char      arg1 [MAX_INPUT_LENGTH];
    char      arg2 [MAX_INPUT_LENGTH];
    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );
        
    if ( IS_NPC(ch) ) return;
    
    if ( arg1[0] == '\0' || arg2[0] == '\0' )
    {
	send_to_char( "Syntax: generation <char> <generation>.\n\r", ch );
    send_to_char("Generation 1 is a Master <Class> and 2 is clan leader.\n\r", ch);
	return;
    }
    
    if ( ( victim = get_char_world( ch, arg1 ) ) == NULL )
    {
	send_to_char( "That player is not here.\n\r", ch);
	return;
    }
    
    gen = is_number( arg2 ) ? atoi( arg2 ) : -1;

    send_to_char("Generation Set.\n\r",ch);
    victim->generation = gen;
    return;
}

void do_darkside( CHAR_DATA *ch, char *argument )
{
    char      arg [MAX_INPUT_LENGTH];
    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if (!IS_IMMUNE(ch, IMM_DEMON))
    {
/*
        send_to_char("That would be a very bad idea...\n\r",ch);
        return;
*/
        send_to_char("You will now allow Lloth to turn you to the dark side.\n\r",ch);
        SET_BIT(ch->immune, IMM_DEMON);
        return;

    }
    send_to_char("You will no longer allow Lloth into your mind.\n\r",ch);
    REMOVE_BIT(ch->immune, IMM_DEMON);
    return;
}

void do_arms( CHAR_DATA *ch, char *argument )
{

    if (IS_NPC(ch)) return;
    if (!IS_CLASS(ch, CLASS_HIGHLANDER))
    {
      send_to_char("Huh?\n\r", ch);
      return;
    }
   
    if (ch->practice < 75)
    {
        send_to_char( "It costs at least 75 points of primal energy to grow arms.\n\r", ch);
        return;
    }

   SET_BIT(ch->newbits, THIRD_HAND);
   SET_BIT(ch->newbits, FOURTH_HAND);
   stc("You scream in pain as two hulking arms grow from your sides.\n\r",ch);
   return;

}

void do_clan( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    char lord[MAX_INPUT_LENGTH];
    CHAR_DATA *gch;

    one_argument( argument, arg );

    if (IS_NPC(ch)) return;
    if (!IS_CLASS(ch, CLASS_HIGHLANDER))
    {
        send_to_char("Huh?\n\r",ch); 
       return;
    }

        if (ch->generation < 3)
                strcpy(lord,ch->name);
        else strcpy(lord,ch->lord);
    sprintf( buf, "The Highlanders of %s:\n\r", lord );
    send_to_char( buf, ch );
    send_to_char("#2[       Name       ] [ Hits ] [ Mana ] [ Move ] [  Exp  ]#n\n\r",ch);
    for ( gch = char_list; gch != NULL; gch = gch->next )
    {
        if ( IS_NPC(gch) ) continue;
        if ( !IS_CLASS(gch, CLASS_HIGHLANDER))
            continue;
        if ( !str_cmp(gch->lord,lord) || !str_cmp(gch->name,lord))
        {
            sprintf( buf,
            "#2[#n%-18s#2] [#n%-6d#2] [#n%-6d#2] [#n%-6d#2] [#n%7d#2]#n\n\r",
                capitalize( gch->name ),
                gch->hit,gch->mana,gch->move, gch->exp);
                send_to_char( buf, ch );
        }
    }
    return;
}

void do_weaponteach( CHAR_DATA *ch, char *argument )
{
    char      buf [MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    char      arg [MAX_INPUT_LENGTH];

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch, CLASS_HIGHLANDER))
    {
        send_to_char("Huh?\n\r",ch);
        return;
    }

    if (arg[0] == '\0')
    {
        send_to_char( "Teach who the basics of weapons?\n\r", ch );
        return;
    }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
        send_to_char( "They aren't here.\n\r", ch );
        return;
    }

    if ( IS_NPC(victim) )
    {
	send_to_char( "Not on NPC's.\n\r", ch );
        return;
    }

    if ( ch == victim )
    {
        send_to_char("Not on yourself.\n\r", ch );
        return;
    }

    if (victim->class != 0)
    {
        send_to_char("You can't make a classed person a highlander.\n\r", ch);
        return;}

    if ( victim->level != LEVEL_AVATAR && !IS_IMMORTAL(victim) )
    {
        send_to_char( "Only on avatars.\n\r", ch );
        return;
    }

    if (!IS_IMMUNE(victim,IMM_DEMON))
    {
        send_to_char( "Not on an unwilling person.\n\r", ch);
        return;
    }

    if (ch->exp < 10000)
    {
        send_to_char("You cannot afford the 10,000 exp.\n\r",ch);
        return;
    }

    ch->exp = ch->exp - 10000;
    act("You make $N a highlander!", ch, NULL, victim, TO_CHAR);
    act("$n makes $N a highlander!", ch, NULL, victim, TO_NOTVICT);
    act("$n makes you a highlander!", ch, NULL, victim, TO_VICT);
    victim->class=16;
    victim->class=CLASS_HIGHLANDER;
    victim->special=0;

    if (IS_CLASS(victim, CLASS_VAMPIRE)) do_mortalvamp(victim,"");
    REMOVE_BIT(victim->act, PLR_HOLYLIGHT);
    REMOVE_BIT(victim->act, PLR_WIZINVIS);
    REMOVE_BIT(victim->special, SPC_SIRE);
    REMOVE_BIT(victim->special, SPC_ANARCH);
    victim->rage = 0;
    victim->generation = ch->generation + 1;
        victim->special = 0;
    free_string(victim->morph);
    victim->morph=str_dup("");

    free_string(victim->lord);
    if (ch->generation == 1)
        victim->lord=str_dup(ch->name);
    else
    {
        sprintf(buf,"%s %s",ch->lord,ch->name);
        victim->lord=str_dup(buf);
    }

    save_char_obj(ch);
    save_char_obj(victim);
    return;
}

void reset_weapon( CHAR_DATA *ch, int dtype )
{
	if ( ch->wpn[dtype] > 200 )
		ch->wpn[dtype] = 200;
	return;
}

void reset_spell( CHAR_DATA *ch, int dtype )
{
	if ( ch->spl[dtype] > 200 )
		ch->spl[dtype] = 200;
	return;
}


void do_stake( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    OBJ_DATA  *stake;
    char      arg [MAX_INPUT_LENGTH];
    int       blood;

    stc("You plunge a stake into a Fuzzy little bunny, who is a wizended whore, which spreads it's plagues throughout the lands with a large dildo and a man named Thomas.  On Tuesdays he spanks his father. Thank you.\n\r",ch);
    return;

    argument = one_argument( argument, arg );
    if (IS_NPC( ch )) return;

    if ( arg[0] == '\0' )
    {
	send_to_char( "Stake whom?\n\r", ch );
	return;
    }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    stake = get_eq_char( ch, WEAR_HOLD );
    if ( stake == NULL || stake->item_type != ITEM_STAKE )
    {
	stake = get_eq_char( ch, WEAR_WIELD );
	if ( stake == NULL || stake->item_type != ITEM_STAKE )
	{
	    send_to_char( "How can you stake someone down without holding a stake?\n\r", ch );
	    return;
	}
    }

    if ( IS_NPC(victim) )
    {
	send_to_char( "Not on NPC's.\n\r", ch );
	return;
    }

    if ( ch == victim )
    {
	send_to_char( "You cannot stake yourself.\n\r", ch );
	return;
    }

    if (!IS_CLASS(victim, CLASS_VAMPIRE))
    {
	send_to_char( "You can only stake vampires.\n\r", ch );
	return;
    }

    if (victim->position > POS_MORTAL)
    {
	send_to_char( "You can only stake down a vampire who is mortally wounded.\n\r", ch );
	return;
    }

    act("You plunge $p into $N's heart.", ch, stake, victim, TO_CHAR);
    act("$n plunges $p into $N's heart.", ch, stake, victim, TO_NOTVICT);
    send_to_char( "You feel a stake plunged through your heart.\n\r", victim );
    if (IS_IMMUNE(victim,IMM_STAKE)) return;

    /* Have to make sure they have enough blood to change back */
    blood = victim->pcdata->condition[COND_THIRST];
    victim->pcdata->condition[COND_THIRST] = 666;

    /* To take care of vampires who have powers in affect. */
    if (IS_VAMPAFF(victim,VAM_DISGUISED) ) do_mask(victim,"self");
    if (IS_IMMUNE(victim,IMM_SHIELDED) ) do_shield(victim,"");
    if (IS_AFFECTED(victim,AFF_SHADOWPLANE) ) do_shadowplane(victim,"");
    if (IS_VAMPAFF(victim,VAM_FANGS) ) do_fangs(victim,"");
    if (IS_VAMPAFF(victim,VAM_CLAWS) ) do_claws(victim,"");
    if (IS_VAMPAFF(victim,VAM_NIGHTSIGHT) ) do_nightsight(victim,"");
    if (IS_AFFECTED(victim,AFF_SHADOWSIGHT) ) do_shadowsight(victim,"");
    if (IS_SET(victim->act,PLR_HOLYLIGHT) ) do_truesight(victim,"");
    if (IS_VAMPAFF(victim,VAM_CHANGED) ) do_change(victim,"human");
    if (IS_POLYAFF(victim,POLY_SERPENT) ) do_serpent(victim,"");
    victim->rage = 0;
    victim->pcdata->condition[COND_THIRST] = blood;

    REMOVE_BIT(victim->class, CLASS_VAMPIRE);
    obj_from_char(stake);
    obj_to_char(stake,victim);
    ch->exp = ch->exp + 1000;
    victim->home = 3001;
    return;
}

void do_mask( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char      arg [MAX_INPUT_LENGTH];
    char      buf [MAX_INPUT_LENGTH];

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch, CLASS_VAMPIRE))
    {
	send_to_char( "Huh?\n\r", ch );
	return;
    }
    if (ch->power[DISC_VAMP_OBFU] < 2  )
    {
        send_to_char("You must obtain at least level 2 in Obfuscate to use Mask.\n\r",ch);
	return;
    }

    if ( arg[0] == '\0' )
    {
	send_to_char( "Change to look like whom?\n\r", ch );
	return;
    }

    if (IS_AFFECTED(ch,AFF_POLYMORPH) && !IS_VAMPAFF(ch,VAM_DISGUISED))
    {
	send_to_char( "Not while polymorphed.\n\r", ch );
	return;
    }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( IS_NPC(victim) )
    {
	send_to_char( "Not on NPC's.\n\r", ch );
	return;
    }

    if ( IS_IMMORTAL(victim) && victim != ch )
    {
	send_to_char( "You can only mask avatars or lower.\n\r", ch );
	return;
    }

    if ( ch->pcdata->condition[COND_THIRST] < 40 )
    {
	send_to_char("You have insufficient blood.\n\r",ch);
	return;
    }
    ch->pcdata->condition[COND_THIRST] -= number_range(30,40);

    if ( ch == victim )
    {
	if (!IS_AFFECTED(ch,AFF_POLYMORPH) && !IS_VAMPAFF(ch,VAM_DISGUISED))
	{
	    send_to_char( "You already look like yourself!\n\r", ch );
	    return;
	}
	sprintf(buf,"Your form shimmers and transforms into %s.",ch->name);
	act(buf,ch,NULL,victim,TO_CHAR);
	sprintf(buf,"%s's form shimmers and transforms into %s.",ch->morph,ch->name);
	act(buf,ch,NULL,victim,TO_ROOM);
	REMOVE_BIT(ch->affected_by, AFF_POLYMORPH);
	REMOVE_BIT(ch->pcdata->stats[UNI_AFF], VAM_DISGUISED);
    	free_string( ch->morph );
    	ch->morph = str_dup( "" );
	return;
    }
    if (IS_VAMPAFF(ch,VAM_DISGUISED))
    {
    	sprintf(buf,"Your form shimmers and transforms into a clone of %s.",victim->name);
    	act(buf,ch,NULL,victim,TO_CHAR);
    	sprintf(buf,"%s's form shimmers and transforms into a clone of %s.",ch->morph,victim->name);
    	act(buf,ch,NULL,victim,TO_NOTVICT);
    	sprintf(buf,"%s's form shimmers and transforms into a clone of you!",ch->morph);
    	act(buf,ch,NULL,victim,TO_VICT);
    	free_string( ch->morph );
    	ch->morph = str_dup( victim->name );
	return;
    }
    sprintf(buf,"Your form shimmers and transforms into a clone of %s.",victim->name);
    act(buf,ch,NULL,victim,TO_CHAR);
    sprintf(buf,"%s's form shimmers and transforms into a clone of %s.",ch->name,victim->name);
    act(buf,ch,NULL,victim,TO_NOTVICT);
    sprintf(buf,"%s's form shimmers and transforms into a clone of you!",ch->name);
    act(buf,ch,NULL,victim,TO_VICT);
    SET_BIT(ch->affected_by, AFF_POLYMORPH);
    SET_BIT(ch->pcdata->stats[UNI_AFF], VAM_DISGUISED);
    free_string( ch->morph );
    ch->morph = str_dup( victim->name );
    return;
}

void do_change( CHAR_DATA *ch, char *argument )
{
    char arg [MAX_INPUT_LENGTH]; 
    char buf [MAX_STRING_LENGTH]; 
    argument = one_argument( argument, arg ); 

    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch, CLASS_VAMPIRE))
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }

    if (ch->power[DISC_VAMP_PROT] < 3  )
    {
        send_to_char("You must obtain at least level 3 in Protean to use Minor Change.\n\r",ch);
	return;
    }

    if ( arg[0] == '\0' )
    {
	send_to_char( "You can change between 'human', 'bat', 'wolf' and 'mist' forms.\n\r", ch );
	return;
    }

    if ( !str_cmp(arg,"bat") )
    {
	if (IS_AFFECTED(ch, AFF_POLYMORPH))
	{
	    send_to_char( "You can only polymorph from human form.\n\r", ch );
	    return;
	}
    	if ( ch->pcdata->condition[COND_THIRST] < 50 )
    	{
	    send_to_char("You have insufficient blood.\n\r",ch);
	    return;
    	}
	if (ch->stance[0] != -1) do_stance(ch,"");
	if (ch->mounted == IS_RIDING) do_dismount(ch,"");
    	ch->pcdata->condition[COND_THIRST] -= number_range(40,50);
	clear_stats(ch);
	act( "You transform into bat form.", ch, NULL, NULL, TO_CHAR );
	act( "$n transforms into a bat.", ch, NULL, NULL, TO_ROOM );
	SET_BIT(ch->pcdata->stats[UNI_AFF], VAM_FLYING);
	SET_BIT(ch->pcdata->stats[UNI_AFF], VAM_SONIC);
/*	SET_BIT(ch->pcdata->powers[WOLF_POLYAFF], POLY_BAT);*/
	SET_BIT(ch->polyaff, POLY_BAT);
	SET_BIT(ch->pcdata->stats[UNI_AFF], VAM_CHANGED);
	SET_BIT(ch->affected_by, AFF_POLYMORPH);
	sprintf(buf, "%s the vampire bat", ch->name);
    	free_string( ch->morph );
    	ch->morph = str_dup( buf );
	return;
    }
    else if ( !str_cmp(arg,"wolf") )
    {
	if (IS_AFFECTED(ch, AFF_POLYMORPH))
	{
	    send_to_char( "You can only polymorph from human form.\n\r", ch );
	    return;
	}
    	if ( ch->pcdata->condition[COND_THIRST] < 50 )
    	{
	    send_to_char("You have insufficient blood.\n\r",ch);
	    return;
    	}
	if (ch->stance[0] != -1) do_stance(ch,"");
	if (ch->mounted == IS_RIDING) do_dismount(ch,"");
    	ch->pcdata->condition[COND_THIRST] -= number_range(40,50);
	act( "You transform into wolf form.", ch, NULL, NULL, TO_CHAR );
	act( "$n transforms into a dire wolf.", ch, NULL, NULL, TO_ROOM );
	clear_stats(ch);
    	if (ch->wpn[0] > 0)
    	{
	    ch->hitroll += (ch->wpn[0]);
	    ch->damroll += (ch->wpn[0]);
	    ch->armor   -= (ch->wpn[0] * 3);
    	}
    	ch->pcdata->mod_str = 10;
/*	SET_BIT(ch->pcdata->powers[WOLF_POLYAFF], POLY_WOLF);*/
	SET_BIT(ch->polyaff, POLY_WOLF);
	SET_BIT(ch->affected_by, AFF_POLYMORPH);
	SET_BIT(ch->pcdata->stats[UNI_AFF], VAM_CHANGED);
	ch->max_hit = ch->max_hit + 500;
	ch->hit = ch->hit + 500;
	sprintf(buf, "%s the dire wolf", ch->name);
    	free_string( ch->morph );
    	ch->morph = str_dup( buf );
	return;
    }
    else if ( !str_cmp(arg,"mist") )
    {
	if (IS_AFFECTED(ch, AFF_POLYMORPH))
	{
	    send_to_char( "You can only polymorph from human form.\n\r",
ch );
	    return;
	}

	if (has_timer(ch)) return;

    	if ( ch->pcdata->condition[COND_THIRST] < 50 )
    	{
	    send_to_char("You have insufficient blood.\n\r",ch);
	    return;
    	}

	if (ch->stance[0] != -1) do_stance(ch,"");
	if (ch->mounted == IS_RIDING) do_dismount(ch,"");
    	ch->pcdata->condition[COND_THIRST] -= number_range(40,50);
	act( "You transform into mist form.", ch, NULL, NULL, TO_CHAR );
	act( "$n transforms into a white mist.", ch, NULL, NULL, TO_ROOM );
	if (IS_EXTRA(ch, TIED_UP))
	{
	    act("The ropes binding you fall through your ethereal form.",ch,NULL,NULL,TO_CHAR);
	    act("The ropes binding $n fall through $s ethereal form.",ch,NULL,NULL,TO_ROOM);
	    REMOVE_BIT(ch->extra, TIED_UP);
	    REMOVE_BIT(ch->extra, GAGGED);
	    REMOVE_BIT(ch->extra, BLINDFOLDED);
	}
	if (is_affected(ch, gsn_web))
	{
	    act("The webbing entrapping $n falls through $s ethereal form.",ch,NULL,NULL,TO_ROOM);
	    send_to_char("The webbing entrapping you falls through your ethereal form.\n\r",ch);
	    affect_strip(ch, gsn_web);
	}
	clear_stats(ch);
/*	SET_BIT(ch->pcdata->powers[WOLF_POLYAFF], POLY_MIST);*/
	SET_BIT(ch->polyaff, POLY_MIST);
	SET_BIT(ch->pcdata->stats[UNI_AFF], VAM_CHANGED);
	SET_BIT(ch->affected_by, AFF_POLYMORPH);
	SET_BIT(ch->affected_by, AFF_ETHEREAL);
	sprintf(buf, "%s the white mist", ch->name);
    	free_string( ch->morph );
    	ch->morph = str_dup( buf );
	return;
    }
    else if ( !str_cmp(arg,"human") )
    {
       if (!IS_AFFECTED(ch, AFF_POLYMORPH))
	{
	    send_to_char( "You are already in human form.\n\r", ch );
	    return;
	}
	if (IS_VAMPAFF(ch, VAM_CHANGED) && IS_POLYAFF(ch, POLY_BAT))
	{
	    REMOVE_BIT(ch->pcdata->stats[UNI_AFF], VAM_FLYING);
	    REMOVE_BIT(ch->pcdata->stats[UNI_AFF], VAM_SONIC);
	    REMOVE_BIT(ch->polyaff, POLY_BAT);
/*	    REMOVE_BIT(ch->pcdata->powers[WOLF_POLYAFF], POLY_BAT);*/
	}
	else if (IS_VAMPAFF(ch, VAM_CHANGED) && IS_POLYAFF(ch, POLY_WOLF))
	{
/*	    REMOVE_BIT(ch->pcdata->powers[WOLF_POLYAFF], POLY_WOLF);*/
	    REMOVE_BIT(ch->polyaff, POLY_WOLF);
	    ch->max_hit = ch->max_hit - 500;
	    ch->hit = ch->hit - 500;
	    if (ch->hit < 1) ch->hit = 1;
	}
	else if (IS_VAMPAFF(ch, VAM_CHANGED) && IS_POLYAFF(ch, POLY_MIST))
	{
/*	    REMOVE_BIT(ch->pcdata->powers[WOLF_POLYAFF], POLY_MIST);*/
	    REMOVE_BIT(ch->polyaff, POLY_MIST);
	    REMOVE_BIT(ch->affected_by, AFF_ETHEREAL);
	}
	else
	{
	    /* In case they try to change to human from a non-vamp form */
	    send_to_char( "You seem to be stuck in this form.\n\r", ch );
	    return;
	}
	act( "You transform into human form.", ch, NULL, NULL, TO_CHAR );
	act( "$n transforms into human form.", ch, NULL, NULL, TO_ROOM );
	REMOVE_BIT(ch->affected_by, AFF_POLYMORPH);
	REMOVE_BIT(ch->pcdata->stats[UNI_AFF], VAM_CHANGED);
	clear_stats(ch);
  	free_string( ch->morph );
    	ch->morph = str_dup( "" );
	return;
    }
    else
	send_to_char( "You can change between 'human', 'bat', 'wolf' and 'mist' forms.\n\r", ch );
    return;
}

void do_clandisc( CHAR_DATA *ch, char *argument )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch, CLASS_VAMPIRE))
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }

    if (arg1[0] == '\0' && arg2[0] == '\0')
    {
        do_stat(ch,"");
        return;
    }
    if (arg2[0] == '\0')
    {
        if (!str_cmp(arg1,"animalism"))
	{
            send_to_char("Animalism: The discipline of nature control.\n\r",ch);
            if (ch->power[DISC_VAMP_ANIM] < 1) 
                send_to_char("You have none of the Animalism powers.\n\r",ch);
            if (ch->power[DISC_VAMP_ANIM] > 0) 
                send_to_char("Serenity: You can sooth the most aggressive soul (Golconda Required).\n\r",ch);
	    return;
	}
        else if (!str_cmp(arg1,"auspex"))
	{
            send_to_char("Auspex: The discipline of extrasensory awareness.\n\r",ch);
            if (ch->power[DISC_VAMP_AUSP] < 1) 
                send_to_char("You have none of the Auspex discipline powers.\n\r",ch);
            if (ch->power[DISC_VAMP_AUSP] > 0) 
                send_to_char("Truesight: The user can see everything, including invis.\n\r",ch);
            if (ch->power[DISC_VAMP_AUSP] > 1) 
                send_to_char("Scry: Allows you to view the room the specified target is in.\n\r",ch);
            if (ch->power[DISC_VAMP_AUSP] > 2) 
                send_to_char("Readaura: Gives you detained information about a creature or object.\n\r",ch);
	    return;
	}
        else if (!str_cmp(arg1,"celerity"))
	{
            send_to_char("Celerity: The discipline of superior speed.\n\r",ch);
            return;
	}
        else if (!str_cmp(arg1,"chimerstry"))
        {
            send_to_char("chimerstry: The discipline of illusion.\n\r",ch);
            return;
        }
	else if (!str_cmp(arg1,"daimoinon"))
	{
            send_to_char("Daimoinon: The discipline of dark corruption.\n\r",ch);
            if (ch->power[DISC_VAMP_DAIM] < 1) 
                send_to_char("You have none of the Daimoinon discipline powers.\n\r",ch);
	    return;
        }

        else if (!str_cmp(arg1,"dominate"))
	{
            send_to_char("Dominate: The discipline of control.\n\r",ch);
            if (ch->power[DISC_VAMP_DOMI] < 1) 
                send_to_char("You have none of the Dominate discipline powers.\n\r",ch);
            if (ch->power[DISC_VAMP_DOMI] > 0) 
                send_to_char("Command: You can plant suggestions in the mind of others.\n\r",ch);
            if (ch->power[DISC_VAMP_DOMI] > 1) 
                send_to_char("Shield: You are able to shield your mind from scrying and aura-reading.\n\r",ch);
            if (ch->power[DISC_VAMP_DOMI] > 3) 
                send_to_char("Possession: You can take control of mobs by feeding them blood.\n\r",ch);
	    return;
	}
        else if (!str_cmp(arg1,"fortitude"))
	{
            send_to_char("Fortitude: The discipline of supernatural toughness and vigor.\n\r",ch);
            if (ch->power[DISC_VAMP_FORT] < 1) 
		send_to_char("You have no fortitude.\n\r",ch);
	    return;
	}
        else if (!str_cmp(arg1,"obfuscate"))
	{
            send_to_char("Obfuscate: The discipline of stealth.\n\r",ch);
            if (ch->power[DISC_VAMP_OBFU] < 1) 
                send_to_char("You have none of the Obfuscate discipline powers.\n\r",ch);
	    return;
	}
        else if (!str_cmp(arg1,"obtenebration"))
	{
            send_to_char("Obtenebration: The discipline of darkness manipulation.\n\r",ch);
            if (ch->power[DISC_VAMP_OBTE] < 1) 
                send_to_char("You have none of the Obtenebration discipline powers.\n\r",ch);
	    return;
	}
        else if (!str_cmp(arg1,"potence"))
	{
            send_to_char("Potence: The discipline of superior strength.\n\r",ch);
            return;
	}
        else if (!str_cmp(arg1,"presence"))
	{
            send_to_char("Presence: The discipline of appeal and attractiveness.\n\r",ch);
            if (ch->power[DISC_VAMP_PRES] < 1) 
                send_to_char("You have none of the Presence discipline powers.\n\r",ch);
	    return;
        }
        else if (!str_cmp(arg1,"protean"))
	{
            send_to_char("Protean: The discipline of neutral transformation.\n\r",ch);
            if (ch->power[DISC_VAMP_PROT] < 1) 
                send_to_char("You have none of the Protean discipline powers.\n\r",ch);
	    return;
        }
        else if (!str_cmp(arg1,"quietus"))
	{
            send_to_char("Quietus: The discipline of death.\n\r",ch);
            if (ch->power[DISC_VAMP_QUIE] < 1) 
                send_to_char("You have none of the Quietus discipline powers.\n\r",ch);
            if (ch->power[DISC_VAMP_QUIE] > 3)
                send_to_char("Spit: You can project your deadly spit at a foe\n\r",ch); 
           return;
        }
        else if (!str_cmp(arg1,"serpentis"))
	{
            send_to_char("Serpentis: The discipline of temptation and corruption.\n\r",ch);
            if (ch->power[DISC_VAMP_SERP] < 1) 
                send_to_char("You have none of the Serpentis discipline powers.\n\r",ch);
	    return;
        }
        else if (!str_cmp(arg1,"thaumaturgy"))
	{
            send_to_char("Thaumaturgy: The discipline of blood magic.\n\r",ch);
            if (ch->power[DISC_VAMP_THAU] < 1) 
                send_to_char("You have none of the Thaumaturgy discipline powers.\n\r",ch);
            if (ch->power[DISC_VAMP_THAU] > 0) 
                send_to_char("Theft: You can take from the blood pool of other players.\n\r",ch);

            return;
        }
        else if (!str_cmp(arg1,"vicissitude"))
	{
            send_to_char("Vicissitude: The discipline of evil body control.\n\r",ch);
            if (ch->power[DISC_VAMP_VICI] < 1) 
                send_to_char("You have none of the Vicissitude discipline powers.\n\r",ch);
            if (ch->power[DISC_VAMP_VICI] > 3) 
                send_to_char("Zuloform: Transformation into a powerful being.\n\r",ch);

            return;
        }
        do_stat(ch,"");
        return;

    }
    if (!str_cmp(arg2,"improve"))
    {
	int improve;
	int cost;
	int max;
        int maxlevel;
/*
	stc("Please use the new commands, Disciplines and research.\n\r",ch);
	return;
*/
	if (ch->generation == 13)
          maxlevel=10;
         else if (ch->generation == 12)
          maxlevel=10;
         else if (ch->generation == 11)
          maxlevel=10;
          else if (ch->generation == 10)
          maxlevel=10;
          else if (ch->generation == 9)
          maxlevel=10;
          else if (ch->generation == 8)
          maxlevel=10;
          else if (ch->generation == 7)
          maxlevel=10;
        else if (ch->generation == 6)
          maxlevel=10;
	else if (ch->generation == 5)
	  maxlevel=10;        
	else if (ch->generation  == 4)
          maxlevel=10;
        else
         maxlevel=10;
             if (!str_cmp(arg1,"animalism"       )) {improve = DISC_VAMP_ANIM;          max=maxlevel;}
        else if (!str_cmp(arg1,"auspex"          )) {improve = DISC_VAMP_AUSP;          max=maxlevel;}
        else if (!str_cmp(arg1,"celerity"        )) {improve = DISC_VAMP_CELE;        max=maxlevel;}
        else if (!str_cmp(arg1,"chimerstry"      )) {improve = DISC_VAMP_CHIM; max=maxlevel;}
	else if (!str_cmp(arg1,"dominate"        )) {improve = DISC_VAMP_DOMI;        max=maxlevel;}
        else if (!str_cmp(arg1,"daimoinon"       )) {improve = DISC_VAMP_DAIM;max=maxlevel;}
        else if (!str_cmp(arg1,"fortitude"       )) {improve = DISC_VAMP_FORT;       max=maxlevel;}
        else if (!str_cmp(arg1,"obfuscate"       )) {improve = DISC_VAMP_OBFU;       max=maxlevel;}
        else if (!str_cmp(arg1,"obtenebration"   )) {improve = DISC_VAMP_OBTE;   max=maxlevel;}
        else if (!str_cmp(arg1,"potence"         )) {improve = DISC_VAMP_POTE;         max=maxlevel;}
        else if (!str_cmp(arg1,"presence"        )) {improve = DISC_VAMP_PRES;        max=maxlevel;}
        else if (!str_cmp(arg1,"protean"         )) {improve = DISC_VAMP_PROT;         max=maxlevel;}
        else if (!str_cmp(arg1,"quietus"         )) {improve = DISC_VAMP_QUIE;         max=maxlevel;}
        else if (!str_cmp(arg1,"serpentis"       )) {improve = DISC_VAMP_SERP;       max=maxlevel;}
        else if (!str_cmp(arg1,"thaumaturgy"     )) {improve = DISC_VAMP_THAU;            max=maxlevel;}
        else if (!str_cmp(arg1,"vicissitude"     )) {improve = DISC_VAMP_VICI;     max=maxlevel;}
	else if (!str_cmp(arg1,"obeah"		 )) {improve =
DISC_VAMP_OBEA; max = maxlevel; }
	else if (!str_cmp(arg1,"melpominee"	 )) {improve =
DISC_VAMP_MELP; max = maxlevel; }
	else if (!str_cmp(arg1,"necromancy"	 )) {improve =
DISC_VAMP_NECR; max = maxlevel; }
	else if (!str_cmp(arg1,"thanatosis"	 )) {improve =
DISC_VAMP_THAN; max = maxlevel; }
        else
	{
            send_to_char("You can improve: Animalism, Auspex, Celerity, Dominate, Fortitude, Obfuscate,\n\r Obtenebration, Potence, Presence, Protean, Quietus, Serpentis,\n\r Thaumaturgy or Vicissitude.\n\r",ch);
	    return;
	}
        cost = (ch->power[improve]+1) * 10;
	arg1[0] = UPPER(arg1[0]);
	if ( ch->power[improve] >= max && ch->pcdata->rank ==AGE_METHUSELAH)
	{
            sprintf(buf,"You have already gained all the powers of the %s discipline.\n\r", arg1);
	    send_to_char(buf,ch);
	    return;
	}
        if (ch->power[improve] >= max)
        {
           sprintf(buf,"You have already maxed %s.\n\r",arg1);
           send_to_char(buf,ch);
           return;
        }
	if ( cost > ch->practice )
	{
            sprintf(buf,"It costs you %d primal to improve your %s discipline.\n\r", cost, arg1);
	    send_to_char(buf,ch);
	    return;
	}
	ch->power[improve] += 1;
	ch->practice -= cost;
        sprintf(buf,"You improve your ability in the %s discipline.\n\r", arg1);
	send_to_char(buf,ch);
    }
    else send_to_char("To improve a discipline, type: Clandisc <discipline type> improve.\n\r",ch);
    return;
}


void do_vampire( CHAR_DATA *ch, char *argument )
{
    char      arg [MAX_INPUT_LENGTH];
    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if (!IS_IMMUNE(ch, IMM_VAMPIRE))
    {
	send_to_char("You will now allow vampires to bite you.\n\r",ch);
	SET_BIT(ch->immune, IMM_VAMPIRE);
	return;
    }
    send_to_char("You will no longer allow vampires to bite you.\n\r",ch);
    REMOVE_BIT(ch->immune, IMM_VAMPIRE);
    return;
}

void do_shadowplane( CHAR_DATA *ch, char *argument )
{
    OBJ_DATA *obj;
    char      arg [MAX_INPUT_LENGTH];
    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch, CLASS_WEREWOLF) || ch->power[DISC_WERE_OWL] < 3)
    {
	if (!IS_CLASS(ch, CLASS_VAMPIRE))
	{
	    send_to_char("Huh?\n\r",ch);
	    return;
	}
        if (ch->power[DISC_VAMP_OBTE] < 3)
	{
            send_to_char("You must obtain at least level 3 in Obtenebration to use Shadowplane .\n\r",ch);
	    return;
	}
    }

	if (has_timer(ch)) return;

    if (IS_CLASS(ch, CLASS_VAMPIRE) && ch->pcdata->condition[COND_THIRST] < 75)
    {
	send_to_char("You have insufficient blood.\n\r",ch);
	return;
    }
    
    if (IS_CLASS(ch, CLASS_VAMPIRE))
	ch->pcdata->condition[COND_THIRST] -= number_range(65,75);

    if ( arg[0] == '\0' )
    {
    	if (!IS_AFFECTED(ch, AFF_SHADOWPLANE))
    	{
	    send_to_char("You fade into the plane of shadows.\n\r",ch);
	    act("The shadows flicker and swallow up $n.",ch,NULL,NULL,TO_ROOM);
	    SET_BIT(ch->affected_by, AFF_SHADOWPLANE);
	    do_look(ch,"auto");
	    return;
    	}
    	REMOVE_BIT(ch->affected_by, AFF_SHADOWPLANE);
    	send_to_char("You fade back into the real world.\n\r",ch);
	act("The shadows flicker and $n fades into existance.",ch,NULL,NULL,TO_ROOM);
	do_look(ch,"auto");
	return;
    }

    if ( ( obj = get_obj_here( ch, arg ) ) == NULL )
    {
	send_to_char( "What do you wish to toss into the shadow plane?\n\r", ch );
	return;
    }

    if (IS_AFFECTED(ch, AFF_SHADOWPLANE))
    	send_to_char( "You toss it to the ground and it vanishes.\n\r", ch );
    else
    	send_to_char( "You toss it into a shadow and it vanishes.\n\r", ch );
    return;
}


void do_darkheart( CHAR_DATA *ch, char *argument )
{
    char      arg [MAX_INPUT_LENGTH];

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch, CLASS_VAMPIRE) )
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }
    if (ch->power[DISC_VAMP_SERP] < 1  )
    {
        send_to_char("You must obtain at least level 1 in Serpentis to use Darkheart.\n\r",ch);
	return;
    }
    if (IS_IMMUNE(ch,IMM_STAKE) )
    {
	send_to_char("But you've already torn your heart out!\n\r",ch);
	return;
    }
    if ( ch->pcdata->condition[COND_THIRST] < 1000 / ch->generation )
    {
	send_to_char("You have insufficient blood.\n\r",ch);
	return;
    }
    ch->pcdata->condition[COND_THIRST] -= 100;
    send_to_char("You rip your heart from your body and toss it to the ground.\n\r",ch);
    act("$n rips $s heart out and tosses it to the ground.", ch, NULL, NULL, TO_ROOM);
    make_part( ch, "heart" );
    ch->hit = ch->hit - number_range(10,20);
    update_pos(ch);
    if (ch->position == POS_DEAD && !IS_HERO(ch))
    {
	send_to_char( "You have been KILLED!!\n\r\n\r", ch );
	raw_kill(ch);
	return;
    }
    SET_BIT(ch->immune, IMM_STAKE);
    return;
}

void do_truesight( CHAR_DATA *ch, char *argument )
{
    if ( IS_NPC(ch) )
	return;

         if (!IS_CLASS(ch, CLASS_VAMPIRE) && 
	!IS_CLASS(ch, CLASS_HIGHLANDER) && 
	!IS_CLASS(ch, CLASS_MAGE) && 
	!IS_CLASS(ch, CLASS_DEMON) && 
	!IS_CLASS(ch, CLASS_MONK) &&
	!IS_CLASS(ch, CLASS_WEREWOLF))
	 {
	     send_to_char("Huh?\n\r",ch);
	     return;
         }
/*
 if ((ch->max_hit < 1000) && IS_CLASS(ch,CLASS_HIGHLANDER))
        {
        stc("You dont have enough hps to use truesight",ch);
        return;
        }*/
   
 if ((ch->power[DISC_VAMP_AUSP] < 1) && IS_CLASS(ch, CLASS_VAMPIRE))
	{
	send_to_char("You must obtain at least level 1 in Auspex to use Truesight.\n\r", ch);
        return;
        }

    if ((ch->power[DISC_WERE_OWL] < 3) && IS_CLASS(ch,CLASS_WEREWOLF))
        {
	send_to_char("You must obtain level 3 in the Owl totem to use Truesight.\n\r",ch);
	return;
	}
    
	if (!IS_DEMPOWER( ch, DEM_TRUESIGHT) && IS_CLASS(ch,CLASS_DEMON))
    {
        stc("You must inpart truesight first.\n\r",ch);
        return;
    }

   if ( IS_CLASS(ch, CLASS_MONK) && ch->monkab[AWARE] < 3 )
    {
	stc("You must obtain level 4 in Awareness first.\n\r",ch);
	return;
    }
   
    if ( IS_SET(ch->act, PLR_HOLYLIGHT) )
    {
	REMOVE_BIT(ch->act, PLR_HOLYLIGHT);
	send_to_char( "Your senses return to normal.\n\r", ch );
    }
    else
    {
	SET_BIT(ch->act, PLR_HOLYLIGHT);
	send_to_char( "Your senses increase to incredible proportions.\n\r", ch );
    }

    return;
}

void do_majesty( CHAR_DATA *ch, char *argument )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];

    smash_tilde( argument );
    argument = one_argument( argument, arg1 );
    strcpy( arg2, argument );

    if ( IS_NPC(ch) )
	return;

    if (!IS_CLASS(ch, CLASS_VAMPIRE) )
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }
    if (ch->power[DISC_VAMP_PRES] < 5  )
    {
        send_to_char("You must obtain at least level 5 in Presence to use Majesty.\n\r",ch);
	return;
    }

    if (has_timer(ch)) return;

    if (IS_AFFECTED(ch, AFF_PEACE))
    {
        REMOVE_BIT(ch->affected_by, AFF_PEACE);
        act( "You lower your majesty.",  ch, NULL, NULL, TO_CHAR    );
        act( "$n looks less imposing.",  ch, NULL, NULL, TO_NOTVICT );
        return;
    }
    if ( ch->pcdata->condition[COND_THIRST] < 45 )
    {
	send_to_char( "You have insufficient blood.\n\r", ch );
	return;
    }

    ch->pcdata->condition[COND_THIRST] -= number_range(35,45);
    SET_BIT(ch->affected_by, AFF_PEACE);
    act( "You raise your majesty.",  ch, NULL, NULL, TO_CHAR    );
    act( "$n suddenly looks very imposing.",  ch, NULL, NULL, TO_NOTVICT);
    return;
}

void do_scry( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    ROOM_INDEX_DATA *chroom;
    ROOM_INDEX_DATA *victimroom;
    char      arg [MAX_INPUT_LENGTH];

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if (!IS_ITEMAFF(ch, ITEMA_VISION))
    {
	if (!IS_CLASS(ch, CLASS_VAMPIRE) && !IS_CLASS(ch, CLASS_MONK)
	  && !IS_CLASS(ch, CLASS_DEMON) )
	{
	    stc("Huh?\n\r",ch);
	    return;
	}
    }

  if ( !IS_ITEMAFF(ch, ITEMA_VISION) )
  {
    if (IS_CLASS(ch, CLASS_VAMPIRE) && ch->power[DISC_VAMP_AUSP] < 2 )
    {
        send_to_char("You must obtain at least level 2 Auspex to use Scry.\n\r",ch);
	return;
    }

    if (IS_CLASS(ch, CLASS_MONK) && ch->monkab[AWARE] < 4)
    {
	send_to_char("You need to obtain level 4 in Awareness to use scry.\n\r",ch);
	return;
    }

    if (IS_CLASS(ch, CLASS_DEMON) && !IS_DEMPOWER(ch, DEM_SCRY) )
    {
	stc("You have not been granted the power of Scry.\n\r",ch);
	return;
    }
  }

    if ( arg[0] == '\0' )
    {
	send_to_char( "Scry on whom?\n\r", ch );
	return;
    }

    if ( ( victim = get_char_world( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if (!IS_NPC(victim) && IS_IMMUNE(victim,IMM_SHIELDED))
    {
       send_to_char( "You cannot find them.\n\r",ch);
       return;
    }

    if (IS_CLASS(ch, CLASS_VAMPIRE) && ch->pcdata->condition[COND_THIRST] < 25 
	&& !IS_ITEMAFF(ch, ITEMA_VISION))
    {
	send_to_char("You have insufficient blood.\n\r",ch);
	return;
    }

    if (!IS_ITEMAFF(ch, ITEMA_VISION) && IS_CLASS(ch, CLASS_VAMPIRE))
	ch->pcdata->condition[COND_THIRST] -= number_range(15,25);

    chroom = ch->in_room;
    victimroom = victim->in_room;

    char_from_room(ch);
    char_to_room(ch,victimroom);
    if (IS_AFFECTED(ch, AFF_SHADOWPLANE) && (!IS_AFFECTED(victim, AFF_SHADOWPLANE)))
    {
	REMOVE_BIT(ch->affected_by, AFF_SHADOWPLANE);
	do_look(ch,"auto");
	SET_BIT(ch->affected_by, AFF_SHADOWPLANE);
    }
    else if (!IS_AFFECTED(ch, AFF_SHADOWPLANE) && (IS_AFFECTED(victim, AFF_SHADOWPLANE)))
    {
	SET_BIT(ch->affected_by, AFF_SHADOWPLANE);
	do_look(ch,"auto");
	REMOVE_BIT(ch->affected_by, AFF_SHADOWPLANE);
    }
    else
	do_look(ch,"auto");
    char_from_room(ch);
    char_to_room(ch,chroom);
    ch->fight_timer = 10;
    
    if ( IS_CLASS(ch, CLASS_VAMPIRE) && IS_SET(ch->flag2, AFF_SPIRITGUARD))
    {
      act("Your spirit guardian sends you a message:",ch,NULL,victim,TO_VICT);
      act("\"$n is scrying you.\"",ch,NULL,victim,TO_VICT);
    }
    return;
}

void do_readaura( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    OBJ_DATA  *obj;
    char      arg [MAX_INPUT_LENGTH];
    char      buf [MAX_INPUT_LENGTH];

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch, CLASS_VAMPIRE) && !IS_ITEMAFF(ch, ITEMA_VISION)
	&& !IS_CLASS(ch, CLASS_MONK))
    {
	send_to_char( "Huh?\n\r", ch );
	return;
    }

    if (IS_CLASS(ch, CLASS_VAMPIRE) && ch->power[DISC_VAMP_AUSP] < 3 && !IS_ITEMAFF(ch, ITEMA_VISION))
    {
        send_to_char("You must obtain at least level 3 in Auspex to use Readaura.\n\r",ch);
	return;
    }

    if (IS_CLASS(ch, CLASS_MONK) && ch->pcdata->powers[PMONK] < 2)
    {
	send_to_char("You must obtain the level 2 Mantra first!\n\r",ch);
	return;
    }

    if ( arg[0] == '\0' )
    {
	send_to_char( "Read the aura on what?\n\r", ch );
	return;
    }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
        if ( ( obj = get_obj_carry( ch, arg ) ) == NULL )
	{
	    send_to_char( "Read the aura on what?\n\r", ch );
	    return;
	}
    	if ( ch->pcdata->condition[COND_THIRST] < 50 && !IS_ITEMAFF(ch, ITEMA_VISION)
	     && !IS_CLASS(ch, CLASS_MONK))
    	{
	    send_to_char("You have insufficient blood.\n\r",ch);
	    return;
    	}
	if (!IS_ITEMAFF(ch, ITEMA_VISION) && !IS_CLASS(ch, CLASS_MONK))
	    ch->pcdata->condition[COND_THIRST] -= number_range(40,50);
	act("$n examines $p intently.",ch,obj,NULL,TO_ROOM);
	spell_identify( skill_lookup( "identify" ), ch->level, ch, obj );
	return;
    }

    if (ch->pcdata->condition[COND_THIRST] < 50 && !IS_ITEMAFF(ch,ITEMA_VISION))
    {
	send_to_char("You have insufficient blood.\n\r",ch);
	return;
    }
    if (!IS_ITEMAFF(ch, ITEMA_VISION))
	ch->pcdata->condition[COND_THIRST] -= number_range(40,50);
    if (!IS_NPC(victim) && (IS_IMMUNE(victim,IMM_SHIELDED) ||
(IS_CLASS(victim, CLASS_DROW) &&
IS_SET(victim->pcdata->powers[1],DPOWER_DROWSHIELD))) && !IS_ITEMAFF(ch, ITEMA_VISION))
    {
	send_to_char("You are unable to read their aura.\n\r",ch);
	return;
    }

    act("$n examines $N intently.",ch,NULL,victim,TO_NOTVICT);
    act("$n examines you intently.",ch,NULL,victim,TO_VICT);
    if (IS_NPC(victim)) sprintf(buf, "%s is an NPC.\n\r",victim->short_descr);
    else 
    {
	if      (victim->level == 12) sprintf(buf, "%s is an Implementor.\n\r", victim->name);
	else if (victim->level == 11) sprintf(buf, "%s is a High Judge.\n\r", victim->name);
	else if (victim->level == 10) sprintf(buf, "%s is a Judge.\n\r", victim->name);
	else if (victim->level == 9 ) sprintf(buf, "%s is an Enforcer.\n\r", victim->name);
	else if (victim->level == 8 ) sprintf(buf, "%s is a Quest Maker.\n\r", victim->name);
	else if (victim->level == 7 ) sprintf(buf, "%s is a Builder.\n\r", victim->name);
	else if (victim->level >= 3 ) sprintf(buf, "%s is an Avatar.\n\r", victim->name);
	else sprintf(buf, "%s is a Mortal.\n\r", victim->name);
    }
    send_to_char(buf,ch);
    if (!IS_NPC(victim))
    {
	sprintf(buf,"Str:%d, Int:%d, Wis:%d, Dex:%d, Con:%d.\n\r",get_curr_str(victim),get_curr_int(victim),get_curr_wis(victim),get_curr_dex(victim),get_curr_con(victim));
	send_to_char(buf,ch);
    }
    sprintf(buf,"Hp:%d/%d, Mana:%d/%d, Move:%d/%d.\n\r",victim->hit,victim->max_hit,victim->mana,victim->max_mana,victim->move,victim->max_move);
    send_to_char(buf,ch);
    if (!IS_NPC(victim)) sprintf(buf,"Hitroll:%d, Damroll:%d, AC:%d.\n\r",char_hitroll(victim),char_damroll(victim),char_ac(victim));
    else sprintf(buf,"AC:%d.\n\r",char_ac(victim));
    send_to_char(buf,ch);
    if (!IS_NPC(victim))
    {
	sprintf(buf,"Status:%d, ",victim->race);
	send_to_char(buf,ch);
	if (IS_CLASS(victim, CLASS_VAMPIRE))    
	{
	    sprintf(buf,"Blood:%d, ",victim->pcdata->condition[COND_THIRST]);
	    send_to_char(buf,ch);
	}
    }
    sprintf(buf,"Alignment:%d.\n\r",victim->alignment);
    send_to_char(buf,ch);
    if (!IS_NPC(victim) && IS_EXTRA(victim, EXTRA_PREGNANT))
	act("$N is pregnant.",ch,NULL,victim,TO_CHAR);
    if (!IS_NPC(victim) && IS_CLASS(victim, CLASS_VAMPIRE))    
    {
	send_to_char("Disciplines:",ch);
	if (IS_VAMPAFF(victim, VAM_PROTEAN)) send_to_char(" Protean",ch);
	if (IS_VAMPAFF(victim, VAM_CELERITY)) send_to_char(" Celerity",ch);
	if (IS_VAMPAFF(victim, VAM_FORTITUDE)) send_to_char(" Fortitude",ch);
	if (IS_VAMPAFF(victim, VAM_POTENCE)) send_to_char(" Potence",ch);
	if (IS_VAMPAFF(victim, VAM_OBFUSCATE)) send_to_char(" Obfuscate",ch);
	if (IS_VAMPAFF(victim, VAM_OBTENEBRATION)) send_to_char(" Obtenebration",ch);
	if (IS_VAMPAFF(victim, VAM_SERPENTIS)) send_to_char(" Serpentis",ch);
	if (IS_VAMPAFF(victim, VAM_AUSPEX)) send_to_char(" Auspex",ch);
	if (IS_VAMPAFF(victim, VAM_DOMINATE)) send_to_char(" Dominate",ch);
	if (IS_VAMPAFF(victim, VAM_PRESENCE)) send_to_char(" Presence",ch);
        if (IS_VAMPAFF(victim, VAM_VICISSITUDE)) send_to_char(" Vicissitude",ch);
        if (IS_VAMPAFF(victim, VAM_THAU)) send_to_char(" Thaumaturgy",ch);
        if (IS_VAMPAFF(victim, VAM_ANIMAL)) send_to_char(" Animalism",ch);
        if (IS_VAMPAFF(victim, VAM_QUIETUS)) send_to_char(" Quietus",ch);
        send_to_char(".\n\r",ch);
    }
    return;
}

void do_mortal( CHAR_DATA *ch, char *argument )
{
    char      arg [MAX_INPUT_LENGTH];
    int       blood;

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;
    if (!IS_CLASS(ch, CLASS_VAMPIRE) && !IS_VAMPAFF(ch, VAM_MORTAL))
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }
    if (ch->power[DISC_VAMP_OBFU] < 4)
    {
        send_to_char("You must obtain at least level 4 in Obfuscate to use Mortal Facade.\n\r",ch);
	return;
    }
    if (IS_CLASS(ch,CLASS_VAMPIRE) )
    {
        if ( ch->pcdata->condition[COND_THIRST] < 1000 / ch->generation )
        {
	    send_to_char("You must be at full blood to use this power.\n\r",ch);
	    return;
    	}
    	/* Have to make sure they have enough blood to change back */
    	blood = ch->pcdata->condition[COND_THIRST];
    	ch->pcdata->condition[COND_THIRST] = 666;

	/* Remove physical vampire attributes when you take mortal form */
    	if (IS_VAMPAFF(ch,VAM_DISGUISED) ) do_mask(ch,"self");
    	if (IS_IMMUNE(ch,IMM_SHIELDED) ) do_shield(ch,"");
    	if (IS_AFFECTED(ch,AFF_SHADOWPLANE) ) do_shadowplane(ch,"");
    	if (IS_VAMPAFF(ch,VAM_FANGS) ) do_fangs(ch,"");
    	if (IS_VAMPAFF(ch,VAM_CLAWS) ) do_claws(ch,"");
    	if (IS_VAMPAFF(ch,VAM_NIGHTSIGHT) ) do_nightsight(ch,"");
    	if (IS_AFFECTED(ch,AFF_SHADOWSIGHT) ) do_shadowsight(ch,"");
    	if (IS_SET(ch->act,PLR_HOLYLIGHT) ) do_truesight(ch,"");
    	if (IS_VAMPAFF(ch,VAM_CHANGED) ) do_change(ch,"human");
    	if (IS_POLYAFF(ch,POLY_SERPENT) ) do_serpent(ch,"");
	ch->rage = 0;
    	ch->pcdata->condition[COND_THIRST] = blood;

    	send_to_char("Colour returns to your skin and you warm up a little.\n\r",ch);
    	act("Colour returns to $n's skin.", ch, NULL, NULL, TO_ROOM);

    	REMOVE_BIT(ch->class, CLASS_VAMPIRE);
    	SET_BIT(ch->pcdata->stats[UNI_AFF], VAM_MORTAL);
	return;
    }
    send_to_char("You skin pales and cools.\n\r",ch);
    act("$n's skin pales slightly.", ch, NULL, NULL, TO_ROOM);
    ch->class=CLASS_VAMPIRE;
    REMOVE_BIT(ch->pcdata->stats[UNI_AFF], VAM_MORTAL);
    return;
}

void do_mortalvamp( CHAR_DATA *ch, char *argument )
{
    char      arg [MAX_INPUT_LENGTH];
    int       blood;

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;
    if (IS_CLASS(ch,CLASS_VAMPIRE) )
    {
    	/* Have to make sure they have enough blood to change back */
    	blood = ch->pcdata->condition[COND_THIRST];
    	ch->pcdata->condition[COND_THIRST] = 666;

	/* Remove physical vampire attributes when you take mortal form */
    	if (IS_VAMPAFF(ch,VAM_DISGUISED) ) do_mask(ch,"self");
    	if (IS_IMMUNE(ch,IMM_SHIELDED) ) do_shield(ch,"");
    	if (IS_AFFECTED(ch,AFF_SHADOWPLANE) ) do_shadowplane(ch,"");
    	if (IS_VAMPAFF(ch,VAM_FANGS) ) do_fangs(ch,"");
    	if (IS_VAMPAFF(ch,VAM_CLAWS) ) do_claws(ch,"");
    	if (IS_VAMPAFF(ch,VAM_NIGHTSIGHT) ) do_nightsight(ch,"");
    	if (IS_AFFECTED(ch,AFF_SHADOWSIGHT) ) do_shadowsight(ch,"");
    	if (IS_SET(ch->act,PLR_HOLYLIGHT) ) do_truesight(ch,"");
    	if (IS_VAMPAFF(ch,VAM_CHANGED) ) do_change(ch,"human");
    	if (IS_POLYAFF(ch,POLY_SERPENT) ) do_serpent(ch,"");
	ch->rage = 0;
    	ch->pcdata->condition[COND_THIRST] = blood;

    	send_to_char("You loose your vampire powers.\n\r",ch);

    	REMOVE_BIT(ch->class, CLASS_VAMPIRE);
    	SET_BIT(ch->pcdata->stats[UNI_AFF], VAM_MORTAL);
	return;
    }
    send_to_char("You regain your vampire powers.\n\r",ch);
    ch->class= CLASS_VAMPIRE;
    REMOVE_BIT(ch->pcdata->stats[UNI_AFF], VAM_MORTAL);
    return;
}

void do_shield( CHAR_DATA *ch, char *argument )
{
    char      arg [MAX_INPUT_LENGTH];

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;
    if (!IS_CLASS(ch, CLASS_WEREWOLF) || ch->power[DISC_WERE_OWL] < 2)
    {
	if (!IS_CLASS(ch, CLASS_VAMPIRE) && !IS_CLASS(ch, CLASS_DROW)
	 && !IS_CLASS(ch, CLASS_DEMON) && !IS_CLASS(ch, CLASS_MONK))
	{
	    send_to_char("Huh?\n\r",ch);
	    return;
	}
    }
	if (!IS_DEMPOWER( ch, DEM_SHIELD) && IS_CLASS(ch,CLASS_DEMON))
	{
        send_to_char("You must inpart it first!\n\r",ch);
        return;
    }
	if (IS_CLASS(ch, CLASS_DROW) && !IS_SET(ch->pcdata->powers[1],DPOWER_DROWSHIELD))
	{  send_to_char("You don't have that power.\n\r", ch );
		return;}
    if (IS_CLASS(ch, CLASS_MONK) && !IS_NPC(ch) && ch->pcdata->powers[PMONK] < 2)
    {
	send_to_char("You must improve your Mantras to level 2 first!\n\r",ch);
	return;
    }

    if (ch->power[DISC_VAMP_OBFU] < 3 && ch->power[DISC_VAMP_DOMI] < 2 && 
	!IS_CLASS(ch, CLASS_DROW) && !IS_CLASS(ch, CLASS_WEREWOLF) && !IS_CLASS(ch, CLASS_DEMON) )
    {
        send_to_char("You must obtain at least level 3 in Obfuscate or level 2 in Dominate.\n\r",ch);
	return;
    }
    if (IS_CLASS(ch, CLASS_VAMPIRE) && ch->pcdata->condition[COND_THIRST] < 60)
    {
	send_to_char("You have insufficient blood.\n\r",ch);
	return;
    }
    if (IS_CLASS(ch, CLASS_VAMPIRE))
	ch->pcdata->condition[COND_THIRST] -= number_range(50,60);
    if (!IS_IMMUNE(ch,IMM_SHIELDED) )
    {
    	send_to_char("You shield your aura from those around you.\n\r",ch);
    	SET_BIT(ch->immune, IMM_SHIELDED);
	return;
    }
    send_to_char("You stop shielding your aura.\n\r",ch);
    REMOVE_BIT(ch->immune, IMM_SHIELDED);
    return;
}

void do_serpent( CHAR_DATA *ch, char *argument )
{
    char arg [MAX_INPUT_LENGTH]; 
    char buf [MAX_STRING_LENGTH]; 
    argument = one_argument( argument, arg ); 

    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch, CLASS_VAMPIRE))
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }

    if (ch->power[DISC_VAMP_SERP] < 2)
    {
        send_to_char("You must obtain at least level 2 in Serpentis to use Serpent Form.\n\r",ch);
	return;
    }

    if (IS_AFFECTED(ch, AFF_POLYMORPH))
    {
	if (!IS_POLYAFF(ch,POLY_SERPENT))
	{
	    send_to_char( "You cannot polymorph from this form.\n\r", ch );
	    return;
	}
	act( "You transform back into human.", ch, NULL, NULL, TO_CHAR );
	act( "$n transform into human form.", ch, NULL, NULL, TO_ROOM );
	REMOVE_BIT(ch->polyaff, POLY_SERPENT);
	REMOVE_BIT(ch->affected_by, AFF_POLYMORPH);
	clear_stats(ch);
	free_string( ch->morph );
	ch->morph = str_dup( "" );
	ch->max_hit = ch->max_hit - 250;
	ch->hit = ch->hit - 250;
	if (ch->hit < 1) ch->hit = 1;
	ch->max_mana = ch->max_mana + 50;
	return;
    }
    if ( ch->pcdata->condition[COND_THIRST] < 50 )
    {
	send_to_char("You have insufficient blood.\n\r",ch);
	return;
    }
    ch->pcdata->condition[COND_THIRST] -= number_range(40,50);
    clear_stats(ch);
    if (ch->wpn[0] > 0)
    {
    	ch->hitroll += ch->wpn[0] * 0.75;
    	ch->damroll += ch->wpn[0] * 0.75;
    	ch->armor   -= ch->wpn[0] * 3;
    }
    if (ch->stance[0] != -1) do_stance(ch,"");
    if (ch->mounted == IS_RIDING) do_dismount(ch,"");
    ch->pcdata->mod_str = 10;
    act( "You transform into a huge serpent.", ch, NULL, NULL, TO_CHAR );
    act( "$n transforms into a huge serpent.", ch, NULL, NULL, TO_ROOM );
    SET_BIT(ch->polyaff, POLY_SERPENT);
    SET_BIT(ch->affected_by, AFF_POLYMORPH);
    sprintf(buf, "%s the huge serpent", ch->name);
    free_string( ch->morph );
    ch->morph = str_dup( buf );
    ch->max_hit = ch->max_hit + 250;
    ch->hit = ch->hit + 250;
    ch->max_mana = ch->max_mana - 50;
    return;
}

void do_poison( CHAR_DATA *ch, char *argument )
{
    OBJ_DATA  *obj;
    char       arg [MAX_INPUT_LENGTH];

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch, CLASS_VAMPIRE))
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }

    if (ch->power[DISC_VAMP_SERP] < 3)
    {
        send_to_char("You must obtain at least level 3 in Serpentis to use Poison.\n\r",ch);
	return;
    }

    if ( ( ( obj = get_eq_char( ch, WEAR_WIELD ) ) == NULL )
    &&   ( ( obj = get_eq_char( ch, WEAR_HOLD ) ) == NULL ) )
    {
	send_to_char( "You must wield the weapon you wish to poison.\n\r", ch );
	return;
    }

    if ( obj->value[0] != 0 )
    {
	send_to_char( "This weapon cannot be poisoned.\n\r", ch );
	return;
    }

    if ( ch->pcdata->condition[COND_THIRST] < 15 )
    {
	send_to_char("You have insufficient blood.\n\r",ch);
	return;
    }
    ch->pcdata->condition[COND_THIRST] -= number_range(5,15);
    act("You run your tongue along $p, poisoning it.",ch,obj,NULL,TO_CHAR);
    act("$n runs $s tongue along $p, poisoning it.",ch,obj,NULL,TO_ROOM);
    obj->value[0] = 53;
    obj->timer = number_range(10,20);

    return;
}

void do_regenerate( CHAR_DATA *ch, char *argument )
{
    char       arg [MAX_INPUT_LENGTH];

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch, CLASS_VAMPIRE))
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }

    if (ch->rage > 0)
    {
	send_to_char("You cannot control your regenerative powers while the beast is so strong.\n\r",ch);
	return;
    }

    if ( ch->position == POS_FIGHTING )
    {
	send_to_char("You cannot regenerate while fighting.\n\r",ch);
	return;
    }

    if ( ch->hit >= ch->max_hit && ch->mana >= ch->max_mana && ch->move >= ch->max_move )
    {
	send_to_char("But you are already completely regenerated!\n\r",ch);
	return;
    }

    if ( ch->pcdata->condition[COND_THIRST] < 5 )
    {
	send_to_char("You have insufficient blood.\n\r",ch);
	return;
    }

    ch->pcdata->condition[COND_THIRST] -= number_range(10,20);
    if ( ch->hit >= ch->max_hit && ch->mana >= ch->max_mana && ch->move >= ch->max_move )
    {
    	send_to_char("Your body has completely regenerated.\n\r",ch);
    	act("$n's body completely regenerates itself.",ch,NULL,NULL,TO_ROOM);
    }
    else
    	send_to_char("Your body slowly regenerates itself.\n\r",ch);
    if (ch->hit < 1 )
    {
	ch->hit = ch->hit + 1;
	update_pos(ch);
	WAIT_STATE( ch, 24 );
    }
    else
    {
    	ch->hit = UMIN(ch->hit + 250, ch->max_hit);
    	ch->mana = UMIN(ch->mana + 250, ch->max_mana);
    	ch->move = UMIN(ch->move + 250, ch->max_move);
	WAIT_STATE(ch,8);
        update_pos(ch);
    }
    return;
}

void werewolf_regen( CHAR_DATA *ch )
{
    int min = 5;
    int max = 10;

    if (IS_NPC(ch)) return;

    if (ch->hit < 1 ) 
    {
	ch->hit = ch->hit + number_range(1,3);
	update_pos(ch);
    }
    else
    {
	min += 10 - ch->generation;
	min += 20 - (ch->generation * 2);
    	ch->hit = UMIN(ch->hit + number_range(min,max), ch->max_hit);
    	ch->mana = UMIN(ch->mana + number_range(min,max), ch->max_mana);
    	ch->move = UMIN(ch->move + number_range(min,max), ch->max_move);
	if ( ch->hit >= ch->max_hit && ch->mana >= ch->max_mana && ch->move >= ch->max_move )
	    send_to_char("Your body has completely regenerated itself.\n\r",ch);
    }
    return;
}

void reg_mend( CHAR_DATA *ch )
{
    int ribs = 0;
    int teeth = 0;

    if (IS_BODY(ch,BROKEN_RIBS_1 )) ribs += 1;
    if (IS_BODY(ch,BROKEN_RIBS_2 )) ribs += 2;
    if (IS_BODY(ch,BROKEN_RIBS_4 )) ribs += 4;
    if (IS_BODY(ch,BROKEN_RIBS_8 )) ribs += 8;
    if (IS_BODY(ch,BROKEN_RIBS_16)) ribs += 16;
    if (IS_HEAD(ch,LOST_TOOTH_1  )) teeth += 1;
    if (IS_HEAD(ch,LOST_TOOTH_2  )) teeth += 2;
    if (IS_HEAD(ch,LOST_TOOTH_4  )) teeth += 4;
    if (IS_HEAD(ch,LOST_TOOTH_8  )) teeth += 8;
    if (IS_HEAD(ch,LOST_TOOTH_16 )) teeth += 16;

    if (ribs > 0)
    {
    	if (IS_BODY(ch,BROKEN_RIBS_1 ))
	    REMOVE_BIT(ch->loc_hp[1],BROKEN_RIBS_1);
    	if (IS_BODY(ch,BROKEN_RIBS_2 ))
	    REMOVE_BIT(ch->loc_hp[1],BROKEN_RIBS_2);
	if (IS_BODY(ch,BROKEN_RIBS_4 ))
	    REMOVE_BIT(ch->loc_hp[1],BROKEN_RIBS_4);
	if (IS_BODY(ch,BROKEN_RIBS_8 ))
	    REMOVE_BIT(ch->loc_hp[1],BROKEN_RIBS_8);
	if (IS_BODY(ch,BROKEN_RIBS_16))
	    REMOVE_BIT(ch->loc_hp[1],BROKEN_RIBS_16);
	ribs -= 1;
	if (ribs >= 16) {ribs -= 16;
	    SET_BIT(ch->loc_hp[1],BROKEN_RIBS_16);}
	if (ribs >= 8 ) {ribs -= 8;
	    SET_BIT(ch->loc_hp[1],BROKEN_RIBS_8);}
	if (ribs >= 4 ) {ribs -= 4;
	    SET_BIT(ch->loc_hp[1],BROKEN_RIBS_4);}
	if (ribs >= 2 ) {ribs -= 2;
	    SET_BIT(ch->loc_hp[1],BROKEN_RIBS_2);}
	if (ribs >= 1 ) {ribs -= 1;
	    SET_BIT(ch->loc_hp[1],BROKEN_RIBS_1);}
	act("One of $n's ribs snap back into place.",ch,NULL,NULL,TO_ROOM);
	act("One of your ribs snap back into place.",ch,NULL,NULL,TO_CHAR);
    }
    else if (IS_HEAD(ch,LOST_EYE_L))
    {
	act("An eyeball appears in $n's left eye socket.",ch,NULL,NULL,TO_ROOM);
	act("An eyeball appears in your left eye socket.",ch,NULL,NULL,TO_CHAR);
	REMOVE_BIT(ch->loc_hp[LOC_HEAD],LOST_EYE_L);
    }
    else if (IS_HEAD(ch,LOST_EYE_R))
    {
	act("An eyeball appears in $n's right eye socket.",ch,NULL,NULL,TO_ROOM);
	act("An eyeball appears in your right eye socket.",ch,NULL,NULL,TO_CHAR);
	REMOVE_BIT(ch->loc_hp[LOC_HEAD],LOST_EYE_R);
    }
    else if (IS_HEAD(ch,LOST_EAR_L))
    {
	act("An ear grows on the left side of $n's head.",ch,NULL,NULL,TO_ROOM);
	act("An ear grows on the left side of your head.",ch,NULL,NULL,TO_CHAR);
	REMOVE_BIT(ch->loc_hp[LOC_HEAD],LOST_EAR_L);
    }
    else if (IS_HEAD(ch,LOST_EAR_R))
    {
	act("An ear grows on the right side of $n's head.",ch,NULL,NULL,TO_ROOM);
	act("An ear grows on the right side of your head.",ch,NULL,NULL,TO_CHAR);
	REMOVE_BIT(ch->loc_hp[LOC_HEAD],LOST_EAR_R);
    }
    else if (IS_HEAD(ch,LOST_NOSE))
    {
	act("A nose grows on the front of $n's face.",ch,NULL,NULL,TO_ROOM);
	act("A nose grows on the front of your face.",ch,NULL,NULL,TO_CHAR);
	REMOVE_BIT(ch->loc_hp[LOC_HEAD],LOST_NOSE);
	REMOVE_BIT(ch->loc_hp[LOC_HEAD],BROKEN_NOSE);
    }
    else if (teeth > 0)
    {
    	if (IS_HEAD(ch,LOST_TOOTH_1 ))
	    REMOVE_BIT(ch->loc_hp[LOC_HEAD],LOST_TOOTH_1);
    	if (IS_HEAD(ch,LOST_TOOTH_2 ))
	    REMOVE_BIT(ch->loc_hp[LOC_HEAD],LOST_TOOTH_2);
    	if (IS_HEAD(ch,LOST_TOOTH_4 ))
	    REMOVE_BIT(ch->loc_hp[LOC_HEAD],LOST_TOOTH_4);
    	if (IS_HEAD(ch,LOST_TOOTH_8 ))
	    REMOVE_BIT(ch->loc_hp[LOC_HEAD],LOST_TOOTH_8);
    	if (IS_HEAD(ch,LOST_TOOTH_16))
	    REMOVE_BIT(ch->loc_hp[LOC_HEAD],LOST_TOOTH_16);
	teeth -= 1;
	if (teeth >= 16) {teeth -= 16;
	    SET_BIT(ch->loc_hp[LOC_HEAD],LOST_TOOTH_16);}
	if (teeth >= 8 ) {teeth -= 8;
	    SET_BIT(ch->loc_hp[LOC_HEAD],LOST_TOOTH_8);}
	if (teeth >= 4 ) {teeth -= 4;
	    SET_BIT(ch->loc_hp[LOC_HEAD],LOST_TOOTH_4);}
	if (teeth >= 2 ) {teeth -= 2;
	    SET_BIT(ch->loc_hp[LOC_HEAD],LOST_TOOTH_2);}
	if (teeth >= 1 ) {teeth -= 1;
	    SET_BIT(ch->loc_hp[LOC_HEAD],LOST_TOOTH_1);}
	act("A missing tooth grows in your mouth.",ch,NULL,NULL,TO_CHAR);
	act("A missing tooth grows in $n's mouth.",ch,NULL,NULL,TO_ROOM);
    }
    else if (IS_HEAD(ch,BROKEN_NOSE))
    {
	act("$n's nose snaps back into place.",ch,NULL,NULL,TO_ROOM);
	act("Your nose snaps back into place.",ch,NULL,NULL,TO_CHAR);
	REMOVE_BIT(ch->loc_hp[LOC_HEAD],BROKEN_NOSE);
    }
    else if (IS_HEAD(ch,BROKEN_JAW))
    {
	act("$n's jaw snaps back into place.",ch,NULL,NULL,TO_ROOM);
	act("Your jaw snaps back into place.",ch,NULL,NULL,TO_CHAR);
	REMOVE_BIT(ch->loc_hp[LOC_HEAD],BROKEN_JAW);
    }
    else if (IS_HEAD(ch,BROKEN_SKULL))
    {
	act("$n's skull knits itself back together.",ch,NULL,NULL,TO_ROOM);
	act("Your skull knits itself back together.",ch,NULL,NULL,TO_CHAR);
	REMOVE_BIT(ch->loc_hp[LOC_HEAD],BROKEN_SKULL);
    }
    else if (IS_BODY(ch,BROKEN_SPINE))
    {
	act("$n's spine knits itself back together.",ch,NULL,NULL,TO_ROOM);
	act("Your spine knits itself back together.",ch,NULL,NULL,TO_CHAR);
	REMOVE_BIT(ch->loc_hp[LOC_BODY],BROKEN_SPINE);
    }
    else if (IS_BODY(ch,BROKEN_NECK))
    {
	act("$n's neck snaps back into place.",ch,NULL,NULL,TO_ROOM);
	act("Your neck snaps back into place.",ch,NULL,NULL,TO_CHAR);
	REMOVE_BIT(ch->loc_hp[LOC_BODY],BROKEN_NECK);
    }
    else if (IS_ARM_L(ch,LOST_ARM))
    {
	act("An arm grows from the stump of $n's left shoulder.",ch,NULL,NULL,TO_ROOM);
	act("An arm grows from the stump of your left shoulder.",ch,NULL,NULL,TO_CHAR);
	REMOVE_BIT(ch->loc_hp[LOC_ARM_L],LOST_ARM);
	REMOVE_BIT(ch->loc_hp[LOC_ARM_L],BROKEN_ARM);
	SET_BIT(ch->loc_hp[LOC_ARM_L],LOST_HAND);
    }
    else if (IS_ARM_R(ch,LOST_ARM))
    {
	act("An arm grows from the stump of $n's right shoulder.",ch,NULL,NULL,TO_ROOM);
	act("An arm grows from the stump of your right shoulder.",ch,NULL,NULL,TO_CHAR);
	REMOVE_BIT(ch->loc_hp[LOC_ARM_R],LOST_ARM);
	REMOVE_BIT(ch->loc_hp[LOC_ARM_R],BROKEN_ARM);
	SET_BIT(ch->loc_hp[LOC_ARM_R],LOST_HAND);
    }
    else if (IS_LEG_L(ch,LOST_LEG))
    {
	act("A leg grows from the stump of $n's left hip.",ch,NULL,NULL,TO_ROOM);
	act("A leg grows from the stump of your left hip.",ch,NULL,NULL,TO_CHAR);
	REMOVE_BIT(ch->loc_hp[LOC_LEG_L],LOST_LEG);
	REMOVE_BIT(ch->loc_hp[LOC_LEG_L],BROKEN_LEG);
	SET_BIT(ch->loc_hp[LOC_LEG_L],LOST_FOOT);
    }
    else if (IS_LEG_R(ch,LOST_LEG))
    {
	act("A leg grows from the stump of $n's right hip.",ch,NULL,NULL,TO_ROOM);
	act("A leg grows from the stump of your right hip.",ch,NULL,NULL,TO_CHAR);
	REMOVE_BIT(ch->loc_hp[LOC_LEG_R],LOST_LEG);
	REMOVE_BIT(ch->loc_hp[LOC_LEG_R],BROKEN_LEG);
	SET_BIT(ch->loc_hp[LOC_LEG_R],LOST_FOOT);
    }
    else if (IS_ARM_L(ch,BROKEN_ARM))
    {
	act("$n's left arm snaps back into place.",ch,NULL,NULL,TO_ROOM);
	act("Your left arm snaps back into place.",ch,NULL,NULL,TO_CHAR);
	REMOVE_BIT(ch->loc_hp[LOC_ARM_L],BROKEN_ARM);
    }
    else if (IS_ARM_R(ch,BROKEN_ARM))
    {
	act("$n's right arm snaps back into place.",ch,NULL,NULL,TO_ROOM);
	act("Your right arm snaps back into place.",ch,NULL,NULL,TO_CHAR);
	REMOVE_BIT(ch->loc_hp[LOC_ARM_R],BROKEN_ARM);
    }
    else if (IS_LEG_L(ch,BROKEN_LEG))
    {
	act("$n's left leg snaps back into place.",ch,NULL,NULL,TO_ROOM);
	act("Your left leg snaps back into place.",ch,NULL,NULL,TO_CHAR);
	REMOVE_BIT(ch->loc_hp[LOC_LEG_L],BROKEN_LEG);
    }
    else if (IS_LEG_R(ch,BROKEN_LEG))
    {
	act("$n's right leg snaps back into place.",ch,NULL,NULL,TO_ROOM);
	act("Your right leg snaps back into place.",ch,NULL,NULL,TO_CHAR);
	REMOVE_BIT(ch->loc_hp[LOC_LEG_R],BROKEN_LEG);
    }
    else if (IS_ARM_L(ch,LOST_HAND))
    {
	act("A hand grows from the stump of $n's left wrist.",ch,NULL,NULL,TO_ROOM);
	act("A hand grows from the stump of your left wrist.",ch,NULL,NULL,TO_CHAR);
	REMOVE_BIT(ch->loc_hp[LOC_ARM_L],LOST_HAND);
	SET_BIT(ch->loc_hp[LOC_ARM_L],LOST_THUMB);
	SET_BIT(ch->loc_hp[LOC_ARM_L],LOST_FINGER_I);
	SET_BIT(ch->loc_hp[LOC_ARM_L],LOST_FINGER_M);
	SET_BIT(ch->loc_hp[LOC_ARM_L],LOST_FINGER_R);
	SET_BIT(ch->loc_hp[LOC_ARM_L],LOST_FINGER_L);
    }
    else if (IS_ARM_R(ch,LOST_HAND))
    {
	act("A hand grows from the stump of $n's right wrist.",ch,NULL,NULL,TO_ROOM);
	act("A hand grows from the stump of your right wrist.",ch,NULL,NULL,TO_CHAR);
	REMOVE_BIT(ch->loc_hp[LOC_ARM_R],LOST_HAND);
	SET_BIT(ch->loc_hp[LOC_ARM_R],LOST_THUMB);
	SET_BIT(ch->loc_hp[LOC_ARM_R],LOST_FINGER_I);
	SET_BIT(ch->loc_hp[LOC_ARM_R],LOST_FINGER_M);
	SET_BIT(ch->loc_hp[LOC_ARM_R],LOST_FINGER_R);
	SET_BIT(ch->loc_hp[LOC_ARM_R],LOST_FINGER_L);
    }
    else if (IS_LEG_L(ch,LOST_FOOT))
    {
	act("A foot grows from the stump of $n's left ankle.",ch,NULL,NULL,TO_ROOM);
	act("A foot grows from the stump of your left ankle.",ch,NULL,NULL,TO_CHAR);
	REMOVE_BIT(ch->loc_hp[LOC_LEG_L],LOST_FOOT);
    }
    else if (IS_LEG_R(ch,LOST_FOOT))
    {
	act("A foot grows from the stump of $n's right ankle.",ch,NULL,NULL,TO_ROOM);
	act("A foot grows from the stump of your right ankle.",ch,NULL,NULL,TO_CHAR);
	REMOVE_BIT(ch->loc_hp[LOC_LEG_R],LOST_FOOT);
    }
    else if (IS_ARM_L(ch,LOST_THUMB))
    {
	act("A thumb slides out of $n's left hand.",ch,NULL,NULL,TO_ROOM);
	act("A thumb slides out of your left hand.",ch,NULL,NULL,TO_CHAR);
	REMOVE_BIT(ch->loc_hp[LOC_ARM_L],LOST_THUMB);
	REMOVE_BIT(ch->loc_hp[LOC_ARM_L],BROKEN_THUMB);
    }
    else if (IS_ARM_L(ch,BROKEN_THUMB))
    {
	act("$n's left thumb snaps back into place.",ch,NULL,NULL,TO_ROOM);
	act("Your left thumb snaps back into place.",ch,NULL,NULL,TO_CHAR);
	REMOVE_BIT(ch->loc_hp[LOC_ARM_L],BROKEN_THUMB);
    }
    else if (IS_ARM_L(ch,LOST_FINGER_I))
    {
	act("An index finger slides out of $n's left hand.",ch,NULL,NULL,TO_ROOM);
	act("An index finger slides out of your left hand.",ch,NULL,NULL,TO_CHAR);
	REMOVE_BIT(ch->loc_hp[LOC_ARM_L],LOST_FINGER_I);
	REMOVE_BIT(ch->loc_hp[LOC_ARM_L],BROKEN_FINGER_I);
    }
    else if (IS_ARM_L(ch,BROKEN_FINGER_I))
    {
	act("$n's left index finger snaps back into place.",ch,NULL,NULL,TO_ROOM);
	act("Your left index finger snaps back into place.",ch,NULL,NULL,TO_CHAR);
	REMOVE_BIT(ch->loc_hp[LOC_ARM_L],BROKEN_FINGER_I);
    }
    else if (IS_ARM_L(ch,LOST_FINGER_M))
    {
	act("A middle finger slides out of $n's left hand.",ch,NULL,NULL,TO_ROOM);
	act("A middle finger slides out of your left hand.",ch,NULL,NULL,TO_CHAR);
	REMOVE_BIT(ch->loc_hp[LOC_ARM_L],LOST_FINGER_M);
	REMOVE_BIT(ch->loc_hp[LOC_ARM_L],BROKEN_FINGER_M);
    }
    else if (IS_ARM_L(ch,BROKEN_FINGER_M))
    {
	act("$n's left middle finger snaps back into place.",ch,NULL,NULL,TO_ROOM);
	act("Your left middle finger snaps back into place.",ch,NULL,NULL,TO_CHAR);
	REMOVE_BIT(ch->loc_hp[LOC_ARM_L],BROKEN_FINGER_M);
    }
    else if (IS_ARM_L(ch,LOST_FINGER_R))
    {
	act("A ring finger slides out of $n's left hand.",ch,NULL,NULL,TO_ROOM);
	act("A ring finger slides out of your left hand.",ch,NULL,NULL,TO_CHAR);
	REMOVE_BIT(ch->loc_hp[LOC_ARM_L],LOST_FINGER_R);
	REMOVE_BIT(ch->loc_hp[LOC_ARM_L],BROKEN_FINGER_R);
    }
    else if (IS_ARM_L(ch,BROKEN_FINGER_R))
    {
	act("$n's left ring finger snaps back into place.",ch,NULL,NULL,TO_ROOM);
	act("Your left ring finger snaps back into place.",ch,NULL,NULL,TO_CHAR);
	REMOVE_BIT(ch->loc_hp[LOC_ARM_L],BROKEN_FINGER_R);
    }
    else if (IS_ARM_L(ch,LOST_FINGER_L))
    {
	act("A little finger slides out of $n's left hand.",ch,NULL,NULL,TO_ROOM);
	act("A little finger slides out of your left hand.",ch,NULL,NULL,TO_CHAR);
	REMOVE_BIT(ch->loc_hp[LOC_ARM_L],LOST_FINGER_L);
	REMOVE_BIT(ch->loc_hp[LOC_ARM_L],BROKEN_FINGER_L);
    }
    else if (IS_ARM_L(ch,BROKEN_FINGER_L))
    {
	act("$n's left little finger snaps back into place.",ch,NULL,NULL,TO_ROOM);
	act("Your left little finger snaps back into place.",ch,NULL,NULL,TO_CHAR);
	REMOVE_BIT(ch->loc_hp[LOC_ARM_L],BROKEN_FINGER_L);
    }
    else if (IS_ARM_R(ch,LOST_THUMB))
    {
	act("A thumb slides out of $n's right hand.",ch,NULL,NULL,TO_ROOM);
	act("A thumb slides out of your right hand.",ch,NULL,NULL,TO_CHAR);
	REMOVE_BIT(ch->loc_hp[LOC_ARM_R],LOST_THUMB);
	REMOVE_BIT(ch->loc_hp[LOC_ARM_R],BROKEN_THUMB);
    }
    else if (IS_ARM_R(ch,BROKEN_THUMB))
    {
	act("$n's right thumb snaps back into place.",ch,NULL,NULL,TO_ROOM);
	act("Your right thumb snaps back into place.",ch,NULL,NULL,TO_CHAR);
	REMOVE_BIT(ch->loc_hp[LOC_ARM_R],BROKEN_THUMB);
    }
    else if (IS_ARM_R(ch,LOST_FINGER_I))
    {
	act("An index finger slides out of $n's right hand.",ch,NULL,NULL,TO_ROOM);
	act("An index finger slides out of your right hand.",ch,NULL,NULL,TO_CHAR);
	REMOVE_BIT(ch->loc_hp[LOC_ARM_R],LOST_FINGER_I);
	REMOVE_BIT(ch->loc_hp[LOC_ARM_R],BROKEN_FINGER_I);
    }
    else if (IS_ARM_R(ch,BROKEN_FINGER_I))
    {
	act("$n's right index finger snaps back into place.",ch,NULL,NULL,TO_ROOM);
	act("Your right index finger snaps back into place.",ch,NULL,NULL,TO_CHAR);
	REMOVE_BIT(ch->loc_hp[LOC_ARM_R],BROKEN_FINGER_I);
    }
    else if (IS_ARM_R(ch,LOST_FINGER_M))
    {
	act("A middle finger slides out of $n's right hand.",ch,NULL,NULL,TO_ROOM);
	act("A middle finger slides out of your right hand.",ch,NULL,NULL,TO_CHAR);
	REMOVE_BIT(ch->loc_hp[LOC_ARM_R],LOST_FINGER_M);
	REMOVE_BIT(ch->loc_hp[LOC_ARM_R],BROKEN_FINGER_M);
    }
    else if (IS_ARM_R(ch,BROKEN_FINGER_M))
    {
	act("$n's right middle finger snaps back into place.",ch,NULL,NULL,TO_ROOM);
	act("Your right middle finger snaps back into place.",ch,NULL,NULL,TO_CHAR);
	REMOVE_BIT(ch->loc_hp[LOC_ARM_R],BROKEN_FINGER_M);
    }
    else if (IS_ARM_R(ch,LOST_FINGER_R))
    {
	act("A ring finger slides out of $n's right hand.",ch,NULL,NULL,TO_ROOM);
	act("A ring finger slides out of your right hand.",ch,NULL,NULL,TO_CHAR);
	REMOVE_BIT(ch->loc_hp[LOC_ARM_R],LOST_FINGER_R);
	REMOVE_BIT(ch->loc_hp[LOC_ARM_R],BROKEN_FINGER_R);
    }
    else if (IS_ARM_R(ch,BROKEN_FINGER_R))
    {
	act("$n's right ring finger snaps back into place.",ch,NULL,NULL,TO_ROOM);
	act("Your right ring finger snaps back into place.",ch,NULL,NULL,TO_CHAR);
	REMOVE_BIT(ch->loc_hp[LOC_ARM_R],BROKEN_FINGER_R);
    }
    else if ( IS_ARM_R(ch,LOST_FINGER_L))
    {
	act("A little finger slides out of $n's right hand.",ch,NULL,NULL,TO_ROOM);
	act("A little finger slides out of your right hand.",ch,NULL,NULL,TO_CHAR);
	REMOVE_BIT(ch->loc_hp[LOC_ARM_R],LOST_FINGER_L);
	REMOVE_BIT(ch->loc_hp[LOC_ARM_R],BROKEN_FINGER_L);
    }
    else if ( IS_ARM_R(ch,BROKEN_FINGER_L))
    {
	act("$n's right little finger snaps back into place.",ch,NULL,NULL,TO_ROOM);
	act("Your right little finger snaps back into place.",ch,NULL,NULL,TO_CHAR);
	REMOVE_BIT(ch->loc_hp[LOC_ARM_R],BROKEN_FINGER_L);
    }
    else if (IS_BODY(ch,CUT_THROAT))
    {
    	if (IS_SET(ch->loc_hp[6], BLEEDING_THROAT)) return;
	act("The wound in $n's throat closes up.",ch,NULL,NULL,TO_ROOM);
	act("The wound in your throat closes up.",ch,NULL,NULL,TO_CHAR);
	REMOVE_BIT(ch->loc_hp[LOC_BODY],CUT_THROAT);
    }
    return;
}

void vamp_rage( CHAR_DATA *ch )
{
    if (IS_NPC(ch)) return;

    send_to_char("You scream with rage as the beast within consumes you!\n\r",ch);
    act("$n screams with rage as $s inner beast consumes $m!.", ch, NULL, NULL, TO_ROOM);
    do_beastlike(ch,"");
    do_frenzy(ch,"");
    return;
}

void do_humanity( CHAR_DATA *ch, char *argument )
{
    char       arg [MAX_INPUT_LENGTH];

    argument = one_argument( argument, arg );

    if (IS_NPC( ch )) return;

    if (!IS_NPC(ch) && IS_CLASS(ch,CLASS_VAMPIRE) && ch->beast > 0
	&& ch->beast < 100 && number_range(1, 300) <= ch->beast)
    {
	if (ch->beast == 1)
	{
	    send_to_char("You have attained Golconda!\n\r", ch);
	    ch->exp += 1000000;
	    if (!IS_IMMUNE(ch, IMM_SUNLIGHT))
		SET_BIT(ch->immune, IMM_SUNLIGHT);
	}
	else
	    send_to_char("You feel slightly more in control of your beast.\n\r", ch);
	ch->beast -= 1;
    }
    return;
}

void do_beastlike( CHAR_DATA *ch, char *argument )
{
    char       arg [MAX_INPUT_LENGTH];
    int blood;

    argument = one_argument( argument, arg );

    if (IS_NPC( ch )) return;

    if (!IS_NPC(ch) && IS_CLASS(ch,CLASS_VAMPIRE) && ch->beast < 100
	&& ch->beast > 0 && number_range(1, 500) <= ch->beast)
    {
	if (ch->beast < 99)
	    send_to_char("You feel your beast take more control over your actions.\n\r", ch);
	else
	    send_to_char("Your beast has fully taken over control of your actions!\n\r", ch);
	ch->beast += 1;
    	blood = ch->pcdata->condition[COND_THIRST];
    	ch->pcdata->condition[COND_THIRST] = 666;
    	if ((IS_VAMPAFF(ch,VAM_PROTEAN) || (IS_VAMPAFF(ch,VAM_OBTENEBRATION)))
		&& !IS_VAMPAFF(ch,VAM_NIGHTSIGHT) ) do_nightsight(ch,"");
    	if (!IS_VAMPAFF(ch,VAM_FANGS) ) do_fangs(ch,"");
    	if (IS_VAMPAFF(ch,VAM_PROTEAN) &&
		!IS_VAMPAFF(ch,VAM_CLAWS) ) do_claws(ch,"");
    	ch->pcdata->condition[COND_THIRST] = blood;
    }
    return;
}

void do_feed( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char      arg [MAX_INPUT_LENGTH];
    char      buf [MAX_INPUT_LENGTH];
    char      bufch [MAX_INPUT_LENGTH];
    char      bufvi [MAX_INPUT_LENGTH];
    int       blood;

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;
    if (!IS_CLASS(ch, CLASS_VAMPIRE))
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }
    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }
    if (IS_NPC(victim))
    {
	send_to_char("Not on NPC's.\n\r",ch);
	return;
    }
    if (!IS_CLASS(victim, CLASS_VAMPIRE))
    {
	send_to_char("Blood does them no good at all.\n\r",ch);
	return;
    }
    if (!IS_IMMUNE(victim, IMM_VAMPIRE))
    {
	send_to_char("They refuse to drink your blood.\n\r",ch);
	return;
    }
    if ( ch->pcdata->condition[COND_THIRST] < 20 )
    {
	send_to_char("You don't have enough blood.\n\r",ch);
	return;
    }

    blood = number_range(5,10);
    ch->pcdata->condition[COND_THIRST] -= (blood * 2);
    victim->pcdata->condition[COND_THIRST] += blood;

    if (IS_AFFECTED(ch,AFF_POLYMORPH)) sprintf(bufch,ch->morph);
    else sprintf(bufch,ch->name);
    if (IS_AFFECTED(victim,AFF_POLYMORPH)) sprintf(bufvi,victim->morph);
    else sprintf(bufvi,victim->name);
    sprintf(buf,"You cut open your wrist and feed some blood to %s.",bufvi);
    act(buf,ch,NULL,victim,TO_CHAR);
    sprintf(buf,"%s cuts open $s wrist and feeds some blood to %s.",bufch,bufvi);
    act(buf, ch, NULL, victim, TO_NOTVICT);
    if (victim->position < POS_RESTING)
	send_to_char("You feel some blood poured down your throat.\n\r",victim);
    else
    {
	sprintf(buf,"%s cuts open $s wrist and feeds you some blood.",bufch);
	act(buf, ch, NULL, victim, TO_VICT);
    }
    return;
}

void do_upkeep( CHAR_DATA *ch, char *argument )
{
    char      arg [MAX_INPUT_LENGTH];
    char      buf [MAX_INPUT_LENGTH];
    char      buf2 [MAX_INPUT_LENGTH];

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;
    if (IS_CLASS(ch, CLASS_DEMON) || IS_SET(ch->special, SPC_CHAMPION))
    {

send_to_char("----------------------------------------------------------------------------\n\r",ch);
	send_to_char("                              -= Demonic powers =-\n\r",ch);

send_to_char("----------------------------------------------------------------------------\n\r",ch);

	if (ch->pcdata->powers[DPOWER_FLAGS] < 1)
	    send_to_char("You have no demonic powers.\n\r",ch);
    	if ( IS_DEMPOWER(ch,DEM_FANGS) )
	{
	    if (IS_VAMPAFF(ch, VAM_FANGS)) send_to_char("You have a pair of long pointed fangs extending from your gums.\n\r",ch);
	    else send_to_char("You have a pair of long pointed fangs, but they are not currently extended.\n\r",ch);
	}
    	if ( IS_DEMPOWER(ch,DEM_CLAWS) )
	{
	    if (IS_VAMPAFF(ch, VAM_CLAWS)) send_to_char("You have a pair of razor sharp claws extending from your fingers.\n\r",ch);
	    else send_to_char("You have a pair of razor sharp claws, but they are not currently extended.\n\r",ch);
	}
    	if ( IS_DEMPOWER(ch,DEM_HORNS) )
	{
	    if (IS_DEMAFF(ch, DEM_HORNS)) send_to_char("You have a pair of curved horns extending from your forehead.\n\r",ch);
	    else send_to_char("You have a pair of curved horns, but they are not currently extended.\n\r",ch);
	}
    	if ( IS_DEMPOWER(ch,DEM_TAIL) )
	{
	    if (IS_DEMAFF(ch, DEM_TAIL)) send_to_char("You have a huge tail extended from your backside.\n\r",ch);
	    else send_to_char("You have a tail, but it is  not currently extended.\n\r",ch);
	}
            if ( IS_DEMPOWER(ch,DEM_HOOVES) )
	{
	    if (IS_DEMAFF(ch, DEM_HOOVES)) send_to_char("You have hooves instead of feet.\n\r",ch);
	    else send_to_char("You are able to transform your feet into hooves at will.\n\r",ch);
	}
    	if ( IS_DEMPOWER(ch,DEM_EYES) )
	{
	    if (IS_VAMPAFF(ch, VAM_NIGHTSIGHT)) send_to_char("Your eyes are glowing bright red, allowing you to see in the dark.\n\r",ch);
	    else send_to_char("You are able to see in the dark, although that power is not currently activated.\n\r",ch);
	}
    	if ( IS_DEMPOWER(ch,DEM_WINGS) )
	{
	    if (!IS_DEMAFF(ch, DEM_WINGS)) send_to_char("You have the ability to extend wings from your back.\n\r",ch);
	    else if (IS_DEMAFF(ch, DEM_UNFOLDED)) send_to_char("You have a pair of large leathery wings unfolded behind your back.\n\r",ch);
	    else send_to_char("You have a pair of large leathery wings folded behind your back.\n\r",ch);
	}
    	if ( IS_DEMPOWER(ch,DEM_MIGHT) )
	    send_to_char("Your muscles ripple with supernatural strength.\n\r",ch);
    	if ( IS_DEMPOWER(ch,DEM_TOUGH) )
	    send_to_char("Your skin reflects blows with supernatural toughness.\n\r",ch);
    	if ( IS_DEMPOWER(ch,DEM_SPEED) )
	    send_to_char("You move with supernatural speed and grace.\n\r",ch);
    	if ( IS_DEMPOWER(ch,DEM_TRAVEL) )
	    send_to_char("You are able to travel to other demons at will.\n\r",ch);
    	if ( IS_DEMPOWER(ch,DEM_SCRY) )
	    send_to_char("You are able to scry over great distances at will.\n\r",ch);
    	if ( IS_DEMPOWER(ch,DEM_SHADOWSIGHT) )
	{
	    if (IS_AFFECTED(ch, AFF_SHADOWSIGHT)) send_to_char("You are able see things in the shadowplane.\n\r",ch);
	    else send_to_char("You are able to view the shadowplane, although you are not currently doing so.\n\r",ch);
	}
    }
    else if (IS_CLASS(ch, CLASS_VAMPIRE))
    {
	send_to_char("----------------------------------------------------------------------------\n\r",ch);
	send_to_char("                              -= Vampire upkeep =-\n\r",ch);
	send_to_char("----------------------------------------------------------------------------\n\r",ch);
	send_to_char("Staying alive...upkeep 1.\n\r",ch);

    	if (IS_VAMPAFF(ch,VAM_DISGUISED) )
	{
	    if      (ch->beast == 0  ) sprintf(buf,"You are disguised as %s...no upkeep.\n\r",ch->morph);
	    else if (ch->beast == 100) sprintf(buf,"You are disguised as %s...upkeep 10-20.\n\r",ch->morph);
	    else sprintf(buf,"You are disguised as %s...upkeep 5-10.\n\r",ch->morph);
	    send_to_char(buf,ch);
	}
    	if (IS_IMMUNE(ch,IMM_SHIELDED) )
	{
	    if      (ch->beast == 0  ) sprintf(buf,"You are shielded...no upkeep.\n\r");
	    else if (ch->beast == 100) sprintf(buf,"You are shielded...upkeep 2-6.\n\r");
	    else sprintf(buf,"You are shielded...upkeep 1-3.\n\r");
	    send_to_char(buf,ch);
	}
    	if (IS_AFFECTED(ch,AFF_SHADOWPLANE) )
	{
	    if      (ch->beast == 0  ) sprintf(buf,"You are in the shadowplane...no upkeep.\n\r");
	    else if (ch->beast == 100) sprintf(buf,"You are in the shadowplane...no upkeep.\n\r");
	    else sprintf(buf,"You are in the shadowplane...no upkeep.\n\r");
	    send_to_char(buf,ch);
	}
    	if (IS_VAMPAFF(ch,VAM_FANGS) )
	{
	    if      (ch->beast == 0  ) sprintf(buf,"You have your fangs out...no upkeep.\n\r");
	    else if (ch->beast == 100) sprintf(buf,"You have your fangs out...upkeep 2.\n\r");
	    else sprintf(buf,"You have your fangs out...upkeep 1.\n\r");
	    send_to_char(buf,ch);
	}
    	if (IS_VAMPAFF(ch,VAM_CLAWS) )
	{
	    if      (ch->beast == 0  ) sprintf(buf,"You have your claws out...no upkeep.\n\r");
	    else if (ch->beast == 100) sprintf(buf,"You have your claws out...upkeep 2-6.\n\r");
	    else sprintf(buf,"You have your claws out...upkeep 1-3.\n\r");
	    send_to_char(buf,ch);
	}
    	if (IS_VAMPAFF(ch,VAM_NIGHTSIGHT) )
	{
	    if      (ch->beast == 0  ) sprintf(buf,"You have nightsight...no upkeep.\n\r");
	    else if (ch->beast == 100) sprintf(buf,"You have nightsight...upkeep 2.\n\r");
	    else sprintf(buf,"You have nightsight...upkeep 1.\n\r");
	    send_to_char(buf,ch);
	}
    	if (IS_AFFECTED(ch,AFF_SHADOWSIGHT) )
	{
	    if      (ch->beast == 0  ) sprintf(buf,"You have shadowsight...no upkeep.\n\r");
	    else if (ch->beast == 100) sprintf(buf,"You are shadowsight...upkeep 2-6.\n\r");
	    else sprintf(buf,"You are shadowsight...upkeep 1-3.\n\r");
	    send_to_char(buf,ch);
	}
    	if (IS_SET(ch->act,PLR_HOLYLIGHT) )
	{
	    if      (ch->beast == 0  ) sprintf(buf,"You have truesight...no upkeep.\n\r");
	    else if (ch->beast == 100) sprintf(buf,"You have truesight...upkeep 2-10.\n\r");
	    else sprintf(buf,"You have truesight...upkeep 1-5.\n\r");
	    send_to_char(buf,ch);
	}
    	if (IS_VAMPAFF(ch,VAM_CHANGED) )
	{
	    if      (IS_POLYAFF(ch,POLY_BAT))  sprintf(buf2,"bat" );
	    else if (IS_POLYAFF(ch,POLY_WOLF)) sprintf(buf2,"wolf");
	    else                               sprintf(buf2,"mist");
	    if      (ch->beast == 0  ) sprintf(buf,"You have changed into %s form...no upkeep.\n\r",buf2);
	    else if (ch->beast == 100) sprintf(buf,"You have changed into %s form...upkeep 10-20.\n\r",buf2);
	    else sprintf(buf,"You have changed into %s form...upkeep 5-10.\n\r",buf2);
	    send_to_char(buf,ch);
	}
    	if (IS_POLYAFF(ch,POLY_SERPENT) )
	{
	    if      (ch->beast == 0  ) sprintf(buf,"You are in serpent form...no upkeep.\n\r");
	    else if (ch->beast == 100) sprintf(buf,"You are in serpent form...upkeep 6-8.\n\r");
	    else sprintf(buf,"You are in serpent form...upkeep 1-3.\n\r");
	    send_to_char(buf,ch);
       	}
        if (IS_POLYAFF(ch,POLY_ZULOFORM))
        {
        send_to_char("You are in Zuloform.\n\r",ch);
        if (IS_EXTRA(ch,EXTRA_DRAGON))
        {
        send_to_char("You are a huge dragon.\n\r",ch);
        return;
        }
        }
        if (IS_EXTRA(ch, EXTRA_AWE))
        {
        send_to_char("You are awe inspiring.\n\r",ch);
        }
if (IS_AFFECTED(ch, AFF_PEACE)) send_to_char("Your majesty is up.\n\r",ch);
if (IS_SET(ch->newbits, NEW_MONKFLAME)) send_to_char("Your hands and weapon are engulfed in flames.\n\r",ch);       
if (IS_EXTRA(ch, EXTRA_PLASMA)) send_to_char("You are in plasmaform.\n\r",ch);     
if (ch->power[DISC_VAMP_PROT] > 8) send_to_char("Your flesh is as hard as marble.\n\r",ch);
if (ch->rage > 0) send_to_char("You are in frenzy.\n\r",ch);
if (IS_SET(ch->act, PLR_WIZINVIS)) send_to_char("You are blended with the Shade.\n\r",ch);
if (IS_EXTRA(ch, EXTRA_POTENCY)) send_to_char("Your blood is more potent then usual.\n\r",ch);
if (IS_VAMPAFF(ch, VAM_HEAD)) send_to_char("You have the head of a lion.\n\r",ch);
if (IS_VAMPAFF(ch, VAM_TAIL)) send_to_char("A long tail protrudes from your backside.\n\r",ch);
if (IS_VAMPAFF(ch, VAM_EXOSKELETON)) send_to_char("Your body is covered by a bony exoskeleton.\n\r",ch);
if (IS_VAMPAFF(ch, VAM_HORNS)) send_to_char("Large horns protrude from your head.\n\r",ch);
if (IS_VAMPAFF(ch, VAM_WINGS)) send_to_char("Large wings protrude from your back.\n\r",ch);
}
else if (IS_CLASS(ch,CLASS_WEREWOLF))
{
send_to_char("---------------------------------------------------------------------------\n\r",ch);
send_to_char(
"                          Werewolf Upkeep\n\r",ch);
send_to_char("---------------------------------------------------------------------------\n\r",ch);
if (ch->rage>50)
send_to_char("You are raged into a werewolf.\n\r",ch);
sprintf(buf,"You have %d points of tolerance against silver.\n\r",ch->siltol);
send_to_char(buf,ch);
if (IS_SET(ch->newbits,NEW_REND))
send_to_char("You are focused on rending your opponents body.\n\r",ch);
if (IS_SET(ch->newbits,NEW_SLAM))
send_to_char("You will stun and strike your victim when he is down.\n\r",ch);
if (IS_SET(ch->newbits,NEW_QUILLS))
send_to_char("Razor sharp quills are extended from your back.\n\r",ch);
if (ch->power[DISC_WERE_RAPT] > 0)
send_to_char("Your fangs are much sharper then usual.\n\r",ch);
if (IS_SET(ch->newbits,NEW_JAWLOCK))
send_to_char("Your jaw is strengthened to clamp on your foes.\n\r",ch);
if (IS_SET(ch->newbits,NEW_SKIN))
send_to_char("Your skin is very tough, making it hard to slash and pierce.\n\r",ch);
if (IS_SET(ch->newbits,NEW_PERCEPTION))
send_to_char("You can sense the slightest movement.\n\r",ch);
if (ch->power[DISC_WERE_BOAR] > 2)
send_to_char("You are extra tough, halving damage.\n\r",ch);

send_to_char("---------------------------------------------------------------------------\n\r",ch);
return;
}

    else
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }
    send_to_char("----------------------------------------------------------------------------\n\r",ch);
    return;
}

void do_werewolf( CHAR_DATA *ch, char *argument )
{
    char       buf[MAX_INPUT_LENGTH];
    char       arg[MAX_INPUT_LENGTH];
    CHAR_DATA *vch;
    CHAR_DATA *vch_next;
    OBJ_DATA  *obj;

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;
    if (!IS_CLASS(ch, CLASS_WEREWOLF)) return;
    if (IS_SET(ch->special, SPC_WOLFMAN)) return;
    SET_BIT(ch->special, SPC_WOLFMAN);

    send_to_char("You throw back your head and howl with rage!\n\r",ch);
    act("$n throws back $s head and howls with rage!.", ch, NULL, NULL, TO_ROOM);
    send_to_char("Coarse dark hair sprouts from your body.\n\r",ch);
    act("Coarse dark hair sprouts from $n's body.",ch,NULL,NULL,TO_ROOM);
    if (!IS_VAMPAFF(ch,VAM_NIGHTSIGHT))
    {
	send_to_char("Your eyes start glowing red.\n\r",ch);
	act("$n's eyes start glowing red.",ch,NULL,NULL,TO_ROOM);
	SET_BIT(ch->pcdata->stats[UNI_AFF], VAM_NIGHTSIGHT);
    }
    if (!IS_VAMPAFF(ch,VAM_FANGS))
    {
	send_to_char("A pair of long fangs extend from your mouth.\n\r",ch);
	act("A pair of long fangs extend from $n's mouth.",ch,NULL,NULL,TO_ROOM);
	SET_BIT(ch->pcdata->stats[UNI_AFF], VAM_FANGS);
    }
    if (!IS_VAMPAFF(ch,VAM_CLAWS))
    {
	send_to_char("Razor sharp talons extend from your fingers.\n\r",ch);
	act("Razor sharp talons extend from $n's fingers.",ch,NULL,NULL,TO_ROOM);
	SET_BIT(ch->pcdata->stats[UNI_AFF], VAM_CLAWS);
    }
    if ((obj = get_eq_char(ch,WEAR_WIELD)) != NULL && !IS_SET(obj->spectype, SITEM_WOLFWEAPON))
    {
	act("$p drops from your right hand.",ch,obj,NULL,TO_CHAR);
	act("$p drops from $n's right hand.",ch,obj,NULL,TO_ROOM);
	obj_from_char(obj);
	obj_to_char(obj, ch);
    }
    if ((obj = get_eq_char(ch,WEAR_HOLD)) != NULL && !IS_SET(obj->spectype, SITEM_WOLFWEAPON))
    {
	act("$p drops from your left hand.",ch,obj,NULL,TO_CHAR);
	act("$p drops from $n's left hand.",ch,obj,NULL,TO_ROOM);
	obj_from_char(obj);
	obj_to_char(obj, ch);
    }
    SET_BIT(ch->affected_by, AFF_POLYMORPH);
    SET_BIT(ch->pcdata->stats[UNI_AFF], VAM_DISGUISED);
    sprintf(buf,"%s the werewolf", ch->name);
    free_string(ch->morph);
    ch->morph = str_dup(buf);
    ch->rage += 25;
    ch->hitroll += 100;
    ch->damroll += 100;
    if (ch->power[DISC_WERE_WOLF] > 3) ch->rage += 200;
    if (ch->rage > 400) 
	ch->rage = 400;

    for ( vch = char_list; vch != NULL; vch = vch_next )
    {
	vch_next	= vch->next;
	if ( vch->in_room == NULL )
	    continue;
	if ( ch == vch )
	{
	    act("You throw back your head and howl with rage!", ch, NULL, NULL, TO_CHAR);
	    continue;
	}
	if ( !IS_NPC(vch) && vch->pcdata->chobj != NULL )
	    continue;
	if (!IS_NPC(vch))
	{
	    if (vch->in_room == ch->in_room)
		act("$n throws back $s head and howls with rage!", ch, NULL, vch, TO_VICT);
	    else if (vch->in_room->area == ch->in_room->area)
		send_to_char("You hear a fearsome howl close by!\n\r", vch);
	    else
/*		send_to_char("You hear a fearsome howl far off in the 
   distance!\n\r", vch);*/
	    if (!CAN_PK(vch)) continue;
	}
	if ( vch->in_room == ch->in_room && can_see( ch, vch) )
	{
	    multi_hit( ch, vch, TYPE_UNDEFINED );
	    if (vch == NULL || vch->position <= POS_STUNNED) continue;
	    multi_hit( ch, vch, TYPE_UNDEFINED );
	    if (vch == NULL || vch->position <= POS_STUNNED) continue;
	    multi_hit( ch, vch, TYPE_UNDEFINED );
	}
    }
    return;
}

void do_unwerewolf( CHAR_DATA *ch, char *argument )
{
    char       arg[MAX_INPUT_LENGTH];

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;
    if (!IS_CLASS(ch, CLASS_WEREWOLF)) return;
    if (!IS_SET(ch->special, SPC_WOLFMAN)) return;
    REMOVE_BIT(ch->special, SPC_WOLFMAN);
    REMOVE_BIT(ch->affected_by, AFF_POLYMORPH);
    REMOVE_BIT(ch->pcdata->stats[UNI_AFF], VAM_DISGUISED);
    free_string(ch->morph);
    ch->morph = str_dup("");
    if (IS_VAMPAFF(ch,VAM_CLAWS))
    {
	send_to_char("Your talons slide back into your fingers.\n\r",ch);
	act("$n's talons slide back into $s fingers.",ch,NULL,NULL,TO_ROOM);
	REMOVE_BIT(ch->pcdata->stats[UNI_AFF], VAM_CLAWS);
    }
    if (IS_VAMPAFF(ch,VAM_FANGS))
    {
	send_to_char("Your fangs slide back into your mouth.\n\r",ch);
	act("$n's fangs slide back into $s mouth.",ch,NULL,NULL,TO_ROOM);
	REMOVE_BIT(ch->pcdata->stats[UNI_AFF], VAM_FANGS);
    }
    if (IS_VAMPAFF(ch,VAM_NIGHTSIGHT))
    {
	send_to_char("The red glow in your eyes fades.\n\r",ch);
	act("The red glow in $n's eyes fades.",ch,NULL,NULL,TO_ROOM);
	REMOVE_BIT(ch->pcdata->stats[UNI_AFF], VAM_NIGHTSIGHT);
    }
    send_to_char("Your coarse hair shrinks back into your body.\n\r",ch);
    act("$n's coarse hair shrinks back into $s body.",ch,NULL,NULL,TO_ROOM);
    ch->rage -= 25;
    ch->hitroll -= 100;
    ch->damroll -= 100;
    if (ch->rage < 0) ch->rage = 0;
    return;
}
void do_possession( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    CHAR_DATA *familiar;
    char arg[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];

    one_argument( argument, arg );

    if ( IS_NPC(ch) )
	return;

    if (!IS_CLASS(ch, CLASS_VAMPIRE) )
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }

/* kavirpoint 
	send_to_char("This ability has been temporarily disabled.\n\r",ch);
	return;
*/
    if (ch->power[DISC_VAMP_DOMI] < 3)
    {
        send_to_char("You must obtain at least level 3 in Dominate to use Possession.\n\r",ch);
	return;
    }

    if ( ( familiar = ch->pcdata->familiar ) != NULL)
    {
	sprintf(buf,"You break your hold over %s.\n\r",familiar->short_descr);
	send_to_char( buf, ch );
	familiar->wizard = NULL;
	ch->pcdata->familiar = NULL;
	return;
    }

    if ( arg[0] == '\0' )
    {
	send_to_char( "What do you wish to Possess?\n\r", ch );
	return;
    }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( ch == victim )
    {
	send_to_char( "What an intelligent idea!\n\r", ch );
	return;
    }

    if ( !IS_NPC(victim) )
    {
	send_to_char( "Not on players.\n\r", ch );
	return;
    }

    if (victim->wizard != NULL)
    {
	send_to_char( "You are unable to possess them.\n\r", ch );
	return;
    }

    if (victim->level > (ch->spl[RED_MAGIC] * 0.25))
    {
	send_to_char( "They are too powerful.\n\r", ch );
	return;
    }

    if ( ch->pcdata->condition[COND_THIRST] < 50 )
    {
	send_to_char("You have insufficient blood.\n\r",ch);
	return;
    }

    ch->pcdata->condition[COND_THIRST] -= 50;
    ch->pcdata->familiar = victim;
    victim->wizard = ch;
    act("You concentrate on $N.",ch,NULL,victim,TO_CHAR);
    act("$n is staring at you!",ch,NULL,victim,TO_VICT);
    act("$n starts staring at $N",ch,NULL,victim,TO_NOTVICT);
    return;
}

void do_familiar( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    CHAR_DATA *familiar;
    char arg[MAX_INPUT_LENGTH];

    one_argument( argument, arg );

    return;

    if ( arg[0] == '\0' )
    {
	send_to_char( "What do you wish to make your familiar?\n\r", ch );
	return;
    }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( ch == victim )
    {
	send_to_char( "Become your own familiar?\n\r", ch );
	return;
    }

    if ( !IS_NPC(victim) )
    {
	send_to_char( "Not on players.\n\r", ch );
	return;
    }

    if ( ( familiar = ch->pcdata->familiar ) != NULL ) 
	familiar->wizard = NULL;
    ch->pcdata->familiar = victim;
    victim->wizard = ch;
    send_to_char("Ok.\n\r",ch);

    return;
}

void do_fcommand( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;

    if (IS_NPC(ch)) return;
/*
    if ((!IS_CLASS(ch, CLASS_VAMPIRE)  ch->level < LEVEL_APPRENTICE) ||
!IS_CLASS(ch, CLASS_DEMON))
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }
*/
    if (IS_CLASS(ch, CLASS_VAMPIRE) && (ch->power[DISC_VAMP_DOMI] < 3) )
    {
	send_to_char("You are not trained in the Dominate discipline.\n\r",ch);
	return;
    }

    if ( ( victim = ch->pcdata->familiar ) == NULL )
    {
	send_to_char( "But you don't have a familiar!\n\r", ch );
	return;
    }

    if ( argument[0] == '\0' )
    {
	send_to_char( "What do you wish to make your familiar do?\n\r", ch );
	return;
    }
    interpret(victim,argument);
    return;
}

void do_vanish( CHAR_DATA *ch, char *argument )
{
    if ( IS_NPC(ch) )
	return;

    if ((IS_CLASS(ch, CLASS_WEREWOLF) && ch->power[DISC_WERE_OWL] < 1)
       || (IS_CLASS(ch, CLASS_VAMPIRE) && ch->power[DISC_VAMP_OBFU] < 1)
       || (!IS_CLASS(ch, CLASS_WEREWOLF) && !IS_CLASS(ch, CLASS_VAMPIRE)))
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }


    if ( IS_SET(ch->act, PLR_WIZINVIS) )
    {
	REMOVE_BIT(ch->act, PLR_WIZINVIS);
	send_to_char( "You slowly fade into existance.\n\r", ch );
	act("$n slowly fades into existance.",ch,NULL,NULL,TO_ROOM);
    }
    else
    {
	send_to_char( "You slowly fade out of existance.\n\r", ch );
	act("$n slowly fades out of existance.",ch,NULL,NULL,TO_ROOM);
	SET_BIT(ch->act, PLR_WIZINVIS);
    }
    return;
}

void do_flex( CHAR_DATA *ch, char *argument )
{
    act("You flex your bulging muscles.",ch,NULL,NULL,TO_CHAR);
    act("$n flexes $s bulging muscles.",ch,NULL,NULL,TO_ROOM);
    if (IS_NPC(ch)) return;

    if ( IS_EXTRA(ch, TIED_UP) )
    {
	act("The ropes restraining you snap.",ch,NULL,NULL,TO_CHAR);
	act("The ropes restraining $n snap.",ch,NULL,NULL,TO_ROOM);
	REMOVE_BIT(ch->extra, TIED_UP);
    }
    if (is_affected(ch, gsn_web))
    {
	act("The webbing entrapping $n breaks away.",ch,NULL,NULL,TO_ROOM);
	send_to_char("The webbing entrapping you breaks away.\n\r",ch);
	affect_strip(ch, gsn_web);
    }
    if (IS_AFFECTED(ch, AFF_WEBBED))
    {
	act("The webbing entrapping $n breaks away.",ch,NULL,NULL,TO_ROOM);
	send_to_char("The webbing entrapping you breaks away.\n\r",ch);
	REMOVE_BIT(ch->affected_by, AFF_WEBBED);
    }
    if (IS_AFFECTED(ch, AFF_TENDRILS))
{
act("The tendrils entrapping $n break away.",ch,NULL,NULL,TO_ROOM);
send_to_char("The tendrils entrapping you break away.\n\r",ch);
REMOVE_BIT(ch->affected_by, AFF_TENDRILS);
}

    WAIT_STATE(ch,12);
    return;
}

void do_rage( CHAR_DATA *ch, char *argument )
{
    if ( IS_NPC(ch) )
	return;

    if (!IS_CLASS(ch, CLASS_WEREWOLF) && !IS_CLASS(ch, CLASS_DEMON))
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }

  if (IS_CLASS(ch, CLASS_WEREWOLF))
  {
/*
    if (ch->power[DISC_WERE_BEAR] < 3)
    {
	stc("You need to obtain level three in the Bear totem.\n\r",ch);
	return;
    }
*/
    if (!IS_SET(ch->special, SPC_WOLFMAN))
    {
	send_to_char("You start snarling angrilly.\n\r",ch);
	act("$n starts snarling angrilly.",ch,NULL,NULL,TO_ROOM);
	ch->rage += number_range(10,50);
	if (ch->rage >= 100) do_werewolf(ch,"");
	WAIT_STATE(ch,12);
	return;
    }
    send_to_char("But you are already in a rage!\n\r",ch);
    }

    if (IS_CLASS(ch, CLASS_DEMON))
    {
	if (ch->power[DISC_DAEM_ATTA] < 3)
        {
	    stc("You try, but cannot summon your beast.\n\r",ch);
	    return;
	}

     if (ch->beast < 1)
	ch->beast = 1;

        if (ch->beast > ch->rage || ch->rage < 25)
	{
	    ch->rage += number_range(ch->generation,25);
	    stc("You scream as you plunge into a mad attacking frenzy.\n\r",ch);
	    act("$n screams in frenzied rage.",ch,NULL,NULL,TO_ROOM);
	    if (number_percent() < (ch->beast + 1))
	    {
		stc("You feel the beast take more control.\n\r",ch);
		ch->beast += 1;
		if (ch->beast > 100)
		  ch->beast = 100;
	    }
	    WAIT_STATE(ch, 12);
	    return;
	}
       
        stc("You have reached the pinnacle of your frenzy.\n\r",ch);
    }

    return;
}

void do_calm( CHAR_DATA *ch, char *argument )
{
    if ( IS_NPC(ch) )
	return;

    if (!IS_CLASS(ch, CLASS_WEREWOLF) && !IS_CLASS(ch, CLASS_DEMON))
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }

 if (IS_CLASS(ch, CLASS_WEREWOLF))
 {

    if (ch->power[DISC_WERE_WOLF] < 3)
    {
	stc("You need level three in the Wolf totem to Calm.\n\r",ch);
	return;
    }  

    if (IS_SET(ch->special, SPC_WOLFMAN))
    {
	send_to_char("You take a deep breath and calm yourself.\n\r",ch);
	act("$n takes a deep breath and tries to calm $mself.",ch,NULL,NULL,TO_ROOM);
	ch->rage -= number_range(20,30);
	if (ch->rage < 100) do_unwerewolf(ch,"");
	WAIT_STATE(ch,12);
	return;
    }
    send_to_char("But you are not in crinos form!\n\r",ch);
 }

   if (IS_CLASS(ch, CLASS_DEMON))
   {

    if (ch->power[DISC_DAEM_ATTA] < 4)
    {
	stc("You need level four in Attack to calm your frenzy.\n\r",ch);
	return;
    }

    if (ch->beast >= 100) ch->beast = 100;
    if (ch->beast <= 0) ch->beast = 0;

    ch->rage -= (40 - (ch->beast / 3) +dice (1, 10));
    if (ch->rage <= 0)
    {
	ch->rage = 0;
	send_to_char("You have calmed out of your rage completely.\n\r", ch);
    }
    else
    {
      send_to_char("You hold your breath and try to calm your frenzy.\n\r", ch);
      WAIT_STATE(ch, 8);
    }
    return;
  } 
    return;
}

void do_totems( CHAR_DATA *ch, char *argument )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    char arg3[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );
    argument = one_argument( argument, arg3 );

    if (IS_NPC(ch)) return;

/*
    send_to_char("Please use the new commands, Disciplines and research.\n\r",ch);
	return;
*/

    if (!IS_CLASS(ch, CLASS_WEREWOLF))
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }

    if (arg1[0] == '\0' && arg2[0] == '\0')
    {
	if (ch->pcdata->ww_researching[TOTEM_RESEARCHING] != 0)
	{
	if ((ch->pcdata->ww_researching[TOTEM_RESEARCHING] == 1)) send_to_char("You are currently researching the bear totem.\n\r",ch);
        else if ((ch->pcdata->ww_researching[TOTEM_RESEARCHING] == 2)) send_to_char("You are currently researching the lynx totem.\n\r",ch);
        else if ((ch->pcdata->ww_researching[TOTEM_RESEARCHING] == 3)) send_to_char("You are currently researching the boar totem.\n\r",ch);
        else if ((ch->pcdata->ww_researching[TOTEM_RESEARCHING] == 4)) send_to_char("You are currently researching the owl totem.\n\r",ch);
        else if ((ch->pcdata->ww_researching[TOTEM_RESEARCHING] == 5)) send_to_char("You are currently researching the spider totem.\n\r",ch);
        else if ((ch->pcdata->ww_researching[TOTEM_RESEARCHING] == 6)) send_to_char("You are currently researching the wolf totem.\n\r",ch);
        else if ((ch->pcdata->ww_researching[TOTEM_RESEARCHING] == 7)) send_to_char("You are currently researching the hawk totem.\n\r",ch);
        else if ((ch->pcdata->ww_researching[TOTEM_RESEARCHING] == 8)) send_to_char("You are currently researching the mantis totem.\n\r",ch);
        else if ((ch->pcdata->ww_researching[TOTEM_RESEARCHING] == 9)) send_to_char("You are currently researching the raptor totem.\n\r",ch);
        else if ((ch->pcdata->ww_researching[TOTEM_RESEARCHING] == 10)) send_to_char("You are currently researching the luna totem.\n\r",ch);
        else if ((ch->pcdata->ww_researching[TOTEM_RESEARCHING] == 11)) send_to_char("You are currently researching the pain totem.\n\r",ch);
        else if ((ch->pcdata->ww_researching[TOTEM_RESEARCHING] == 12)) send_to_char("You are currently researching the congregation totem.\n\r",ch);
	if (ch->pcdata->ww_completed[AMOUNT_COMPLETED] < 1) stc("You have not researched at all.\n\r",ch);
	else
	{
	sprintf(buf,"You have completed %d percent of your research.\n\r",ch->pcdata->ww_completed[AMOUNT_COMPLETED]);
	send_to_char(buf,ch);
	}
	}
	sprintf(buf,"#7Totems:\n\rBear (%d)  Lynx (%d)  Boar (%d)  Owl (%d)\n\rSpider (%d)  Wolf (%d)  Hawk (%d)  Mantis (%d)\n\rRaptor (%d)  Luna (%d)  Pain (%d)  Congregation (%d)\n\r",
	ch->power[DISC_WERE_BEAR], ch->power[DISC_WERE_LYNX],
	ch->power[DISC_WERE_BOAR], ch->power[DISC_WERE_OWL],
	ch->power[DISC_WERE_SPID], ch->power[DISC_WERE_WOLF],
	ch->power[DISC_WERE_HAWK],ch->power[DISC_WERE_MANT],
        ch->power[DISC_WERE_RAPT],ch->power[DISC_WERE_LUNA],
        ch->power[DISC_WERE_PAIN],ch->power[DISC_WERE_CONG]);

	send_to_char(buf,ch);
	return;
    }
    if (arg2[0] == '\0')
    {
	if (!str_cmp(arg1,"bear"))
	{
	    send_to_char("Bear: The totem of strength and aggression.\n\r",ch);
	    if (ch->power[DISC_WERE_BEAR] < 1) 
		send_to_char("You have none of the Bear totem powers.\n\r",ch);
	    if (ch->power[DISC_WERE_BEAR] > 0) 
		send_to_char("Flex: You strength is so great that no ropes can hold you.\n\r",ch);
	    if (ch->power[DISC_WERE_BEAR] > 1) 
		send_to_char("Rage: You are able to build yourself up a rage at will.\n\r",ch);
	    if (ch->power[DISC_WERE_BEAR] > 2) 
		send_to_char("Steel claws: Your claws are so tough that they can parry weapons.\n\r",ch);
	    if (ch->power[DISC_WERE_BEAR] > 3) 
		send_to_char("Hibernation: Your wounds heal at amazing speeds when you sleep.\n\r",ch);
	    return;
	}
	else if (!str_cmp(arg1,"boar"))
	{
	    send_to_char("Boar: The totem of toughness and perserverance.\n\r",ch);
	    if (ch->power[DISC_WERE_BOAR] < 1) 
		send_to_char("You have none of the Boar totem powers.\n\r",ch);
	    if (ch->power[DISC_WERE_BOAR] > 0) 
		send_to_char("Shatter: No door is sturdy enough to resist you.\n\r",ch);
	    if (ch->power[DISC_WERE_BOAR] > 1) 
		send_to_char("Charge: Your first blow in combat has a +50 damage bonus.\n\r",ch);
	    if (ch->power[DISC_WERE_BOAR] > 2) 
		send_to_char("Toughness: Your skin is extremely tough. You take half damage in combat.\n\r",ch);
	    if (ch->power[DISC_WERE_BOAR] > 3) 
		send_to_char("Immovability: You are able to shrug off blows that would knock out most people.\n\r",ch);
	    return;
	}
	else if (!str_cmp(arg1,"lynx"))
	{
	    send_to_char("Lynx: The totem of speed and agility.\n\r",ch);
	    if (ch->power[DISC_WERE_LYNX] < 1) 
		send_to_char("You have none of the Lynx totem powers.\n\r",ch);
	    if (ch->power[DISC_WERE_LYNX] > 0) 
		send_to_char("Light footed: You move so lightly that you leave no tracks behind you.\n\r",ch);
	    if (ch->power[DISC_WERE_LYNX] > 1) 
		send_to_char("Stalker: You are able hunt people with much greater speed than normal.\n\r",ch);
	    if (ch->power[DISC_WERE_LYNX] > 2) 
		send_to_char("Combat speed: You have an extra attack in combat.\n\r",ch);
	    if (ch->power[DISC_WERE_LYNX] > 3) 
		send_to_char("Lightning Claws: Yours claws parry blows with lightning fast speed.\n\r",ch);
	    return;
	}
	else if (!str_cmp(arg1,"Owl"))
	{
	    send_to_char("Owl: The totem of thought and spiritualism.\n\r",ch);
	    if (ch->power[DISC_WERE_OWL] < 1) 
		send_to_char("You have none of the Owl totem powers.\n\r",ch);
	    if (ch->power[DISC_WERE_OWL] > 0) 
		send_to_char("Vanish: You are able to conceal yourself from all but the most perceptive.\n\r",ch);
	    if (ch->power[DISC_WERE_OWL] > 1) 
		send_to_char("Shield: You are able to shield your mind from scrying and aura-reading.\n\r",ch);
	    if (ch->power[DISC_WERE_OWL] > 2) 
		send_to_char("Shadowplane: You are able to enter the shadow plane.\n\r",ch);
	    if (ch->power[DISC_WERE_OWL] > 3) 
		send_to_char("Magical Control: You are able to fully control your magic in crinos form.\n\r",ch);
	    return;
	}
	else if (!str_cmp(arg1,"Spider"))
	{
	    send_to_char("Spider: The totem of ambush and cunning.\n\r",ch);
	    if (ch->power[DISC_WERE_SPID] < 1) 
		send_to_char("You have none of the Spider totem powers.\n\r",ch);
	    if (ch->power[DISC_WERE_SPID] > 0) 
		send_to_char("Poisonous bite: Your bite injects your opponents with a deadly venom.\n\r",ch);
	    if (ch->power[DISC_WERE_SPID] > 1) 
		send_to_char("Web: You are able to shoot a web at your opponents to entrap them.\n\r",ch);
	    if (ch->power[DISC_WERE_SPID] > 2) 
		send_to_char("Immunity to poison: Poisons have no affect upon you.\n\r",ch);
	    return;
	}
	else if (!str_cmp(arg1,"Wolf"))
	{
	    send_to_char("Wolf: Controlling your innate wolf powers.\n\r",ch);
	    if (ch->power[DISC_WERE_WOLF] < 1) 
		send_to_char("You have none of the Wolf totem powers.\n\r",ch);
	    if (ch->power[DISC_WERE_WOLF] > 0) 
		send_to_char("Claws: You can extend or retract your claws at will.\n\r",ch);
	    if (ch->power[DISC_WERE_WOLF] > 1) 
		send_to_char("Fangs: You can extend or retract your fangs at will.\n\r",ch);
	    if (ch->power[DISC_WERE_WOLF] > 2) 
		send_to_char("Calm: You are able to repress your inner beast at will.\n\r",ch);
	    if (ch->power[DISC_WERE_WOLF] > 3) 
		send_to_char("Spirit of Fenris: You are able to enter rage faster than normal.\n\r",ch);
	    return;
	}
	else if (!str_cmp(arg1,"Hawk"))
	{
	    send_to_char("Hawk: The totem of vision and perception.\n\r",ch);
	    if (ch->power[DISC_WERE_HAWK] < 1) 
		send_to_char("You have none of the Wolf totem powers.\n\r",ch);
	    if (ch->power[DISC_WERE_HAWK] > 0) 
		send_to_char("Nightsight: You can see perfectly well in the dark.\n\r",ch);
	    if (ch->power[DISC_WERE_HAWK] > 1) 
		send_to_char("Shadowsight: You can see into the plane of shadows.\n\r",ch);
	    if (ch->power[DISC_WERE_HAWK] > 2) 
		send_to_char("Truesight: You have perfect vision.\n\r",ch);
	    return;
	}
	else if (!str_cmp(arg1,"Mantis"))
	{
	   send_to_char("Mantis: The totem of dexterity and reflexes.\n\r",ch);
	    if (ch->power[DISC_WERE_MANT] < 1) 
		send_to_char("You have none of the Mantis totem powers.\n\r",ch);
	    else if (ch->power[DISC_WERE_MANT] > 9) 
		send_to_char("Insanely fast attacks: Your opponents get -50 to parry and -100 to dodge.\n\r",ch);
	    else if (ch->power[DISC_WERE_MANT] > 8) 
		send_to_char("Insanely fast attacks: Your opponents get -45 to parry and -90 to dodge.\n\r",ch);
	    else if (ch->power[DISC_WERE_MANT] > 7) 
		send_to_char("Insanely fast attacks: Your opponents get -40 to parry and -80 to dodge.\n\r",ch);
	    else if (ch->power[DISC_WERE_MANT] > 6) 
		send_to_char("Insanely fast attacks: Your opponents get -35 to parry and -70 to dodge.\n\r",ch);
	    else if (ch->power[DISC_WERE_MANT] > 5) 
		send_to_char("Insanely fast attacks: Your opponents get -30 to parry and -60 to dodge.\n\r",ch);
	    else if (ch->power[DISC_WERE_MANT] > 4) 
		send_to_char("Insanely fast attacks: Your opponents get -25 to parry and -50 to dodge.\n\r",ch);
	    else if (ch->power[DISC_WERE_MANT] > 3) 
		send_to_char("Incredibly fast attacks: Your opponents get -20 to parry and -40 to dodge.\n\r",ch);
	    else if (ch->power[DISC_WERE_MANT] > 2) 
		send_to_char("Extremely fast attacks: Your opponents get -15 to parry and -30 to dodge.\n\r",ch);
	    else if (ch->power[DISC_WERE_MANT] > 1) 
		send_to_char("Very fast attacks: Your opponents get -10 to parry and -20 to dodge.\n\r",ch);
	    else if (ch->power[DISC_WERE_MANT] > 0) 
		send_to_char("Fast attacks: Your opponents get -5 to parry and -10 to dodge.\n\r",ch);
	    return;
	}
	else if (!str_cmp(arg1,"Pain"))
	{
	    send_to_char("Pain: The totem of pain and empowerment.\n\r",ch);
	    if (ch->power[DISC_WERE_PAIN] < 1) 
		send_to_char("You have none of the Pain totem powers.\n\r",ch);
            return; 
        }
	else if (!str_cmp(arg1,"Luna"))
	{
	    send_to_char("Luna: The totem of the moon and serenity.\n\r",ch);
	    if (ch->power[DISC_WERE_LUNA] < 1) 
		send_to_char("You have none of the Luna totem powers.\n\r",ch);
	    if (ch->power[DISC_WERE_LUNA] > 0)
                send_to_char("Flameclaws:  You have the power to turn your claws into flames.\n\r",ch);
	    if (ch->power[DISC_WERE_LUNA] > 2)
                send_to_char("Moonarmour:  You have the power to create moon eq.\n\r",ch);
	    if (ch->power[DISC_WERE_LUNA] > 3)
                send_to_char("Mothers:  You have the power of Mothers Touch.\n\r",ch);
	    if (ch->power[DISC_WERE_LUNA] > 4)
                send_to_char("Gmothers:  You have the power of Grandmothers Touch.\n\r",ch);
	    if (ch->power[DISC_WERE_LUNA] > 5)
                send_to_char("Sclaws:  You can change your claws into pure silver.\n\r",ch);
	    if (ch->power[DISC_WERE_LUNA] > 6)
                send_to_char("Moon Spirit:  The Power of the Moon increases your damage.\n\rMoongate:  You can use the power of the moon to gate to places.\n\r",ch);
	    if (ch->power[DISC_WERE_LUNA] > 8)
                send_to_char("Moonbeam:  You can strike down foes with a Moonbeam.\n\r",ch);
	    if (ch->power[DISC_WERE_LUNA] > 9)
                send_to_char("Absorb:  You have the power to absorb damage.\n\r",ch);
            return; 
        }
	else if (!str_cmp(arg1,"raptor"))
	{
	    send_to_char("Raptor: The totem of beastiality and animalism.\n\r",ch);
	    if (ch->power[DISC_WERE_RAPT] < 1) 
		send_to_char("You have none of the Raptor totem powers.\n\r",ch);
	    if (ch->power[DISC_WERE_RAPT] > 2)
                send_to_char("Run:  You have the power to Run like the wind.\n\r",ch);
	    if (ch->power[DISC_WERE_RAPT] > 3)
                send_to_char("Perception:  You have the power of view all hidden things.\n\r",ch);
	    if (ch->power[DISC_WERE_RAPT] > 5)
                send_to_char("Devour:  You can devour life from corpses.\n\r",ch);
	    if (ch->power[DISC_WERE_RAPT] > 7)
                send_to_char("Shred:  You can Shred people through the Shadowplane.\n\r",ch);
	    if (ch->power[DISC_WERE_RAPT] > 8)
                send_to_char("Lockjaw:  You can lock your jaws on your opponent.\n\r",ch);
	    if (ch->power[DISC_WERE_RAPT] > 10)
                send_to_char("Talons:  You have the power of massive Talons.\n\r",ch);
            return; 
        }
	else if (!str_cmp(arg1,"congregation"))
	{
	    send_to_char("Congregation: The totem of pain and empowerment.\n\r",ch);
	    if (ch->power[DISC_WERE_CONG] < 1) 
		send_to_char("You have none of the Congregation totem powers.\n\r",ch);
            return; 
        }
        sprintf(buf,"#7Totems:\n\rBear (%d)  Lynx (%d)  Boar (%d)  Owl (%d)\n\rSpider (%d)  Wolf (%d)  Hawk (%d)  Mantis (%d)\n\rRaptor(%d)  Luna (%d)  Pain (%d)  Congregation(%d)\n\r",
	ch->power[DISC_WERE_BEAR], ch->power[DISC_WERE_LYNX],
	ch->power[DISC_WERE_BOAR], ch->power[DISC_WERE_OWL],
	ch->power[DISC_WERE_SPID], ch->power[DISC_WERE_WOLF],
        ch->power[DISC_WERE_HAWK],ch->power[DISC_WERE_MANT],
	ch->power[DISC_WERE_RAPT],ch->power[DISC_WERE_LUNA],
        ch->power[DISC_WERE_PAIN],ch->power[DISC_WERE_CONG]);        
        send_to_char(buf,ch);
	return;
    }
    else if (!str_cmp(arg2,"research"))
    {
    int max;

	if (!str_cmp(arg3,"abandon"))
	{
	ch->pcdata->ww_researching[TOTEM_RESEARCHING] = 0;
	ch->pcdata->ww_completed[AMOUNT_COMPLETED] = 0;
	send_to_char("You abandon researching.\n\r",ch);
	return;
	}
	else
	{
	if (ch->pcdata->ww_researching[TOTEM_RESEARCHING] != 0)
	{
	send_to_char("But are already researching a totem.\n\r",ch);
	return;
	}
	
	if (!str_cmp(arg1,"bear")) {ch->pcdata->ww_researching[TOTEM_RESEARCHING] += 1;}
	else if (!str_cmp(arg1,"lynx")) {ch->pcdata->ww_researching[TOTEM_RESEARCHING] += 2;}
	else if (!str_cmp(arg1,"boar")) {ch->pcdata->ww_researching[TOTEM_RESEARCHING] += 3;}
	else if (!str_cmp(arg1,"owl")) {ch->pcdata->ww_researching[TOTEM_RESEARCHING] += 4;}
	else if (!str_cmp(arg1,"spider")) {ch->pcdata->ww_researching[TOTEM_RESEARCHING] += 5;}
	else if (!str_cmp(arg1,"wolf")) {ch->pcdata->ww_researching[TOTEM_RESEARCHING] += 6;}
	else if (!str_cmp(arg1,"hawk")) {ch->pcdata->ww_researching[TOTEM_RESEARCHING] += 7;}
	else if (!str_cmp(arg1,"mantis")) {ch->pcdata->ww_researching[TOTEM_RESEARCHING] += 8;}
	else if (!str_cmp(arg1,"raptor")) {ch->pcdata->ww_researching[TOTEM_RESEARCHING] += 9;}
	else if (!str_cmp(arg1,"luna")) {ch->pcdata->ww_researching[TOTEM_RESEARCHING] += 10;}
	else if (!str_cmp(arg1,"pain")) {ch->pcdata->ww_researching[TOTEM_RESEARCHING] += 11;}
	else if (!str_cmp(arg1,"congregation")) {ch->pcdata->ww_researching[TOTEM_RESEARCHING] += 12;}
	else
	{
	stc("syntax: totem (totem) (research or improve).\n\r",ch);
	return;
	}
	sprintf(buf,"You start researching the %s totem.\n\r",arg1);
	send_to_char(buf,ch);
	return;
	}
	}
    else if (!str_cmp(arg2,"improve"))
    {
	int improve;
	int max;

	if (!str_cmp(arg1,"bear"   ))
	{
	if (ch->pcdata->ww_researching[TOTEM_RESEARCHING] != 1)
	{
	stc("You are not researching the bear totem.\n\r",ch);
	return;
	}
	improve = DISC_WERE_BEAR;
	max=10;
	}
	else if (!str_cmp(arg1,"boar"   )) 
	{
	if (ch->pcdata->ww_researching[TOTEM_RESEARCHING] != 3)
	{
	stc("You are not researching the boar totem.\n\r",ch);
	return;
	}
	improve = DISC_WERE_BOAR;
	max=10;
	}
	else if (!str_cmp(arg1,"lynx"   )) 
	{
	if (ch->pcdata->ww_researching[TOTEM_RESEARCHING] != 2)
	{
	stc("You are not researching the lynx totem.\n\r",ch);
	return;
	}
	improve = DISC_WERE_LYNX;
	max=10;
	}
	else if (!str_cmp(arg1,"owl"    )) 
	{
	if (ch->pcdata->ww_researching[TOTEM_RESEARCHING] != 4)
	{
	stc("You are not researching the owl totem.\n\r",ch);
	return;
	}
	improve = DISC_WERE_OWL;
	max=10;
	}
	else if (!str_cmp(arg1,"spider" )) 
	{
	if (ch->pcdata->ww_researching[TOTEM_RESEARCHING] != 5)
	{
	stc("You are not researching the spider totem.\n\r",ch);
	return;
	}
	improve = DISC_WERE_SPID;
	max=10;
	}
	else if (!str_cmp(arg1,"wolf"   )) 
	{
	if (ch->pcdata->ww_researching[TOTEM_RESEARCHING] != 6)
	{
	stc("You are not researching the wolf totem.\n\r",ch);
	return;
	}
	improve = DISC_WERE_WOLF;
	max=10;
	}
	else if (!str_cmp(arg1,"hawk"   )) 
	{
	if (ch->pcdata->ww_researching[TOTEM_RESEARCHING] != 7)
	{
	stc("You are not researching the hawk totem.\n\r",ch);
	return;
	}
	improve = DISC_WERE_HAWK;
	max=10;
	}
	else if (!str_cmp(arg1,"mantis" )) 
	{
	if (ch->pcdata->ww_researching[TOTEM_RESEARCHING] != 8)
	{
	stc("You are not researching the mantis totem.\n\r",ch);
	return;
	}
	improve = DISC_WERE_MANT;
	max=10;
	}
	else if (!str_cmp(arg1,"raptor" )) 
	{
	if (ch->pcdata->ww_researching[TOTEM_RESEARCHING] != 9)
	{
	stc("You are not researching the raptor totem.\n\r",ch);
	return;
	}
	improve = DISC_WERE_RAPT;
	max=10;
	}
        else if (!str_cmp(arg1,"luna"   )) 
	{
	if (ch->pcdata->ww_researching[TOTEM_RESEARCHING] != 10)
	{
	stc("You are not researching the luna totem.\n\r",ch);
	return;
	}
	improve = DISC_WERE_LUNA;
	max=10;
	}
        else if (!str_cmp(arg1,"pain"   )) 
	{
	if (ch->pcdata->ww_researching[TOTEM_RESEARCHING] != 11)
	{
	stc("You are not researching the pain totem.\n\r",ch);
	return;
	}
	improve = DISC_WERE_PAIN;
	max=10;
	}
        else if (!str_cmp(arg1,"congregation"))
	{
	if (ch->pcdata->ww_researching[TOTEM_RESEARCHING] != 12)
	{
	stc("You are not researching the congregation totem.\n\r",ch);
	return;
	}
	improve=DISC_WERE_CONG;
	max=10;
	}
 
      else
	{
	    send_to_char("#7You can improve: Bear, Boar, Lynx, Owl, Spider, Wolf, Hawk, Mantis, Raptor, Pain, Luna, Congregation\n\r",ch);
	    return;
	}
	arg1[0] = UPPER(arg1[0]);
	if ( ch->pcdata->ww_completed[AMOUNT_COMPLETED] < 100 )
	{
	send_to_char("You must fully research the totem before improving it.\n\r",ch);
	return;
	}
	if ( ch->power[improve] >= max )
	{
	    sprintf(buf,"You have already gained all the powers of the %s totem.\n\r", arg1);
	    send_to_char(buf,ch);
	    return;
	}
	ch->pcdata->ww_researching[TOTEM_RESEARCHING] = 0;
	ch->pcdata->ww_completed[AMOUNT_COMPLETED] = 0;
	ch->power[improve] += 1;
	sprintf(buf,"You improve your ability in the %s totem.\n\r", arg1);
	send_to_char(buf,ch);
    }
    else send_to_char("To improve a totem, type: Totem <totem type> improve.\n\r",ch);
    return;
}

void do_web( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char arg [MAX_INPUT_LENGTH];
    int sn;
    int level;
    int spelltype;

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;

	if (!IS_CLASS(ch, CLASS_WEREWOLF) && !IS_CLASS(ch, CLASS_DROW))
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }

	if (IS_CLASS(ch, CLASS_WEREWOLF) && ch->power[DISC_WERE_SPID] < 2) 
	{send_to_char("You don't have that power yet.\n\r", ch );
	return;}

	if (IS_CLASS(ch, CLASS_DROW) && !IS_SET(ch->pcdata->powers[1],DPOWER_WEB))
	{send_to_char("You don't have that power yet.\n\r", ch );
	return;}


    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( ch == victim )
    {
	send_to_char( "You cannot web yourself.\n\r", ch );
	return;
    }

    if ( IS_AFFECTED(victim, AFF_ETHEREAL) )
    {
	send_to_char( "You cannot web an ethereal person.\n\r", ch );
	return;
    }

    if ( ( sn = skill_lookup( "web" ) ) < 0 ) return;
    spelltype = skill_table[sn].target;
    level = ch->spl[spelltype] * 0.25;
    (*skill_table[sn].spell_fun) ( sn, level, ch, victim );
    WAIT_STATE( ch, 12 );
    return;
}

void do_birth( CHAR_DATA *ch, char *argument )
{
    char buf2[MAX_STRING_LENGTH];

    if (IS_NPC(ch)) return;

    if (!IS_EXTRA(ch, EXTRA_PREGNANT))
    {
	send_to_char("But you are not even pregnant!\n\r",ch);
	return;
    }

    if (!IS_EXTRA(ch, EXTRA_LABOUR))
    {
	send_to_char("You're not ready to give birth yet.\n\r",ch);
	return;
    }

    if ( argument[0] == '\0' )
    {
	if (ch->pcdata->genes[4] == SEX_MALE)
	    send_to_char( "What do you wish to name your little boy?\n\r", ch );
	else if (ch->pcdata->genes[4] == SEX_FEMALE)
	    send_to_char( "What do you wish to name your little girl?\n\r", ch );
	else
	    send_to_char( "What do you wish to name your child?\n\r", ch );
	return;
    }

    if (!check_parse_name( argument ))
    {
	send_to_char( "Thats an illegal name.\n\r", ch );
	return;
    }

    if ( char_exists(FALSE,argument) )
    {
	send_to_char( "That player already exists.\n\r", ch );
	return;
    }

    strcpy(buf2,ch->pcdata->cparents);
    strcat(buf2," ");
    strcat(buf2,argument);
    if (!birth_ok(ch, buf2))
    {
	send_to_char( "Bug - please inform KaVir.\n\r", ch );
	return;
    }
    argument[0] = UPPER(argument[0]);
    birth_write( ch, argument );
    ch->pcdata->genes[9] += 1;
    REMOVE_BIT(ch->extra, EXTRA_PREGNANT);
    REMOVE_BIT(ch->extra, EXTRA_LABOUR);
    save_char_obj(ch);
    return;
}

bool birth_ok( CHAR_DATA *ch, char *argument )
{
    char buf [MAX_STRING_LENGTH];
    char mum [MAX_INPUT_LENGTH];
    char dad [MAX_INPUT_LENGTH];
    char child [MAX_INPUT_LENGTH];

    argument = one_argument( argument, mum );
    argument = one_argument( argument, dad );
    argument = one_argument( argument, child );

    if (dad[0] == '\0')
    {
	send_to_char("You are unable to give birth - please inform KaVir.\n\r",ch);
	return FALSE;
    }
    if (child[0] == '\0')
    {
	send_to_char("You are unable to give birth - please inform KaVir.\n\r",ch);
	return FALSE;
    }
    dad[0] = UPPER(dad[0]);
    if (!str_cmp(dad,"Kavir")) strcpy(dad,"KaVir");
    child[0] = UPPER(child[0]);
    if (ch->pcdata->genes[4] == SEX_MALE)
    {
	send_to_char("You give birth to a little boy!\n\r",ch);
	sprintf(buf,"%s has given birth to %s's son, named %s!",ch->name,dad,child);
	do_info(ch,buf);
	return TRUE; 
    }
    else if (ch->pcdata->genes[4] == SEX_FEMALE)
    {
	send_to_char("You give birth to a little girl!\n\r",ch);
	sprintf(buf,"%s has given birth to %s's daughter, named %s!",ch->name,dad,child);
	do_info(ch,buf);
	return TRUE; 
    }
    return FALSE;
}


bool char_exists( bool backup, char *argument )
{
    FILE *fp;
    char buf [MAX_STRING_LENGTH];
    bool found = FALSE;

    fclose( fpReserve );
    if (backup)
    	sprintf( buf, "%sbackup/%s", PLAYER_DIR, capitalize( argument ) );
    else
    	sprintf( buf, "%s%s", PLAYER_DIR, capitalize( argument ) );
    if ( ( fp = fopen( buf, "r" ) ) != NULL )
    {
	found = TRUE;
	fclose( fp );
    }
    fpReserve = fopen( NULL_FILE, "r" );
    return found;
}

void birth_write( CHAR_DATA *ch, char *argument )
{
    FILE *fp;
    char buf [MAX_STRING_LENGTH];
    char *strtime;

    strtime = ctime( &current_time );
    strtime[strlen(strtime)-1] = '\0';

    sprintf( buf, "%s%s", PLAYER_DIR, capitalize( argument ) );
    if ( ( fp = fopen(buf, "w") ) != NULL) 
    {  
	fprintf( fp, "#PLAYER\n");
	fprintf( fp, "Name         %s~\n",capitalize( argument ));
	fprintf( fp, "ShortDescr   ~\n"				);
	fprintf( fp, "LongDescr    ~\n"				);
	fprintf( fp, "Description  ~\n"				);
	fprintf( fp, "Lord         ~\n"				);
	fprintf( fp, "Morph        ~\n"				);
	fprintf( fp, "Createtime   %s~\n",str_dup( strtime )	);
 	fprintf( fp, "Lasttime     ~\n"				);
	fprintf( fp, "Lasthost     ~\n"				);
	fprintf( fp, "Poweraction  ~\n"				);
	fprintf( fp, "Powertype    ~\n"				);
	fprintf( fp, "Prompt       ~\n"				);
	fprintf( fp, "Cprompt      ~\n"				);
	fprintf( fp, "Sex          %d\n",ch->pcdata->genes[4]	);
	fprintf( fp, "Race         0\n"				);
	fprintf( fp, "Immune       %d\n",ch->pcdata->genes[3]	);
	fprintf( fp, "Polyaff      0\n"				);
	fprintf( fp, "Itemaffect   0\n"				);
	fprintf( fp, "Vampaff      0\n"				);
	fprintf( fp, "Vamppass     0\n"				);
	fprintf( fp, "Form         32767\n"			);
	fprintf( fp, "Beast        15\n"			);
	fprintf( fp, "Vampgen      -1\n"			);
	fprintf( fp, "Spectype     0\n"				);
	fprintf( fp, "Specpower    0\n"				);
	fprintf( fp, "Home         3001\n"			);
	fprintf( fp, "Level        2\n"				);
	fprintf( fp, "Trust        0\n"				);
	fprintf( fp, "Played       0\n"				);
	fprintf( fp, "Room         %d\n",ch->in_room->vnum 	);
	fprintf( fp, "PkPdMkMd     0 0 0 0\n"			);
	fprintf( fp, "Weapons      0 0 0 0 0 0 0 0 0 0 0 0 0\n"	);
	fprintf( fp, "Spells       4 4 4 4 4\n"			);
	fprintf( fp, "Combat       0 0 0 0 0 0 0 0\n"		);
	fprintf( fp, "Stance       0 0 0 0 0 0 0 0 0 0 0\n"	);
	fprintf( fp, "Locationhp   0 0 0 0 0 0 0\n"		);
	fprintf( fp, "HpManaMove   %d %d %d %d %d %d\n",
	    ch->pcdata->genes[0], ch->pcdata->genes[0], ch->pcdata->genes[1], 
	    ch->pcdata->genes[1], ch->pcdata->genes[2], ch->pcdata->genes[2]);
	fprintf( fp, "Gold         0\n"				);
	fprintf( fp, "Exp          0\n"				);
	fprintf( fp, "Act          1600\n"   			);
	fprintf( fp, "Extra        32768\n"   			);
	fprintf( fp, "AffectedBy   0\n"				);
	fprintf( fp, "Position     7\n"				);
	fprintf( fp, "Practice     0\n"				);
	fprintf( fp, "SavingThrow  0\n"				);
	fprintf( fp, "Alignment    0\n"				);
	fprintf( fp, "Hitroll      0\n"				);
	fprintf( fp, "Damroll      0\n"				);
	fprintf( fp, "Armor        100\n"			);
	fprintf( fp, "Wimpy        0\n"				);
	fprintf( fp, "Deaf         0\n"				);
	fprintf( fp, "Password     %s~\n",ch->pcdata->pwd	);
	fprintf( fp, "Bamfin       ~\n"				);
	fprintf( fp, "Bamfout      ~\n"				);
	fprintf( fp, "Title         the mortal~\n"		);
	fprintf( fp, "Conception   ~\n"				);
	fprintf( fp, "Parents      %s~\n",ch->pcdata->cparents	);
	fprintf( fp, "Cparents     ~\n"				);
	fprintf( fp, "AttrPerm     %d %d %d %d %d\n",
	    ch->pcdata->perm_str,
	    ch->pcdata->perm_int,
	    ch->pcdata->perm_wis,
	    ch->pcdata->perm_dex,
	    ch->pcdata->perm_con );
	fprintf( fp, "AttrMod      0 0 0 0 0\n"			);
	fprintf( fp, "Quest        0\n"				);
	fprintf( fp, "Wolf         0\n"				);
	fprintf( fp, "Rank         0\n"				);
	fprintf( fp, "Stage        0 0 0\n"			);
	fprintf( fp, "Wolfform     0 0\n"			);
	fprintf( fp, "Runes        0 0 0 0\n"			);
	fprintf( fp, "Disc         0 0 0 0 0 0 0 0 0 0 0\n"	);
	fprintf( fp, "Genes        0 0 0 0 0 0 0 0 0 0\n"	);
	fprintf( fp, "Power        0 0\n"			);
	fprintf( fp, "FakeCon      0 0 0 0 0 0 0 0\n"		);
	fprintf( fp, "Condition    0 48 48\n"			);
	fprintf( fp, "End\n\n" );
	fprintf( fp, "#END\n" );
	fclose( fp );
    }
    return;
}

void do_teach( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char      arg [MAX_INPUT_LENGTH];


    if (IS_NPC(ch)) return;


    if (!IS_CLASS(ch, CLASS_MAGE))
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }

    if (ch->level == LEVEL_APPRENTICE)
    {
	send_to_char("You don't know enough to teach another.\n\r",ch);
	return;
    }

    if ( arg[0] == '\0' )
    {
	send_to_char( "Teach whom?\n\r", ch );
	return;
    }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( IS_NPC(victim) )
    {
	send_to_char( "Not on NPC's.\n\r", ch );
	return;
    }

    if ( IS_IMMORTAL(victim) )
    {
	send_to_char( "Not on Immortals's.\n\r", ch );
	return;
    }

    if ( ch == victim )
    {
	send_to_char( "You cannot teach yourself.\n\r", ch );
	return;
    }

    if (IS_CLASS(victim, CLASS_MAGE))
    {
	send_to_char( "They are already a mage.\n\r", ch );
	return;
    }

    if ( victim->level != LEVEL_AVATAR && !IS_IMMORTAL(victim) )
    {
	send_to_char( "You can only teach avatars.\n\r", ch );
	return;
    }

    if (IS_CLASS(victim, CLASS_VAMPIRE) || IS_SET(victim->pcdata->stats[UNI_AFF], VAM_MORTAL))
    {
	send_to_char( "You are unable to teach vampires!\n\r", ch );
	return;
    }

	if (IS_CLASS(victim, CLASS_DROW)) {
		send_to_char("Not on a drow!\n\r", ch );
		return; }

    if (IS_CLASS(victim, CLASS_WEREWOLF))
    {
	send_to_char( "You are unable to teach werewolves!\n\r", ch );
	return;
    }

    if (IS_CLASS(victim, CLASS_DEMON) || IS_SET(victim->special, SPC_CHAMPION))
    {
	send_to_char( "You are unable to teach demons!\n\r", ch );
	return;
    }


    if (IS_CLASS(victim, CLASS_HIGHLANDER))
    {
	send_to_char( "You are unable to teach highlanders.\n\r", ch );
	return;
    }

    if (!IS_IMMUNE(victim,IMM_VAMPIRE))
    {
	send_to_char( "You cannot teach an unwilling person.\n\r", ch );
	return;
    }

    if (ch->exp < 100000)
    {
	send_to_char("You cannot afford the 100000 exp required to teach them.\n\r",ch);
	return;
    }

    if (victim->exp < 100000)
    {
	send_to_char("They cannot afford the 100000 exp required to learn from you.\n\r",ch);
	return;
    }

    ch->exp -= 100000;
    victim->exp -= 100000;

    act("You teach $N the basics of magic.", ch, NULL, victim, TO_CHAR);
    act("$n teaches $N the basics of magic.", ch, NULL, victim, TO_NOTVICT);
    act("$n teaches you the basics of magic.", ch, NULL, victim, TO_VICT);
    victim->level = LEVEL_APPRENTICE;
    victim->trust = LEVEL_APPRENTICE;
    send_to_char( "You are now an apprentice.\n\r", victim );
    free_string(victim->lord);
    victim->lord = str_dup(ch->name);
    victim->pcdata->powers[MPOWER_RUNE0] = ch->pcdata->powers[MPOWER_RUNE0];
    victim->class    = CLASS_MAGE;
    save_char_obj(ch);
    save_char_obj(victim);
    return;
}


void do_mitsukeru( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    ROOM_INDEX_DATA *chroom;
    ROOM_INDEX_DATA *victimroom;
    char      arg [MAX_INPUT_LENGTH];

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;

	if (!IS_CLASS(ch, CLASS_NINJA) || ch->pcdata->powers[NPOWER_SORA] <1) {
	send_to_char("Huh?\n\r", ch );
	return;}
	if (arg[0] == '\0')
    {
	send_to_char( "Scry on whom?\n\r", ch );
	return;
    }

    if ( ( victim = get_char_world( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    chroom = ch->in_room;
    victimroom = victim->in_room;

    char_from_room(ch);
    char_to_room(ch,victimroom);
    if (IS_AFFECTED(ch, AFF_SHADOWPLANE) && (!IS_AFFECTED(victim, AFF_SHADOWPLANE)))
    {
	REMOVE_BIT(ch->affected_by, AFF_SHADOWPLANE);
	do_look(ch,"auto");
	SET_BIT(ch->affected_by, AFF_SHADOWPLANE);
    }
    else if (!IS_AFFECTED(ch, AFF_SHADOWPLANE) && (IS_AFFECTED(victim, AFF_SHADOWPLANE)))
    {
	SET_BIT(ch->affected_by, AFF_SHADOWPLANE);
	do_look(ch,"auto");
	REMOVE_BIT(ch->affected_by, AFF_SHADOWPLANE);
    }
    else
	do_look(ch,"auto");
    char_from_room(ch);
    char_to_room(ch,chroom);
    ch->fight_timer = 10;
    return;
}

void do_koryou( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    OBJ_DATA  *obj;
    char      arg [MAX_INPUT_LENGTH];
    char      buf [MAX_INPUT_LENGTH];

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;

	if (!IS_CLASS(ch, CLASS_NINJA) || ch->pcdata->powers[NPOWER_SORA] <2) {
	send_to_char( "Huh?\n\r", ch );
	return;
    }

    if ( arg[0] == '\0' )
    {
	send_to_char( "Read the aura on what?\n\r", ch );
	return;
    }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
        if ( ( obj = get_obj_carry( ch, arg ) ) == NULL )
	{
	    send_to_char( "Read the aura on what?\n\r", ch );
	    return;
	}
	act("$n examines $p intently.",ch,obj,NULL,TO_ROOM);
	spell_identify( skill_lookup( "identify" ), ch->level, ch, obj );
	return;
    }

    if (!IS_NPC(victim) && (IS_IMMUNE(victim,IMM_SHIELDED) ||
(IS_CLASS(victim, CLASS_DROW) &&
IS_SET(victim->pcdata->powers[1],DPOWER_DROWSHIELD))) && !IS_ITEMAFF(ch, ITEMA_VISION))
    {
	send_to_char("You are unable to read their aura.\n\r",ch);
	return;
    }

    act("$n examines $N intently.",ch,NULL,victim,TO_NOTVICT);
    act("$n examines you intently.",ch,NULL,victim,TO_VICT);
    if (IS_NPC(victim)) sprintf(buf, "%s is an NPC.\n\r",victim->short_descr);
    else 
    {
	if      (victim->level == 12) sprintf(buf, "%s is an Implementor.\n\r", victim->name);
	else if (victim->level == 11) sprintf(buf, "%s is a High Judge.\n\r", victim->name);
	else if (victim->level == 10) sprintf(buf, "%s is a Judge.\n\r", victim->name);
	else if (victim->level == 9 ) sprintf(buf, "%s is an Enforcer.\n\r", victim->name);
	else if (victim->level == 8 ) sprintf(buf, "%s is a Quest Maker.\n\r", victim->name);
	else if (victim->level == 7 ) sprintf(buf, "%s is a Builder.\n\r", victim->name);
	else if (victim->level >= 3 ) sprintf(buf, "%s is an Avatar.\n\r", victim->name);
	else sprintf(buf, "%s is a Mortal.\n\r", victim->name);
    }
    send_to_char(buf,ch);
    if (!IS_NPC(victim))
    {
	sprintf(buf,"Str:%d, Int:%d, Wis:%d, Dex:%d, Con:%d.\n\r",get_curr_str(victim),get_curr_int(victim),get_curr_wis(victim),get_curr_dex(victim),get_curr_con(victim));
	send_to_char(buf,ch);
    }
    sprintf(buf,"Hp:%d/%d, Mana:%d/%d, Move:%d/%d.\n\r",victim->hit,victim->max_hit,victim->mana,victim->max_mana,victim->move,victim->max_move);
    send_to_char(buf,ch);
    if (!IS_NPC(victim)) sprintf(buf,"Hitroll:%d, Damroll:%d, AC:%d.\n\r",char_hitroll(victim),char_damroll(victim),char_ac(victim));
    else sprintf(buf,"AC:%d.\n\r",char_ac(victim));
    send_to_char(buf,ch);
    if (!IS_NPC(victim))
    {
	sprintf(buf,"Status:%d, ",victim->race);
	send_to_char(buf,ch);
	if (IS_CLASS(victim, CLASS_VAMPIRE))    
	{
	    sprintf(buf,"Blood:%d, ",victim->pcdata->condition[COND_THIRST]);
	    send_to_char(buf,ch);
	}
    }
    sprintf(buf,"Alignment:%d.\n\r",victim->alignment);
    send_to_char(buf,ch);
    if (!IS_NPC(victim) && IS_EXTRA(victim, EXTRA_PREGNANT))
	act("$N is pregnant.",ch,NULL,victim,TO_CHAR);
    if (!IS_NPC(victim) && IS_CLASS(victim, CLASS_VAMPIRE))    
    {
	send_to_char("Disciplines:",ch);
	if (IS_VAMPAFF(victim, VAM_PROTEAN)) send_to_char(" Protean",ch);
	if (IS_VAMPAFF(victim, VAM_CELERITY)) send_to_char(" Celerity",ch);
	if (IS_VAMPAFF(victim, VAM_FORTITUDE)) send_to_char(" Fortitude",ch);
	if (IS_VAMPAFF(victim, VAM_POTENCE)) send_to_char(" Potence",ch);
	if (IS_VAMPAFF(victim, VAM_OBFUSCATE)) send_to_char(" Obfuscate",ch);
	if (IS_VAMPAFF(victim, VAM_OBTENEBRATION)) send_to_char(" Obtenebration",ch);
	if (IS_VAMPAFF(victim, VAM_SERPENTIS)) send_to_char(" Serpentis",ch);
	if (IS_VAMPAFF(victim, VAM_AUSPEX)) send_to_char(" Auspex",ch);
	if (IS_VAMPAFF(victim, VAM_DOMINATE)) send_to_char(" Dominate",ch);
	if (IS_VAMPAFF(victim, VAM_PRESENCE)) send_to_char(" Presence",ch);
        if (IS_VAMPAFF(victim, VAM_VICISSITUDE)) send_to_char(" Vicissitude",ch);
        if (IS_VAMPAFF(victim, VAM_THAU)) send_to_char(" Thaumaturgy",ch);
        if (IS_VAMPAFF(victim, VAM_ANIMAL)) send_to_char(" Animalism",ch);
        if (IS_VAMPAFF(victim, VAM_QUIETUS)) send_to_char(" Quietus",ch);
        send_to_char(".\n\r",ch);
    }
    return;
}







 * Class save, etc.  Used for.. stuff.				  *
 ******************************************************************/

#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"

void save_config args(( void ));
void load_config args(( void ));
void check_class args(( CHAR_DATA *ch ));

void check_class( CHAR_DATA *ch )
{
    if ( IS_CLASS(ch, CLASS_VAMPIRE) )
    {
      if ( (config_info->drow + config_info->demons + config_info->ninjas
+ config_info->monks) / 3 < config_info->vampires )
      {
	stc("Sorry. There are too many Vampires at the moment.\n",ch);
	stc("Try another class, or select None for now.\n\r",ch);
	ch->class = 0;
	ch->generation = 1;
      }
    }

    else if ( IS_CLASS(ch, CLASS_DROW) )
    {
      if ( (config_info->vampires + config_info->demons +
config_info->ninjas + config_info->monks) / 3
         < config_info->drow )
      {
        stc("Sorry. There are too many Drow at the moment.\n\r",ch);
        stc("Try another class, or select None for now.\n\r",ch);
        ch->class = 0;
        ch->generation = 1;
      }
    }

    else if ( IS_CLASS(ch, CLASS_DEMON) )
    {
      if ( (config_info->vampires + config_info->drow +
config_info->ninjas + config_info->monks) / 3
         < config_info->demons )
      {
	stc("Sorry. There are too many Demons at the moment.\n\r",ch);
	stc("Try another class, or select None for now.\n\r",ch);
	ch->class = 0;
	ch->generation = 1;
      }
    }

     else if ( IS_CLASS(ch, CLASS_NINJA) )
    {
      if ( (config_info->vampires + config_info->drow +
config_info->demons + config_info->monks) / 3
         < config_info->ninjas )
      {
        stc("Sorry. There are too many Ninjas at the moment.\n\r",ch);
        stc("Try another class, or select None for now.\n\r",ch);
        ch->class = 0;
        ch->generation = 1;
      }
    }

    else if ( IS_CLASS(ch, CLASS_MONK) )
    {
      if ( (config_info->vampires + config_info->drow + 
config_info->ninjas + config_info->demons) / 3
         < config_info->monks )
      {
	stc("Sorry. There are too many Monks at the moment.\n\r",ch);
	stc("Try another class, or select None for now.\n\r",ch);
	ch->class = 0;
	ch->generation = 1;
      }
    }
  
    else return;

  return;

}
/*
void do_configure(CHAR_DATA *ch, char *argument)
{
    char buf[MAX_STRING_LENGTH];
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    char arg3[MAX_INPUT_LENGTH];
    char *wholearg;
    CHAR_DATA *vch;
    int ox, oy;

    argument = one_argument( argument, arg1 );
    wholearg = argument;
    argument = one_argument( argument, arg2 );
    argument = one_argument( argument, arg3 );

    if (arg1[0] == '\0')
    {
	send_to_char("Current Configuration: \n\r",ch);

	sprintf(buf, "hitpoints = Mobile Hp     *= %d / %d\n\r",
	    config_info->mob_hp_mult, config_info->mob_hp_div);
	send_to_char(buf, ch);
	sprintf(buf, "level     = Mobile Level  *= %d / %d\n\r",
	    config_info->mob_level_mult, config_info->mob_level_div);
	send_to_char(buf, ch);
    	sprintf(buf, "damage    = Mobile Damage *= %d / %d\n\r",
	    config_info->mob_dam_mult, config_info->mob_dam_div);
    	send_to_char(buf, ch);
    	sprintf(buf, "Exp       = Exp Given     *= %d / %d\n\r",
	    config_info->research_exp_mult, config_info->research_exp_div);
    	send_to_char(buf, ch);
        sprintf(buf, "Forge     = Number-Range     %d , %d\n\r",
	    config_info->forge1, config_info->forge2);
	sprintf(buf, "autohelp = Automatic Help Prompt = %s\n\r",config_info->autohelp);
	send_to_char(buf, ch);
	return;
    }

    if (!str_prefix(arg1, "autohelp"))
    {
	if (wholearg[0] == '\0')
	{
	    send_to_char("Syntax:  configure autohelp <help page>",ch);
	    return;
	}

	free_string( config_info->autohelp );
	config_info->autohelp = str_dup( wholearg );
	send_to_char("Successfully updated Auto Help.\n\r",ch);
	save_config();
	send_to_char("Parameters successfully saved in config.sys.\n\r",ch);
	return;
    }	

    if (!is_number(arg2) || !is_number(arg3))
    {
	send_to_char("Syntax:  configure <variable> <x> <y>\n\r",ch);
	send_to_char("where x:y is the ratio you wish to set the variable to.\n\r",ch);
	send_to_char("eg. configure hitpoints 2 1\n\r",ch);
	send_to_char("Doubles the number of hp every mob has.\n\r",ch);
	send_to_char("Configure on it's own lists all variables.\n\r",ch);
	return;
    }

    if (atoi(arg3) == 0 || atoi(arg2)==0)
    {
	send_to_char("Values of zero are not allowed.\n\r",ch);
	return;
    }

    if (atoi(arg2) / atoi(arg3) > 6)
    {
	send_to_char("Ratio too large.\n\r",ch);
	return;
    }

    if (atoi(arg3) / atoi(arg2) > 6)
    {
	send_to_char("Ratio too small.\n\r",ch);
	return;
    }

    if (!str_prefix(arg1, "forge"))
    {
	ox = config_info->forge1;
	oy = config_info->forge2;

	config_info->forge1 = atoi(arg2);
	config_info->forge2 = atoi(arg3);

	save_config();
	stc("Forge updated.\n\r",ch);
	return;
   }

    if (!str_prefix(arg1, "hitpoints"))
    {
	ox = config_info->mob_hp_mult;
	oy = config_info->mob_hp_div;

	config_info->mob_hp_mult = atoi(arg2);
	config_info->mob_hp_div  = atoi(arg3);

	stc("Successful update of config.sys.\n\r",ch);

	for (vch = char_list; vch != NULL; vch = vch->next)
	{
	    if (IS_NPC(vch))
	    {
		vch->hit = vch->hit * oy / ox;
		vch->hit = vch->hit * config_info->mob_hp_mult / config_info->mob_hp_div;
		vch->max_hit = vch->max_hit * oy / ox;
		vch->max_hit = vch->max_hit * config_info->mob_hp_mult / config_info->mob_hp_div;
	    }
	}

	send_to_char("Successful update of mobile hitpoints.\n\r",ch);
	save_config();
	send_to_char("Parameters successfully saved in config.sys.\n\r",ch);
	return;
    }

    if (!str_prefix(arg1, "damage"))
    {

	ox = config_info->mob_dam_mult;
	oy = config_info->mob_dam_div;

	config_info->mob_dam_mult = atoi(arg2);
	config_info->mob_dam_div  = atoi(arg3);

	for (vch = char_list; vch != NULL; vch = vch->next)
	{
	    if (IS_NPC(vch))
	    {
		vch->damroll = vch->damroll * oy / ox;
		vch->damroll = vch->damroll * config_info->mob_hp_mult / config_info->mob_hp_div; 
	    }
	}

	send_to_char("Successful update of mobile damage.\n\r",ch);
	save_config();
	send_to_char("Parameters successfully saved in config.sys.\n\r",ch);
	return;
    }

    if (!str_prefix(arg1, "level"))
    {
	ox = config_info->mob_level_mult;
	oy = config_info->mob_level_div;

	config_info->mob_level_mult = atoi(arg2);
	config_info->mob_level_div  = atoi(arg3);

	for (vch = char_list; vch != NULL; vch = vch->next)
	{
	    if (IS_NPC(vch))
	    {
		int lvl;
		lvl = vch->level;
		vch->level = vch->level * oy / ox;
		vch->level = vch->level * config_info->mob_level_mult / config_info->mob_level_div;
		if (vch->level < lvl)
		    vch->level = lvl;
	    }
	}

	send_to_char("Successful update of mobile level.\n\r",ch);
	save_config();
	send_to_char("Parameters successfully saved in config.sys.\n\r",ch);
	return;
    }

    if (!str_prefix(arg1, "exp"))
    {
	config_info->research_exp_mult = atoi(arg2);
	config_info->research_exp_div  = atoi(arg3);

	send_to_char("Successful update of exp.\n\r",ch);
	save_config();
	send_to_char("Parameters successfully saved in config.sys.\n\r",ch);
	return;
    }

    if (!str_prefix(arg1, "points"))
    {
	config_info->prac_exp_mult = atoi(arg2);
	config_info->prac_exp_div  = atoi(arg3);

	fread_word(fp);
	send_to_char("Successful update of Disc Points.\n\r",ch);
	send_to_char("Parameters successfully saved in config.sys.\n\r",ch);
	return;
    }


    send_to_char("Cannot update a non-existant variable.\n\r",ch);
    send_to_char("config with no arguments to list.\n\r",ch);

}
*/

void initialise_config()
{
    if (config_info == NULL)
	config_info = alloc_perm( sizeof(*config_info) );

    config_info->demons		= 0;
    config_info->mages		= 0;
    config_info->vampires	= 0;
    config_info->werewolves	= 0;
    config_info->drow		= 0;
    config_info->monks		= 0;
    config_info->ninjas		= 0;
    load_config();
}

void load_config()
{
    FILE *fp;

    if ((fp = fopen("config.sys","r")) == NULL)
    {
	bug("Creating config.sys",0);
	save_config();
	return;
    }

    fread_to_eol( fp );
	fread_word(fp);
    config_info->demons		= fread_number( fp ); 
	fread_word(fp);
    config_info->mages		= fread_number( fp ); 
	fread_word(fp);
    config_info->vampires	= fread_number( fp ); 
	fread_word(fp);
    config_info->werewolves	= fread_number( fp ); 
	fread_word(fp);
    config_info->drow		= fread_number( fp ); 
	fread_word(fp);
    config_info->monks		= fread_number( fp ); 
        fread_word(fp);
    config_info->ninjas         = fread_number( fp );
    fclose( fp );
}


void save_config()
{
    FILE *fp;

    if ((fp = fopen("config.sys","w")) == NULL)
    {
	bug("Error saving to config.sys",0);
	return;
    }

    fprintf( fp, "Config.sys - Stuff for Classes, etc.\n");
    fprintf( fp, "Demons	%d\n",config_info->demons    );
    fprintf( fp, "Mages		%d\n",config_info->mages     );
    fprintf( fp, "Vampires      %d\n",config_info->vampires  );
    fprintf( fp, "Werewolves	%d\n",config_info->werewolves);
    fprintf( fp, "Drow		%d\n",config_info->drow	     );
    fprintf( fp, "Monks		%d\n",config_info->monks     );
    fprintf( fp, "Ninjas        %d\n",config_info->ninjas    );
    fclose( fp );
}



67326736  10330

 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
 *                                                                         *
 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
 *  Chastain, Michael Quan, and Mitchell Tse.                              *
 *                                                                         *
 *  In order to use any part of this Merc Diku Mud, you must comply with   *
 *  both the original Diku license in 'license.doc' as well the Merc       *
 *  license in 'license.txt'.  In particular, you may not remove either of *
 *  these copyright notices.                                               *
 *                                                                         *
 *  Thanks to abaddon for proof-reading our comm.c and pointing out bugs.  *
 *  Any remaining bugs are, of course, our work, not his.  :)              *
 *                                                                         *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 ***************************************************************************/

/*
 * This file contains all of the OS-dependent stuff:
 *   startup, signals, BSD sockets for tcp/ip, i/o, timing.
 *
 * The data flow for input is:
 *    Game_loop ---> Read_from_descriptor ---> Read
 *    Game_loop ---> Read_from_buffer
 *
 * The data flow for output is:
 *    Game_loop ---> Process_Output ---> Write_to_descriptor -> Write
 *
 * The OS-dependent functions are Read_from_descriptor and Write_to_descriptor.
 * -- Furey  26 Jan 1993
 */

#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#include <sys/time.h>
#endif

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

#include "merc.h"



/*
 * Malloc debugging stuff.
 */
#if defined(sun)
#undef MALLOC_DEBUG
#endif

#if defined(MALLOC_DEBUG)
#include <malloc.h>
extern	int	malloc_debug	args( ( int  ) );
extern	int	malloc_verify	args( ( void ) );
#endif


void check_class args(( CHAR_DATA *ch ));
void save_config args(( void ));


/*
 * Signal handling.
 * Apollo has a problem with __attribute(atomic) in signal.h,
 *   I dance around it.
 */
#if defined(apollo)
#define __attribute(x)
#endif

#if defined(unix)
#include <signal.h>
#include <unistd.h>
#include <sys/resource.h>	/* for RLIMIT_NOFILE */
#endif

#if defined(apollo)
#undef __attribute
#endif

/*
 * Socket and TCP/IP stuff.
 */
#if	defined(macintosh) || defined(MSDOS)
const	char	echo_off_str	[] = { '\0' };
const	char	echo_on_str	[] = { '\0' };
const	char 	go_ahead_str	[] = { '\0' };
#endif

#if	defined(unix)
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/telnet.h>
const	char	echo_off_str	[] = { IAC, WILL, TELOPT_ECHO, '\0' };
const	char	echo_on_str	[] = { IAC, WONT, TELOPT_ECHO, '\0' };
const	char 	go_ahead_str	[] = { IAC, GA, '\0' };
void show_string args((DESCRIPTOR_DATA *d, char *input ));

#endif



/*
 * OS-dependent declarations.
 */
#if	defined(_AIX)
#include <sys/select.h>
int	accept		args( ( int s, struct sockaddr *addr, int *addrlen ) );
int	bind		args( ( int s, struct sockaddr *name, int namelen ) );
void	bzero		args( ( char *b, int length ) );
int	getpeername	args( ( int s, struct sockaddr *name, int *namelen ) );
int	getsockname	args( ( int s, struct sockaddr *name, int *namelen ) );
int	gettimeofday	args( ( struct timeval *tp, struct timezone *tzp ) );
int	listen		args( ( int s, int backlog ) );
int	setsockopt	args( ( int s, int level, int optname, void *optval,
			    int optlen ) );
int	socket		args( ( int domain, int type, int protocol ) );
#endif

#if	defined(apollo)
#include <unistd.h>
void	bzero		args( ( char *b, int length ) );
#endif

#if	defined(__hpux)
int	accept		args( ( int s, void *addr, int *addrlen ) );
int	bind		args( ( int s, const void *addr, int addrlen ) );
void	bzero		args( ( char *b, int length ) );
int	getpeername	args( ( int s, void *addr, int *addrlen ) );
int	getsockname	args( ( int s, void *name, int *addrlen ) );
int	gettimeofday	args( ( struct timeval *tp, struct timezone *tzp ) );
int	listen		args( ( int s, int backlog ) );
int	setsockopt	args( ( int s, int level, int optname,
 				const void *optval, int optlen ) );
int	socket		args( ( int domain, int type, int protocol ) );
#endif

#if	defined(interactive)
#include <net/errno.h>
#include <sys/fcntl.h>
#endif

#if	defined(linux)
/* mercpoint: commented out to enable compiling
int	accept		args( ( int s, struct sockaddr *addr, int *addrlen ) );
int	bind		args( ( int s, struct sockaddr *name, int namelen ) );
*/
int	close		args( ( int fd ) );
//int	getpeername	args( ( int s, struct sockaddr *name, int *namelen ) );
//int	getsockname	args( ( int s, struct sockaddr *name, int *namelen ) );
int	gettimeofday	args( ( struct timeval *tp, struct timezone *tzp ) );
//int	listen		args( ( int s, int backlog ) );
/* kavirpoint: put this in for nin site.
int	read		args( ( int fd, char *buf, int nbyte ) );
*/
int	select		args( ( int width, fd_set *readfds, fd_set *writefds,
			    fd_set *exceptfds, struct timeval *timeout ) );
int	socket		args( ( int domain, int type, int protocol ) );
/* kavirpoint: put this in for nin site.
int	write		args( ( int fd, char *buf, int nbyte ) );
*/
#endif

#if	defined(macintosh)
#include <console.h>
#include <fcntl.h>
#include <unix.h>
struct	timeval
{
	time_t	tv_sec;
	time_t	tv_usec;
};
#if	!defined(isascii)
#define	isascii(c)		( (c) < 0200 )
#endif
static	long			theKeys	[4];

int	gettimeofday		args( ( struct timeval *tp, void *tzp ) );
#endif

#if	defined(MIPS_OS)
extern	int		errno;
#endif

#if	defined(MSDOS)
int	gettimeofday	args( ( struct timeval *tp, void *tzp ) );
int	kbhit		args( ( void ) );
#endif

#if	defined(NeXT)
int	close		args( ( int fd ) );
int	fcntl		args( ( int fd, int cmd, int arg ) );
#if	!defined(htons)
u_short	htons		args( ( u_short hostshort ) );
#endif
#if	!defined(ntohl)
u_long	ntohl		args( ( u_long hostlong ) );
#endif
int	read		args( ( int fd, char *buf, int nbyte ) );
int	select		args( ( int width, fd_set *readfds, fd_set *writefds,
			    fd_set *exceptfds, struct timeval *timeout ) );
int	write		args( ( int fd, char *buf, int nbyte ) );
#endif

#if	defined(sequent)
int	accept		args( ( int s, struct sockaddr *addr, int *addrlen ) );
int	bind		args( ( int s, struct sockaddr *name, int namelen ) );
int	close		args( ( int fd ) );
int	fcntl		args( ( int fd, int cmd, int arg ) );
int	getpeername	args( ( int s, struct sockaddr *name, int *namelen ) );
int	getsockname	args( ( int s, struct sockaddr *name, int *namelen ) );
int	gettimeofday	args( ( struct timeval *tp, struct timezone *tzp ) );
#if	!defined(htons)
u_short	htons		args( ( u_short hostshort ) );
#endif
int	listen		args( ( int s, int backlog ) );
#if	!defined(ntohl)
u_long	ntohl		args( ( u_long hostlong ) );
#endif
int	read		args( ( int fd, char *buf, int nbyte ) );
int	select		args( ( int width, fd_set *readfds, fd_set *writefds,
			    fd_set *exceptfds, struct timeval *timeout ) );
int	setsockopt	args( ( int s, int level, int optname, caddr_t optval,
			    int optlen ) );
int	socket		args( ( int domain, int type, int protocol ) );
int	write		args( ( int fd, char *buf, int nbyte ) );
#endif

/*
 * This includes Solaris SYSV as well.
 */
#if defined(sun)
int	accept		args( ( int s, struct sockaddr *addr, int *addrlen ) );
int	bind		args( ( int s, struct sockaddr *name, int namelen ) );
void	bzero		args( ( char *b, int length ) );
int	close		args( ( int fd ) );
int	getpeername	args( ( int s, struct sockaddr *name, int *namelen ) );
int	getsockname	args( ( int s, struct sockaddr *name, int *namelen ) );
int	gettimeofday	args( ( struct timeval *tp, struct timezone *tzp ) );
int	listen		args( ( int s, int backlog ) );
int	read		args( ( int fd, char *buf, int nbyte ) );
int	select		args( ( int width, fd_set *readfds, fd_set *writefds,
			    fd_set *exceptfds, struct timeval *timeout ) );
#if defined(SYSV)
int	setsockopt	args( ( int s, int level, int optname, 
                            const char *optval, int optlen ) );
#else 
int	setsockopt	args( ( int s, int level, int optname, void *optval,
			    int optlen ) );
#endif
int	socket		args( ( int domain, int type, int protocol ) );
int	write		args( ( int fd, char *buf, int nbyte ) );
#endif

#if defined(ultrix)
int	accept		args( ( int s, struct sockaddr *addr, int *addrlen ) );
int	bind		args( ( int s, struct sockaddr *name, int namelen ) );
void	bzero		args( ( char *b, int length ) );
int	close		args( ( int fd ) );
int	getpeername	args( ( int s, struct sockaddr *name, int *namelen ) );
int	getsockname	args( ( int s, struct sockaddr *name, int *namelen ) );
int	gettimeofday	args( ( struct timeval *tp, struct timezone *tzp ) );
int	listen		args( ( int s, int backlog ) );
int	read		args( ( int fd, char *buf, int nbyte ) );
int	select		args( ( int width, fd_set *readfds, fd_set *writefds,
			    fd_set *exceptfds, struct timeval *timeout ) );
int	setsockopt	args( ( int s, int level, int optname, void *optval,
			    int optlen ) );
int	socket		args( ( int domain, int type, int protocol ) );
int	write		args( ( int fd, char *buf, int nbyte ) );
#endif



/*
 * Global variables.
 */
DESCRIPTOR_DATA *   descriptor_free;	/* Free list for descriptors	*/
DESCRIPTOR_DATA *   descriptor_list;	/* All open descriptors		*/
DESCRIPTOR_DATA *   d_next;		/* Next descriptor in loop	*/
FILE *		    fpReserve;		/* Reserved file handle		*/
bool		    god;		/* All new chars are gods!	*/
bool		    merc_down;		/* Shutdown			*/
bool		    wizlock;		/* Game is wizlocked		*/
char		    str_boot_time[MAX_INPUT_LENGTH];
char		    crypt_pwd[MAX_INPUT_LENGTH];
time_t		    current_time;	/* Time of this pulse		*/
int		    arena;
/* Colour scale char list - Calamar */

char *scale[SCALE_COLS] = {
	L_RED,
	L_BLUE,
	L_GREEN,
	YELLOW
};

/*
 * OS-dependent local functions.
 */
#if defined(macintosh) || defined(MSDOS)
void	game_loop_mac_msdos	args( ( void ) );
bool	read_from_descriptor	args( ( DESCRIPTOR_DATA *d ) );
bool	write_to_descriptor	args( ( int desc, char *txt, int length ) );
#endif

#if defined(unix)
void	game_loop_unix		args( ( int control ) );
int	init_socket		args( ( int port ) );
void	new_descriptor		args( ( int control ) );
bool	read_from_descriptor	args( ( DESCRIPTOR_DATA *d ) );
bool	write_to_descriptor	args( ( int desc, char *txt, int length ) );
#endif




/*
 * Other local functions (OS-independent).
 */
bool	check_reconnect		args( ( DESCRIPTOR_DATA *d, char *name,
				    bool fConn ) );
bool	check_kickoff		args( ( DESCRIPTOR_DATA *d, char *name,
				    bool fConn ) );
bool	check_playing		args( ( DESCRIPTOR_DATA *d, char *name ) );
int	main			args( ( int argc, char **argv ) );
void	nanny			args( ( DESCRIPTOR_DATA *d, char *argument ) );
bool	process_output		args( ( DESCRIPTOR_DATA *d, bool fPrompt ) );
void	read_from_buffer	args( ( DESCRIPTOR_DATA *d ) );
void	stop_idling		args( ( CHAR_DATA *ch ) );
void	bust_a_prompt		args( ( DESCRIPTOR_DATA *d ) );
void     bust_a_header          args((DESCRIPTOR_DATA *d));

int main( int argc, char **argv )
{
    struct timeval now_time;
    int port;

#if defined(unix)
    int control;
#endif

    /*
     * Memory debugging if needed.
     */
#if defined(MALLOC_DEBUG)
    malloc_debug( 2 );
#endif

#ifdef RLIMIT_NOFILE
#ifndef min
# define min(a,b)     (((a) < (b)) ? (a) : (b))
#endif
        { 
        struct  rlimit rlp;
        (void)getrlimit(RLIMIT_NOFILE, &rlp);
        rlp.rlim_cur=min(rlp.rlim_max,FD_SETSIZE);
        (void)setrlimit(RLIMIT_NOFILE, &rlp);
	}
#endif

    /*
     * Init time and encryption.
     */
    gettimeofday( &now_time, NULL );
    current_time = (time_t) now_time.tv_sec;
    strcpy( str_boot_time, ctime( &current_time ) );
    strcpy( crypt_pwd, "Don't bother." );

    /*
     * Macintosh console initialization.
     */
#if defined(macintosh)
    console_options.nrows = 31;
    cshow( stdout );
    csetmode( C_RAW, stdin );
    cecho2file( "log file", 1, stderr );
#endif

    /*
     * Reserve one channel for our use.
     */
    if ( ( fpReserve = fopen( NULL_FILE, "r" ) ) == NULL )
    {
	perror( NULL_FILE );
	exit( 1 );
    }

    /*
     * Get the port number.
     */
    port = 4678;
    if ( argc > 1 )
    {
	if ( !is_number( argv[1] ) )
	{
	    fprintf( stderr, "Usage: %s [port #]\n", argv[0] );
	    exit( 1 );
	}
	else if ( ( port = atoi( argv[1] ) ) <= 1024 )
	{
	    fprintf( stderr, "Port number must be above 1024.\n" );
	    exit( 1 );
	}
    }

    /*
     * Run the game.
     */
#if defined(macintosh) || defined(MSDOS)
    boot_db( );
    log_string( "Lords of War is ready to rock." );
    game_loop_mac_msdos( );
#endif

#if defined(unix)
    control = init_socket( port );
    boot_db( );
    arena = FIGHT_OPEN;
    sprintf( log_buf, "Lords of War is ready to rock on port %d.", port );
    log_string( log_buf );
    game_loop_unix( control );
    close( control );
#endif

    /*
     * That's all, folks.
     */
    log_string( "Normal termination of game." );
    exit( 0 );
    return 0;
}



#if defined(unix)
int init_socket( int port )
{
    static struct sockaddr_in sa_zero;
    struct sockaddr_in sa;
    int x;
    int fd;

    if ( ( fd = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 )
    {
	perror( "Init_socket: socket" );
	exit( 1 );
    }

    if ( setsockopt( fd, SOL_SOCKET, SO_REUSEADDR,
    (char *) &x, sizeof(x) ) < 0 )
    {
	perror( "Init_socket: SO_REUSEADDR" );
	close( fd );
	exit( 1 );
    }

#if defined(SO_DONTLINGER) && !defined(SYSV)
    {
	struct	linger	ld;

	ld.l_onoff  = 1;
	ld.l_linger = 1000;

	if ( setsockopt( fd, SOL_SOCKET, SO_DONTLINGER,
	(char *) &ld, sizeof(ld) ) < 0 )
	{
	    perror( "Init_socket: SO_DONTLINGER" );
	    close( fd );
	    exit( 1 );
	}
    }
#endif

    sa		    = sa_zero;
    sa.sin_family   = AF_INET;
    sa.sin_port	    = htons( port );

    if ( bind( fd, (struct sockaddr *) &sa, sizeof(sa) ) < 0 )
    {
	perror( "Init_socket: bind" );
	close( fd );
	exit( 1 );
    }

    if ( listen( fd, 3 ) < 0 )
    {
	perror( "Init_socket: listen" );
	close( fd );
	exit( 1 );
    }

    return fd;
}
#endif



#if defined(macintosh) || defined(MSDOS)
void game_loop_mac_msdos( void )
{
    struct timeval last_time;
    struct timeval now_time;
    static DESCRIPTOR_DATA dcon;

    gettimeofday( &last_time, NULL );
    current_time = (time_t) last_time.tv_sec;

    /*
     * New_descriptor analogue.
     */
    dcon.descriptor	= 0;
    dcon.connected	= CON_GET_NAME;
    dcon.host		= str_dup( "localhost" );
    dcon.outsize	= 2000;
    dcon.outbuf		= alloc_mem( dcon.outsize );
    dcon.next		= descriptor_list;
    descriptor_list	= &dcon;

    /*
     * Send the greeting.
     */
    {
	extern char * help_greeting;
	if ( help_greeting[0] == '.' )
	    write_to_buffer( &dcon, help_greeting+1, 0 );
	else
	    write_to_buffer( &dcon, help_greeting  , 0 );
    }

    /* Main loop */
    while ( !merc_down )
    {
	DESCRIPTOR_DATA *d;

	/*
	 * Process input.
	 */
	for ( d = descriptor_list; d != NULL; d = d_next )
	{
	    d_next	= d->next;
	    d->fcommand	= FALSE;

#if defined(MSDOS)
	    if ( kbhit( ) )
#endif
	    {
		if ( d->character != NULL )
		    d->character->timer = 0;
		if ( !read_from_descriptor( d ) )
		{
		    if ( d->character != NULL )
			save_char_obj( d->character );
		    d->outtop	= 0;
		    close_socket( d );
		    continue;
		}
	    }

	    if ( d->character != NULL && d->character->wait > 0 )
	    {
		--d->character->wait;
		continue;
	    }

	    read_from_buffer( d );
	    if ( d->incomm[0] != '\0' )
	    {
		d->fcommand	= TRUE;
		stop_idling( d->character );

                /* OLC */
                if ( d->showstr_point )
                    show_string( d, d->incomm );
                else
                if ( d->pString )
                    string_add( d->character, d->incomm );
                else
		switch( d->connected )
		{
	     	        default:
 			nanny( d, d->incomm );
			break;
		   case CON_PLAYING:
                        if ( !run_olc_editor( d ) )
                            interpret( d->character, d->incomm );
			break;
		   case CON_EDITING:
			edit_buffer( d->character, d->incomm );
			break;
		  }

		d->incomm[0]	= '\0';
	    }
	}



	/*
	 * Autonomous game motion.
	 */
	update_handler( );



	/*
	 * Output.
	 */
	for ( d = descriptor_list; d != NULL; d = d_next )
	{
	    d_next = d->next;

	    if ( ( d->fcommand || d->outtop > 0 ) )
	    {
		if ( !process_output( d, TRUE ) )
		{
		    if ( d->character != NULL )
			save_char_obj( d->character );
		    d->outtop	= 0;
		    close_socket( d );
		}
	    }
	}



	/*
	 * Synchronize to a clock.
	 * Busy wait (blargh).
	 */
	now_time = last_time;
	for ( ; ; )
	{
	    int delta;

#if defined(MSDOS)
	    if ( kbhit( ) )
#endif
	    {
		if ( dcon.character != NULL )
		    dcon.character->timer = 0;
		if ( !read_from_descriptor( &dcon ) )
		{
		    if ( dcon.character != NULL )
			save_char_obj( d->character );
		    dcon.outtop	= 0;
		    close_socket( &dcon );
		}
#if defined(MSDOS)
		break;
#endif
	    }

	    gettimeofday( &now_time, NULL );
	    delta = ( now_time.tv_sec  - last_time.tv_sec  ) * 1000 * 1000
		  + ( now_time.tv_usec - last_time.tv_usec );
	    if ( delta >= 1000000 / PULSE_PER_SECOND )
		break;
	}
	last_time    = now_time;
	current_time = (time_t) last_time.tv_sec;
    }

    return;
}
#endif



#if defined(unix)

void excessive_cpu(int blx)
{
    CHAR_DATA *vch;
    CHAR_DATA *vch_next;

    for ( vch = char_list; vch != NULL; vch = vch_next )
    {
	vch_next = vch->next;

	if ( !IS_NPC(vch) )
	{
	    send_to_char("Mud frozen: Autosave and quit.  The mud will reboot in 2 seconds.\n\r",vch);
	    interpret( vch, "quit" );
	}
    }
    exit(1);
}

void game_loop_unix( int control )
{
    static struct timeval null_time;
    struct timeval last_time;

    signal( SIGPIPE, SIG_IGN );
    gettimeofday( &last_time, NULL );
    current_time = (time_t) last_time.tv_sec;

    /* Main loop */
    while ( !merc_down )
    {
	fd_set in_set;
	fd_set out_set;
	fd_set exc_set;
	DESCRIPTOR_DATA *d;
	int maxdesc;

#if defined(MALLOC_DEBUG)
	if ( malloc_verify( ) != 1 )
	    abort( );
#endif

	/*
	 * Poll all active descriptors.
	 */
	FD_ZERO( &in_set  );
	FD_ZERO( &out_set );
	FD_ZERO( &exc_set );
	FD_SET( control, &in_set );
	maxdesc	= control;
/* kavirpoint
	maxdesc	= control * 2;
*/
	for ( d = descriptor_list; d != NULL; d = d->next )
	{
	    maxdesc = UMAX( maxdesc, d->descriptor );
	    FD_SET( d->descriptor, &in_set  );
	    FD_SET( d->descriptor, &out_set );
	    FD_SET( d->descriptor, &exc_set );
	}

	if ( select( maxdesc+1, &in_set, &out_set, &exc_set, &null_time ) < 0 )
	{
	    perror( "Game_loop: select: poll" );
	    exit( 1 );
	}

	/*
	 * New connection?
	 */
	if ( FD_ISSET( control, &in_set ) )
	    new_descriptor( control );

	/*
	 * Kick out the freaky folks.
	 */
	for ( d = descriptor_list; d != NULL; d = d_next )
	{
	    d_next = d->next;   
	    if ( FD_ISSET( d->descriptor, &exc_set ) )
	    {
		FD_CLR( d->descriptor, &in_set  );
		FD_CLR( d->descriptor, &out_set );
		if ( d->character )
		    save_char_obj( d->character );
		d->outtop	= 0;
		close_socket( d );
	    }
	}

	/*
	 * Process input.
	 */
	for ( d = descriptor_list; d != NULL; d = d_next )
	{
	    d_next	= d->next;
	    d->fcommand	= FALSE;

	    if ( FD_ISSET( d->descriptor, &in_set ) )
	    {
		if ( d->character != NULL )
		    d->character->timer = 0;
		if ( !read_from_descriptor( d ) )
		{
		    FD_CLR( d->descriptor, &out_set );
		    if ( d->character != NULL )
			save_char_obj( d->character );
		    d->outtop	= 0;
		    close_socket( d );
		    continue;
		}
	    }

	    if ( d->character != NULL && d->character->wait > 0 )
	    {
		--d->character->wait;
		continue;
	    }

	    read_from_buffer( d );
	    if ( d->incomm[0] != '\0' )
	    {
		d->fcommand	= TRUE;
		stop_idling( d->character );

                /* OLC */
                if ( d->showstr_point )
                    show_string( d, d->incomm );
                else
                if ( d->pString )
                    string_add( d->character, d->incomm );
                else 
		switch( d->connected )
			  {
			   default:
 				nanny( d, d->incomm );
				break;
			   case CON_PLAYING:
                        if ( !run_olc_editor( d ) )
				interpret( d->character, d->incomm );
				break;
			   case CON_EDITING:
				edit_buffer( d->character, d->incomm );
				break;
			  }

		d->incomm[0]	= '\0';
	    }
	}



	/*
	 * Autonomous game motion.
	 */
	update_handler( );



	/*
	 * Output.
	 */
	for ( d = descriptor_list; d != NULL; d = d_next )
	{
	    d_next = d->next;

	    if ( ( d->fcommand || d->outtop > 0 )
	    &&   FD_ISSET(d->descriptor, &out_set) )
	    {
		if ( !process_output( d, TRUE ) )
		{
		    if ( d->character != NULL )
			save_char_obj( d->character );
		    d->outtop	= 0;
		    close_socket( d );
		}
	    }
	}



	/*
	 * Synchronize to a clock.
	 * Sleep( last_time + 1/PULSE_PER_SECOND - now ).
	 * Careful here of signed versus unsigned arithmetic.
	 */
	{
	    struct timeval now_time;
	    long secDelta;
	    long usecDelta;

	    gettimeofday( &now_time, NULL );
	    usecDelta	= ((int) last_time.tv_usec) - ((int) now_time.tv_usec)
			+ 1000000 / PULSE_PER_SECOND;
	    secDelta	= ((int) last_time.tv_sec ) - ((int) now_time.tv_sec );
	    while ( usecDelta < 0 )
	    {
		usecDelta += 1000000;
		secDelta  -= 1;
	    }

	    while ( usecDelta >= 1000000 )
	    {
		usecDelta -= 1000000;
		secDelta  += 1;
	    }

	    if ( secDelta > 0 || ( secDelta == 0 && usecDelta > 0 ) )
	    {
		struct timeval stall_time;

		stall_time.tv_usec = usecDelta;
		stall_time.tv_sec  = secDelta;
		if ( select( 0, NULL, NULL, NULL, &stall_time ) < 0 )
		{
		    perror( "Game_loop: select: stall" );
		    exit( 1 );
		}
	    }
	}

	gettimeofday( &last_time, NULL );
	current_time = (time_t) last_time.tv_sec;
    }

    return;
}
#endif



#if defined(unix)
void new_descriptor( int control )
{
    static DESCRIPTOR_DATA d_zero;
    char buf[MAX_STRING_LENGTH];
    DESCRIPTOR_DATA *dnew;
    BAN_DATA *pban;
    struct sockaddr_in sock;
    struct hostent *from;
    int desc;
    int size;


    size = sizeof(sock);
    getsockname( control, (struct sockaddr *) &sock, &size );
    if ( ( desc = accept( control, (struct sockaddr *) &sock, &size) ) < 0 )
    {
	perror( "New_descriptor: accept" );
	return;
    }

#if !defined(FNDELAY)
#define FNDELAY O_NDELAY
#endif

    if ( fcntl( desc, F_SETFL, FNDELAY ) == -1 )
    {
	perror( "New_descriptor: fcntl: FNDELAY" );
	return;
    }

    /*
     * Cons a new descriptor.
     */
    if ( descriptor_free == NULL )
    {
	dnew		= alloc_perm( sizeof(*dnew) );
    }
    else
    {
	dnew		= descriptor_free;
	descriptor_free	= descriptor_free->next;
    }

    *dnew		= d_zero;
    dnew->descriptor	= desc;
    dnew->connected	= CON_GET_NAME;
    dnew->outsize	= 2000;
    dnew->outbuf	= alloc_mem( dnew->outsize );
    dnew->pEdit         = NULL;                 /* OLC */
    dnew->pString       = NULL;                 /* OLC */
    dnew->editor        = 0;                    /* OLC */

    size = sizeof(sock);
    if ( getpeername( desc, (struct sockaddr *) &sock, &size ) < 0 )
    {
	perror( "New_descriptor: getpeername" );
	dnew->host = str_dup( "(unknown)" );
    }
    else
    {
	/*
	 * Would be nice to use inet_ntoa here but it takes a struct arg,
	 * which ain't very compatible between gcc and system libraries.
	 */
	int addr;

	addr = ntohl( sock.sin_addr.s_addr );
	sprintf( buf, "%d.%d.%d.%d",
	    ( addr >> 24 ) & 0xFF, ( addr >> 16 ) & 0xFF,
	    ( addr >>  8 ) & 0xFF, ( addr       ) & 0xFF
	    );
	sprintf( log_buf, "Sock.sinaddr:  %s", buf );
	log_string( log_buf );
	from = gethostbyaddr( (char *) &sock.sin_addr,
	    sizeof(sock.sin_addr), AF_INET );
	dnew->host = str_dup( from ? from->h_name : buf );
    }
	
    /*
     * Swiftest: I added the following to ban sites.  I don't
     * endorse banning of sites, but Copper has few descriptors now
     * and some people from certain sites keep abusing access by
     * using automated 'autodialers' and leaving connections hanging.
     *
     * Furey: added suffix check by request of Nickel of HiddenWorlds.
     */
    for ( pban = ban_list; pban != NULL; pban = pban->next )
    {
	if ( !str_suffix( pban->name, dnew->host ) )
	{
	    write_to_descriptor( desc,
		"Your site has been banned from this Mud.\n\r", 0 );
	    close( desc );
	    free_string( dnew->host );
	    free_mem( dnew->outbuf, dnew->outsize );
	    dnew->next		= descriptor_free;
	    descriptor_free	= dnew;
	    return;
	}
    }

/*    
        if ( !str_suffix( "chico.cmc.net", dnew->host)
        || !str_suffix( "rg.anc.net", dnew->host)
          || !str_suffix( "sfpl.lib.ca.us", dnew->host)
	  || !str_suffix( "AKCACHE.COM",dnew->host)
	  || !str_suffix( "clpgh.org", dnew->host))
	{
            write_to_descriptor( desc,
                "Your site has been banned from this Mud.\n\r", 0 );
            close( desc );
            free_string( dnew->host );
            free_mem( dnew->outbuf, dnew->outsize );
            dnew->next          = descriptor_free;
            descriptor_free     = dnew;
            return;
        }
*/

    /*
     * Init descriptor data.
     */
    dnew->next			= descriptor_list;
    descriptor_list		= dnew;

    /*
     * Send the greeting.
     */
    {
	extern char * help_greeting;
	if ( help_greeting[0] == '.' )
	    write_to_buffer( dnew, help_greeting+1, 0 );
	else
	    write_to_buffer( dnew, help_greeting  , 0 );
    }

    return;
}
#endif



void close_socket( DESCRIPTOR_DATA *dclose )
{
    CHAR_DATA *ch;

    if ( dclose->outtop > 0 )
	process_output( dclose, FALSE );

    if ( dclose->snoop_by != NULL )
    {
	write_to_buffer( dclose->snoop_by,
	    "Your victim has left the game.\n\r", 0 );
    }

    if ( dclose->character != NULL && 
	(dclose->connected == CON_PLAYING || dclose->connected == CON_EDITING) &&
	IS_NPC(dclose->character) ) do_return(dclose->character,"");
/*
    if ( dclose->character != NULL 
	&& dclose->connected == CON_PLAYING
	&& !IS_NPC(dclose->character)
	&& dclose->character->pcdata != NULL
	&& dclose->character->pcdata->obj_vnum != 0
	&& dclose->character->pcdata->chobj != NULL)
	    extract_obj(dclose->character->pcdata->chobj);
*/
    {
	DESCRIPTOR_DATA *d;

	for ( d = descriptor_list; d != NULL; d = d->next )
	{
	    if ( d->snoop_by == dclose )
		d->snoop_by = NULL;
	}
    }

    if ( ( ch = dclose->character ) != NULL )
    {
	sprintf( log_buf, "Closing link to %s.", ch->name );
	log_string( log_buf );
 	/* If ch is writing note or playing, just lose link otherwise clear char */
 	if ( (dclose->connected == CON_PLAYING) || 
 	  ((dclose->connected >= CON_NOTE_TO) && 
 	   (dclose->connected <= CON_NOTE_FINISH)))
	{
	    if (IS_NPC(ch) || ch->pcdata->obj_vnum == 0)
	    	act( "$n has lost $s link.", ch, NULL, NULL, TO_ROOM );
	            if ( IS_SET(ch->act,PLR_CHALLENGED) && arena == FIGHT_START )
               do_decline(ch,ch->challenger->name);
            if ( IS_SET(ch->act,PLR_CHALLENGER) && arena == FIGHT_START )
            {
               char buf[MAX_STRING_LENGTH];

               REMOVE_BIT(ch->act,PLR_CHALLENGER);
               REMOVE_BIT(ch->challenged->act,PLR_CHALLENGED);
               ch->challenged->challenger = NULL;
               ch->challenged = NULL;
               arena = FIGHT_OPEN;
     sprintf(buf, "[Arena] %s has lost $s link. Arena is OPEN.", ch->name);
 {
 DESCRIPTOR_DATA *d;
 for ( d = descriptor_list; d; d = d->next )
  
     if( d->connected == CON_PLAYING || d->connected == CON_EDITING)
     {
        send_to_char( buf, d->character );
     }
  }
            }
	    ch->desc = NULL;
	}
	else
	{
	    free_char( dclose->character );
	}
    }

    if ( d_next == dclose )
	d_next = d_next->next;   

    if ( dclose == descriptor_list )
    {
	descriptor_list = descriptor_list->next;
    }
    else
    {
	DESCRIPTOR_DATA *d;

	for ( d = descriptor_list; d && d->next != dclose; d = d->next )
	    ;
	if ( d != NULL )
	    d->next = dclose->next;
	else
	    bug( "Close_socket: dclose not found.", 0 );
    }

    close( dclose->descriptor );
    free_string( dclose->host );

    /* RT socket leak fix */
    free_mem( dclose->outbuf, dclose->outsize );

    dclose->next	= descriptor_free;
    descriptor_free	= dclose;
#if defined(MSDOS) || defined(macintosh)
    exit(1);
#endif
    return;
}

/* For a better kickoff message :) KaVir */
void close_socket2( DESCRIPTOR_DATA *dclose, bool kickoff )
{
    CHAR_DATA *ch;

    if ( dclose->outtop > 0 )
	process_output( dclose, FALSE );

    if ( dclose->snoop_by != NULL )
    {
	write_to_buffer( dclose->snoop_by,
	    "Your victim has left the game.\n\r", 0 );
    }

    if ( dclose->character != NULL && 
       (dclose->connected == CON_PLAYING || dclose->connected == CON_EDITING )&&
	IS_NPC(dclose->character) ) do_return(dclose->character,"");
/*
    if ( dclose->character != NULL 
	&& ( dclose->connected == CON_PLAYING || dclose->connected == CON_EDITING)
	&& !IS_NPC(dclose->character)
	&& dclose->character->pcdata != NULL
	&& dclose->character->pcdata->obj_vnum != 0
	&& dclose->character->pcdata->chobj != NULL)
	    extract_obj(dclose->character->pcdata->chobj);
*/
    {
	DESCRIPTOR_DATA *d;

	for ( d = descriptor_list; d != NULL; d = d->next )
	{
	    if ( d->snoop_by == dclose )
		d->snoop_by = NULL;
	}
    }

    if ( ( ch = dclose->character ) != NULL )
    {
	if ( dclose->connected == CON_PLAYING
		|| dclose->connected == CON_EDITING )
	{
	    if (kickoff)
		act( "$n doubles over in agony and $s eyes roll up into $s head.", ch, NULL, NULL, TO_ROOM );
 	    save_char_obj( ch );
	    ch->desc = NULL;
	}
	else
	{
	    free_char( dclose->character );
	}
    }

    if ( d_next == dclose )
	d_next = d_next->next;   

    if ( dclose == descriptor_list )
    {
	descriptor_list = descriptor_list->next;
    }
    else
    {
	DESCRIPTOR_DATA *d;

	for ( d = descriptor_list; d && d->next != dclose; d = d->next )
	    ;
	if ( d != NULL )
	    d->next = dclose->next;
	else
	    bug( "Close_socket: dclose not found.", 0 );
    }
    close( dclose->descriptor );
    free_string( dclose->host );
    dclose->next	= descriptor_free;
    descriptor_free	= dclose;
#if defined(MSDOS) || defined(macintosh)
    exit(1);
#endif
    return;
}



bool read_from_descriptor( DESCRIPTOR_DATA *d )
{
    int iStart;

    /* Hold horses if pending command already. */
    if ( d->incomm[0] != '\0' )
	return TRUE;

    /* Check for overflow. */
    iStart = strlen(d->inbuf);
    if ( iStart >= sizeof(d->inbuf) - 10 )
    {
	if (d != NULL && d->character != NULL)
	    sprintf( log_buf, "%s input overflow!", d->character->lasthost );
	else
	    sprintf( log_buf, "%s input overflow!", d->host );
	log_string( log_buf );

	write_to_descriptor( d->descriptor,
	    "\n\r*** PUT A LID ON IT!!! ***\n\r", 0 );
	return FALSE;
    }

    /* Snarf input. */
#if defined(macintosh)
    for ( ; ; )
    {
	int c;
	c = getc( stdin );
	if ( c == '\0' || c == EOF )
	    break;
	putc( c, stdout );
	if ( c == '\r' )
	    putc( '\n', stdout );
	d->inbuf[iStart++] = c;
	if ( iStart > sizeof(d->inbuf) - 10 )
	    break;
    }
#endif

#if defined(MSDOS) || defined(unix)
    for ( ; ; )
    {
	int nRead;

	nRead = read( d->descriptor, d->inbuf + iStart,
	    sizeof(d->inbuf) - 10 - iStart );
	if ( nRead > 0 )
	{
	    iStart += nRead;
	    if ( d->inbuf[iStart-1] == '\n' || d->inbuf[iStart-1] == '\r' )
		break;
	}
	else if ( nRead == 0 )
	{
	    log_string( "EOF encountered on read." );
	    return FALSE;
	}
	else if ( errno == EWOULDBLOCK )
	    break;
	else
	{
	    perror( "Read_from_descriptor" );
	    return FALSE;
	}
    }
#endif

    d->inbuf[iStart] = '\0';
    return TRUE;
}



/*
 * Transfer one line from input buffer to input line.
 */
void read_from_buffer( DESCRIPTOR_DATA *d )
{
    int i, j, k;

    /*
     * Hold horses if pending command already.
     */
    if ( d->incomm[0] != '\0' )
	return;

    /*
     * Look for at least one new line.
     */
    for ( i = 0; d->inbuf[i] != '\n' && d->inbuf[i] != '\r'; i++ )
    {
	if ( d->inbuf[i] == '\0' )
	    return;
    }

    /*
     * Canonical input processing.
     */
    for ( i = 0, k = 0; d->inbuf[i] != '\n' && d->inbuf[i] != '\r'; i++ )
    {
	if ( k >= MAX_INPUT_LENGTH - 2 )
	{
	    write_to_descriptor( d->descriptor, "Line too long.\n\r", 0 );

	    /* skip the rest of the line */
	    for ( ; d->inbuf[i] != '\0'; i++ )
	    {
		if ( d->inbuf[i] == '\n' || d->inbuf[i] == '\r' )
		    break;
	    }
	    d->inbuf[i]   = '\n';
	    d->inbuf[i+1] = '\0';
	    break;
	}

	if ( d->inbuf[i] == '\b' && k > 0 )
	    --k;
	else if ( isascii(d->inbuf[i]) && isprint(d->inbuf[i]) )
	    d->incomm[k++] = d->inbuf[i];
    }

    /*
     * Finish off the line.
     */
    if ( k == 0 )
	d->incomm[k++] = ' ';
    d->incomm[k] = '\0';

    /*
     * Deal with bozos with #repeat 1000 ...
     */
    if ( k > 1 || d->incomm[0] == '!' )
    {
    	if ( d->incomm[0] != '!' && strcmp( d->incomm, d->inlast ) )
	{
	    d->repeat = 0;
	}
	else
	{
	    if ( ++d->repeat >= 40 )
	    {
		if (d != NULL && d->character != NULL)
		    sprintf( log_buf, "%s input spamming!", d->character->lasthost );
		else
		    sprintf( log_buf, "%s input spamming!", d->host );
		log_string( log_buf );
		write_to_descriptor( d->descriptor,
		    "\n\r*** PUT A LID ON IT!!! ***\n\r", 0 );
		strcpy( d->incomm, "quit" );
	    }
	}
    }

    /*
     * Do '!' substitution.
     */
    if ( d->incomm[0] == '!' )
	strcpy( d->incomm, d->inlast );
    else
	strcpy( d->inlast, d->incomm );

    /*
     * Shift the input buffer.
     */
    while ( d->inbuf[i] == '\n' || d->inbuf[i] == '\r' )
	i++;
    for ( j = 0; ( d->inbuf[j] = d->inbuf[i+j] ) != '\0'; j++ )
	;
    return;
}



/*
 * Low level output function.
 */
/*
bool process_output( DESCRIPTOR_DATA *d, bool fPrompt )
{
    extern bool merc_down;

    if ( fPrompt && !merc_down && d->connected == CON_PLAYING )
        if ( d->showstr_point )
            write_to_buffer( d,
  "[Please type (c)ontinue, (r)efresh, (b)ack, (h)elp, (q)uit, or RETURN]:  ",
                            0 );
        else
        if ( d->pString )
            write_to_buffer( d, "> ", 2 );
        else
 
{
	CHAR_DATA *ch;

	ch = d->original ? d->original : d->character;
	if ( IS_SET(ch->act, PLR_BLANK) )
	    write_to_buffer( d, "\n\r", 2 );

		
           
	if (IS_SET(ch->act, PLR_PROMPT) && IS_EXTRA(ch, EXTRA_PROMPT))
	    bust_a_prompt( d );
	else if ( IS_SET(ch->act, PLR_PROMPT) )
	{
	    char buf[MAX_STRING_LENGTH];
	    char cond[MAX_INPUT_LENGTH];
	    char hit_str[MAX_INPUT_LENGTH];
	    char mana_str[MAX_INPUT_LENGTH];
	    char move_str[MAX_INPUT_LENGTH];
	    char exp_str[MAX_INPUT_LENGTH];
	    int per;

	    ch = d->character;
	    if (IS_HEAD(ch,LOST_HEAD) || IS_EXTRA(ch,EXTRA_OSWITCH))
	    {
		sprintf(exp_str, "%d", ch->exp);
		COL_SCALE(exp_str, ch, ch->exp, 1000);

	        sprintf( buf, "<[%sX] [?H ?M ?V]> ",exp_str );
	    }
	    else if (ch->position == POS_FIGHTING)
	    {

	      victim = ch->fighting;
		if ((victim->hit*100/victim->max_hit) < 25)
		{
		    strcpy(cond, "Awful");
		    ADD_COLOUR(ch, cond, L_RED);
		}
		else if ((victim->hit*100/victim->max_hit) < 50)
		{
		    strcpy(cond, "Poor");
		    ADD_COLOUR(ch, cond, L_BLUE);
		}
		else if ((victim->hit*100/victim->max_hit) < 75)
		{
		    strcpy(cond, "Fair");
		    ADD_COLOUR(ch, cond, L_GREEN);
		}
		else if ((victim->hit*100/victim->max_hit) < 100)
		{
		    strcpy(cond, "Good");
		    ADD_COLOUR(ch, cond, YELLOW);
		}
		else if ((victim->hit*100/victim->max_hit) >= 100)
		{
		    strcpy(cond, "Perfect");
		    ADD_COLOUR(ch, cond, L_CYAN);
		}
		sprintf(hit_str, "%d", ch->hit);
		COL_SCALE(hit_str, ch, ch->hit, ch->max_hit);
		sprintf(mana_str, "%d", ch->mana);
		COL_SCALE(mana_str, ch, ch->mana, ch->max_mana);
		sprintf(move_str, "%d", ch->move);
		COL_SCALE(move_str, ch, ch->move, ch->max_move);
		sprintf( buf, "<%s [%sH %sM %sV]> ", cond, hit_str, mana_str, move_str );
	    }
	    else
	    {
		sprintf(hit_str, "%d", ch->hit);
		COL_SCALE(hit_str, ch, ch->hit, ch->max_hit);
		sprintf(mana_str, "%d", ch->mana);
		COL_SCALE(mana_str, ch, ch->mana, ch->max_mana);
		sprintf(move_str, "%d", ch->move);
		COL_SCALE(move_str, ch, ch->move, ch->max_move);
		sprintf(exp_str, "%d", ch->exp);
		COL_SCALE(exp_str, ch, ch->exp, 1000);
	        sprintf( buf, "<[%s] [%sH %sM %sV]> ",exp_str, hit_str, mana_str, move_str );
	    }
	    write_to_buffer( d, buf, 0 );
	}

	if ( IS_SET(ch->act, PLR_TELNET_GA) )
	    write_to_buffer( d, go_ahead_str, 0 );
    }

    if ( d->outtop == 0 )
	return TRUE;

    if ( d->snoop_by != NULL )
    {
	write_to_buffer( d->snoop_by, "% ", 2 );
	write_to_buffer( d->snoop_by, d->outbuf, d->outtop );
    }

    if ( !write_to_descriptor( d->descriptor, d->outbuf, d->outtop ) )
    {
	d->outtop = 0;
	return FALSE;
    }
    else
    {
	d->outtop = 0;
	return TRUE;
    }

}
*/

bool process_output( DESCRIPTOR_DATA *d, bool fPrompt )
{
    extern bool merc_down;

    /*
     * Bust a prompt.
     */
    if ( fPrompt && !merc_down && d->connected == CON_PLAYING )
    {
	CHAR_DATA *ch;
	CHAR_DATA *victim;

	ch = d->original ? d->original : d->character;
	if ( IS_SET(ch->act, PLR_BLANK) )
	    write_to_buffer( d, "\n\r", 2 );

	if (IS_SET(ch->act, PLR_PROMPT) && IS_EXTRA(ch, EXTRA_PROMPT))
	    bust_a_prompt( d );
	else if ( IS_SET(ch->act, PLR_PROMPT) )
	{
	    char buf[MAX_STRING_LENGTH];
	    char cond[MAX_INPUT_LENGTH];
	    char hit_str[MAX_INPUT_LENGTH];
	    char mana_str[MAX_INPUT_LENGTH];
	    char move_str[MAX_INPUT_LENGTH];
	    char exp_str[MAX_INPUT_LENGTH];

	    ch = d->character;
	    if (IS_HEAD(ch,LOST_HEAD) || IS_EXTRA(ch,EXTRA_OSWITCH))
	    {
		sprintf(exp_str, "%d", ch->exp);
		COL_SCALE(exp_str, ch, ch->exp, 1000);
/*
	        sprintf( buf, "[%s exp] <?hp ?m ?mv> ",exp_str );
*/
	        sprintf( buf, "#7<[#4%sX#7] [#3?#1H #3?#6M #3?#2V#7]>#n
",exp_str );
	    }
	    else if (ch->position == POS_FIGHTING)
	    {
	        victim = ch->fighting;
		if ((victim->hit*100/victim->max_hit) < 25)
		{
		    strcpy(cond, "Awful");
		    ADD_COLOUR(ch, cond, L_RED);
		}
		else if ((victim->hit*100/victim->max_hit) < 50)
		{
		    strcpy(cond, "Poor");
		    ADD_COLOUR(ch, cond, L_BLUE);
		}
		else if ((victim->hit*100/victim->max_hit) < 75)
		{
		    strcpy(cond, "Fair");
		    ADD_COLOUR(ch, cond, L_GREEN);
		}
		else if ((victim->hit*100/victim->max_hit) < 100)
		{
		    strcpy(cond, "Good");
		    ADD_COLOUR(ch, cond, YELLOW);
		}
		else if ((victim->hit*100/victim->max_hit) >= 100)
		{
		    strcpy(cond, "Perfect");
		    ADD_COLOUR(ch, cond, L_CYAN);
		}
		sprintf(hit_str, "%d", ch->hit);
		COL_SCALE(hit_str, ch, ch->hit, ch->max_hit);
		sprintf(mana_str, "%d", ch->mana);
		COL_SCALE(mana_str, ch, ch->mana, ch->max_mana);
		sprintf(move_str, "%d", ch->move);
		COL_SCALE(move_str, ch, ch->move, ch->max_move);
/*
		sprintf( buf, "[%s] <%shp %sm %smv> ", cond, hit_str, mana_str, move_str );
*/
		sprintf( buf, "#7<[%s] [%sH %sM %sV]> ", cond,
hit_str, mana_str, move_str );
	    }
	    else
	    {
		sprintf(hit_str, "%d", ch->hit);
		COL_SCALE(hit_str, ch, ch->hit, ch->max_hit);
		sprintf(mana_str, "%d", ch->mana);
		COL_SCALE(mana_str, ch, ch->mana, ch->max_mana);
		sprintf(move_str, "%d", ch->move);
		COL_SCALE(move_str, ch, ch->move, ch->max_move);
		sprintf(exp_str, "%d", ch->exp);
		COL_SCALE(exp_str, ch, ch->exp, 1000);
/*
	        sprintf( buf, "[%s exp] <%shp %sm %smv> ",exp_str, hit_str, mana_str, move_str
);
	        sprintf( buf, "<[%sX] [%sH %sM %sV]> ",exp_str, hit_str, mana_str, move_str );
*/
	        sprintf( buf, "#7<[%s] [%sH %sM %sV]> ",exp_str, hit_str,
mana_str, move_str );
	    }
	    write_to_buffer( d, buf, 0 );
	}

	if ( IS_SET(ch->act, PLR_TELNET_GA) )
	    write_to_buffer( d, go_ahead_str, 0 );
    }

    /*
     * Short-circuit if nothing to write.
     */
    if ( d->outtop == 0 )
	return TRUE;

    /*
     * Snoop-o-rama.
     */
    if ( d->snoop_by != NULL )
    {
	write_to_buffer( d->snoop_by, "% ", 2 );
	write_to_buffer( d->snoop_by, d->outbuf, d->outtop );
    }

    /*
     * OS-dependent output.
     */
    if ( !write_to_descriptor( d->descriptor, d->outbuf, d->outtop ) )
    {
	d->outtop = 0;
	return FALSE;
    }
    else
    {
	d->outtop = 0;
	return TRUE;
    }
}


/*
 * Append onto an output buffer.
 */
void write_to_buffer( DESCRIPTOR_DATA *d, const char *txt, int length )
{
    char tb[MAX_STRING_LENGTH], ccode;
    int i,j;
    bool ansi, grfx = FALSE;

/*
    if (d != NULL && d->as != NULL) d = d->as;
*/

    /*
     * Find length in case caller didn't.
     */
    if ( length <= 0 )
	length = strlen(txt);

    if ( length >= MAX_STRING_LENGTH )
    {
	bug( "Write_to_buffer: Way too big. Closing.", 0 );
	return;
    }

    if (d->character == NULL ||
	(d->connected != CON_PLAYING && d->connected != CON_EDITING))
	ansi = FALSE;
    else ansi = (IS_SET(d->character->act, PLR_ANSI)) ? TRUE : FALSE;

    /*
     * Initial \n\r if needed.
     */
    if ( d->outtop == 0 && !d->fcommand )
    {
	d->outbuf[0]    = '\n';
	d->outbuf[1]    = '\r';
	d->outtop       = 2;
    }

    /*
     * Expand d->outbuf for ansi info
     */

    j = 0;
    ccode = '3';
    tb[0] = '\0';
    for (i = 0; i < length ; i++)
    {
	if (txt[i] == '\n')
	{
// added to fix stupid PC telnet incompatibility with the rest of the world
		    tb[j++] = 27; tb[j++] = '['; tb[j++] = '1'; tb[j++] = ';';
		    tb[j++] = ccode; tb[j++] = '7'; tb[j++] = 'm';
// end.
		    tb[j++] = 27; tb[j++] = '['; tb[j++] = '0'; tb[j++] = 'm';
	}
	if (txt[i] == '#' && txt[i+1] != 'I' && txt[i+1] != 'N')
	{
	    if (txt[++i] == 'B')
	    {
		ccode = '3';
		i++;
	    }
	    else ccode = '3';

	    switch (txt[i])
	    {
		default : break;
		case '#': tb[j++] = '#'; break;
		case '-': tb[j++] = '~'; break;
		case '+': tb[j++] = '%'; break;
		case 'I':
		case 'i': tb[j++] = 27; tb[j++] = '['; tb[j++] = '7';
			  tb[j++] = 'm'; break;
		case 'b': if (!ansi) continue;
/*		    tb[j++] = 27; tb[j++] = '['; tb[j++] = '5'; tb[j++] = 'm'; */
/* bold just selects colour white for now */
		    tb[j++] = 27; tb[j++] = '['; tb[j++] = '1'; tb[j++] = ';';
		    tb[j++] = '3'; tb[j++] = '7'; tb[j++] = 'm';
		    break;
		case 'G': if (!ansi) continue;
		    tb[j++] = 27; tb[j++]='('; tb[j++]='0'; grfx = TRUE;
		    break;
		case 'g': if (!ansi) continue;
		    tb[j++] = 27; tb[j++]='('; tb[j++]='B'; grfx = TRUE;
		    break;
		case 'N':
		case 'n':
// added to fix stupid PC telnet incompatibility with the rest of the world
		    tb[j++] = 27; tb[j++] = '['; tb[j++] = '1'; tb[j++] = ';';
		    tb[j++] = ccode; tb[j++] = '7'; tb[j++] = 'm';
// end.
		    tb[j++] = 27; tb[j++] = '['; tb[j++] = '0'; tb[j++] = 'm';
		    break;
		case '0': if (!ansi) continue;
		    tb[j++] = 27; tb[j++] = '['; tb[j++] = '1'; tb[j++] = ';';
		    tb[j++] = ccode; tb[j++] = '0'; tb[j++] = 'm';
		    break;
		case '1': if (!ansi) continue;
		    tb[j++] = 27; tb[j++] = '['; tb[j++] = '1'; tb[j++] = ';';
		    tb[j++] = ccode; tb[j++] = '1'; tb[j++] = 'm';
		    break;
		case '2': if (!ansi) continue;
		    tb[j++] = 27; tb[j++] = '['; tb[j++] = '1'; tb[j++] = ';';
		    tb[j++] = ccode; tb[j++] = '2'; tb[j++] = 'm';
		    break;
		case '3': if (!ansi) continue;
		    tb[j++] = 27; tb[j++] = '['; tb[j++] = '1'; tb[j++] = ';';
		    tb[j++] = ccode; tb[j++] = '3'; tb[j++] = 'm';
		    break;
		case '4': if (!ansi) continue;
		    tb[j++] = 27; tb[j++] = '['; tb[j++] = '1'; tb[j++] = ';';
		    tb[j++] = ccode; tb[j++] = '4'; tb[j++] = 'm';
		    break;
		case '5': if (!ansi) continue;
		    tb[j++] = 27; tb[j++] = '['; tb[j++] = '1'; tb[j++] = ';';
		    tb[j++] = ccode; tb[j++] = '5'; tb[j++] = 'm';
		    break;
		case '6': if (!ansi) continue;
		    tb[j++] = 27; tb[j++] = '['; tb[j++] = '1'; tb[j++] = ';';
		    tb[j++] = ccode; tb[j++] = '6'; tb[j++] = 'm';
		    break;
		case '7': if (!ansi) continue;
		    tb[j++] = 27; tb[j++] = '['; tb[j++] = '1'; tb[j++] = ';';
		    tb[j++] = ccode; tb[j++] = '7'; tb[j++] = 'm';
		    break;
	    }
	}
	else tb[j++] = txt[i];
    }

    {
    	tb[j++] = 27;
    	tb[j++] = '[';
    	tb[j++] = '0';
    	tb[j++] = 'm';
	if (grfx)
	{
		tb[j++] = 27;
		tb[j++]='('; 
		tb[j++]='B';
	}
    }
    tb[j]   = '\0';

    length = j;

    /*
     * Expand the buffer as needed.
     */
    while ( d->outtop + length >= d->outsize )
    {
	char *outbuf;

	if (d->outsize >= 32000)
	{
	    bug("Buffer overflow. Closing.\n\r",0);
	    close_socket(d);
	    return;
	}
	outbuf      = alloc_mem( 2 * d->outsize );
	strncpy( outbuf, d->outbuf, d->outtop );
	free_mem( d->outbuf, d->outsize );
	d->outbuf   = outbuf;
	d->outsize *= 2;
    }

    /*
     * Copy.
     */
    strncpy( d->outbuf + d->outtop, tb, length);
    d->outtop += length;
    return;
}



/*
 * Lowest level output function.
 * Write a block of text to the file descriptor.
 * If this gives errors on very long blocks (like 'ofind all'),
 *   try lowering the max block size.
 */
bool write_to_descriptor( int desc, char *txt, int length )
{
    int iStart;
    int nWrite;
    int nBlock;

#if defined(macintosh) || defined(MSDOS)
    if ( desc == 0 )
	desc = 1;
#endif

    if ( length <= 0 )
	length = strlen(txt);

    for ( iStart = 0; iStart < length; iStart += nWrite )
    {
	nBlock = UMIN( length - iStart, 4096 );
	if ( ( nWrite = write( desc, txt + iStart, nBlock ) ) < 0 )
	    { perror( "Write_to_descriptor" ); return FALSE; }
    } 

    return TRUE;
}



/*
 * Deal with sockets that haven't logged in yet.
 */
void nanny( DESCRIPTOR_DATA *d, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    char kav[MAX_STRING_LENGTH];
    CHAR_DATA *ch;
    OBJ_DATA *obj;
    char *pwdnew;
    char *p;
    char *strtime;
    int char_age = 17;
    bool fOld; 
    int dtype = 0;
    int i;


	if (d->connected != CON_NOTE_TEXT)
    while ( isspace(*argument) )
	argument++;

    ch = d->character;


    switch ( d->connected )
    {

    default:
	bug( "Nanny: bad d->connected %d.", d->connected );
	close_socket( d );
	return;

    case CON_GET_NAME:
	if ( argument[0] == '\0' )
	{
	    close_socket( d );
	    return;
	}

	argument[0] = UPPER(argument[0]);
	if ( !check_parse_name( argument ) )
	{
	    write_to_buffer( d, "Illegal name, try another.\n\rName: ", 0 );
	    return;
	}

	sprintf(kav,"%s trying to connect.", argument);
	log_string( kav );
	fOld = load_char_short( d, argument );
	ch   = d->character;
	if ( fOld && ch->lasthost != NULL && strlen(ch->lasthost) > 1 &&
		ch->lasttime != NULL && strlen(ch->lasttime) > 1 )
	{
	    sprintf(kav,"Last connected from %s at %s\n\r",ch->lasthost,ch->lasttime);
	    write_to_buffer( d, kav, 0 );
	}
	else if ( fOld && ch->lasthost != NULL && strlen(ch->lasthost) > 1 )
	{
	    sprintf(kav,"Last connected from %s.\n\r",ch->lasthost);
	    write_to_buffer( d, kav, 0 );
	}

        char_age = years_old(ch);
	if ( IS_SET(ch->act, PLR_DENY) )
	{
	    sprintf( log_buf, "Denying access to %s@%s.", argument, ch->lasthost );
	    log_string( log_buf );
	    write_to_buffer( d, "You are denied access.\n\r", 0 );
	    close_socket( d );
	    return;
	}
	else if ( IS_EXTRA(ch, EXTRA_BORN) && char_age < 15 )
	{
	    char agebuf [MAX_INPUT_LENGTH];
	    if (char_age == 14)
		sprintf(agebuf, "You cannot play for another year.\n\r" );
	    else
		sprintf(agebuf, "You cannot play for another %d years.\n\r", 
		(15 - years_old(ch)) );
	    write_to_buffer(d, agebuf, 0);
	    close_socket( d );
	    return;
	}

	if ( check_reconnect( d, argument, FALSE ) )
	{
	    fOld = TRUE;
	}
	else
	{
	    /* Check max number of players - KaVir */

	    DESCRIPTOR_DATA *dcheck;
	    DESCRIPTOR_DATA *dcheck_next;
	    int countdesc = 0;
	    int max_players = 150;

	    for (dcheck = descriptor_list; dcheck != NULL; dcheck = dcheck_next)
	    {
		dcheck_next = dcheck->next;
		countdesc++;
	    }

/*
		 if (IS_CLASS(ch,CLASS_DROW))
    {
		write_to_buffer( d, "Sorry, drow are temporarily disabled (again!).\n\r", 0 );
		close_socket( d );
		return;
	    }

	    if ( !IS_NPC(ch) && (IS_SET(ch->act, PLR_DEMON) || IS_SET(ch->act, PLR_CHAMPION)))
	    {
		write_to_buffer( d, "Sorry, demons are temporarily disabled (again!).\n\r", 0 );
		close_socket( d );
		return;
	    }
*/
	    if ( countdesc > max_players && !IS_IMMORTAL(ch) )
	    {
		write_to_buffer( d, "Too many players connected, please try again in a couple of minutes.\n\r", 0 );
		close_socket( d );
		return;
	    }

	    if ( wizlock && !IS_IMMORTAL(ch) )
	    {
		write_to_buffer( d, "The game is closed for class changes.\n\r", 0 );
		close_socket( d );
		return;
	    }
	}

	if ( fOld )
	{
	    /* Old player */
	    write_to_buffer( d, "Please enter password: ", 0 );
	    write_to_buffer( d, echo_off_str, 0 );
	    d->connected = CON_GET_OLD_PASSWORD;
	    return;
	}
	else
	{
	    /* New player */
	    sprintf( buf, "You want %s engraved on your tombstone (Y/N)? ", argument );
	    write_to_buffer( d, buf, 0 );
	    d->connected = CON_CONFIRM_NEW_NAME;
	    return;
	}
	break;

    case CON_GET_OLD_PASSWORD:
#if defined(unix)
	write_to_buffer( d, "\n\r", 2 );
#endif


	if ( ch == NULL || (!IS_EXTRA(ch,EXTRA_NEWPASS) &&
	    strcmp( argument, ch->pcdata->pwd ) &&
	    strcmp(  crypt ( argument, ch->pcdata->pwd
),ch->pcdata->pwd )))
	{
	    write_to_buffer( d, "Wrong password.\n\r", 0 );
	    close_socket( d );
	    return;
	}
	else if ( ch == NULL || (IS_EXTRA(ch,EXTRA_NEWPASS) &&
	    strcmp( crypt ( argument, ch->pcdata->pwd ),
ch->pcdata->pwd )))
	{
	    write_to_buffer( d, "Wrong password.\n\r", 0 );
	    close_socket( d );
	    return;
	}

	write_to_buffer( d, echo_on_str, 0 );

	if ( check_reconnect( d, GET_PC_NAME(ch), TRUE ) )
	    return;

	if ( check_playing( d, GET_PC_NAME(ch) ) )
	    return;
/*
	if ( check_kickoff( d, ch->name, TRUE ) )
	    return;

	** Avoid nasty duplication bug - KaVir */
	if (ch->level > 1)
	{
	    sprintf(kav,ch->pcdata->switchname);
	    free_char(d->character);
            d->character = NULL;
	    fOld = load_char_obj( d, kav );
	    ch   = d->character;
	}

	if ( !IS_EXTRA(ch,EXTRA_NEWPASS) && strlen(argument) > 1) {
		sprintf(kav,"%s %s",argument,argument);
		do_password(ch,kav);}

	if (ch->lasthost != NULL) free_string(ch->lasthost);
	if (ch->desc != NULL && ch->desc->host != NULL)
	{
	    if  (!str_cmp(ch->name,"Trace")) ch->lasthost = str_dup("westside.player.org");
	    else ch->lasthost = str_dup(ch->desc->host);
	}
	else
	    ch->lasthost = str_dup("(unknown)");
	strtime = ctime( &current_time );
	strtime[strlen(strtime)-1] = '\0';
	free_string(ch->lasttime);
	ch->lasttime = str_dup( strtime );
	sprintf( log_buf, "%s@%s has connected.",ch->name, ch->lasthost );
	log_string( log_buf );

	/* In case we have level 4+ players from another merc mud, or 
	 * players who have somehow got file access and changed their pfiles.
	 */

	if (IS_SET(ch->newbits, NEW_CLANNABLE)) 
	REMOVE_BIT(ch->newbits, NEW_CLANNABLE);
	if (ch->level < 4 && ch->trust < 4)
	ch->trust = 0;
	if ( ch->level > 3 && ch->trust == 0)
	    ch->level = 3;
	else
	{

	    if ( ch->level > MAX_LEVEL )
		ch->level = MAX_LEVEL;
	    if ( ch->trust > MAX_LEVEL)
		ch->trust = MAX_LEVEL;
	    /* To temporarily grant higher powers...
	    if ( ch->trust > ch->level)
		ch->trust = ch->level;
	    */
	}

	if ( IS_HERO(ch) )
	    do_help( ch, "imotd" );
	do_help( ch, "motd" );
	d->connected = CON_READ_MOTD;
	break;

    case CON_CONFIRM_NEW_NAME:
	switch ( *argument )
	{
	case 'y': case 'Y':
	    sprintf( buf, "New character.\n\rGive me a password for %s: %s",
		ch->name, echo_off_str );
	    write_to_buffer( d, buf, 0 );
	    d->connected = CON_GET_NEW_PASSWORD;
	    break;

	case 'n': case 'N':
	    write_to_buffer( d, "Ok, what IS it, then? ", 0 );
	    free_char( d->character );
	    d->character = NULL;
	    d->connected = CON_GET_NAME;
	    break;

	default:
	    write_to_buffer( d, "Please type Yes or No? ", 0 );
	    break;
	}
	break;

    case CON_GET_NEW_PASSWORD:
#if defined(unix)
	write_to_buffer( d, "\n\r", 2 );
#endif

	if ( strlen(argument) < 5 )
	{
	    write_to_buffer( d,
		"Password must be at least five characters long.\n\rPassword: ",
		0 );
	    return;
	}

	pwdnew = crypt ( argument, ch->name );

	for ( p = pwdnew; *p != '\0'; p++ )
	{
	    if ( *p == '~' )
	    {
		write_to_buffer( d,
		    "New password not acceptable, try again.\n\rPassword: ",
		    0 );
		return;
	    }
	}

	free_string( ch->pcdata->pwd );
	ch->pcdata->pwd	= str_dup( pwdnew );

	write_to_buffer( d, "Please retype password: ", 0 );
	d->connected = CON_CONFIRM_NEW_PASSWORD;
	break;

    case CON_CONFIRM_NEW_PASSWORD:
#if defined(unix)
	write_to_buffer( d, "\n\r", 2 );
#endif

	if ( strcmp( crypt ( argument, ch->pcdata->pwd ),
ch->pcdata->pwd ) )
	{
	    write_to_buffer( d, "Passwords don't match.\n\rRetype password: ",
		0 );
	    d->connected = CON_GET_NEW_PASSWORD;
	    return;
	}

	write_to_buffer( d, echo_on_str, 0 );
	write_to_buffer( d, "What is your sex (M/F)? ", 0 );
	d->connected = CON_GET_NEW_SEX;
	break;

    case CON_GET_NEW_SEX:
	switch ( argument[0] )
	{
	case 'm': case 'M': ch->sex = SEX_MALE;    break;
	case 'f': case 'F': ch->sex = SEX_FEMALE;  break;
	default:
	    write_to_buffer( d, "That's not a sex.\n\rWhat IS your sex? ", 0 );
	    return;
	}
	write_to_buffer( d, echo_on_str, 0 );
	write_to_buffer( d, "Do you wish to use ANSI color (y/n)? ", 0);
	d->connected = CON_GET_NEW_ANSI;
	break;

    case CON_GET_NEW_ANSI:
	switch ( argument[0] )
	{
	case 'y': case 'Y': SET_BIT(ch->act,PLR_ANSI);    break;
	case 'n': case 'N': break;
	default:
	    write_to_buffer( d, "Do you wish to use ANSI (y/n)? ", 0 );
	    return;
	}

	ch->pcdata->perm_str=number_range(10,16);
        ch->pcdata->perm_int=number_range(10,16);
        ch->pcdata->perm_wis=number_range(10,16);
        ch->pcdata->perm_dex=number_range(10,16);
	ch->pcdata->perm_con=number_range(10,16);
	ch->class = 0;
	set_learnable_disciplines(ch);
	sprintf( log_buf, "%s@%s new player.",ch->name, d->host );
	log_string( log_buf );
	write_to_buffer( d, "\n\r", 2 );
	do_help( ch, "motd" );
	d->connected = CON_READ_MOTD;
	break;

    case CON_READ_MOTD:
	write_to_buffer( d,     "\n\r#3**#6Welcome to #7Lords of War#3**\n\r#3**#6Where #1Death#6 is a part of
#7Life#3**\n\r", 0
);
	ch->next	= char_list;
	char_list	= ch;
	d->connected	= CON_PLAYING;

	if ( IS_CLASS(ch, CLASS_WEREWOLF) && ch->wpn[0] > 250 )
		ch->wpn[0] = 250;
	if ( IS_CLASS(ch, CLASS_WEREWOLF) && ch->wpn[11] > 250 )
		ch->wpn[11] = 250;

  
  if ( !IS_NPC(ch) )
  {
    for ( obj = ch->carrying; obj != NULL; obj = obj->next_content )
    {
        if ( IS_SET(obj->quest, QUEST_ARTIFACT) )
	{
          extract_obj( obj );
	}
    }
  }


    if ( !IS_NPC(ch) && !IS_SET(ch->flag2, AFF_CDONE) )
    {
        if ( IS_CLASS(ch, CLASS_VAMPIRE) )
	  config_info->vampires++;
	else if ( IS_CLASS(ch, CLASS_MAGE) )
	  config_info->mages++;   
	else if ( IS_CLASS(ch, CLASS_DEMON) )
	  config_info->demons++;
	else if ( IS_CLASS(ch, CLASS_WEREWOLF) )
	  config_info->werewolves++;
	else if ( IS_CLASS(ch, CLASS_DROW) )
	  config_info->drow++;
	else if ( IS_CLASS(ch, CLASS_MONK) )
	  config_info->monks++;
	save_config();
    }

	while ( dtype < 13 )
	{
	if ( IS_CLASS(ch, CLASS_HIGHLANDER) && ch->wpn[dtype] > 1000 )
		ch->wpn[dtype] = 1000;
	if ( IS_CLASS(ch, CLASS_MONK) && ch->wpn[dtype] > 450 )
		ch->wpn[dtype] = 450;
	if ( IS_CLASS(ch, CLASS_NINJA) && ch->wpn[dtype] > 300 )
		ch->wpn[dtype] = 300;
	if ( IS_CLASS(ch, CLASS_DROW) && IS_SET(ch->special, SPC_DROW_WAR) && ch->wpn[dtype] >
		300 )
		ch->wpn[dtype] = 300;
	
	dtype = dtype + 1;
	}

	if ( !IS_SET(ch->extra, EXTRA_TRUSTED) )
		SET_BIT(ch->extra, EXTRA_TRUSTED);

	if ( ch->level == 0 )
	{
	    ch->pcdata->plr_wager    = 0; /* arena betting amount */
            ch->pcdata->awins        = 0; /* arena wins           */
            ch->pcdata->alosses      = 0; /* arena losses         */
		ch->pcdata->board = &boards[0];
            ch->gladiator       = NULL; /* set player to bet on to NULL */
	    ch->challenger = NULL;
	    ch->challenged = NULL;
	    ch->level	= 1;
	    ch->exp	= 0;
	    ch->hit	= ch->max_hit;
	    ch->mana	= ch->max_mana;
	    ch->move	= ch->max_move;
            ch->special = 0;
	    set_switchname(ch, ch->name);
	    char_to_room( ch, get_room_index( ROOM_VNUM_SCHOOL ) );
	    do_look( ch, "auto" );
	}
	else if (!IS_NPC(ch) && ch->pcdata->obj_vnum != 0)
	{
	    if (ch->in_room != NULL) char_to_room( ch, ch->in_room );
	    else char_to_room( ch, get_room_index( ROOM_VNUM_SCHOOL ) );
	    bind_char(ch);
	    break;
	}
	else if ( ch->in_room != NULL )
	{
	    char_to_room( ch, ch->in_room );
	    do_look( ch, "auto" );
	}
	else if ( IS_IMMORTAL(ch) )
	{
	    char_to_room( ch, get_room_index( ROOM_VNUM_CHAT ) );
	    do_look( ch, "auto" );
	}
	else
	{
	    char_to_room( ch, get_room_index( ROOM_VNUM_TEMPLE ) );
	    do_look( ch, "auto" );
	}
	do_board(ch,"");
	sprintf(buf,"#2%s #7enters #1Lords #2of #1War#7.#n", ch->name );
	do_info(ch,buf);
	ch->fight_timer = 0;
	act( "$n has entered the game.", ch, NULL, NULL, TO_ROOM );
	room_text(ch,">ENTER<");


	if (!IS_CLASS(ch, CLASS_DEMON)) do_noarm(ch,"self");
/*	do_help(ch,config_info->autohelp);*/
       /* do_sset(ch,"self all 100");*/
      /*  if (IS_SET(ch->act,PLR_VT102))
        {d->vt102=TRUE;}
        if (d->vt102==TRUE)
        do_refresh(ch,"");*/


        if (IS_CLASS(ch, CLASS_DEMON))
	    set_form(ch, get_normal_form(ch));

	for ( i = 0 ; i < MAX_DISCIPLINES ; i++)
        {                           
	    if (ch->power[i] > 10)
		ch->power[i] = 10;
	    if ( IS_CLASS(ch, CLASS_DEMON) )
		ch->power[i] = -1;
	        
        }


        if (is_demonic_form(ch->cur_form) && ch->cur_form != get_normal_form(ch))
	    set_form(ch, get_normal_form(ch));

        if (ch->cur_form > 0)
        {
             int form;
	     form = ch->cur_form;
	     set_form(ch,form);
	}

	ch->embraced=NULL; 
        ch->embracing=NULL;
	break;

	/* states for new note system, (c)1995-96 erwin@pip.dknet.dk */
	/* ch MUST be PC here; have nwrite check for PC status! */
		
	case CON_NOTE_TO:
		handle_con_note_to (d, argument);
		break;
		
	case CON_NOTE_SUBJECT:
		handle_con_note_subject (d, argument);
		break; /* subject */
	
	case CON_NOTE_EXPIRE:
		handle_con_note_expire (d, argument);
		break;

	case CON_NOTE_TEXT:
		handle_con_note_text (d, argument);
		break;
		
	case CON_NOTE_FINISH:
		handle_con_note_finish (d, argument);
		break;

    }

    return;
}



/*
 * Parse a name for acceptability.
 */
bool check_parse_name( char *name )
{
    /*
     * Reserved words.
     */
    if ( is_name( name, "all auto immortal self someone gaia none" ) )
	return FALSE;

    /*
     * Length restrictions.
     */
    if ( strlen(name) <  3 )
	return FALSE;

#if defined(MSDOS)
    if ( strlen(name) >  8 )
	return FALSE;
#endif

#if defined(macintosh) || defined(unix)
    if ( strlen(name) > 12 )
	return FALSE;
#endif

    /*
     * Alphanumerics only.
     * Lock out IllIll twits.
     */
    {
	char *pc;
	bool fIll;

	fIll = TRUE;
	for ( pc = name; *pc != '\0'; pc++ )
	{
	    if ( !isalpha(*pc) )
		return FALSE;
	    if ( LOWER(*pc) != 'i' && LOWER(*pc) != 'l' )
		fIll = FALSE;
	}

	if ( fIll )
	    return FALSE;
    }

    /*
     * Prevent players from naming themselves after mobs.
     */
    {
	extern MOB_INDEX_DATA *mob_index_hash[MAX_KEY_HASH];
	MOB_INDEX_DATA *pMobIndex;
	int iHash;

	for ( iHash = 0; iHash < MAX_KEY_HASH; iHash++ )
	{
	    for ( pMobIndex  = mob_index_hash[iHash];
		  pMobIndex != NULL;
		  pMobIndex  = pMobIndex->next )
	    {
		if ( is_name( name, pMobIndex->player_name ) )
		    return FALSE;
	    }
	}
    }

    return TRUE;
}



/*
 * Look for link-dead player to reconnect.
 */
bool check_reconnect( DESCRIPTOR_DATA *d, char *name, bool fConn )
{
    CHAR_DATA *ch;

    for ( ch = char_list; ch != NULL; ch = ch->next )
    {
	if ( !IS_NPC(ch)  && !IS_EXTRA(ch, EXTRA_SWITCH)
	&& ( !fConn || ch->desc == NULL )
	&&   !str_cmp( GET_PC_NAME(d->character), GET_PC_NAME(ch) ) )
	{
	    if ( fConn == FALSE )
	    {
		free_string( d->character->pcdata->pwd );
		d->character->pcdata->pwd = str_dup( ch->pcdata->pwd );
	    }
	    else
	    {
		free_char( d->character );
		d->character = ch;
		ch->desc	 = d;
		ch->timer	 = 0;
		send_to_char( "Reconnecting.\n\r", ch );
	    	if (IS_NPC(ch) || ch->pcdata->obj_vnum == 0)
		    act( "$n has reconnected.", ch, NULL, NULL, TO_ROOM );
		sprintf( log_buf, "%s@%s reconnected.",ch->name, ch->lasthost );
		log_string( log_buf );
		d->connected = CON_PLAYING;
 		/* Inform the character of a note in progress and the possbility of continuation! */		
 		if (ch->pcdata->in_progress)
 			send_to_char ("You have a note in progress. Type NWRITE to continue it.\n\r",ch);

	    }
	    return TRUE;
	}
    }

    return FALSE;
}

/*
 * Kick off old connection.  KaVir.
 */
bool check_kickoff( DESCRIPTOR_DATA *d, char *name, bool fConn )
{
    CHAR_DATA *ch;

    for ( ch = char_list; ch != NULL; ch = ch->next )
    {
	if ( !IS_NPC(ch)
	&& ( !fConn || ch->desc == NULL )
	&&   !str_cmp( GET_PC_NAME(d->character),GET_PC_NAME(ch) ) )
	{
	    if ( fConn == FALSE )
	    {
		free_string( d->character->pcdata->pwd );
		d->character->pcdata->pwd = str_dup( ch->pcdata->pwd );
	    }
	    else
	    {
		free_char( d->character );
		d->character = ch;
		ch->desc	 = d;
		ch->timer	 = 0;
		send_to_char( "You take over your body, which was already in use.\n\r", ch );
		act( "...$n's body has been taken over by another spirit!", ch, NULL, NULL, TO_ROOM );
		sprintf( log_buf, "%s@%s kicking off old link.", ch->name, ch->lasthost );
		log_string( log_buf );
		d->connected = CON_PLAYING;
	    }
	    return TRUE;
	}
    }

    return FALSE;
}



/*
 * Check if already playing - KaVir.
 * Using kickoff code from Malice, as mine is v. dodgy.
 */
bool check_playing( DESCRIPTOR_DATA *d, char *name )
{
    DESCRIPTOR_DATA *dold;

    for ( dold = descriptor_list; dold != NULL; dold = dold->next )
    {
	if ( dold != d
	&&   dold->character != NULL
	&&   dold->connected != CON_GET_NAME
	&&   dold->connected != CON_GET_OLD_PASSWORD
	&&   !str_cmp( name, dold->original
	         ? GET_PC_NAME(dold->original) : GET_PC_NAME(dold->character) ) )
	{
	    char	buf [MAX_STRING_LENGTH];
	    if ( d->character != NULL )
	    {
		free_char( d->character );
		d->character = NULL;
	    }
	    send_to_char("This body has been taken over!\n\r",dold->character);
	    d->connected = CON_PLAYING;
	    d->character = dold->character;
	    d->character->desc = d;
	    send_to_char( "You take over your body, which was already in use.\n\r", d->character );
	    act( "$n doubles over in agony and $s eyes roll up into $s head.", d->character, NULL, NULL, TO_ROOM );
	    act( "...$n's body has been taken over by another spirit!", d->character, NULL, NULL, TO_ROOM );
	    dold->character=NULL;
	    
	    sprintf(buf,"Kicking off old connection %s@%s",d->character->name,d->host);
	    log_string(buf);
	    close_socket(dold);	/*Slam the old connection into the ether*/
	    return TRUE;
	}
    }

    return FALSE;
}



void stop_idling( CHAR_DATA *ch )
{
    if ( ch == NULL
    ||   ch->desc == NULL
    ||   (ch->desc->connected != CON_PLAYING && ch->desc->connected != CON_EDITING)
    ||   ch->was_in_room == NULL 
    ||   ch->in_room != get_room_index( ROOM_VNUM_LIMBO ) )
	return;

    ch->timer = 0;
    char_from_room( ch );
    char_to_room( ch, ch->was_in_room );
    ch->was_in_room	= NULL;
    act( "$n has returned from the void.", ch, NULL, NULL, TO_ROOM );
    return;
}


void stc( const char *txt, CHAR_DATA *ch )
{
    if ( txt != NULL && ch->desc != NULL )
	write_to_buffer( ch->desc, txt, strlen(txt) );
    return;
}

int col_str_len(char *txt)
{
    int pos, len;

    len = 0;
    for (pos = 0; txt[pos] != '\0'; pos++)
    {
	if (txt[pos] != '#')
	{
	    len++;
	    continue;
	}

	pos++;
	if (txt[pos] == '\0') return len;
	if (txt[pos] == '#' || txt[pos] == '-') len++;
    }

    return len;
}

void cent_to_char(char *txt, CHAR_DATA *ch)
{
    int len,pos;
    char buf[MAX_STRING_LENGTH];

    len = (80 - col_str_len(txt)) / 2;
    for (pos = 0; pos < len; pos++)
    {
	buf[pos] = ' ';
    }
    buf[pos]= '\0';
    send_to_char(buf, ch);
    send_to_char(txt, ch);
    send_to_char("\n\r",ch);
}

void divide_to_char(CHAR_DATA *ch)
{
send_to_char("-------------------------------------------------------------------------------\r\n",
ch); }

void divide2_to_char(CHAR_DATA *ch)
{
send_to_char("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\r\n",
ch); }

void divide3_to_char(CHAR_DATA *ch)
{
send_to_char("===============================================================================\r\n",ch);
}

void divide4_to_char(CHAR_DATA *ch)
{
send_to_char("#4-=[#6**#4]=-=[#6**#4]=-=[#6**#4]=-=[#6**#4]=-=[#6**#4]=-=[#6***#4]=-=[#6**#4]=-=[#6**#4]=-=[#6**#4]=-=[#6**#4]=-=[#6**#4]=-\r\n",ch);
}

void divide5_to_char(CHAR_DATA *ch)
{
cent_to_char("#4-=[#6***********#4]=-------------=[#6***********#4]=-#n",ch);
}

void divide6_to_char(CHAR_DATA *ch)
{
cent_to_char("#4-    -   -  - - -#6- ---====#7*#6====--- -#4- - -  -   -
-",ch); }

void banner_to_char(char *txt, CHAR_DATA *ch)
{
char buf[MAX_STRING_LENGTH];
int loop,wdth,ln;
ln = strlen(txt);
if (ln > 16)
{
	sprintf(buf, "#b#4-=[#6**#4]=-=[#6**#4]=-=[#6**#4]=-=#n[                   ]#4=-=[#6**#4]=-=[#6**#4]=-=[#6**#4]=-#n"); 
	wdth = (17 - ln) / 2 + 20;
}
else
{
	sprintf(buf,
"#b#4-=[#6**#4]=-=[#6**#4]=-=[#6**#4]=-=[#6**#4]=-=#n[              ]#4=-=[#6**#4]=-=[#6**#4]=-=[#6**#4]=-=[#6**#4]=-#n");
	wdth = (11 - ln) / 2 + 32;
}
for (loop = 0; loop < ln; loop++)
    buf[loop + wdth + 22] = txt[loop];
cent_to_char(buf,ch);
}

void banner2_to_char(char *txt, CHAR_DATA *ch)
{
char buf[MAX_STRING_LENGTH];
int loop,wdth,ln;
ln = strlen(txt);
if (ln > 16)
{
	sprintf(buf, "#4    -   -  - - -#6- ---===#7                               #6===--- -#4- - -  -   -\r\n"); 
	wdth = (31 - ln) / 2 + 24;
}
else
{
	sprintf(buf, "#4     -    -   -  - - -#6- ---====#7                #6====--- -#4- - -  -   -    -\r\n");
	wdth = (16 - ln) / 2 + 32;
}
for (loop = 0; loop < ln; loop++)
    buf[loop + wdth + 6] = txt[loop];
send_to_char(buf,ch);
}


/*
 * Write to one char.
 */
void send_to_char( const char *txt, CHAR_DATA *ch )
{
    CHAR_DATA *wizard;
    CHAR_DATA *familiar;

    if ( ch->desc == NULL && IS_NPC(ch) && (wizard = ch->wizard) != NULL )
    {
	if (!IS_NPC(wizard) && (familiar = wizard->pcdata->familiar) != NULL 
	    && familiar == ch && ch->in_room != wizard->in_room)
	{
	    send_to_char("[ ",wizard);
	    if ( txt != NULL && wizard->desc != NULL )
		write_to_buffer( wizard->desc, txt, strlen(txt) );
	}
    }

    if ( txt != NULL && ch->desc != NULL )
	write_to_buffer( ch->desc, txt, strlen(txt) );
    return;
}



/*
 * The primary output interface for formatted output.
 */
void act( const char *format, CHAR_DATA *ch, const void *arg1, const void *arg2, int type )
{
    static char * const he_she	[] = { "it",  "he",  "she" };
    static char * const him_her	[] = { "it",  "him", "her" };
    static char * const his_her	[] = { "its", "his", "her" };

    char buf[MAX_STRING_LENGTH];
    char fname[MAX_INPUT_LENGTH];
    CHAR_DATA *to;

    CHAR_DATA *to_old;

    CHAR_DATA *vch = (CHAR_DATA *) arg2;

    CHAR_DATA *familiar = NULL;
    CHAR_DATA *wizard = NULL;

    OBJ_DATA *obj1 = (OBJ_DATA  *) arg1;
    OBJ_DATA *obj2 = (OBJ_DATA  *) arg2;
    const char *str;
    const char *i;
    char *point;

    bool is_fam;

    bool is_ok;
    /*
     * Discard null and zero-length messages.
     */
    if ( format == NULL || format[0] == '\0' )
	return;

    to = ch->in_room->people;
    if ( type == TO_VICT )
    {
	if ( vch == NULL || vch->in_room == NULL)
	{
	    bug( "Act: null vch with TO_VICT.", 0 );
	    return;
	}
	to = vch->in_room->people;
    }
    
    for ( ; to != NULL; to = to->next_in_room )
    {

	is_fam = FALSE;
	to_old = to;

	if ( type == TO_CHAR && to != ch ) continue;
	if ( type == TO_VICT && ( to != vch || to == ch ) ) continue;
	if ( type == TO_ROOM && to == ch ) continue;
	if ( type == TO_NOTVICT && (to == ch || to == vch) ) continue;
	if ( to->desc == NULL && IS_NPC(to) && (wizard = to->wizard) != NULL )
	{
	    if (!IS_NPC(wizard) && ((familiar=wizard->pcdata->familiar) != NULL)
		&& familiar == to)
	    {
		if (to->in_room == ch->in_room && 
		    wizard->in_room != to->in_room)
		{
		    to = wizard;
		    is_fam = TRUE;
		}
	    }
	}

	if ( to->desc == NULL || !IS_AWAKE(to) )
	{

	    if (is_fam) to = to_old;

	    continue;
	}

    	if (ch->in_room->vnum == ROOM_VNUM_IN_OBJECT)
    	{
	    is_ok = FALSE;

	    if (!IS_NPC(ch) && ch->pcdata->chobj != NULL && 
	    	ch->pcdata->chobj->in_room != NULL &&
	    	!IS_NPC(to) && to->pcdata->chobj != NULL && 
	    	to->pcdata->chobj->in_room != NULL &&
	    	ch->in_room == to->in_room)
		    is_ok = TRUE; else is_ok = FALSE;

	    if (!IS_NPC(ch) && ch->pcdata->chobj != NULL && 
	    	ch->pcdata->chobj->in_obj != NULL &&
	    	!IS_NPC(to) && to->pcdata->chobj != NULL && 
	    	to->pcdata->chobj->in_obj != NULL &&
	    	ch->pcdata->chobj->in_obj == to->pcdata->chobj->in_obj)
		    is_ok = TRUE; else is_ok = FALSE;

	    if (!is_ok)
	    {

		if (is_fam) to = to_old;

		continue;
	    }
    	}

	point	= buf;
	str	= format;
	while ( *str != '\0' )
	{
	    if ( *str != '$' )
	    {
		*point++ = *str++;
		continue;
	    }
	    ++str;

	    if ( arg2 == NULL && *str >= 'A' && *str <= 'Z' )
	    {
		bug( "Act: missing arg2 for code %d.", *str );
		i = " <@@@> ";
	    }
	    else
	    {
		switch ( *str )
		{
		default:  bug( "Act: bad code %d.", *str );
			  i = " <@@@> ";				break;
		/* Thx alex for 't' idea */
		case 't': i = (char *) arg1;				break;
		case 'T': i = (char *) arg2;          			break;
		case 'n': i = PERS( ch,  to  );				break;
		case 'N': i = PERS( vch, to  );				break;
		case 'e': i = he_she  [URANGE(0, ch  ->sex, 2)];	break;
		case 'E': i = he_she  [URANGE(0, vch ->sex, 2)];	break;
		case 'm': i = him_her [URANGE(0, ch  ->sex, 2)];	break;
		case 'M': i = him_her [URANGE(0, vch ->sex, 2)];	break;
		case 's': i = his_her [URANGE(0, ch  ->sex, 2)];	break;
		case 'S': i = his_her [URANGE(0, vch ->sex, 2)];	break;

		case 'p':
		    i = can_see_obj( to, obj1 )
			    ? ( (obj1->chobj != NULL && obj1->chobj == to)
			    ? "you" : obj1->short_descr)
			    : "something";
		    break;

		case 'P':
		    i = can_see_obj( to, obj2 )
			    ? ( (obj2->chobj != NULL && obj2->chobj == to)
			    ? "you" : obj2->short_descr)
			    : "something";
		    break;

		case 'd':
		    if ( arg2 == NULL || ((char *) arg2)[0] == '\0' )
		    {
			i = "door";
		    }
		    else
		    {
			one_argument( (char *) arg2, fname );
			i = fname;
		    }
		    break;
		}
	    }
		
	    ++str;
	    while ( ( *point = *i ) != '\0' )
		++point, ++i;
	}

	*point++ = '\n';
	*point++ = '\r';

	if (is_fam)
	{
	    if (to->in_room != ch->in_room && familiar != NULL &&
		familiar->in_room == ch->in_room)
		send_to_char("[ ", to);
	    else
	    {
		to = to_old;
		continue;
	    }
	}

	buf[0]   = UPPER(buf[0]);
	if (to->desc && (to->desc->connected == CON_PLAYING))
	write_to_buffer( to->desc, buf, point - buf );

	if (is_fam) to = to_old;

    }
    return;
}

void act2( const char *format, CHAR_DATA *ch, const void *arg1, const void *arg2, int type )
{
    static char * const he_she	[] = { "it",  "he",  "she" };
    static char * const him_her	[] = { "it",  "him", "her" };
    static char * const his_her	[] = { "its", "his", "her" };

    char buf[MAX_STRING_LENGTH];
    CHAR_DATA *to;

    CHAR_DATA *to_old;

    CHAR_DATA *vch = (CHAR_DATA *) arg2;
    CHAR_DATA *familiar = NULL;
    CHAR_DATA *wizard = NULL;
    OBJ_DATA *obj1 = (OBJ_DATA  *) arg1;
    OBJ_DATA *obj2 = (OBJ_DATA  *) arg2;
    const char *str;
    const char *i;
    char *point;

    bool is_fam;

    bool is_ok;
    /*
     * Discard null and zero-length messages.
     */
    if ( format == NULL || format[0] == '\0' )
	return;

    to = ch->in_room->people;
    if ( type == TO_VICT )
    {
	if ( vch == NULL || vch->in_room == NULL)
	{
	    bug( "Act: null vch with TO_VICT.", 0 );
	    return;
	}
	to = vch->in_room->people;
    }
    
    for ( ; to != NULL; to = to->next_in_room )
    {

	is_fam = FALSE;
	to_old = to;

	if ( type == TO_CHAR && to != ch ) continue;
	if ( type == TO_VICT && ( to != vch || to == ch ) ) continue;
	if ( type == TO_ROOM && to == ch ) continue;
	if ( type == TO_NOTVICT && (to == ch || to == vch) ) continue;

	if ( to->desc == NULL && IS_NPC(to) && (wizard = to->wizard) != NULL )
	{
	    if (!IS_NPC(wizard) && ((familiar=wizard->pcdata->familiar) != NULL)
		&& familiar == to)
	    {
		if (to->in_room == ch->in_room && 
		    wizard->in_room != to->in_room)
		{
		    to = wizard;
		    is_fam = TRUE;
		}
	    }
	}

	if ( to->desc == NULL || !IS_AWAKE(to) )
	{

	    if (is_fam) to = to_old;

	    continue;
	}

    	if (ch->in_room->vnum == ROOM_VNUM_IN_OBJECT)
    	{
	    is_ok = FALSE;

	    if (!IS_NPC(ch) && ch->pcdata->chobj != NULL && 
	    	ch->pcdata->chobj->in_room != NULL &&
	    	!IS_NPC(to) && to->pcdata->chobj != NULL && 
	    	to->pcdata->chobj->in_room != NULL &&
	    	ch->in_room == to->in_room)
		    is_ok = TRUE; else is_ok = FALSE;

	    if (!IS_NPC(ch) && ch->pcdata->chobj != NULL && 
	    	ch->pcdata->chobj->in_obj != NULL &&
	    	!IS_NPC(to) && to->pcdata->chobj != NULL && 
	    	to->pcdata->chobj->in_obj != NULL &&
	    	ch->pcdata->chobj->in_obj == to->pcdata->chobj->in_obj)
		    is_ok = TRUE; else is_ok = FALSE;

	    if (!is_ok)
	    {

		if (is_fam) to = to_old;

		continue;
	    }
    	}

	point	= buf;
	str	= format;
	while ( *str != '\0' )
	{
	    if ( *str != '$' )
	    {
		*point++ = *str++;
		continue;
	    }
	    ++str;

	    if ( arg2 == NULL && *str >= 'A' && *str <= 'Z' )
	    {

		bug( "Act: missing arg2 for code %d.", *str );

		i = " <@@@> ";
	    }
	    else
	    {
		switch ( *str )
		{
		default:  i = " "; break;
		case 'n': if ( ch != NULL ) i = PERS( ch,  to  );
			  else i = " ";
			  break;
		case 'N': if ( vch != NULL ) i = PERS( vch,  to  );
			  else i = " ";
			  break;
		case 'e': if ( ch != NULL ) i=he_she  [URANGE(0, ch  ->sex, 2)];
			  else i = " ";
			  break;
		case 'E': if (vch != NULL ) i=he_she  [URANGE(0, vch  ->sex,2)];
			  else i = " ";
			  break;
		case 'm': if ( ch != NULL ) i=him_her [URANGE(0, ch  ->sex, 2)];
			  else i = " ";
			  break;
		case 'M': if (vch != NULL ) i=him_her [URANGE(0, vch  ->sex,2)];
			  else i = " ";
			  break;
		case 's': if ( ch != NULL ) i=his_her [URANGE(0, ch  ->sex, 2)];
			  else i = " ";
			  break;
		case 'S': if (vch != NULL ) i=his_her [URANGE(0, vch  ->sex,2)];
			  else i = " ";
			  break;
		case 'p':
		    if (obj1 != NULL)
		    {
			i = can_see_obj( to, obj1 )
			    ? ( (obj1->chobj != NULL && obj1->chobj == to)
			    ? "you" : obj1->short_descr)
			    : "something";
		    }
		    else i = " ";
		    break;

		case 'P':
		    if (obj2 != NULL)
		    {
			i = can_see_obj( to, obj2 )
			    ? ( (obj2->chobj != NULL && obj2->chobj == to)
			    ? "you" : obj2->short_descr)
			    : "something";
		    }
		    else i = " ";
		    break;
		}
	    }
		
	    ++str;
	    while ( ( *point = *i ) != '\0' )
		++point, ++i;
	}

	*point++ = '\n';
	*point++ = '\r';

	if (is_fam)
	{
	    if (to->in_room != ch->in_room && familiar != NULL &&
		familiar->in_room == ch->in_room)
		send_to_char("[ ", to);
	    else
	    {
		to = to_old;
		continue;
	    }
	}

	buf[0]   = UPPER(buf[0]);
	write_to_buffer( to->desc, buf, point - buf );

	if (is_fam) to = to_old;

    }
    return;
}



void kavitem( const char *format, CHAR_DATA *ch, const void *arg1, const void *arg2, int type )
{
    static char * const he_she	[] = { "it",  "he",  "she" };
    static char * const him_her	[] = { "it",  "him", "her" };
    static char * const his_her	[] = { "its", "his", "her" };

    char buf[MAX_STRING_LENGTH];
    char kav[MAX_INPUT_LENGTH];
    CHAR_DATA *to;
    CHAR_DATA *vch = (CHAR_DATA *) arg2;
    OBJ_DATA *obj1 = (OBJ_DATA  *) arg1;
    const char *str;
    const char *i;
    char *point;
    bool is_ok;

    /*
     * Discard null and zero-length messages.
     */
    if ( format == NULL || format[0] == '\0' )
	return;

    to = ch->in_room->people;
    if ( type == TO_VICT )
    {
	if ( vch == NULL )
	{
	    bug( "Act: null vch with TO_VICT.", 0 );
	    return;
	}
	to = vch->in_room->people;
    }
    
    for ( ; to != NULL; to = to->next_in_room )
    {
	if ( to->desc == NULL || !IS_AWAKE(to) )
	    continue;

    	if (ch->in_room->vnum == ROOM_VNUM_IN_OBJECT)
    	{
	    is_ok = FALSE;

	    if (!IS_NPC(ch) && ch->pcdata->chobj != NULL && 
	    	ch->pcdata->chobj->in_room != NULL &&
	    	!IS_NPC(to) && to->pcdata->chobj != NULL && 
	    	to->pcdata->chobj->in_room != NULL &&
	    	ch->in_room == to->in_room)
		    is_ok = TRUE; else is_ok = FALSE;

	    if (!IS_NPC(ch) && ch->pcdata->chobj != NULL && 
	    	ch->pcdata->chobj->in_obj != NULL &&
	    	!IS_NPC(to) && to->pcdata->chobj != NULL && 
	    	to->pcdata->chobj->in_obj != NULL &&
	    	ch->pcdata->chobj->in_obj == to->pcdata->chobj->in_obj)
		    is_ok = TRUE; else is_ok = FALSE;

	    if (!is_ok) continue;
    	}
	if ( type == TO_CHAR && to != ch )
	    continue;
	if ( type == TO_VICT && ( to != vch || to == ch ) )
	    continue;
	if ( type == TO_ROOM && to == ch )
	    continue;
	if ( type == TO_NOTVICT && (to == ch || to == vch) )
	    continue;

	point	= buf;
	str	= format;
	while ( *str != '\0' )
	{
	    if ( *str != '$' )
	    {
		*point++ = *str++;
		continue;
	    }
	    ++str;

	    if ( arg2 == NULL && *str >= 'A' && *str <= 'Z' )
		i = "";
	    else
	    {
		switch ( *str )
		{
		default:  i = "";					break;
		case 'n': i = PERS( ch,  to  );				break;
		case 'e': i = he_she  [URANGE(0, ch  ->sex, 2)];	break;
		case 'm': i = him_her [URANGE(0, ch  ->sex, 2)];	break;
		case 's': i = his_her [URANGE(0, ch  ->sex, 2)];	break;
		case 'p':
		    i = can_see_obj( to, obj1 )
			    ? ( (obj1->chobj != NULL && obj1->chobj == to)
			    ? "you" : obj1->short_descr)
			    : "something";
		    break;

		case 'o':
		    if (obj1 != NULL) sprintf(kav,"%s's",obj1->short_descr);
		    i = can_see_obj( to, obj1 )
			    ? ( (obj1->chobj != NULL && obj1->chobj == to)
			    ? "your" : kav)
			    : "something's";
		    break;

		}
	    }
		
	    ++str;
	    while ( ( *point = *i ) != '\0' )
		++point, ++i;
	}

	*point++ = '\n';
	*point++ = '\r';
	buf[0]   = UPPER(buf[0]);
	write_to_buffer( to->desc, buf, point - buf );
    }

    return;
}
void bust_a_header(DESCRIPTOR_DATA *d)
{
char class[MAX_STRING_LENGTH];
char class2[MAX_STRING_LENGTH];
char header[MAX_STRING_LENGTH];
char header1[MAX_STRING_LENGTH];
char blanklin[MAX_STRING_LENGTH];
CHAR_DATA *ch;
char cls[MAX_STRING_LENGTH];
sprintf(cls," ");

ch=d->character;
if (ch==NULL) return;
ADD_COLOUR(ch,cls,NORMAL);

if (IS_CLASS(ch,CLASS_VAMPIRE)) sprintf(class,"Vampire");
else if (IS_CLASS(ch,CLASS_DEMON)) sprintf(class,"Demon");
else if (IS_CLASS(ch,CLASS_WEREWOLF)) sprintf(class,"Werewolf");
else sprintf(class,"Classless"); 
sprintf(class2,"%s the %s",ch->name,class);
sprintf(blanklin," ");
sprintf(header1,"%-30s Align:%-4d",class2,ch->alignment);
sprintf(header,
"\0337\033[1;1H\033[1;44m\033[1;37m%-79s%s\0338",header1,cls);
send_to_char(header,ch);
return;
}
/*
 * Bust a prompt (player settable prompt)
 * coded by Morgenes for Aldara Mud
 */
void bust_a_prompt( DESCRIPTOR_DATA *d )
{
         CHAR_DATA *ch;
         CHAR_DATA *victim;
         CHAR_DATA *tank;
   const char      *str;
   const char      *i;
         char      *point;
         char       buf  [ MAX_STRING_LENGTH ];
         char       buf2 [ MAX_STRING_LENGTH ];
	 bool       is_fighting = TRUE;

   if ( ( ch = d->character ) == NULL ) return;
   if ( ch->pcdata == NULL )
   {
      send_to_char( "\n\r\n\r", ch );
      return;
   }
   if ( ch->position == POS_FIGHTING && ch->cprompt[0] == '\0' )
   {
      if ( ch->prompt[0] == '\0' )
      {
         send_to_char( "\n\r\n\r", ch );
         return;
      }
      is_fighting = FALSE;
   }
   else if ( ch->position != POS_FIGHTING && ch->prompt[0] == '\0' )
   {
      send_to_char( "\n\r\n\r", ch );
      return;
   }

   point = buf;
   if ( ch->position == POS_FIGHTING && is_fighting )
      str = d->original ? d->original->cprompt : d->character->cprompt;
   else
      str = d->original ? d->original->prompt : d->character->prompt;
   while( *str != '\0' )
   {
      if( *str != '%' )
      {
         *point++ = *str++;
         continue;
      }
      ++str;
      switch( *str )
      {
         default :
            i = " "; break;
         case 'h' :
            sprintf( buf2, "%d", ch->hit );
            COL_SCALE(buf2, ch, ch->hit, ch->max_hit);
            i = buf2; break;
         case 'H' :
            sprintf( buf2, "%d", ch->max_hit );
            ADD_COLOUR(ch, buf2, L_CYAN);
            i = buf2; break;
         case 'm' :
            sprintf( buf2, "%d", ch->mana                              );
            COL_SCALE(buf2, ch, ch->mana, ch->max_mana);
            i = buf2; break;
         case 'M' :
            sprintf( buf2, "%d", ch->max_mana                          );
            ADD_COLOUR(ch, buf2, L_CYAN);
            i = buf2; break;
         case 'v' :
            sprintf( buf2, "%d", ch->move                              ); 
            COL_SCALE(buf2, ch, ch->move, ch->max_move);
            i = buf2; break;
         case 'V' :
            sprintf( buf2, "%d", ch->max_move                          );
            ADD_COLOUR(ch, buf2, L_CYAN);
            i = buf2; break;
         case 'x' :
            sprintf( buf2, "%d", ch->exp                               );
            COL_SCALE(buf2, ch, ch->exp, 1000);
            i = buf2; break;
         case 'g' :
            sprintf( buf2, "%d", ch->gold                              );
            ADD_COLOUR(ch, buf2, L_CYAN);
            i = buf2; break;
         case 'q' :
            sprintf( buf2, "%d", ch->pcdata->quest                     );
            ADD_COLOUR(ch, buf2, L_CYAN);
            i = buf2; break;
         case 'f' :
            if ( ( victim = ch->fighting ) == NULL )
            {
	       strcpy( buf2, "N/A" );
               ADD_COLOUR(ch, buf2, L_CYAN);
            }
            else
            {
               if ((victim->hit*100/victim->max_hit) < 25)
               {strcpy(buf2, "Awful");ADD_COLOUR(ch, buf2, L_RED);}
               else if ((victim->hit*100/victim->max_hit) < 50)
               {strcpy(buf2, "Poor");ADD_COLOUR(ch, buf2, L_BLUE);}
               else if ((victim->hit*100/victim->max_hit) < 75)
               {strcpy(buf2, "Fair");ADD_COLOUR(ch, buf2, L_GREEN);}
               else if ((victim->hit*100/victim->max_hit) < 100)
               {strcpy(buf2, "Good");ADD_COLOUR(ch, buf2, YELLOW);}
               else if ((victim->hit*100/victim->max_hit) >= 100)
               {strcpy(buf2, "Perfect");ADD_COLOUR(ch, buf2, L_CYAN);}
            }
            i = buf2; break;
         case 'F' :
            if ( ( victim = ch->fighting ) == NULL )
            {
	       strcpy( buf2, "N/A" );
               ADD_COLOUR(ch, buf2, L_CYAN);
            }
            else if ( ( tank = victim->fighting ) == NULL )
            {
	       strcpy( buf2, "N/A" );
               ADD_COLOUR(ch, buf2, L_CYAN);
            }
            else
            {
               if ((tank->hit*100/tank->max_hit) < 25)
               {strcpy(buf2, "Awful");ADD_COLOUR(ch, buf2, L_RED);}
               else if ((tank->hit*100/tank->max_hit) < 50)
               {strcpy(buf2, "Poor");ADD_COLOUR(ch, buf2, L_BLUE);}
               else if ((tank->hit*100/tank->max_hit) < 75)
               {strcpy(buf2, "Fair");ADD_COLOUR(ch, buf2, L_GREEN);}
               else if ((tank->hit*100/tank->max_hit) < 100)
               {strcpy(buf2, "Good");ADD_COLOUR(ch, buf2, YELLOW);}
               else if ((tank->hit*100/tank->max_hit) >= 100)
               {strcpy(buf2, "Perfect");ADD_COLOUR(ch, buf2, L_CYAN);}
            }
            i = buf2; break;
         case 'n' :
            if ( ( victim = ch->fighting ) == NULL )
	       strcpy( buf2, "N/A" );
            else
            {
               if ( IS_AFFECTED(victim, AFF_POLYMORPH) )
                  strcpy(buf2, victim->morph);
               else if ( IS_NPC(victim) )
                  strcpy(buf2, victim->short_descr);
               else
                  strcpy(buf2, victim->name);
               buf2[0] = UPPER(buf2[0]);
            }
            i = buf2; break;
         case 'N' :
            if ( ( victim = ch->fighting ) == NULL )
	       strcpy( buf2, "N/A" );
            else if ( ( tank = victim->fighting ) == NULL )
	       strcpy( buf2, "N/A" );
            else
            {
               if ( ch == tank )
                  strcpy(buf2, "You");
               else if ( IS_AFFECTED(tank, AFF_POLYMORPH) )
                  strcpy(buf2, tank->morph);
               else if ( IS_NPC(victim) )
                  strcpy(buf2, tank->short_descr);
               else
                  strcpy(buf2, tank->name);
               buf2[0] = UPPER(buf2[0]);
            }
            i = buf2; break;
         case 'a' :
            sprintf( buf2, "%s", IS_GOOD( ch ) ? "good"
		                  : IS_EVIL( ch ) ? "evil" : "neutral" );
            ADD_COLOUR(ch, buf2, L_CYAN);
            i = buf2; break;
         case 'A' :
            sprintf( buf2, "%d", ch->alignment                      );
            ADD_COLOUR(ch, buf2, L_CYAN);
            i = buf2; break;
         case 'r' :
            if( ch->in_room )
               sprintf( buf2, "%s", ch->in_room->name                  );
            else
               sprintf( buf2, " "                                      );
            ADD_COLOUR(ch, buf2, L_CYAN);
            i = buf2; break;
         case 'R' :
            if (!IS_NPC(ch) && (IS_CLASS(ch, CLASS_WEREWOLF) || IS_CLASS(ch, CLASS_VAMPIRE) || IS_CLASS(ch, CLASS_DEMON)))
            {
               sprintf( buf2, "%d", ch->rage);
               ADD_COLOUR(ch, buf2, D_RED);
            }
            else strcpy( buf2, "0" );
            i = buf2; break;
         case 'b' :
            sprintf( buf2, "%d", ch->beast );
            ADD_COLOUR(ch, buf2, L_CYAN);
            i = buf2; break;
         case 'B' :
            if (!IS_NPC(ch) && IS_CLASS(ch, CLASS_VAMPIRE))
            {
               sprintf( buf2, "%d", ch->pcdata->condition[COND_THIRST] );
               ADD_COLOUR(ch, buf2, D_RED);
            }
            else strcpy( buf2, "0" );
            i = buf2; break;
         case 'c' :
            sprintf( buf2, "%d", char_ac(ch) );
            i = buf2; break;
         case 'p' :
            sprintf( buf2, "%d", char_hitroll(ch) );
            COL_SCALE(buf2, ch, char_hitroll(ch), 200);
            i = buf2; break;
         case 'P' :
            sprintf( buf2, "%d", char_damroll(ch) );
            COL_SCALE(buf2, ch, char_damroll(ch), 200);
            i = buf2; break;
         case 's' :

            if (!IS_NPC(ch) && ch->pcdata->stage[2]+25 >= ch->pcdata->stage[1]
		&& ch->pcdata->stage[1] > 0)
            {
               sprintf( buf2, "yes" );
               ADD_COLOUR(ch, buf2, WHITE);
            }
            else strcpy( buf2, "no" );
            i = buf2; break;
         case 'O' :
            if ( ( victim = ch->pcdata->partner ) == NULL )
	       strcpy( buf2, "no" );
            else if (!IS_NPC(victim) && victim != NULL && victim->pcdata->stage[1] > 0
		&& victim->pcdata->stage[2]+25 >= victim->pcdata->stage[1])
            {
               sprintf( buf2, "yes" );
               ADD_COLOUR(ch, buf2, WHITE);
            }
            else strcpy( buf2, "no" );
            i = buf2; break;
         case 'l' :
            if ( ( victim = ch->pcdata->partner ) == NULL )
	       strcpy( buf2, "Nobody" );
            else
            {
               if ( IS_AFFECTED(victim, AFF_POLYMORPH) )
                  strcpy(buf2, victim->morph);
               else if ( IS_NPC(victim) )
                  strcpy(buf2, victim->short_descr);
               else
                  strcpy(buf2, victim->name);
               buf2[0] = UPPER(buf2[0]);
            }
            i = buf2; break;
        case '%' :
            sprintf( buf2, "%%"                                        );
            i = buf2; break;
      } 
      ++str;
      while( ( *point = *i ) != '\0' )
         ++point, ++i;      
   }
   write_to_buffer( d, buf, point - buf );
   return;
}


/*
 * Macintosh support functions.
 */
#if defined(macintosh)
int gettimeofday( struct timeval *tp, void *tzp )
{
    tp->tv_sec  = time( NULL );
    tp->tv_usec = 0;
}
#endif
/*

int len(char s)
{
	int l = 0;
	int x;

	if (s[0] == '\0') return 0;

	for (x = 0; x < length(s); x++)
	{
		if (s[x] == '#')
		{
			if s[x+1
		}

	}

	return l;
}
*/

/* OLC, new pager for editing long descriptions. */
/* ========================================================================= */
/* - The heart of the pager.  Thanks to N'Atas-Ha, ThePrincedom for porting  */
/*   this SillyMud code for MERC 2.0 and laying down the groundwork.         */
/* - Thanks to Blackstar, hopper.cs.uiowa.edu 4000 for which the improvements*/
/*   to the pager was modeled from.  - Kahn                                  */
/* - Safer, allows very large pagelen now, and allows to page while switched */
/*   Zavod of jcowan.reslife.okstate.edu 4000.                               */
/* ========================================================================= */

void show_string( DESCRIPTOR_DATA *d, char *input )
{
    char               *start, *end;
    char                arg[MAX_INPUT_LENGTH];
    int                 lines = 0, pagelen;

    /* Set the page length */
    /* ------------------- */

    pagelen = d->original ? d->original->pcdata->pagelen
                          : d->character->pcdata->pagelen;

    /* Check for the command entered */
    /* ----------------------------- */

    one_argument( input, arg );

    switch( UPPER( *arg ) )
    {
        /* Show the next page */

        case '\0':
        case 'C': lines = 0;
                  break;
        
        /* Scroll back a page */

        case 'B': lines = -2 * pagelen;
                  break;

        /* Help for show page */

        case 'H': write_to_buffer( d, "B     - Scroll back one page.\n\r", 0 );
                  write_to_buffer( d, "C     - Continue scrolling.\n\r", 0 );
                  write_to_buffer( d, "H     - This help menu.\n\r", 0 );
                  write_to_buffer( d, "R     - Refresh the current page.\n\r",
                                   0 );
                  write_to_buffer( d, "Enter - Continue Scrolling.\n\r", 0 );
                  return;

        /* refresh the current page */

        case 'R': lines = -1 - pagelen;
                  break;

        /* stop viewing */

        default:  free_string( d->showstr_head );
                  d->showstr_head  = NULL;
                  d->showstr_point = NULL;
                  return;
    }

    /* do any backing up necessary to find the starting point */
    /* ------------------------------------------------------ */

    if ( lines < 0 )
    {
        for( start= d->showstr_point; start > d->showstr_head && lines < 0;
             start-- )
            if ( *start == '\r' )
                lines++;
    }
    else
        start = d->showstr_point;

    /* Find the ending point based on the page length */
    /* ---------------------------------------------- */

    lines  = 0;

    for ( end= start; *end && lines < pagelen; end++ )
        if ( *end == '\r' )
            lines++;

    d->showstr_point = end;

    if ( end - start )
        write_to_buffer( d, start, end - start );

    /* See if this is the end (or near the end) of the string */
    /* ------------------------------------------------------ */

    for ( ; isspace( *end ); end++ );

    if ( !*end )
    {
        free_string( d->showstr_head );
        d->showstr_head  = NULL;
        d->showstr_point = NULL;
    }

    return;
}




 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *


 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *


 *                                                                         *


 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *


 *  Chastain, Michael Quan, and Mitchell Tse.                              *


 *                                                                         *


 *  In order to use any part of this Merc Diku Mud, you must comply with   *


 *  both the original Diku license in 'license.doc' as well the Merc       *


 *  license in 'license.txt'.  In particular, you may not remove either of *


 *  these copyright notices.                                               *


 *                                                                         *


 *  Much time and thought has gone into this software and you are          *


 *  benefitting.  We hope that you share your changes too.  What goes      *


 *  around, comes around.                                                  *


 ***************************************************************************/





#if defined(macintosh)


#include <types.h>


#else


#include <sys/types.h>


#endif


#include <stdio.h>


#include <time.h>


#include "merc.h"





/*


 * Attribute bonus tables.


 */


const	struct	str_app_type	str_app		[26]		=


{


    { -5, -4,   0,  0 },  /* 0  */


    { -5, -4,   3,  1 },  /* 1  */


    { -3, -2,   3,  2 },


    { -3, -1,  10,  3 },  /* 3  */


    { -2, -1,  25,  4 },


    { -2, -1,  55,  5 },  /* 5  */


    { -1,  0,  80,  6 },


    { -1,  0,  90,  7 },


    {  0,  0, 100,  8 },


    {  0,  0, 100,  9 },


    {  0,  0, 115, 10 }, /* 10  */


    {  0,  0, 115, 11 },


    {  0,  0, 140, 12 },


    {  0,  0, 140, 13 }, /* 13  */


    {  0,  1, 170, 14 },


    {  1,  1, 170, 15 }, /* 15  */


    {  1,  2, 195, 16 },


    {  2,  3, 220, 22 },


    {  2,  4, 250, 25 }, /* 18  */


    {  3,  5, 400, 30 },


    {  3,  6, 500, 35 }, /* 20  */


    {  4,  7, 600, 40 },


    {  5,  7, 700, 45 },


    {  6,  8, 800, 50 },


    {  8, 10, 900, 55 },


    { 10, 12, 999, 60 }  /* 25   */


};











const	struct	int_app_type	int_app		[26]		=


{


    {  1 },	/*  0 */


    {  1 },	/*  1 */


    {  1 },


    {  1 },	/*  3 */


    {  1 },


    {  1 },	/*  5 */


    {  1 },


    {  1 },


    {  1 },


    {  1 },


    {  1 },	/* 10 */


    {  1 },


    {  1 },


    {  2 },


    {  2 },


    {  2 },	/* 15 */


    {  2 },


    {  3 },


    {  3 },	/* 18 */


    {  3 },


    {  4 },	/* 20 */


    {  4 },


    {  4 },


    {  6 },


    {  6 },


    {  5 }	/* 25 */


};











const	struct	wis_app_type	wis_app		[26]		=


{


    { 0 },	/*  0 */


    { 0 },	/*  1 */


    { 0 },


    { 0 },	/*  3 */


    { 0 },


    { 1 },	/*  5 */


    { 1 },


    { 1 },


    { 1 },


    { 2 },


    { 2 },	/* 10 */


    { 2 },


    { 2 },


    { 2 },


    { 2 },


    { 3 },	/* 15 */


    { 3 },


    { 4 },


    { 5 },	/* 18 */


    { 5 },


    { 5 },	/* 20 */


    { 6 },


    { 6 },


    { 6 },


    { 6 },


    { 7 }	/* 25 */


};











const	struct	dex_app_type	dex_app		[26]		=


{


    {   60 },   /* 0 */


    {   50 },   /* 1 */


    {   50 },


    {   40 },


    {   30 },


    {   20 },   /* 5 */


    {   10 },


    {    0 },


    {    0 },


    {    0 },


    {    0 },   /* 10 */


    {    0 },


    {    0 },


    {    0 },


    {    0 },


    { - 10 },   /* 15 */


    { - 15 },


    { - 20 },


    { - 30 },


    { - 40 },


    { - 50 },   /* 20 */


    { - 60 },


    { - 75 },


    { - 90 },


    { -105 },


    { -120 }    /* 25 */


};











const	struct	con_app_type	con_app		[26]		=


{


    { -4, 20 },   /*  0 */


    { -3, 25 },   /*  1 */


    { -2, 30 },


    { -2, 35 },	  /*  3 */


    { -1, 40 },


    { -1, 45 },   /*  5 */


    { -1, 50 },


    {  0, 55 },


    {  0, 60 },


    {  0, 65 },


    {  0, 70 },   /* 10 */


    {  0, 75 },


    {  0, 80 },


    {  0, 85 },


    {  0, 88 },


    {  1, 90 },   /* 15 */


    {  2, 95 },


    {  2, 97 },


    {  3, 99 },   /* 18 */


    {  3, 99 },


    {  4, 99 },   /* 20 */


    {  4, 99 },


    {  5, 99 },


    {  6, 99 },


    {  7, 99 },


    {  8, 99 }    /* 25 */


};











/*


 * Liquid properties.


 * Used in world.obj.


 */


const	struct	liq_type	liq_table	[LIQ_MAX]	=


{


    { "water",			"clear",	{  0, 1, 10 }	},  /*  0 */


    { "beer",			"amber",	{  3, 2,  5 }	},


    { "wine",			"rose",		{  5, 2,  5 }	},


    { "ale",			"brown",	{  2, 2,  5 }	},


    { "dark ale",		"dark",		{  1, 2,  5 }	},





    { "whisky",			"golden",	{  6, 1,  4 }	},  /*  5 */


    { "lemonade",		"pink",		{  0, 1,  8 }	},


    { "firebreather",		"boiling",	{ 10, 0,  0 }	},


    { "local specialty",	"everclear",	{  3, 3,  3 }	},


    { "slime mold juice",	"green",	{  0, 4, -8 }	},





    { "milk",			"white",	{  0, 3,  6 }	},  /* 10 */


    { "tea",			"tan",		{  0, 1,  6 }	},


    { "coffee",			"black",	{  0, 1,  6 }	},


    { "blood",			"red",		{  0, 0,  5 }	},


    { "salt water",		"clear",	{  0, 1, -2 }	},





    { "cola",			"cherry",	{  0, 1,  5 }	}   /* 15 */


};











/*


 * The skill and spell table.


 * Slot numbers must never be changed as they appear in #OBJECTS sections.


 */


#define SLOT(n)	n





const	struct	skill_type	skill_table	[MAX_SKILL]	=


{





/*


 * Magic spells.


 */





    {


	"reserved",		99,


	0,			TAR_IGNORE,		POS_STANDING,


	NULL,			SLOT( 0),	 0,	 0,


	"",			""


    },





    {


	"acid blast",		2,


	spell_acid_blast,	TAR_CHAR_OFFENSIVE,	POS_FIGHTING,


	NULL,			SLOT(70),	20,	12,


	"acid blast",		"!Acid Blast!"


    },


/*


    {


	"Godbless",		12,


	spell_godbless,		TAR_CHAR_DEFENSIVE,	POS_STANDING,


	NULL,			SLOT(450),	5,	12,


	"",			"You feel God's blessing leave you."


    },


*/


    {


	"armor",		1,


	spell_armor,		TAR_CHAR_DEFENSIVE,	POS_STANDING,


	NULL,			SLOT( 1),	 5,	12,


	"",			"You feel less protected."


    },





    {


	"bless",		1,


	spell_bless,		TAR_CHAR_DEFENSIVE,	POS_STANDING,


	NULL,			SLOT( 3),	 5,	12,


	"",			"You feel less righteous."


    },





    {


	"blindness",		1,


	spell_blindness,	TAR_CHAR_OFFENSIVE,	POS_FIGHTING,


	&gsn_blindness,		SLOT( 4),	 5,	12,


	"",			"You can see again."


    },





    {


	"burning hands",	2,


	spell_burning_hands,	TAR_CHAR_OFFENSIVE,	POS_FIGHTING,


	NULL,			SLOT( 5),	15,	12,


	"burning hands",	"!Burning Hands!"


    },





    {


	"call lightning",	2,


	spell_call_lightning,	TAR_IGNORE,		POS_FIGHTING,


	NULL,			SLOT( 6),	15,	12,


	"lightning bolt",	"!Call Lightning!"


    },





    {


	"cause critical",	2,


	spell_cause_critical,	TAR_CHAR_OFFENSIVE,	POS_FIGHTING,


	NULL,			SLOT(63),	20,	12,


	"spell",		"!Cause Critical!"


    },





    {


	"cause light",		2,


	spell_cause_light,	TAR_CHAR_OFFENSIVE,	POS_FIGHTING,


	NULL,			SLOT(62),	15,	12,


	"spell",		"!Cause Light!"


    },





    {


	"cause serious",	2,


	spell_cause_serious,	TAR_CHAR_OFFENSIVE,	POS_FIGHTING,


	NULL,			SLOT(64),	17,	12,


	"spell",		"!Cause Serious!"


    },





    {


	"change sex",		2,


	spell_change_sex,	TAR_CHAR_DEFENSIVE,	POS_FIGHTING,


	NULL,			SLOT(82),	15,	12,


	"",			"Your body feels familiar again."


    },





    {


	"charm person",		4,


	spell_charm_person,	TAR_CHAR_OFFENSIVE,	POS_STANDING,


	&gsn_charm_person,	SLOT( 7),	 99,	12,


	"",			"You feel more self-confident."


    },





    {


	"chill touch",		2,


	spell_chill_touch,	TAR_CHAR_OFFENSIVE,	POS_FIGHTING,


	NULL,			SLOT( 8),	15,	12,


	"chilling touch",	"You feel less cold."


    },





    {


	"colour spray",		2,


	spell_colour_spray,	TAR_CHAR_OFFENSIVE,	POS_FIGHTING,


	NULL,			SLOT(10),	15,	12,


	"colour spray",		"!Colour Spray!"


    },





    {


	"continual light",	1,


	spell_continual_light,	TAR_IGNORE,		POS_STANDING,


	NULL,			SLOT(57),	 7,	12,


	"",			"!Continual Light!"


    },





    {


	"control weather",	2,


	spell_control_weather,	TAR_IGNORE,		POS_STANDING,


	NULL,			SLOT(11),	25,	12,


	"",			"!Control Weather!"


    },





    {


	"create food",		1,


	spell_create_food,	TAR_IGNORE,		POS_STANDING,


	NULL,			SLOT(12),	 5,	12,


	"",			"!Create Food!"


    },





    {


	"create spring",	1,


	spell_create_spring,	TAR_IGNORE,		POS_STANDING,


	NULL,			SLOT(80),	20,	12,


	"",			"!Create Spring!"


    },





    {


	"create water",		2,


	spell_create_water,	TAR_OBJ_INV,		POS_STANDING,


	NULL,			SLOT(13),	 5,	12,


	"",			"!Create Water!"


    },





    {


	"cure blindness",	1,


	spell_cure_blindness,	TAR_CHAR_DEFENSIVE,	POS_FIGHTING,


	NULL,			SLOT(14),	 5,	12,


	"",			"!Cure Blindness!"


    },





    {


	"cure critical",	2,


	spell_cure_critical,	TAR_CHAR_DEFENSIVE,	POS_FIGHTING,


	NULL,			SLOT(15),	20,	12,


	"",			"!Cure Critical!"


    },





    {


	"cure light",		2,


	spell_cure_light,	TAR_CHAR_DEFENSIVE,	POS_FIGHTING,


	NULL,			SLOT(16),	10,	12,


	"",			"!Cure Light!"


    },





    {


	"cure poison",		1,


	spell_cure_poison,	TAR_CHAR_DEFENSIVE,	POS_STANDING,


	NULL,			SLOT(43),	 5,	12,


	"",			"!Cure Poison!"


    },





    {


	"cure serious",		2,


	spell_cure_serious,	TAR_CHAR_DEFENSIVE,	POS_FIGHTING,


	NULL,			SLOT(61),	15,	12,


	"",			"!Cure Serious!"


    },





    {


	"curse",		1,


	spell_curse,		TAR_CHAR_OFFENSIVE,	POS_STANDING,


	&gsn_curse,		SLOT(17),	20,	12,


	"curse",		"The curse wears off."


    },





    {


	"detect evil",		2,


	spell_detect_evil,	TAR_CHAR_SELF,		POS_STANDING,


	NULL,			SLOT(18),	 5,	12,


	"",			"The red in your vision disappears."


    },





    {


	"detect hidden",	1,


	spell_detect_hidden,	TAR_CHAR_SELF,		POS_STANDING,


	NULL,			SLOT(44),	 5,	12,


	"",			"You feel less aware of your suroundings."


    },





    {


	"detect invis",		1,


	spell_detect_invis,	TAR_CHAR_SELF,		POS_STANDING,


	NULL,			SLOT(19),	 5,	12,


	"",			"You no longer see invisible objects."


    },





    {


	"detect magic",		2,


	spell_detect_magic,	TAR_CHAR_SELF,		POS_STANDING,


	NULL,			SLOT(20),	 5,	12,


	"",			"The detect magic wears off."


    },





    {


	"detect poison",	2,


	spell_detect_poison,	TAR_OBJ_INV,		POS_STANDING,


	NULL,			SLOT(21),	 5,	12,


	"",			"!Detect Poison!"


    },





    {


	"dispel evil",		2,


	spell_dispel_evil,	TAR_CHAR_OFFENSIVE,	POS_FIGHTING,


	NULL,			SLOT(22),	15,	12,


	"dispel evil",		"!Dispel Evil!"


    },





    {


	"dispel magic",		1,


	spell_dispel_magic,	TAR_CHAR_OFFENSIVE,	POS_FIGHTING,


	NULL,			SLOT(59),	15,	12,


	"",			"!Dispel Magic!"


    },








    {


	"earthquake",		2,


	spell_earthquake,	TAR_IGNORE,		POS_FIGHTING,


	NULL,			SLOT(23),	15,	12,


	"earthquake",		"!Earthquake!"


    },





    {


	"enchant weapon",	1,


	spell_enchant_weapon,	TAR_OBJ_INV,		POS_STANDING,


	NULL,			SLOT(24),	100,	24,


	"",			"!Enchant Weapon!"


    },





    {


	"energy drain",		1,


	spell_energy_drain,	TAR_CHAR_OFFENSIVE,	POS_FIGHTING,


	NULL,			SLOT(25),	35,	12,


	"energy drain",		"!Energy Drain!"


    },





    {


	"faerie fire",		2,


	spell_faerie_fire,	TAR_CHAR_OFFENSIVE,	POS_FIGHTING,


	NULL,			SLOT(72),	 5,	12,


	"faerie fire",		"The pink aura around you fades away."


    },





    {


	"faerie fog",		2,


	spell_faerie_fog,	TAR_IGNORE,		POS_STANDING,


	NULL,			SLOT(73),	12,	12,


	"faerie fog",		"!Faerie Fog!"


    },





    {


	"fireball",		1,


	spell_fireball,		TAR_CHAR_OFFENSIVE,	POS_FIGHTING,


	NULL,			SLOT(26),	15,	12,


	"fireball",		"!Fireball!"


    },





    {


	"flamestrike",		2,


	spell_flamestrike,	TAR_CHAR_OFFENSIVE,	POS_FIGHTING,


	NULL,			SLOT(65),	20,	12,


	"flamestrike",		"!Flamestrike!"


    },





    {


	"fly",			1,


	spell_fly,		TAR_CHAR_DEFENSIVE,	POS_STANDING,


	NULL,			SLOT(56),	10,	18,


	"",			"You slowly float to the ground."


    },





    {


	"gate",			7,


	spell_gate,		TAR_CHAR_DEFENSIVE,	POS_FIGHTING,


	NULL,			SLOT(83),	50,	12,


	"",			"!Gate!"


    },





    {


	"giant strength",	1,


	spell_giant_strength,	TAR_CHAR_DEFENSIVE,	POS_STANDING,


	NULL,			SLOT(39),	20,	12,


	"",			"You feel weaker."


    },





    {


	"harm",			1,


	spell_harm,		TAR_CHAR_OFFENSIVE,	POS_FIGHTING,


	NULL,			SLOT(27),	35,	12,


	"harm spell",		"!Harm!"


    },





    {


	"heal",			1,


	spell_heal,		TAR_CHAR_DEFENSIVE,	POS_FIGHTING,


	NULL,			SLOT(28),	50,	12,


	"",			"!Heal!"


    },





    {


	"identify",		1,


	spell_identify,		TAR_OBJ_INV,		POS_STANDING,


	NULL,			SLOT(53),	12,	24,


	"",			"!Identify!"


    },





    {


	"infravision",		1,


	spell_infravision,	TAR_CHAR_DEFENSIVE,	POS_STANDING,


	NULL,			SLOT(77),	 5,	18,


	"",			"You no longer see in the dark."


    },





    {


	"invis",		1,


	spell_invis,		TAR_CHAR_DEFENSIVE,	POS_STANDING,


	&gsn_invis,		SLOT(29),	 5,	12,


	"",			"You are no longer invisible."


    },





    {


	"know alignment",	2,


	spell_know_alignment,	TAR_CHAR_OFFENSIVE,	POS_FIGHTING,


	NULL,			SLOT(58),	 9,	12,


	"",			"!Know Alignment!"


    },





    {


	"lightning bolt",	2,


	spell_lightning_bolt,	TAR_CHAR_OFFENSIVE,	POS_FIGHTING,


	NULL,			SLOT(30),	15,	12,


	"lightning bolt",	"!Lightning Bolt!"


    },





    {


	"locate object",	1,


	spell_locate_object,	TAR_IGNORE,		POS_STANDING,


	NULL,			SLOT(31),	20,	18,


	"",			"!Locate Object!"


    },





    {


	"magic missile",	2,


	spell_magic_missile,	TAR_CHAR_OFFENSIVE,	POS_FIGHTING,


	NULL,			SLOT(32),	15,	4,


	"magic missile",	"!Magic Missile!"


    },





    {


	"mass invis",		1,


	spell_mass_invis,	TAR_IGNORE,		POS_STANDING,


	&gsn_mass_invis,	SLOT(69),	20,	24,


	"",			"!Mass Invis!"


    },





    {


	"pass door",		1,


	spell_pass_door,	TAR_CHAR_SELF,		POS_STANDING,


	NULL,			SLOT(74),	20,	12,


	"",			"You feel solid again."


    },





    {


	"poison",		1,


	spell_poison,		TAR_CHAR_OFFENSIVE,	POS_STANDING,


	&gsn_poison,		SLOT(33),	10,	12,


	"poison",		"You feel less sick."


    },





    {


	"protection",		1,


	spell_protection,	TAR_CHAR_SELF,		POS_STANDING,


	NULL,			SLOT(34),	 5,	12,


	"",			"You feel less protected."


    },





    {


	"refresh",		2,


	spell_refresh,		TAR_CHAR_DEFENSIVE,	POS_STANDING,


	NULL,			SLOT(81),	12,	18,


	"refresh",		"!Refresh!"


    },





    {


	"remove curse",		2,


	spell_remove_curse,	TAR_IGNORE,		POS_STANDING,


	NULL,			SLOT(35),	 5,	12,


	"",			"!Remove Curse!"


    },





    {


	"sanctuary",		1,


	spell_sanctuary,	TAR_CHAR_DEFENSIVE,	POS_STANDING,


	NULL,			SLOT(36),	75,	12,


	"",			"The white aura around your body fades."


    },





    {


	"shield",		1,


	spell_shield,		TAR_CHAR_DEFENSIVE,	POS_STANDING,


	NULL,			SLOT(67),	12,	18,


	"",			"Your force shield shimmers then fades away."


    },





    {


	"shocking grasp",	2,


	spell_shocking_grasp,	TAR_CHAR_OFFENSIVE,	POS_FIGHTING,


	NULL,			SLOT(37),	15,	12,


	"shocking grasp",	"!Shocking Grasp!"


    },





    {


	"sleep",		4,


	spell_sleep,		TAR_CHAR_OFFENSIVE,	POS_STANDING,


	&gsn_sleep,		SLOT(38),	99,	12,


	"",			"You feel less tired."


    },





    {


	"stone skin",		1,


	spell_stone_skin,	TAR_CHAR_SELF,		POS_STANDING,


	NULL,			SLOT(66),	12,	18,


	"",			"Your skin feels soft again."


    },





    {


	"summon",		2,


	spell_summon,		TAR_IGNORE,		POS_STANDING,


	NULL,			SLOT(40),	50,	12,


	"",			"!Summon!"


    },





    {


	"teleport",		2,


	spell_teleport,		TAR_CHAR_SELF,		POS_FIGHTING,


	NULL,	 		SLOT( 2),	35,	12,


	"",			"!Teleport!"


    },





    {


	"ventriloquate",	2,


	spell_ventriloquate,	TAR_IGNORE,		POS_STANDING,


	NULL,			SLOT(41),	 5,	12,


	"",			"!Ventriloquate!"


    },





    {


	"weaken",		2,


	spell_weaken,		TAR_CHAR_OFFENSIVE,	POS_FIGHTING,


	NULL,			SLOT(68),	20,	12,


	"spell",		"You feel stronger."


    },





    {


	"word of recall",	9,


	spell_word_of_recall,	TAR_CHAR_SELF,		POS_RESTING,


	NULL,			SLOT(42),	 5,	12,


	"",			"!Word of Recall!"


    },





/*


 * Dragon breath


 */


    {


	"acid breath",		1,


	spell_acid_breath,	TAR_CHAR_OFFENSIVE,	POS_FIGHTING,


	NULL,			SLOT(200),	 50,	 12,


	"blast of acid",	"!Acid Breath!"


    },





    {


	"fire breath",		1,


	spell_fire_breath,	TAR_CHAR_OFFENSIVE,	POS_FIGHTING,


	NULL,			SLOT(201),	 50,	 12,


	"blast of flame",	"The smoke leaves your eyes."


    },





    {


	"frost breath",		1,


	spell_frost_breath,	TAR_CHAR_OFFENSIVE,	POS_FIGHTING,


	NULL,			SLOT(202),	 50,	 12,


	"blast of frost",	"!Frost Breath!"


    },





    {


	"gas breath",		1,


	spell_gas_breath,	TAR_IGNORE,		POS_FIGHTING,


	NULL,			SLOT(203),	 50,	 12,


	"blast of gas",		"!Gas Breath!"


    },





    {


	"lightning breath",	1,


	spell_lightning_breath,	TAR_CHAR_OFFENSIVE,	POS_FIGHTING,


	NULL,			SLOT(204),	 50,	 12,


	"blast of lightning",	"!Lightning Breath!"


    },





    {


        "Godbless",             12,


        spell_godbless,         TAR_CHAR_DEFENSIVE,     POS_STANDING,


        NULL,                   SLOT(205),      5,      12,


        "",                     "You feel God's blessing leave you."


    },





/*


 * Fighter and thief skills.


 */


    {


	"backstab",		1,


	spell_null,		TAR_IGNORE,		POS_STANDING,


	&gsn_backstab,		SLOT( 0),	 0,	24,


	"backstab",		"!Backstab!"


    },





    {


	"garotte",		99,


	spell_null,		TAR_IGNORE,		POS_STANDING,


	&gsn_garotte,		SLOT( 0),	0,	24,


	"garotte",		"!Garotte!"


    },





     {


	"spiderform",		99,


	spell_null,		TAR_IGNORE,		POS_FIGHTING,


	&gsn_spiderform,	SLOT(0),	0,	0,


	"spidery arm",		"!Spiderform!"


    },





    {


	"disarm",		1,


	spell_null,		TAR_IGNORE,		POS_FIGHTING,


	&gsn_disarm,		SLOT( 0),	 0,	24,


	"",			"!Disarm!"


    },





    {


	"hide",			1,


	spell_null,		TAR_IGNORE,		POS_RESTING,


	&gsn_hide,		SLOT( 0),	 0,	12,


	"",			"!Hide!"


    },





    {


	"hurl",			1,


	spell_null,		TAR_IGNORE,		POS_STANDING,


	&gsn_hurl,		SLOT( 0),	 0,	24,


	"",			"!Hurl!"


    },





    {


	"kick",			1,


	spell_null,		TAR_CHAR_OFFENSIVE,	POS_FIGHTING,


	&gsn_kick,		SLOT( 0),	 0,	 8,


	"kick",			"!Kick!"


    },



    {
	"laser",		99,
	spell_null,		TAR_CHAR_OFFENSIVE,	POS_FIGHTING,
	&gsn_laser,		SLOT( 0),	0,	24,
	"laser",		"!Laser!"
    },

    {
	"stuntubes",		99,
	spell_null,		TAR_CHAR_OFFENSIVE,	POS_FIGHTING,
	&gsn_stuntubes,		SLOT( 0),	0,	24,
	"stuntubes",		"!Stuntubes!"
    },



    {
	"circle",		99,
	spell_null,		TAR_CHAR_OFFENSIVE,	POS_FIGHTING,
	&gsn_circle,	SLOT(0),	0,	24,
	"swift circle attack",	"!Circle!"
    },

    {


	"peek",			1,


	spell_null,		TAR_IGNORE,		POS_STANDING,


	&gsn_peek,		SLOT( 0),	 0,	 0,


	"",			"!Peek!"


    },





    {


	"pick lock",		1,


	spell_null,		TAR_IGNORE,		POS_STANDING,


	&gsn_pick_lock,		SLOT( 0),	 0,	12,


	"",			"!Pick!"


    },





    {


	"rescue",		1,


	spell_null,		TAR_IGNORE,		POS_FIGHTING,


	&gsn_rescue,		SLOT( 0),	 0,	12,


	"",			"!Rescue!"


    },





    {


	"sneak",		1,


	spell_null,		TAR_IGNORE,		POS_STANDING,


	&gsn_sneak,		SLOT( 0),	 0,	12,


	"",			"Your footsteps are no longer so quiet."


    },





    {


	"steal",		1,


	spell_null,		TAR_IGNORE,		POS_STANDING,


	&gsn_steal,		SLOT( 0),	 0,	24,


	"",			"!Steal!"


    },





/*


 * Spells for mega1.are from Glop/Erkenbrand.


 */


    {


	"general purpose",	7,


	spell_general_purpose,	TAR_CHAR_OFFENSIVE,	POS_FIGHTING,


	NULL,			SLOT(501),	0,	12,


	"general purpose ammo",	"!General Purpose Ammo!"


    },





    {


	"high explosive",	7,


	spell_high_explosive,	TAR_CHAR_OFFENSIVE,	POS_FIGHTING,


	NULL,			SLOT(502),	0,	12,


	"high explosive ammo",	"!High Explosive Ammo!"


    },





/*


 * Spells added by KaVir.


 */


    {


	"guardian",		12,


	spell_guardian,		TAR_CHAR_DEFENSIVE,	POS_STANDING,


	NULL,			SLOT(600),	100,	12,


	"",			"!Guardian!"


    },





    {


	"soulblade",		1,


	spell_soulblade,	TAR_CHAR_DEFENSIVE,	POS_STANDING,


	NULL,			SLOT(601),	100,	12,


	"",			"!Soulblade!"


    },





    {


	"mana",			1,


	spell_mana,		TAR_CHAR_DEFENSIVE,	POS_STANDING,


	NULL,			SLOT(602),	 0,	12,


	"",			"!Mana!"


    },





    {


	"frenzy",		1,


	spell_frenzy,		TAR_CHAR_DEFENSIVE,	POS_STANDING,


	NULL,			SLOT(603),	 20,	12,


	"",			"Your bloodlust subsides."


    },





    {


	"darkblessing",		1,


	spell_darkblessing,	TAR_CHAR_DEFENSIVE,	POS_STANDING,


	NULL,			SLOT(604),	 20,	12,


	"",			"You feel less wicked."


    },





    {


	"portal",		1,


	spell_portal,		TAR_IGNORE,		POS_STANDING,


	NULL,			SLOT(604),	 50,	12,


	"",			"!Portal!"


    },





    {


	"energyflux",		2,


	spell_energyflux,	TAR_CHAR_DEFENSIVE,	POS_STANDING,


	NULL,			SLOT(605),	 0,	12,


	"",			"!EnergyFlux!"


    },





    {


	"voodoo",		1,


	spell_voodoo,		TAR_IGNORE,		POS_STANDING,


	NULL,			SLOT(606),	 100,	12,


	"",			"!Voodoo!"


    },





    {


	"transport",		1,


	spell_transport,	TAR_OBJ_INV,		POS_STANDING,


	NULL,			SLOT(607),	12,	24,


	"",			"!Transport!"


    },





    {


	"regenerate",		1,


	spell_regenerate,	TAR_OBJ_INV,		POS_STANDING,


	NULL,			SLOT(608),	100,	12,


	"",			"!Regenerate!"


    },





    {


	"clot",			1,


	spell_clot,		TAR_CHAR_DEFENSIVE,	POS_STANDING,


	NULL,			SLOT(609),	50,	12,


	"",			"!Clot!"


    },





    {


	"mend",			1,


	spell_mend,		TAR_CHAR_DEFENSIVE,	POS_STANDING,


	NULL,			SLOT(610),	50,	12,


	"",			"!Mend!"


    },





    {


	"punch",		1,


	spell_null,		TAR_IGNORE,		POS_STANDING,


	&gsn_punch,		SLOT( 0),	 0,	24,


	"punch",		"!Punch!"


    },





    {


	"elbow",		99,


	spell_null,		TAR_IGNORE,		POS_STANDING,


	&gsn_elbow,		SLOT( 0),	 0,	24,


	"elbow",		"!Elbow!"


    },





    {


	"headbutt",		99,


	spell_null,		TAR_IGNORE,		POS_STANDING,


	&gsn_headbutt,		SLOT( 0),	 0,	24,


	"headbutt",		"!Headbutt!"


    },



    {
	"shiroken",		99,
	spell_null,		TAR_IGNORE,	POS_STANDING,
	&gsn_shiroken,	SLOT( 0),	0,	24,
	"shiroken",		"!Shiroken!"
    },

    {
	"blinky",		99,
	spell_null,		TAR_IGNORE,		POS_STANDING,
	&gsn_blinky,		SLOT( 0),	0,	24,
	"surprise attack",	"!BLINKY!"
    },

    {
	"inferno",		99,
	spell_null,		TAR_IGNORE,		POS_STANDING,
	&gsn_inferno,		SLOT( 0),	0,	24,
	"blazing flames",	"!Ooo Inferno!"
    },

    {


	"fangs",		99,


	spell_null,		TAR_IGNORE,		POS_STANDING,


	&gsn_fangs,		SLOT( 0),	0,	24,


	"fangs",		"!Fangs!"


    },





    {


	"buffet",		99,


	spell_null,		TAR_IGNORE,		POS_STANDING,


	&gsn_buffet,		SLOT( 0),	0,	24,


	"wing buffet",		"!Buffet!"


    },





    {


	"sweep",		99,


	spell_null,		TAR_IGNORE,		POS_STANDING,


	&gsn_sweep,		SLOT( 0),	 0,	24,


	"tail sweep",		"!Sweep!"


    },



    {
	"backfist",		99,
	spell_null,		TAR_IGNORE,		POS_STANDING,
	&gsn_backfist,		SLOT( 0),	0,	24,
	"backfist",		"!Sweep!"
    },

    {
	"jumpkick",		99,
	spell_null,		TAR_IGNORE,		POS_STANDING,
	&gsn_jumpkick,		SLOT( 0),	0,	24,
	"jump kick",		"!JUMPKICK!"
    },

    {
	"spinkick",		99,
	spell_null,		TAR_IGNORE,		POS_STANDING,
	&gsn_spinkick,		SLOT( 0),	0,	24,
	"spin kick",		"!SPINKICK!"
    },

    {  "monksweep",		99,
	spell_null,		TAR_IGNORE,		POS_STANDING,
	&gsn_monksweep,		SLOT( 0),	0,	24,
	"foot sweep",		"!MONKSWEEEP!"
    },

    {
	"thrust kick",		99,
	spell_null,		TAR_IGNORE,		POS_STANDING,
	&gsn_thrustkick,	SLOT( 0),	0,	24,
	"thrust kick",		"!THRUST KICK!"
    },

    {
	"elbow",		99,
	spell_null,		TAR_IGNORE,		POS_STANDING,
	&gsn_elbow,		SLOT( 0),	0,	24,
	"elbow strike",		"!Elbow!"
    },

    {
	"shinkick",		99,
	spell_null,		TAR_IGNORE,		POS_STANDING,
	&gsn_shinkick,		SLOT( 0),	0,	24,
	"shin kick",		"lala"
    },

    {
	"palm strike",		99,
	spell_null,		TAR_IGNORE,		POS_STANDING,
	&gsn_palmstrike,	SLOT( 0),	0,	24,
	"palm strike",		"lala"
    },

    {
	"lightning kick",	99,
	spell_null,		TAR_IGNORE,		POS_STANDING,
	&gsn_lightningkick,	SLOT( 0),	0,	24,
	"lightning kick",	"lala"
    },

    {
	"tornado kick",		99,
	spell_null,		TAR_IGNORE,		POS_STANDING,
	&gsn_tornadokick,	SLOT( 0),	0,	24,
	"tornado kick",		"poop"
    },

    {


       "rfangs",                99,


        spell_null,             TAR_IGNORE,              POS_STANDING,


        &gsn_rfangs,            SLOT(0),          0,    24, 


        "razor fangs",           "!Rfangs!"


    },


    {


	"knee",			99,


	spell_null,		TAR_IGNORE,		POS_STANDING,


	&gsn_knee,		SLOT( 0),	 0,	24,


	"knee strike",		"!Knee!"


    },





    {


	"quest",		1,


	spell_quest,		TAR_IGNORE,		POS_STANDING,


	NULL,			SLOT(611),	 500,	12,


	"",			"!Quest!"


    },





    {


	"minor creation",	1,


	spell_minor_creation,	TAR_IGNORE,		POS_STANDING,


	NULL,			SLOT(612),	 500,	12,


	"",			"!MinorCreation!"


    },





    {


	"brew",			4,


	spell_brew,		TAR_OBJ_INV,		POS_STANDING,


	NULL,			SLOT(613),	 100,	12,


	"",			"!Brew!"


    },





    {


	"scribe",		4,


	spell_scribe,		TAR_OBJ_INV,		POS_STANDING,


	NULL,			SLOT(614),	 100,	12,


	"",			"!Scribe!"


    },





    {


	"carve",		4,


	spell_carve,		TAR_OBJ_INV,		POS_STANDING,


	NULL,			SLOT(615),	 200,	12,


	"",			"!Carve!"


    },





    {


	"engrave",		4,


	spell_engrave,		TAR_OBJ_INV,		POS_STANDING,


	NULL,			SLOT(616),	 300,	12,


	"",			"!Engrave!"


    },





    {


	"bake",			4,


	spell_bake,		TAR_OBJ_INV,		POS_STANDING,


	NULL,			SLOT(617),	 100,	12,


	"",			"!Bake!"


    },





    {


	"mount",		2,


	spell_mount,		TAR_CHAR_DEFENSIVE,	POS_STANDING,


	NULL,			SLOT(618),	100,	12,


	"",			"!Mount!"


    },





    {


	"berserk",		2,


	spell_null,		TAR_IGNORE,		POS_FIGHTING,


	&gsn_berserk,		SLOT( 0),	 0,	24,


	"",			"!Berserk!"


    },





    {


        "tendrils",                  99,


        spell_tendrils,              TAR_CHAR_OFFENSIVE,     POS_STANDING,


        &gsn_tendrils,               SLOT( 0),       100,   12,


        "",                     "The tendrils surrounding you fade away."


    },








    {


	"scan",			1,


	spell_scan,		TAR_IGNORE,		POS_STANDING,


	NULL,			SLOT(619),	6,	24,


	"",			"!Scan!"


    },





    {


	"repair",		2,


	spell_repair,		TAR_IGNORE,		POS_STANDING,


	NULL,			SLOT(620),	100,	24,


	"",			"!Repair!"


    },





    {


	"spellproof",		2,


	spell_spellproof,	TAR_OBJ_INV,		POS_STANDING,


	NULL,			SLOT(621),	50,	12,


	"",			"!Spellproof!"


    },





    {


	"preserve",		3,


	spell_preserve,		TAR_OBJ_INV,		POS_STANDING,


	NULL,			SLOT(550),	12,	24,


	"",			"!Preserve!"


    },





    {


	"track",		1,


	spell_null,		TAR_IGNORE,		POS_STANDING,


	&gsn_track,		SLOT( 0),	 0,	0,


	"",			"!Track!"


    },





    {


	"major creation",	4,


	spell_major_creation,	TAR_IGNORE,		POS_STANDING,


	NULL,			SLOT(551),	 100,	12,


	"",			"!MajorCreation!"


    },





    {


	"copy",			4,


	spell_copy,		TAR_IGNORE,		POS_STANDING,


	NULL,			SLOT(552),	 100,	12,


	"",			"!Copy!"


    },





    {


	"insert page",		4,


	spell_insert_page,	TAR_IGNORE,		POS_STANDING,


	NULL,			SLOT(553),	 10,	12,


	"",			"!InsertPage!"


    },





    {


	"purple sorcery",	99,


	spell_null,		TAR_IGNORE,		POS_STANDING,


	NULL,			SLOT(554),	 100,	12,


	"",			"The purple spell on you fades away."


    },





    {


	"red sorcery",		99,


	spell_null,		TAR_IGNORE,		POS_STANDING,


	NULL,			SLOT(555),	 100,	12,


	"",			"The red spell on you fades away."


    },





    {


	"blue sorcery",		99,


	spell_null,		TAR_IGNORE,		POS_STANDING,


	NULL,			SLOT(556),	 100,	12,


	"",			"The blue spell on you fades away."


    },





    {


	"green sorcery",	99,


	spell_null,		TAR_IGNORE,		POS_STANDING,


	NULL,			SLOT(557),	 100,	12,


	"",			"The green spell on you fades away."


    },





    {


	"yellow sorcery",	99,


	spell_null,		TAR_IGNORE,		POS_STANDING,


	NULL,			SLOT(558),	 100,	12,


	"",			"The yellow spell on you fades away."


    },





    {


	"chaos blast",		99,


	spell_chaos_blast,	TAR_CHAR_OFFENSIVE,	POS_FIGHTING,


	NULL,			SLOT(559),	20,	12,


	"chaos blast",		"!Chaos Blast!"


    },





    {


	"resistance",		1,


	spell_resistance,	TAR_OBJ_INV,		POS_STANDING,


	NULL,			SLOT(560),	50,	12,


	"",			"!Resistance!"


    },





    {


	"web",			99,


	spell_web,		TAR_CHAR_OFFENSIVE,	POS_STANDING,


	&gsn_web,		SLOT(561),	 100,	12,


	"",			"The web surrounding you breaks away."


    },








    {


	"polymorph",		4,


	spell_polymorph,	TAR_IGNORE,		POS_STANDING,


	&gsn_polymorph,		SLOT(562),	50,	12,


	"",			"You resume your normal form."


    },








    {


	"remove page",		4,


	spell_remove_page,	TAR_IGNORE,		POS_STANDING,


	NULL,			SLOT(564),	 10,	12,


	"",			"!RemovePage!"


    },





    {


	"find familiar",	4,


	spell_find_familiar,	TAR_IGNORE,		POS_STANDING,


	NULL,			SLOT(565),	100,	12,


	"",			""


    },





    {


	"improve",		1,


	spell_improve,		TAR_OBJ_INV,		POS_STANDING,


	NULL,			SLOT(566),	1500,	12,


	"",			"!Improve!"


    },








    { "spew",                   13,


      spell_spew,               TAR_IGNORE,        POS_STANDING,     


      &gsn_spew,                    SLOT(0),         10,     12,


      "spew of blood",         "!Spew!"


    },


    {


	"infirmity",		13,


	spell_infirmity,        	TAR_IGNORE,	POS_STANDING,


        NULL,		SLOT( 0),	 5,	12,


	"infirmity",			"You feel stronger."


    },


    {


	"shred",		13,


	spell_null,		TAR_IGNORE,		POS_STANDING,


	&gsn_shred,		SLOT( 0),	 0,	24,


	"shredding assault",		"!Shred!"


    },








    {


	"cheapshot",		13,


	spell_null,		TAR_IGNORE,		POS_STANDING,


	&gsn_cheapshot,		SLOT( 0),	 0,	24,


	"cheapshot",		"!cheapsht!"


    },





    {


	"quills",		13,


	spell_null,		TAR_IGNORE,		POS_STANDING,


	&gsn_quills,		SLOT( 0),	 0,	24,


	"razor quills",		"!quills!"


    },





    {


        "venom tongue",               13,


        spell_null,             TAR_IGNORE,             POS_STANDING,


        &gsn_venomtong,            SLOT( 0),        0,     24,


        "venom tongue",         "!VTong!"


    },  





    {


        "spiked tail",               13,


        spell_null,             TAR_IGNORE,             POS_STANDING,


        &gsn_spiketail,            SLOT( 0),        0,     24,


        "spiked tail",         "!stail!"


    },  





    {


        "bad breath",               13,


        spell_null,             TAR_IGNORE,             POS_STANDING,


        &gsn_badbreath,            SLOT( 0),        0,     24,


        "bad breath",         "!BBreath!"


    },  





    {


        "magma burst",               13,


        spell_null,             TAR_IGNORE,             POS_STANDING,


        &gsn_magma,            SLOT( 0),        0,     24,


        "magma burst",         "!Magma!"


    },     





    {


        "ice shards",               13,


        spell_null,             TAR_IGNORE,             POS_STANDING,


        &gsn_shards,            SLOT( 0),        0,     24,


        "ice shards",         "!IShards!"


    }, 





    {


	"drowfire",	99,


	spell_drowfire,		TAR_CHAR_OFFENSIVE,   POS_STANDING,


	&gsn_drowfire,		SLOT(570),	100,	12,


	"",			"The drowfire fades away."


	},





    {


	"paradox",		10,


	spell_null,		TAR_CHAR_SELF,	POS_STANDING,


	&gsn_paradox,		SLOT( 90),	 5,	12,


	NULL,			"Your paradox fades."


    }








};








#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"
#include "player.h"

void do_implant( CHAR_DATA *ch, char *argument )
{
  char arg1[MAX_INPUT_LENGTH];
  char arg2[MAX_INPUT_LENGTH];
  char buf[MAX_STRING_LENGTH];

  argument = one_argument( argument, arg1 );
  argument = one_argument( argument, arg2 );

  if (IS_NPC(ch)) return;

  if (!IS_CLASS(ch, CLASS_CYBORG))
  {
    send_to_char("Huh?\n\r",ch);
    return;
  }

  if ( arg1[0] == '\0' && arg2[0] == '\0')
  {
    sprintf(buf,"Current implant levels: #1Face: #9%d, #1Limbs: #9%d, #1Body: #9%d.\n\r",
    ch->pcdata->powers[CYBORG_FACE],
    ch->pcdata->powers[CYBORG_LIMBS],
    ch->pcdata->powers[CYBORG_BODY]);
    send_to_char(buf,ch);
    return;
  }

  if (arg2[0] == '\0')
  {
    if (!str_cmp(arg1,"face"))
    {
      send_to_char("Current Facial Implants:\n\r",ch);
      if (ch->pcdata->powers[CYBORG_FACE] < 1)
      send_to_char("None.\n\r",ch);
      if (ch->pcdata->powers[CYBORG_FACE] > 0)
      {
        if (ch->pcdata->powers[CYBORG_FACE] > 3)
        {
          send_to_char("Your infravision is level 3, you can see everything.\n\r",ch);
          send_to_char("Your head implants radiates a shield protecting you.\n\r",ch);
          send_to_char("Your sensors are improved, allowing you to see the stats\n\rand location of others.\n\r",ch);
          return;
        }
        else if ((ch->pcdata->powers[CYBORG_FACE] = 2))
        send_to_char("Your infravision allows you to see in the night and shadows.n\r",ch);
        else if ((ch->pcdata->powers[CYBORG_FACE] = 1))
        send_to_char("Your infravision allows you to see in the night.\n\r",ch);
      }
    return;
    }
    else if (!str_cmp(arg1,"limbs"))
    {
      send_to_char("Current Limb Implants:\n\r",ch);
      if (ch->pcdata->powers[CYBORG_LIMBS] < 1)
      send_to_char("None.\n\r",ch);
      if (ch->pcdata->powers[CYBORG_LIMBS] > 0)
      send_to_char("You have extra muscle implants giving you super strength.\n\r",ch);
      if (ch->pcdata->powers[CYBORG_LIMBS] > 1)
      send_to_char("Your limbs have been adjusted to move 5 x faster.\n\r",ch);
      if (ch->pcdata->powers[CYBORG_LIMBS] > 2)
      send_to_char("You have extra strength implants in, you can lift anything.\n\r",ch);
      if (ch->pcdata->powers[CYBORG_LIMBS] > 3)
      send_to_char("Your arms have been implanted with the power to have higher weaponskills.\n\r",ch);
      if (ch->pcdata->powers[CYBORG_LIMBS] > 4)
      send_to_char("You have lasers implanted into your arms.\n\r",ch);
      return;
    }
    else if (!str_cmp(arg1,"body"))
    {
      send_to_char("Current Body Implants:\n\r",ch);
      if (ch->pcdata->powers[CYBORG_BODY] < 1)
      send_to_char("None.\n\r",ch);
      if (ch->pcdata->powers[CYBORG_BODY] > 0)
      send_to_char("Your body's armor has been increased greatly.\n\r",ch);
      if (ch->pcdata->powers[CYBORG_BODY] > 1)
      send_to_char("Your body can absorb certain attacks.\n\r",ch);
      if (ch->pcdata->powers[CYBORG_BODY] > 2)
      send_to_char("You body slam your enemy when you have first attack.\n\r",ch);
      if (ch->pcdata->powers[CYBORG_BODY] > 3)
      send_to_char("You have the power to cloak yourself and become invisible.\n\r",ch);
      if (ch->pcdata->powers[CYBORG_BODY] > 4)
      send_to_char("You have poisoned stingers that shoot at your enemies from your body.\n\r",ch);
      if (ch->pcdata->powers[CYBORG_BODY] > 5)
      send_to_char("You regenerate very fast.\n\r",ch);
      return;
    }
    sprintf(buf,"Current implant levels: #1Face: #9%d, #1Limbs: #9%d, #1Body: #9%d.\n\r",
    ch->pcdata->powers[CYBORG_FACE],
    ch->pcdata->powers[CYBORG_LIMBS],
    ch->pcdata->powers[CYBORG_BODY]);
    send_to_char(buf,ch);
    return;
  }
  if (!str_cmp(arg2,"improve"))
  {
      int implant;
      int cost;
      int max;

      if (!str_cmp(arg1,"face" )) {implant = CYBORG_FACE; max = 5;}
      else if (!str_cmp(arg1,"limbs")) {implant = CYBORG_LIMBS; max = 5;}
      else if (!str_cmp(arg1,"body")) {implant = CYBORG_BODY; max = 6;}
      else
      {
        send_to_char("Implants are face, limbs, and body.\n\r",ch);
        return;
      }
      if ((ch->pcdata->powers[implant] == 1)) cost = 3000;
      else if ((ch->pcdata->powers[implant] == 2)) cost = 6000;
      else if ((ch->pcdata->powers[implant] == 3)) cost = 9000;
      else if ((ch->pcdata->powers[implant] == 4)) cost = 12000;
      else if ((ch->pcdata->powers[implant] == 5)) cost = 16000;
      else if ((ch->pcdata->powers[implant] == 6)) cost = 20000;
      else cost = 1000;
      arg1[0] = UPPER(arg1[0]);
      if (ch->pcdata->powers[implant] >= max )
      {
        sprintf(buf,"You already have all implants on your %s.\n\r",arg1);
        send_to_char(buf,ch);
        return;
      }
      if (!str_cmp(arg1,"face"))
      {
        if ((ch->pcdata->powers[CYBORG_FACE] == 4 && ch->pcdata->powers[CYBORG_BODY] < 4))
        {
          send_to_char("You need the body implant for cloaking before you can improve this.\n\r",ch);
          return;
        }
      }

      if (!str_cmp(arg1,"body"))
      {
        if (ch->pcdata->powers[CYBORG_LIMBS] < 1)
        {
          send_to_char("You need at least 1 limb implant before you can get any body implants.\n\r",ch);
          return;
        }
      }

      if ( cost > ch->pcdata->stats[CYBORG_POWER] )
      {
        sprintf(buf,"Your cyborg power must be greater than %d before you can improve your %s implants.\n\r",cost,arg1);
        send_to_char(buf,ch);
        return;
      }

      ch->pcdata->powers[implant] += 1;
      ch->pcdata->stats[CYBORG_POWER] -= cost;
      sprintf(buf,"You add an implant to your %s.\n\r",arg1);
      ADD_COLOUR(ch, buf, L_RED);
      send_to_char(buf,ch);
      return;
  }
  else send_to_char("Syntax: implant (place) improve.\n\r",ch);
  return;
}

void do_assimilate( CHAR_DATA *ch, char *argument )
{
  CHAR_DATA *victim;
  char buf[MAX_STRING_LENGTH];
  char arg[MAX_INPUT_LENGTH];

  argument = one_argument( argument, arg );

  if (IS_NPC(ch)) return;

  if (!IS_CLASS(ch, CLASS_CYBORG))
  {
    send_to_char("Huh?\n\r",ch);
    return;
  }

  if (ch->pcdata->stats[UNI_GEN] > 2)
  {
    send_to_char("Only collective leaders may assimilate others.\n\r",ch);
    return;
  }

  if (ch->pcdata->powers[CYBORG_FACE] != 5 || ch->pcdata->powers[CYBORG_LIMBS] != 5 ||
  ch->pcdata->powers[CYBORG_BODY] != 6)
  {
    send_to_char("You need all implants before you may assimilate others.\n\r",ch);
    return;
  }

  if (arg[0] == '\0' )
  {
    send_to_char("Assimilate who?\n\r",ch);
    return;
  }

  if ( (victim = get_char_room( ch, arg ) ) == NULL)
  {
    send_to_char("They are not here.\n\r",ch);
    return;
  }

  if ( IS_NPC(victim))
  {
    send_to_char("Not on NPC's.\n\r",ch);
    return;
  }

  if (IS_IMMORTAL(victim))
  {
    send_to_char("You cannot assimilate gods.\n\r",ch);
    return;
  }

  if (ch == victim )
  {
    send_to_char("You cannot assimilate yourself.\n\r",ch);
    return;
  }

  if (victim->level != LEVEL_AVATAR && !IS_IMMORTAL(victim))
  {
    send_to_char("You can only assimilate avatars.\n\r",ch);
    return;
  }

  if (ch->pcdata->stats[CYBORG_POWER] < 25000)
  {
    send_to_char("Your power level must be above 25000 before you can assimilate.\n\r",ch);
    return;
  }

  if (victim->class != 0)
  {
    send_to_char("They are already classed.\n\r",ch);
    return;
  }

  ch->pcdata->stats[CYBORG_POWER] -= 25000;
  act("Tubes fly out of your back and impale $N.",ch,NULL,victim,TO_CHAR);
  act("You begin assimilating $N.",ch,NULL,victim,TO_CHAR);
  act("You are drained of power as you complete the assimilation process.",ch,NULL,victim,TO_CHAR);
  act("Tubes fly from $n's back and impale you.",ch,NULL,victim,TO_VICT);
  act("$n begins assimilating you.",ch,NULL,victim,TO_VICT);
  act("$n staggers backwards from loss of power after assimilating you.",ch,NULL,victim,TO_VICT);
  act("Tubes fly from $n's back and impale $N.",ch,NULL,victim,TO_NOTVICT);
  act("$n begins assimilating $N.",ch,NULL,victim,TO_NOTVICT);
  act("$n staggers backwards from power drainage as $s assimilates $N.",ch,NULL,victim,TO_NOTVICT);
  victim->class = CLASS_CYBORG;
  sprintf(buf,"%n has been assimilated.",victim);
  do_info(ch,buf);
  send_to_char("You are now a cyborg.\n\r",victim);
  free_string(victim->lord);
  victim->lord = str_dup(ch->name);
  free_string(victim->clan);
  victim->clan=str_dup(ch->clan);
  victim->pcdata->stats[UNI_GEN] = ch->pcdata->stats[UNI_GEN] + 1;
  save_char_obj(ch);
  save_char_obj(victim);
  return;
}

void do_collective( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    CHAR_DATA *gch;

    if (IS_NPC(ch)) return;
    if (!IS_CLASS(ch, CLASS_CYBORG) )
    {
        send_to_char("Huh?\n\r",ch);
        return;
    }

    if (strlen(ch->clan) < 2)
    {
        send_to_char("You aren't a member of any collective.\n\r",ch);
        return;
    }

    sprintf( buf, "Members of the %s collective:\n\r", ch->clan );
    send_to_char( buf, ch );
    send_to_char("[      Name      ] [ Gen ] [ Hits  % ] [ Mana  % ] [ Move  % ]\n\r", ch );
    for ( gch = char_list; gch != NULL; gch = gch->next )
    {
        if ( IS_NPC(gch) ) continue;
        if ( !IS_CLASS(gch, CLASS_CYBORG) ) continue;
        if ( IS_CLASS(gch,CLASS_CYBORG) )
        {
            send_to_char("[Name] [Hp/Maxhp] [Mana/Max] [Move/Max] [Power] [Face] [Limbs] [Body]\n\r",ch);
            sprintf( buf,
            "[%-16s] [%-6d%3d] [%-6d%3d] [%-6d%3d] [%-7d] [%d] [%d] [%d]\n\r",
                capitalize( gch->name ),
                gch->hit,  gch->max_hit ,
                gch->mana, gch->max_mana,
                gch->move, gch->max_move,
                gch->pcdata->stats[CYBORG_POWER],
                gch->pcdata->powers[CYBORG_FACE],
                gch->pcdata->powers[CYBORG_LIMBS],
                gch->pcdata->powers[CYBORG_BODY] );
                send_to_char( buf, ch );
        }
    }
    return;
}

void do_stuntubes( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    int dam = number_range(250,750) + char_damroll(ch);
  
    if (dam < 500) dam = 750;
        
    if ( IS_NPC(ch) ) return;

    if ( !IS_CLASS(ch, CLASS_CYBORG) )   
    {
    send_to_char("Huh?\n\r", ch);
    return;
    }
        
    if (ch->pcdata->powers[CYBORG_BODY] < 5 || ch->pcdata->powers[CYBORG_LIMBS] < 5 )
    {
      send_to_char("You need level 5 implants on your limbs and body to use this.\n\r",ch);
      return;
    }
        
    if ( ( victim = ch->fighting ) == NULL )
    {
        send_to_char( "You aren't fighting anyone.\n\r", ch );
        return;
    }
    WAIT_STATE( ch,     1 * PULSE_VIOLENCE );
    WAIT_STATE( victim, 3 * PULSE_VIOLENCE );
    act("You fire a laser at $N.",ch,NULL,victim,TO_CHAR);
    act("$n fires a laser at you .",ch,NULL,victim,TO_VICT);
    act("$n fires a laser at $N.",ch,NULL,victim,TO_NOTVICT);
    damage(ch,victim,dam,gsn_laser);
    if (victim == NULL || victim->position == POS_DEAD) return;
    act("You launch your stun tubes at $N.",ch,NULL,victim,TO_CHAR);
    act("$n launches $s stun tubes at you.",ch,NULL,victim,TO_VICT);
    act("$n launches $s stun tubes at $N .",ch,NULL,victim,TO_NOTVICT);
    damage(ch,victim,dam,gsn_stuntubes);
    if (victim == NULL || victim->position == POS_DEAD) return;
    act("You fire multiple lasers at $N.",ch,NULL,victim,TO_CHAR);
    act("$n fires multiple lasers at you.",ch,NULL,victim,TO_VICT);
    act("$n fires multiple lasers at $N.",ch,NULL,victim,TO_NOTVICT);
    damage(ch,victim,dam*1.5,gsn_laser);
    if (victim == NULL || victim->position == POS_DEAD) return;
    act("You launch another volley of stun tubes at $N.",ch,NULL,victim,TO_CHAR);
    act("$n launches another volley of stun tubes at you.",ch,NULL,victim,TO_VICT);
    act("$n launches another volly of stun tubes at $N.",ch,NULL,victim,TO_NOTVICT);
    damage(ch,victim,dam*3,gsn_stuntubes);
    if (victim == NULL || victim->position == POS_DEAD) return;
    act("You charge up your lasers and fire at $N.",ch,NULL,victim,TO_CHAR);
    act("$n charges up $s lasers and fires at you.",ch,NULL,victim,TO_VICT);
    act("$n charges up $s lasers and fires at $N.",ch,NULL,victim,TO_NOTVICT);
    damage(ch,victim,dam*3.5,gsn_laser);
    if (victim == NULL || victim->position == POS_DEAD) return;
    act("You sting $N with your stun tubes, injecting poison.",ch,NULL,victim,TO_CHAR);
    act("$n stings you with $s stun tubes, injecting you with poison.",ch,NULL,victim,TO_VICT);
    act("$n stings $N with $s stun tubes, injecting $S with poison.",ch,NULL,victim,TO_NOTVICT);
    damage(ch,victim,dam*2,gsn_stuntubes);
    if (!IS_AFFECTED(victim, AFF_POISON)) SET_BIT(victim->affected_by, AFF_POISON);
    if (!IS_AFFECTED(victim, AFF_FLAMING)) SET_BIT(victim->affected_by, AFF_FLAMING);
    if (victim == NULL || victim->position == POS_DEAD) return;
    return;
}

void do_cybercloak( CHAR_DATA *ch, char *argument )
{
  if (IS_NPC(ch)) return;

  if (!IS_CLASS(ch, CLASS_CYBORG) )
  {
    send_to_char("Huh?\n\r",ch);
    return;
  }

  if (ch->pcdata->powers[CYBORG_BODY] < 4)
  {
    send_to_char("Your body must have at least 4 implants to cloak.\n\r",ch);
    return;
  }

  if (ch->move < 1000 || ch->mana < 1000)
  {
    send_to_char("You need 1000 mana and 1000 move to cloak.\n\r",ch);
    return;
  }

  if ( IS_SET(ch->itemaffect, ITEMA_VANISH))
  {
    REMOVE_BIT(ch->itemaffect, ITEMA_VANISH);
    act( "$n turns off his cloaking device.",ch,NULL,NULL,TO_ROOM);
    send_to_char("You turn off your cloaking device.\n\r",ch);
    return;
  }
  else
  {
    act( "$n turns on his cloaking device and disappears.",ch,NULL,NULL,TO_ROOM);
    send_to_char("You turn on your cloaking device.\n\r",ch);
    SET_BIT(ch->itemaffect, ITEMA_VANISH);
    return;
  }
  return;
}

void do_infravision( CHAR_DATA *ch, char *argument )
{
  if (IS_NPC(ch)) return;

  if (!IS_CLASS(ch, CLASS_CYBORG))
  {
    send_to_char("Huh?\n\r",ch);
    return;
  }

  if (ch->pcdata->powers[CYBORG_FACE] < 1)
  {
    send_to_char("You need at least 1 implant on your face to use infravision.\n\r",ch);
    return;
  }


  if (ch->pcdata->powers[CYBORG_FACE] > 2)
  {
  if (IS_SET(ch->act, PLR_HOLYLIGHT))
  {
    REMOVE_BIT(ch->act, PLR_HOLYLIGHT);
    send_to_char("You turn off your infravision.\n\r",ch);
  }
  else
  {
    SET_BIT(ch->act, PLR_HOLYLIGHT);
    send_to_char("You turn on your infravision.\n\r",ch);
  }
  }
  else if ((ch->pcdata->powers[CYBORG_FACE] = 2))
  {
    if (IS_SET(ch->affected_by, AFF_SHADOWSIGHT) && IS_SET(ch->pcdata->stats[UNI_AFF], VAM_NIGHTSIGHT))
    {
      REMOVE_BIT(ch->affected_by, AFF_SHADOWSIGHT);
      REMOVE_BIT(ch->pcdata->stats[UNI_AFF], VAM_NIGHTSIGHT);
      send_to_char("You turn off your infravision.\n\r",ch);
    }
    else
    {
      SET_BIT(ch->affected_by, AFF_SHADOWSIGHT);
      SET_BIT(ch->pcdata->stats[UNI_AFF], VAM_NIGHTSIGHT);
      send_to_char("You turn on your infravision.\n\r",ch);
    }
  }
  else if ((ch->pcdata->powers[CYBORG_FACE] = 1))
  {
    if (IS_SET(ch->pcdata->stats[UNI_AFF], VAM_NIGHTSIGHT))
    {
      REMOVE_BIT(ch->pcdata->stats[UNI_AFF], VAM_NIGHTSIGHT);
      send_to_char("You turn off your infravision.\n\r",ch);
    }
    else
    {
      SET_BIT(ch->pcdata->stats[UNI_AFF], VAM_NIGHTSIGHT);
      send_to_char("You turn on your infravision.\n\r",ch);
    }
  }
  return;
}

void do_linkregenerate( CHAR_DATA *ch, char *argument )
{
    if ( !IS_CLASS(ch, CLASS_CYBORG))
    {
        send_to_char("Huh?.\n\r",ch);
        return;
    }

    send_to_char("Not right now\n\r",ch);
    return;

    if ( ch->in_room != NULL && ch->in_room->vnum == 0 )
    {
      send_to_char("You must be in the regeneration chamber to link up.\n\r",ch);
      return;
    }

    switch ( ch->position )
    {
    case POS_SLEEPING:
        send_to_char( "You are already sleeping.\n\r", ch );
        break;

    case POS_RESTING:
        send_to_char( "You are already resting.\n\r", ch );
        break;

    case POS_MEDITATING:
        send_to_char( "You are already meditating.\n\r", ch );
        break;

    case POS_SITTING:
        send_to_char( "You stand up and plug yourself into one of the regeneration pods.\n\r", ch );
        act( "$n stands up and links into a regeneration pod.", ch, NULL, NULL, TO_ROOM );
        break;

    case POS_STANDING:
        send_to_char( "You link yourself into a regeneration pod.\n\r", ch );
        act( "$n links into a regeneration pod.", ch, NULL, NULL, TO_ROOM );
        break;
/*
    case POS_LINKREGEN:
        send_to_char("You are already linked into a regeneration pod.\n\r",ch);
        break;
*/
    case POS_FIGHTING:
        send_to_char( "You are already fighting!\n\r", ch );
        break;
    }

    return;
}





#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"

void frost_breath args(( CHAR_DATA *ch, CHAR_DATA *victim, bool all));
void fire_effect  args(( void *vo, int level, int dam, int target));
DECLARE_DO_FUN( do_stance );

void do_deathsense(CHAR_DATA *ch, char *argument)
{

    if (ch->power[DISC_DAEM_NETH] < 2)
    {
	stc("You need level 2 Nether to use DeathSense.\n\r",ch);
	return;
    }

    if (IS_SET(ch->act, PLR_HOLYLIGHT))
    {
	TOGGLE_BIT(ch->act, PLR_HOLYLIGHT);
	stc("Your unholy sight fades.\n\r",ch);
	return;
    }
    if (!IS_SET(ch->act, PLR_HOLYLIGHT))
    {
	TOGGLE_BIT(ch->act, PLR_HOLYLIGHT);
	stc("Your eyes glow with unholy sight.\n\r",ch);
	return;
    }
  return;

}

void do_leech(CHAR_DATA *ch, char *argument)
{
    CHAR_DATA *victim = NULL;
    char buf[MAX_STRING_LENGTH];

/*    if (ch->power[DISC_DAEM_NETH] < 4)
    {*/
	if (!IS_DEMPOWER( ch, DEM_LEECH))
    {

	stc("You do not have that power.\n\r",ch);
	return;
    }

    if (argument[0] == '\0')
    {
	stc("Who's life do you wish to leech off of?\n\r", ch);
	return;
    }

    if ((victim = get_char_room(ch, argument)) == NULL)
    {
	    stc("They aren't here.\n\r", ch);
	    return;
    }

      if (is_safe(ch, victim)) return;

	WAIT_STATE(ch, 10);

	act("$n stares intently at $N.", ch, NULL, victim, TO_NOTVICT);
	act("You stare intently at $N.", ch, NULL, victim, TO_CHAR);
	act("$n stares intently at you.", ch, NULL, victim, TO_VICT);

      if (victim->hit >= 1000)
      {
	  sh_int power;
	  sh_int dam;
	  power = 20;
	  dam = dice(power, power * 2);
	  if (dam > 300) dam = 300 + (dam / 10);
	  victim->hit -= dam;
	  ch->hit += dam;
	  if (ch->hit >= ch->max_hit + 500)
		ch->hit = ch->max_hit + 500;
	  sprintf(buf,"#1You absorb %d hitpoints.#n\n\r",dam);
	  stc(buf,ch);
	  sprintf(buf,"#1%s absorbed %d of your hitpoints!#n\n\r",ch->name,dam);
	  stc(buf,victim);
	  }
      else stc("Nothing seemed to happen.\n\r",ch);
	return;

}

void do_entomb (CHAR_DATA *ch, char *argument)
{
    int door;

    if (!IS_DEMPOWER(ch, DEM_ENTOMB))
    {
	stc("You have not been granted that power.\n\r",ch);
	return;
    }

    if (ch->in_room->sector_type == SECT_AIR)
    {
	send_to_char("This ability cannot be used in the air.\n\r", ch);
	return;
    }

    if (!TIME_UP(ch, TIMER_ENTOMB)
	&& ch->level < 12)
    {
	send_to_char("This ability can only be used once every 12 hours.\n\r", ch);
	return;
    }

    for (door = 0 ; door < 4 ; door++)
    {
	if (ch->in_room->exit[door] != NULL)
	    make_wall(ch->in_room, door, EX_ICE_WALL);
    }

    ch->hit += (ch->hit *3/2);
       if (ch->hit > ch->max_hit)
		ch->hit = ch->max_hit;
    SET_TIMER(ch, TIMER_ENTOMB, 12);

    act("$n calls forth sheets of ice, blocking your path in every direction.", ch, NULL, NULL, TO_ROOM);
    send_to_char("You call forth sheets of ice to entrap your prey.\n\r", ch);
    send_to_char("You grin wickedly.\n\r",ch);
    do_say(ch,"Prepare to die! Muahahahaha.");

    WAIT_STATE(ch, 20);
}

void do_gust( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA       *victim;
    ROOM_INDEX_DATA *to_room = NULL;
    EXIT_DATA       *pexit;
    EXIT_DATA       *pexit_rev;
    char            buf       [MAX_INPUT_LENGTH];
    char            direction [MAX_INPUT_LENGTH];
    char            arg1      [MAX_INPUT_LENGTH];
    char            arg2      [MAX_INPUT_LENGTH];
    int             door;
    int             rev_dir;
    int             dam;
     
    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if (ch->power[DISC_DAEM_GELU] < 7)
    {
	stc("You must achieve a level seven mastery of Geluge to use Gust.\n\r",ch);
	return;

    }

    if (!TIME_UP(ch, TIMER_CAN_GUST) && ch->level < 120)
    {
	send_to_char("You are out of breath.\n\r", ch);
	return;
    }
     
    if ( arg1[0] == '\0' )
    {
	send_to_char("Who do you wish to blow a gust of wind at?\n\r", ch);
	return;
    }
    if ( ( victim = get_char_room( ch, arg1 ) ) == NULL )
    {
	send_to_char("They are not here.\n\r", ch);
	return;
    }
    
    if ( victim == ch )
    {
	send_to_char( "Not on yourself!\n\r", ch );
	return;
    }
     
    if ( is_safe( ch, victim ) )
      return;
     
    if ( victim->size > ch->size)
    {
	send_to_char("They are too large to affect.\n\r",ch);
	return;
    }
    
    WAIT_STATE( ch, 12 );
    if ( !IS_NPC(ch) && number_percent( )/2 > ch->power[DISC_DAEM_GELU] + ch->generation)
    {
	    send_to_char("You huff and puff but they do not budge.\n\r",ch);
	    act("$n blows a gust of cold air into the room.", ch, NULL, NULL, TO_ROOM);
	    return;
    }
    SET_TIMER(ch, TIMER_CAN_GUST, dice(1,3)+1);    
    act("You breathe a gust of cold air at $N.", ch, NULL, victim, TO_CHAR);
    act("$n breathes a gust of cold air at $N.", ch, NULL, victim, TO_NOTVICT);
    act("$n breathes a gust of cold air at you.", ch, NULL, victim, TO_VICT);

    rev_dir = 0;
    if ( arg2[0] == '\0' )
	door = number_range(0,3);
    else
    {
	if      ( !str_prefix( arg2, "north" ) )
	    door = 0;
	else if ( !str_prefix( arg2, "east" ) )
	    door = 1;
	else if ( !str_prefix( arg2, "south" ) )
	    door = 2;
	else if ( !str_prefix( arg2, "west" ) )
	    door = 3;
	else
	{
	    send_to_char("You can only blow people north, south, east or west.\n\r", ch);
	    return;
	}
    }
     
    if (door == 0) {sprintf(direction,"north");rev_dir = 2;}
    if (door == 1) {sprintf(direction,"east");rev_dir = 3;}
    if (door == 2) {sprintf(direction,"south");rev_dir = 0;}
    if (door == 3) {sprintf(direction,"west");rev_dir = 1;}
     
    if (( pexit = ch->in_room->exit[door]) == NULL)
    {
	sprintf(buf,"$N flies into the %s wall.", direction);
	act(buf,ch,NULL,victim,TO_NOTVICT);
	sprintf(buf,"$N flies into the %s wall.", direction);
	act(buf,ch,NULL,victim,TO_CHAR);
	sprintf(buf,"You smash into the %s wall.", direction);
	act(buf,ch,NULL,victim,TO_VICT);
	dam = dice(victim->size*3+1, ch->power[DISC_DAEM_GELU] * 3);
	  damage_old(ch, victim, dam, 0, DAM_OTHER, FALSE);
	return;
    }
    
    pexit = victim->in_room->exit[door];
    if (IS_SET(pexit->exit_info, EX_CLOSED) )
    {
	if (IS_SET(pexit->exit_info, EX_LOCKED))
	    REMOVE_BIT(pexit->exit_info, EX_LOCKED);
	if (IS_SET(pexit->exit_info, EX_CLOSED))
	    REMOVE_BIT(pexit->exit_info, EX_CLOSED);
	sprintf(buf,"$N is blown into the air and flies %s.", direction);
	act(buf,ch,NULL,victim,TO_NOTVICT);
	sprintf(buf,"$N is blown into the air and flies %s.", direction);
	act(buf,ch,NULL,victim,TO_CHAR);
	sprintf(buf,"You are blown into the air and fly %s.", direction);
	act(buf,ch,NULL,victim,TO_VICT);
	sprintf(buf,"There is a loud crash as $n smashes through the $d.");
	act(buf,victim,NULL,pexit->keyword,TO_ROOM);
     
	if ( ( to_room   = pexit->to_room               ) != NULL
	&&   ( pexit_rev = to_room->exit[rev_dir] ) != NULL
	&&   pexit_rev->to_room == ch->in_room
	&&   pexit_rev->keyword != NULL )
	{
	    if (IS_SET(pexit_rev->exit_info, EX_LOCKED))
		REMOVE_BIT( pexit_rev->exit_info, EX_LOCKED );
	    if (IS_SET(pexit_rev->exit_info, EX_CLOSED))
		REMOVE_BIT( pexit_rev->exit_info, EX_CLOSED );
	    if (door == 0) sprintf(direction,"south");
	    if (door == 1) sprintf(direction,"west");
	    if (door == 2) sprintf(direction,"north");
	    if (door == 3) sprintf(direction,"east");
	    char_from_room(victim);
	    char_to_room(victim,to_room);
	    sprintf(buf,"$n comes smashing in through the %s $d.", direction);
	    act(buf,victim,NULL,pexit->keyword,TO_ROOM);
	    dam = dice(victim->size*3+1, ch->power[DISC_DAEM_GELU] * 7);
		damage_old(ch, victim, dam, 0, DAM_OTHER, FALSE);
	}
    }
    else
    {
	sprintf(buf,"$N flies %s.", direction);
	act(buf,ch,NULL,victim,TO_NOTVICT);
	sprintf(buf,"$N flies %s.", direction);   
	act(buf,ch,NULL,victim,TO_CHAR);
	sprintf(buf,"You fly %s.", direction);  
	act(buf,ch,NULL,victim,TO_VICT);
	if (door == 0) sprintf(direction,"south");
	if (door == 1) sprintf(direction,"west");
	if (door == 2) sprintf(direction,"north");
	if (door == 3) sprintf(direction,"east");
	  char_from_room(victim);
	char_to_room(victim,pexit->to_room);
	sprintf(buf,"$n comes flying in from the %s.", direction);
	act(buf,victim,NULL,NULL,TO_ROOM);
	dam = dice(victim->size*3+1, ch->power[DISC_DAEM_GELU] * 5);
	  damage_old(ch, victim, dam, 0, DAM_OTHER, FALSE);
    }
    return;
}

void do_caust(CHAR_DATA *ch, char *argument)
{
    OBJ_DATA *obj;

    if (!IS_DEMPOWER(ch, DEM_CAUST))
    {
	stc("You have not been granted that power.\n\r",ch);
	return;
    }

    if (argument[0] == '\0')
    {
	send_to_char("Which item do you wish to caust?\n\r", ch);
	return;
    }

    if ( (obj = get_obj_carry(ch, argument)) == NULL)
    {
	send_to_char("You are not carrying that item.\n\r", ch);
	return;
    }

    if (obj->item_type != ITEM_WEAPON)
    {
	send_to_char("That is not a weapon!\n\r", ch);
	return;
    }

    if (dice(1, 100) == 1)
    {
	act("$p is disintegrated by $n's poison.", ch,obj, NULL, TO_ROOM);
	act("Your poison eats through $p.", ch,obj, NULL, TO_CHAR);
	extract_obj(obj);
	return;
    }

    if (IS_WEAP(obj, WEAPON_POISON))
    {
	act("$p is already coated with deadly poison.", ch, obj, NULL, TO_CHAR);
	return;
    }

    act("You run your tongue along $p, coating it with a sickly venom.", ch, obj, NULL, TO_CHAR);
    act("$n runs $m tongue along $p, coating it with a sickly venom.", ch, obj, NULL, TO_ROOM);

    WAIT_STATE(ch, 8);
    SET_BIT(obj->weapflags, WEAPON_POISON);
    obj->value[1] += ch->generation;
    obj->value[2] += ch->generation;
}

void do_chaosport( CHAR_DATA *ch, char *argument )
{
char buf[MAX_STRING_LENGTH];
CHAR_DATA *victim;

 /*if (!victim = ch->fighting)
   return; */
 
 
    if (ch->power[DISC_DAEM_DISC] < 4)
    {
	stc("You need at least level 4 in Discord to use Chaos Portal\n\r",ch);
	return;
    }

    if (IS_AFFECTED(ch, AFF_WEBBED))
    {
	send_to_char("You are unable to move with all this sticky webbing on.\n\r",ch);
	return;
    }
  if (ch->fighting && IS_CLASS(ch->fighting, CLASS_MONK) &&

IS_SET(ch->fighting->newbits,NEW_JAWLOCK) && number_percent( ) > 30)
{
sprintf(buf,"Not with god holding you!");
send_to_char(buf,ch);
act("$n cant escape god's mighty hold!",ch,NULL,victim,TO_ROOM);
return;
}

   if (ch->fighting && IS_CLASS(ch->fighting, CLASS_WEREWOLF) && 

IS_SET(ch->fighting->newbits,NEW_JAWLOCK) && number_percent( ) > 10)
{
sprintf(buf,"Not with %s's jaws clamped on your neck!",ch->fighting->name);
send_to_char(buf,ch);
act("$n cant escape $N's clamped jaws!",ch,NULL,ch->fighting,TO_ROOM);
return;
}
    if (IS_AFFECTED(ch,AFF_TENDRILS))
{
send_to_char("You are unable to move while tangled in tendrils.\n\r",ch);
return;
}
    
    if (ch->fighting != NULL)
    {
	if (number_range(1,4) == 3)
	{
	    stc("The powers of Chaos fail you.\n\r",ch);
	    act("$n tries in vain to summon a chaos portal.",ch,NULL,NULL,TO_ROOM);
	    SET_TIMER(ch, TIMER_CHAOSPORT, 3);
		WAIT_STATE(ch, 12);
	    return;
	}
    }

    act("$n disappears through a rift in time.",ch,NULL,NULL,TO_ROOM);
    stc("You are swept away through a rift in time.\n\r",ch);
    if (ch->fighting != NULL)
	stop_fighting( ch, TRUE );
    char_from_room(ch);
    char_to_room(ch, get_random_room(ch));
    stc("You reappear in a swirling storm of chaos.\n\r",ch);
    act("$n appears in a swirling wind of Chaos.",ch,NULL,NULL,TO_ROOM);
    do_look(ch,"auto");
	WAIT_STATE(ch, 12);
    SET_TIMER(ch, TIMER_CHAOSPORT, 10);
    return;
}


void do_bane (CHAR_DATA *ch, char *argument)
{
    OBJ_DATA *obj;

    if (ch->power[DISC_DAEM_CORR] < 3)
    {
	stc("You need level three Corruption to use this power.\n\r",ch);
	return;
    }

    if (argument[0] == '\0')
    {
	send_to_char("Who do you wish to call the Bane against?\n\r", ch);
	return;
    }

    if (!IS_OUTSIDE(ch) && ch->in_room->sector_type != SECT_FOREST)
    { 
	send_to_char("You must be outside to use Bane.\n\r", ch);
	return;
    }
    
    if (!TIME_UP(ch, TIMER_CAN_CALL_ROCKS) )
    {
	send_to_char("You call out but nothing comes.\n\r", ch);
	return;
    }

    act("$n cries out and a menacing sword appears to aid $s.", ch, NULL, NULL,TO_ROOM);
    send_to_char("A wicked longsword joins your battle against good.\n\r",ch);

    obj = create_object(get_obj_index(89), 0);
    obj_to_room(obj, ch->in_room);
    obj->timer = ch->generation / 2 + 2;
    SET_BIT(obj->extra_flags2, ITEM_ATTACK_GOOD);
    SET_TIMER(ch, TIMER_CAN_CALL_ROCKS, 3);

    if (ch->generation > 5)
    {
	obj = create_object(get_obj_index(89), 0);
	obj_to_room(obj, ch->in_room);
	obj->timer = ch->generation / 2 + 1;
	SET_BIT(obj->extra_flags2, ITEM_ATTACK_GOOD);
    }

    if (ch->generation > 10)
    {
	obj = create_object(get_obj_index(89), 0);
	obj_to_room(obj, ch->in_room);
	obj->timer = ch->generation / 2 + 1;
	SET_BIT(obj->extra_flags2, ITEM_ATTACK_GOOD);
    }
}

void do_unnerve(CHAR_DATA *ch, char *argument)
{
    CHAR_DATA *victim;

    if (!IS_DEMPOWER(ch, DEM_UNNERVE))
    {
	stc("You have not been granted that power.\n\r",ch);
	return;
    }

    if (argument[0] == '\0')
    {
	stc("Who do you wish to unnerve?\n\r", ch);
	return;
    }

    if ( ( victim = get_char_room(ch, argument) ) == NULL)
    {
	stc("They aren't here.\n\r", ch);
	return;
    }

    WAIT_STATE(ch, 7);
    do_say(ch,"#1Xeus Dominus Mortai!#n");
    do_stance(victim, "");
}

void do_wfreeze(CHAR_DATA *ch, char *argument)
{
    OBJ_DATA *obj;

    if (!IS_DEMPOWER(ch, DEM_FREEZEWEAPON))
    {
	stc("You have not been granted that power.\n\r",ch);
	return;
    }

    if (argument[0] == '\0')
    {
	send_to_char("Which item do you wish to freeze?\n\r", ch);
	return;
    }

    if ( (obj = get_obj_carry(ch, argument)) == NULL)
    {
	send_to_char("You are not carrying that item.\n\r", ch);
	return;
    }

    if (obj->item_type != ITEM_WEAPON)
    {
	send_to_char("That is not a weapon!\n\r", ch);
	return;
    }

    if (dice(1, 100) == 1)
    {
	act("$p freezes and shatters.", ch,obj, NULL, TO_ROOM);
	act("$p freezes and shatters.", ch,obj, NULL, TO_CHAR);
	extract_obj(obj);
	return;
    }

    if (IS_WEAP(obj, WEAPON_FROST))
    {
	act("$p is already frozen.", ch, obj, NULL, TO_CHAR);
	return;
    }

    act("$p is surrounded by ice crystals.", ch, obj, NULL, TO_CHAR);
    act("$p, carried by $n is surrounded by ice crystals.", ch, obj, NULL, TO_ROOM);

    WAIT_STATE(ch, 8);
    SET_BIT(obj->weapflags, WEAPON_FROST);
}



void do_transform( CHAR_DATA *ch, char *argument )
{
    OBJ_DATA *obj;
    int trans = 0;

    if (IS_NPC(ch)) return;

    if (ch->power[DISC_DAEM_MORP] < 2)
    {
	stc("You must obtain a level two mastery of Morphosis.\n\r",ch);
	return;
    }

    if (argument[0] == '\0')
    {
	send_to_char("You can transform into the following items:\n\r",ch);
	send_to_char("    A Daemonic Helm\n\r",ch);
	if (ch->power[DISC_DAEM_MORP] > 2)
	    send_to_char("    Black Steel Greaves\n\r",ch);
	if (ch->power[DISC_DAEM_MORP] > 3)
	{
	    send_to_char("    A Black Opera Cloak\n\r",ch);
	    send_to_char("    Daemonic Plate Armor\n\r",ch);
	}
	if (ch->power[DISC_DAEM_MORP] > 4)
	{
	    send_to_char("    Ring of Cacophony\n\r",ch);
	    send_to_char("    Blood-Ruby Sword\n\r",ch);
	}
	if (ch->power[DISC_DAEM_MORP] > 5)
	    send_to_char("    Shield of Bone\n\r",ch);
	return;
    }

    if (!str_cmp(argument, "back") )
    {
	if ( ( obj = ch->pcdata->chobj ) == NULL )
      {
	send_to_char("You are already in human form.\n\r",ch);
	return;
      }

      ch->pcdata->obj_vnum = 0;
      obj->chobj = NULL;
      ch->pcdata->chobj = NULL;
      REMOVE_BIT(ch->affected_by, AFF_POLYMORPH);
      REMOVE_BIT(ch->extra, EXTRA_OSWITCH);
      free_string(ch->morph);
      ch->morph = str_dup("");
      act("$p transforms into $n.",ch,obj,NULL,TO_ROOM);
      act("Your reform your human body.",ch,obj,NULL,TO_CHAR);
      extract_obj(obj);
      if (ch->in_room->vnum == ROOM_VNUM_IN_OBJECT)
      {
	char_from_room(ch);
	char_to_room(ch,get_room_index(ROOM_VNUM_ALTAR));
      }
	return;
    }


	 if (!str_prefix(argument, "helm")
	 && ch->power[DISC_DAEM_MORP] > 1)
	trans = OBJ_VNUM_DHELM;
    else if (!str_prefix(argument, "greaves")
	 && ch->power[DISC_DAEM_MORP] > 2)
	trans = OBJ_VNUM_DGREAVES;
    else if (!str_prefix(argument, "cloak")
	&& ch->power[DISC_DAEM_MORP] > 3)
	trans = OBJ_VNUM_DCLOAK;
    else if (!str_prefix(argument, "armor")
	&& ch->power[DISC_DAEM_MORP] > 3)
	trans = OBJ_VNUM_DARMOR;
    else if (!str_prefix(argument, "ring")
	&& ch->power[DISC_DAEM_MORP] > 4)
	trans = OBJ_VNUM_DRING;
    else if (!str_prefix(argument, "sword")
	&& ch->power[DISC_DAEM_MORP] > 4)
	trans = OBJ_VNUM_DSWORD;
    else if (!str_prefix(argument, "shield")
	&& ch->power[DISC_DAEM_MORP] > 5)
	trans = OBJ_VNUM_DSHIELD;
    else
    {
	do_transform(ch, "");
	return;
    }   

    if ((obj = create_object(get_obj_index(trans),60)) == NULL)
    {
	send_to_char( "You are unable to polymorph into that weapon.\n\r", ch);
	return;
    }

    if (IS_AFFECTED(ch,AFF_WEBBED))
    {
	send_to_char( "Not with all this sticky webbing on.\n\r", ch);
	return;
    }

    obj_to_room(obj,ch->in_room);
    act("$n transforms into $p and falls to the ground.",ch,obj,NULL,TO_ROOM);
    act("You transform into $p and fall to the ground.",ch,obj,NULL,TO_CHAR);
    ch->pcdata->obj_vnum = trans;
    obj->chobj = ch;
    ch->pcdata->chobj = obj;
    SET_BIT(ch->affected_by, AFF_POLYMORPH);
    SET_BIT(ch->extra, EXTRA_OSWITCH);
    SET_TIMER(ch, TIMER_DAEMONIC_TRANSFORM , 24);
    free_string(ch->morph);
    ch->morph = str_dup(obj->short_descr);
    if (!str_cmp(argument, "sword"))
    {
	SET_BIT(obj->weapflags, WEAPON_FLAMING);
	SET_BIT(obj->weapflags, WEAPON_VAMPIRIC);
	SET_BIT(obj->weapflags, WEAPON_FROST);
	SET_BIT(obj->weapflags, WEAPON_SUNBLADE);
	SET_BIT(obj->weapflags, WEAPON_ELE_EARTH);
	SET_BIT(obj->weapflags, WEAPON_ELE_AIR);
	SET_BIT(obj->weapflags, WEAPON_SHOCKING);
    }
    return;
}


int get_polymorph_power (CHAR_DATA *ch)
{
    if (ch->class == CLASS_DEMON)
	return ch->power[DISC_DAEM_MORP] - 1;

    if (ch->level == 12)
	return 100;

    return 0;
}

void do_polymorph (CHAR_DATA *ch, char *argument)
{
    int i, col = 0;
    char buf[MAX_INPUT_LENGTH];
    bool changed = FALSE;


    if (ch->power[DISC_DAEM_MORP] < 2 )
    {
	stc("You require level 2 morphosis.\n\r",ch);
	return;
    }

    if (argument[0] == '\0')
    {
	stc("Syntax : polymorph [<form> list back]\n\r", ch);
	return;
    }

    if (!str_cmp(argument, "list"))
    {
	cent_to_char("Available forms", ch);
	cent_to_char("---===> <===---", ch);

	for (i = 0 ; i < MAX_FORMS ; i++)
	{
	    if (form_data[i].polymorph_level > 0
		&& form_data[i].polymorph_level <= get_polymorph_power(ch)
		&& form_data[i].lookname != NULL )
	    {
		sprintf(buf, "   %-12s", form_data[i].lookname);
		stc(buf, ch);
		if ( ++col % 5 == 0)
		    send_to_char("\n\r", ch);
	    }
	}
	if (col % 5 != 0)
	    stc("\n\r", ch);
	return;
    }

    if (!str_cmp(argument, "back"))
    {
	if (ch->cur_form == get_normal_form(ch))
	{
	    stc("You are already in your normal form.\n\r", ch);
	    return;
	}
	sprintf(buf, "$n polymorphs back into %s.",
	    GET_PROPER_NAME(ch));
	act(buf, ch, NULL, NULL, TO_ROOM);
	stc("You return to your demonic form.\n\r", ch);
	set_form(ch, get_normal_form(ch) );
	WAIT_STATE(ch, 7);
	return;
    }

    if (!TIME_UP(ch, TIMER_CAN_POLYMORPH) && ch->level != 12)
    {
	stc("You have not got enough energy to polymorph so soon.\n\r", ch);
	return;
    }

    for ( i = 0 ; i < MAX_FORMS ; i++ )
    {
	if (form_data[i].lookname != NULL
	    && !str_prefix(argument, form_data[i].lookname)
	    && form_data[i].polymorph_level > 0
	    && form_data[i].polymorph_level <= get_polymorph_power(ch) )
	{
	    if (ch->cur_form == i)
	    {
		stc("You are already in that form.\n\r", ch);
		return;
	    }
	    changed = TRUE;
	    sprintf(buf, "$n transforms into a%s %s.",
		(is_vowel(form_data[i].lookname[0])) ? "n" : "",
		form_data[i].lookname);
	    act(buf, ch, NULL, NULL, TO_ROOM);

	    sprintf(buf, "You transform into a%s %s.\n\r",
		(is_vowel(form_data[i].lookname[0])) ? "n" : "",
		form_data[i].lookname);
	    stc(buf, ch);
	    WAIT_STATE(ch, 8);
	    set_form(ch, i);
	    SET_TIMER(ch, TIMER_CAN_POLYMORPH, dice(2, 3) );
	}
    }    
    if (!changed)    
	stc("No forms of that name found.\n\r", ch);
    return;
}

void do_hellfire (CHAR_DATA *ch, char *argument)
{
    int door;

    if (ch->power[DISC_DAEM_HELL] < 7)
	return;

    if (ch->in_room->sector_type == SECT_AIR)
    {
	send_to_char("This ability cannot be used in the air.\n\r", ch);
	return;
    }

    if ( IS_SET(ch->in_room->room_flags,ROOM_SAFE) )
    {
	stc("You cannot desecrate this Holy Place.\n\r",ch);
	return;
    }

    if (!TIME_UP(ch, TIMER_HELLFIRE_SUMMON)
	&& ch->level < 12)
    {
	send_to_char("This ability can only be used once every 12 hours.\n\r", ch);
	return;
    }

    for (door = 0 ; door < 4 ; door++)
    {
	if (ch->in_room->exit[door] != NULL)
	    make_wall(ch->in_room, door, EX_FIRE_WALL);
    }

    SET_TIMER(ch, TIMER_HELLFIRE_SUMMON, 12);
    stc("You summon the fires of hell!\n\r",ch);
    act("$n summons the Abyssal fires of Hell!",ch,NULL,NULL,TO_ROOM);
}

const sh_int  revdir [6] =
{
    2, 3, 0, 1, 5, 4
};

void put_wall(ROOM_INDEX_DATA *room, int dir, int wall)
{
    int timer;

    timer = dice(2, 2);

    switch (dir)
    {
	case DIR_NORTH :
	    SET_RTIMER(room, RTIMER_WALL_NORTH, timer);
	    SET_RTIMER(room->exit[dir]->to_room, RTIMER_WALL_SOUTH, timer);
	break;
	case DIR_EAST :
	    SET_RTIMER(room, RTIMER_WALL_EAST, timer);
	    SET_RTIMER(room->exit[dir]->to_room, RTIMER_WALL_WEST, timer);
	break;
	case DIR_SOUTH :
	    SET_RTIMER(room, RTIMER_WALL_SOUTH, timer);
	    SET_RTIMER(room->exit[dir]->to_room, RTIMER_WALL_NORTH, timer);
	break;
	case DIR_WEST :
	    SET_RTIMER(room, RTIMER_WALL_WEST, timer);
	    SET_RTIMER(room->exit[dir]->to_room, RTIMER_WALL_EAST, timer);
	break;
	case DIR_UP :
	    SET_RTIMER(room, RTIMER_WALL_UP, timer);
	    SET_RTIMER(room->exit[dir]->to_room, RTIMER_WALL_DOWN, timer);
	break;
	case DIR_DOWN :
	    SET_RTIMER(room, RTIMER_WALL_DOWN, timer);
	    SET_RTIMER(room->exit[dir]->to_room, RTIMER_WALL_UP, timer);
	break;
    }   
    room->exit[dir]->exit_info = wall;

}

void make_wall(ROOM_INDEX_DATA *room, int dir, int wall)
{
    int was;
    bool makewall = TRUE;

    if (dir < 0 || dir > 5)
    {
	bug("Invalid direction (create wall)", 0);
	return;
    }

    if (room->exit[dir] == NULL)
    {
	bug ("Cant make wall!!!!", 0);
	return;
    }

    was = room->exit[dir]->exit_info;

    if (was == EX_ICE_WALL && wall == EX_FIRE_WALL)
    {
	room_message(room, "The wall of ice bursts into flames.");
	room_message(room->exit[dir]->to_room, "The wall of ice bursts into flames.");
    }

    if (was == EX_FIRE_WALL && wall == EX_ICE_WALL)
    {
	room_message(room, "The wall of flames flickers blue for a second.");
	room_message(room->exit[dir]->to_room, "The wall of flames flickers blue for a second.");
	makewall = FALSE;
    }

    if (makewall) put_wall(room, dir, wall);

    if (room->exit[dir]->to_room == NULL)
    {
	bug("Exit doesnt lead anywhere (create wall).", 0);
	return;
    }

    if (room->exit[dir]->to_room->exit[revdir[dir]] == NULL)
    {
	bug("Reverse Exit doesnt lead anywhere (create wall).", 0);
	return;
    }

    if (makewall) put_wall(room->exit[dir]->to_room, revdir[dir], wall);
}

ROOM_INDEX_DATA * locate_obj (OBJ_DATA *obj)
{
    if (obj->in_obj != NULL)
	return locate_obj(obj->in_obj);

    if (obj->carried_by != NULL)
	return obj->carried_by->in_room;

    return obj->in_room;
}

void do_seed(CHAR_DATA *ch, char *argument)
{
    OBJ_DATA *obj;

    if (ch->power[DISC_DAEM_HELL] < 7)
    {
	stc("You must obtain a level seven Mastery of the Hellfire Discipline.\n\r",ch);
	return;
    }

    if ( IS_SET(ch->in_room->room_flags,ROOM_SAFE) )
    {
	stc("You cannot desecrate this Holy Place!\n\r",ch);
	return;
    }

    if (argument[0] == '\0')
    {
	send_to_char("Which item do you wish to plant with Deamonseed?\n\r", ch);
	return;
    }

    if ((obj = get_obj_carry(ch, argument) ) == NULL)
    {
	send_to_char("You do not have that item in your inventory.\n\r",ch);
	return;
    }
  
    if (IS_OBJ_STAT2(obj, ITEM_DAEMONSEED) )
    {
	send_to_char("That item is already set to explode.\n\r", ch);
	return;
    }

    if (IS_OBJ_STAT(obj, ITEM_BLESS)
	|| IS_OBJ_STAT(obj, ITEM_ANTI_EVIL) )
    {
	send_to_char("You cannot affect such a holy item.\n\r", ch);
	return;
    }

    if (IS_SET(obj->quest, QUEST_ARTIFACT)
	|| IS_SET(obj->quest, QUEST_RELIC) )
    {
	send_to_char("You cannot affect such a powerful item.\n\r", ch);
	return;
    }

    act("$p starts to shudder and vibrate in your hands.", ch, obj, NULL, TO_CHAR);
    act("$n lays $s hands on $p.", ch, obj, NULL, TO_ROOM);

    WAIT_STATE(ch, 12);
    SET_BIT(obj->extra_flags2, ITEM_DAEMONSEED);
    obj->timer = ch->generation / 2 + dice(1,3);
}


void do_immolate(CHAR_DATA *ch, char *argument)
{
    OBJ_DATA *obj;

    if (!IS_DEMPOWER(ch, DEM_IMMOLATE))
    {
	stc("You have not been granted that power.\n\r",ch);
	return;
    }

    if (argument[0] == '\0')
    {
	send_to_char("Which item do you wish to immolate?\n\r", ch);
	return;
    }

    if ( (obj = get_obj_carry(ch, argument)) == NULL)
    {
	send_to_char("You are not carrying that item.\n\r", ch);
	return;
    }

    if (obj->item_type != ITEM_WEAPON)
    {
	send_to_char("That is not a weapon!\n\r", ch);
	return;
    }

    if (dice(1, 100) == 1)
    {
	act("$p explodes in a burst of flames.", ch,obj, NULL, TO_ROOM);
	act("$p explodes in a burst of flames.", ch,obj, NULL, TO_CHAR);
	damage(ch,ch,500,gsn_inferno);
	extract_obj(obj);
	return;
    }

    if (IS_WEAP(obj, WEAPON_FLAMING))
    {
	act("$p is already flaming.", ch, obj, NULL, TO_CHAR);
	return;
    }

    act("$p bursts into flames.", ch, obj, NULL, TO_CHAR);
    act("$p, carried by $n bursts into flames.", ch, obj, NULL, TO_ROOM);

    WAIT_STATE(ch, 8);
    SET_BIT(obj->weapflags, WEAPON_FLAMING);
}

void do_destroy (CHAR_DATA *ch, char *argument)
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;

    argument = one_argument( argument, arg );
    
    if (ch->power[DISC_DAEM_HELL] < 5)
    {
	send_to_char("Only true masters of the hellfire discipline may use this ability.\n\r", ch);
	return;
    }


    if ( arg[0] == '\0' )
    {
	send_to_char( "Which daemon do you wish to destroy?\n\r", ch );
	return;
    }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( victim == ch )
    {
	send_to_char("You cannot destroy yourself.\n\r",ch);
	return;
    }

    if ( victim->class != ch->class && ch->level != 120)
    {
	send_to_char("You may only destroy daemons.\n\r",ch);
	return;
    }

    if ( victim->generation >= ch->generation)
    {
	send_to_char("They are too powerful to destroy.\n\r",ch);
	return;
    }
    
    if (ch->generation < 12)
    {
	send_to_char("Only Pit Fiends or above may use the destroy ability.\n\r", ch);
	return;
    }

    ch->alignment -= 30;
    if (ch->alignment < -1000) ch->alignment = -1000;

    act("You breathe out a huge gout of abyssal flame and incinerate $N.", ch, NULL, victim, TO_CHAR);
    act("$n breathes out a huge gout of abyssal flame and incinerates you.", ch, NULL, victim, TO_VICT);
    act("$n breathes out a huge gout of flame and incinerates $N.", ch, NULL, victim, TO_NOTVICT);
    send_to_char("You have been KILLED!", victim);
    act("$n drops dead.", victim, NULL, NULL, TO_ROOM);
    victim->hit = -10;
    victim->move /= 3;
    update_pos(victim);
}

void do_dinferno(CHAR_DATA *ch, char *argument)
{
    CHAR_DATA *vch, *vch_next;
    char buf[MAX_STRING_LENGTH];    

    if (!IS_DEMPOWER(ch, DEM_INFERNO))
    {
	send_to_char("You have not been granted that power.\n\r", ch);
	return;
    }

    if ( !TIME_UP(ch, TIMER_INFERNO) )
    {
	sprintf(buf,"You cannot use Inferno for another %d hours.\n\r",ch->tick_timer[TIMER_INFERNO] );
	stc(buf,ch);
	return;
    }

    if ( ch->hit > 0 )
    {
	send_to_char("This is only used as a last resort.\n\r",ch);
	return;
    }

    act("$n explodes, sending forth a massive fireballs in all directions.",ch,NULL,NULL,TO_ROOM);
    send_to_char("You explode in a huge blast of abyssal flame.\n\r",ch);
    for (vch = ch->in_room->people; vch != NULL; vch = vch_next)
    {
	    vch_next = vch->next_in_room;
	    if (vch != ch)
	    {
		damage(vch, ch, number_range(1500,2000), gsn_inferno);
		damage(ch, ch, number_range(1500,2000), gsn_inferno);
		fire_effect(vch, ch->level, 2000, TARGET_CHAR);
	    }
    }
    WAIT_STATE(ch, 56);
    ch->hit = 10;
    update_pos(ch);
    SET_TIMER(ch, TIMER_INFERNO, 80);
}   

void acid_effect(void *vo, int level, int dam, int target)
{
    if (target == TARGET_ROOM) /* nail objects on the floor */
     {
	ROOM_INDEX_DATA *room = (ROOM_INDEX_DATA *) vo;
	OBJ_DATA *obj, *obj_next;

	for (obj = room->contents; obj != NULL; obj = obj_next)
	{
	    obj_next = obj->next_content;
	    acid_effect(obj,level,dam,TARGET_OBJ);
	}
	return;
    }

    if (target == TARGET_CHAR)  /* do the effect on a victim */
    {
	CHAR_DATA *victim = (CHAR_DATA *) vo;
	OBJ_DATA *obj, *obj_next;

	/* let's toast some gear */
	for (obj = victim->carrying; obj != NULL; obj = obj_next)
	{
	    obj_next = obj->next_content;
	    acid_effect(obj,level,dam,TARGET_OBJ);
	}
	return;
    }

    if (target == TARGET_OBJ) /* toast an object */
    {
	OBJ_DATA *obj = (OBJ_DATA *) vo;
	OBJ_DATA *t_obj,*n_obj;
	int chance;
	char *msg;

	
	chance = level / 4 + dam / 10;

	if (chance > 25)
	    chance = (chance - 25) / 2 + 25;
	 if (chance > 50)
	    chance = (chance - 50) / 2 + 50;

	if (IS_OBJ_STAT(obj,ITEM_BLESS))
	    chance -= 5;

	chance -= obj->level * 2;

	switch (obj->item_type)
	{
	    default:
		return;
	    case ITEM_CONTAINER:
	    case ITEM_CORPSE_PC:
	    case ITEM_CORPSE_NPC:
		msg = "$p fumes and dissolves.";
		break;
	    case ITEM_STAFF:
	    case ITEM_WAND:
		chance -= 10;
		msg = "$p corrodes and breaks.";
		break;
	    case ITEM_SCROLL:
		chance += 10;
		msg = "$p is burned into waste.";
		break; 
	}

	chance = URANGE(5,chance,95);

	if (number_percent() > chance)
	    return;

	if (IS_SET(obj->quest, QUEST_SPELLPROOF))
	    return;

	if (obj->carried_by != NULL)
	    act(msg,obj->carried_by,obj,NULL,TO_ALL);
	else if (obj->in_room != NULL && obj->in_room->people != NULL)
	    act(msg,obj->in_room->people,obj,NULL,TO_ALL);

	/* get rid of the object */
	if (obj->contains)  /* dump contents */
	{
	    for (t_obj = obj->contains; t_obj != NULL; t_obj = n_obj)
	    {
		n_obj = t_obj->next_content;
		obj_from_obj(t_obj);
		if (obj->in_room != NULL)
		    obj_to_room(t_obj,obj->in_room);
		else if (obj->carried_by != NULL)
		    obj_to_room(t_obj,obj->carried_by->in_room);
		else
		{
		    extract_obj(t_obj);
		    continue;
		}

		acid_effect(t_obj,level/2,dam/2,TARGET_OBJ);
	    }
	}

	extract_obj(obj);
	return;
    }
}


void shock_effect(void *vo,int level, int dam, int target)
{
    if (target == TARGET_ROOM)
    {
	ROOM_INDEX_DATA *room = (ROOM_INDEX_DATA *) vo;
	OBJ_DATA *obj, *obj_next;

	for (obj = room->contents; obj != NULL; obj = obj_next)
	{
	    obj_next = obj->next_content;
	    shock_effect(obj,level,dam,TARGET_OBJ);
	}
	return;
    }

    if (target == TARGET_CHAR)
    {
	CHAR_DATA *victim = (CHAR_DATA *) vo;
	OBJ_DATA *obj, *obj_next;

	/* toast some gear */
	for (obj = victim->carrying; obj != NULL; obj = obj_next)
	{
	    obj_next = obj->next_content;
	    shock_effect(obj,level,dam,TARGET_OBJ);
	}
	return;
    }

    if (target == TARGET_OBJ)
    {
	OBJ_DATA *obj = (OBJ_DATA *) vo;
	int chance;
	char *msg;

	chance = level / 4 + dam / 10;

	if (chance > 25)
	    chance = (chance - 25) / 2 + 25;
	if (chance > 50)
	    chance = (chance - 50) /2 + 50;

	if (IS_OBJ_STAT(obj,ITEM_BLESS))
	    chance -= 5;

	chance -= obj->level * 2;

	switch(obj->item_type)
	{
	    default:
		return;
	   case ITEM_WAND:
	   case ITEM_STAFF:
		chance += 10;
		msg = "$p overloads and explodes!";
		break;
	}

	chance = URANGE(5,chance,95);

	if (number_percent() > chance)
	    return;

	if (IS_SET(obj->quest, QUEST_SPELLPROOF))
	    return;

	if (obj->carried_by != NULL)
	    act(msg,obj->carried_by,obj,NULL,TO_ALL);
	else if (obj->in_room != NULL && obj->in_room->people != NULL)
	    act(msg,obj->in_room->people,obj,NULL,TO_ALL);

	extract_obj(obj);
	return;
    }
}       

void fire_effect(void *vo, int level, int dam, int target)
{
    if (target == TARGET_ROOM)  /* nail objects on the floor */
    {
	ROOM_INDEX_DATA *room = (ROOM_INDEX_DATA *) vo;
	OBJ_DATA *obj, *obj_next;

	for (obj = room->contents; obj != NULL; obj = obj_next)
	{
	    obj_next = obj->next_content;
	    fire_effect(obj,level,dam,TARGET_OBJ);
	}
	return;
    }

    if (target == TARGET_CHAR)   /* do the effect on a victim */
    {
	CHAR_DATA *victim = (CHAR_DATA *) vo;
	OBJ_DATA *obj, *obj_next;

	/* chance of blindness */
	if (!IS_AFFECTED(victim,AFF_BLIND))
	{
	    AFFECT_DATA af;
	    act("$n is blinded by smoke!",victim,NULL,NULL,TO_ROOM);
	    act("Your eyes tear up from smoke...you can't see a thing!",
		victim,NULL,NULL,TO_CHAR);

	    af.type         = skill_lookup("fire breath");
	    af.duration     = number_range(0,level/10);
	    af.location     = APPLY_HITROLL;
	    af.modifier     = -20;
	    af.bitvector    = AFF_BLIND;

	    affect_to_char(victim,&af);
	}

	/* let's toast some gear! */
	for (obj = victim->carrying; obj != NULL; obj = obj_next)
	{
	    obj_next = obj->next_content;
	    fire_effect(obj,level,dam,TARGET_OBJ);
	}
	return;
    }

    if (target == TARGET_OBJ)  /* toast an object */
    {
	OBJ_DATA *obj = (OBJ_DATA *) vo;
	OBJ_DATA *t_obj,*n_obj;
	int chance;
	char *msg;

	chance = level / 4 + dam / 10;
 
	if (chance > 25)
	    chance = (chance - 25) / 2 + 25;
	if (chance > 50)
	    chance = (chance - 50) / 2 + 50;

	if (IS_OBJ_STAT(obj,ITEM_BLESS))
	    chance -= 5;
	chance -= obj->level * 2;

	switch ( obj->item_type )
	{
	default:         
	    return;
	case ITEM_CONTAINER:
	    msg = "$p ignites and burns!";
	    break;
	case ITEM_POTION:
	    chance += 25;
	    msg = "$p bubbles and boils!";
	    break;
	case ITEM_SCROLL:
	    chance += 50;
	    msg = "$p crackles and burns!";
	    break;
	case ITEM_STAFF:
	    chance += 10;
	    msg = "$p smokes and chars!";
	    break;
	case ITEM_WAND:
	    msg = "$p sparks and sputters!";
	    break;
	case ITEM_FOOD:
	    msg = "$p blackens and crisps!";
	    break;
	case ITEM_PILL:
	    msg = "$p melts and drips!";
	    break;
	}

	chance = URANGE(5,chance,95);

	if (number_percent() > chance)
	    return;
 
	if (IS_SET(obj->quest, QUEST_SPELLPROOF))
	    return;      

	if (obj->carried_by != NULL)
	    act( msg, obj->carried_by, obj, NULL, TO_ALL );
	else if (obj->in_room != NULL && obj->in_room->people != NULL)
	    act(msg,obj->in_room->people,obj,NULL,TO_ALL);

	if (obj->contains)
	{
	    /* dump the contents */
 
	    for (t_obj = obj->contains; t_obj != NULL; t_obj = n_obj)
	    {
		n_obj = t_obj->next_content;
		obj_from_obj(t_obj);
		if (obj->in_room != NULL)
		    obj_to_room(t_obj,obj->in_room);
		else if (obj->carried_by != NULL)
		    obj_to_room(t_obj,obj->carried_by->in_room);
		else
		{
		    extract_obj(t_obj);
		    continue;
		}
		fire_effect(t_obj,level/2,dam/2,TARGET_OBJ);
	    }
	}

	extract_obj( obj );
	return;
    }
}

void do_blink(CHAR_DATA *ch, char *argument)
{
    CHAR_DATA *victim;
/*
    if (ch->power[DISC_DAEM_ATTA] < 6)
    {
	stc("You need level 6 Attack to use blink.\n\r",ch);
	return;
    }
*/

	if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch,CLASS_DEMON))
    {
      send_to_char("Huh?\n\r",ch);
      return;
    }


    if (!IS_DEMPOWER( ch, DEM_BLINK) && IS_CLASS(ch,CLASS_DEMON))
    {
        stc("You need to get blink first.\n\r",ch);
        return;
    }


    if (ch->fighting == NULL && argument[0] == '\0')
    {
	stc("Who do you wish to blink into combat with?\n\r", ch);
	return;
    }

    if (ch->fighting == NULL)
    {
	if ( (victim = get_char_room(ch, argument) ) == NULL)
	{
	    stc("They aren't here.\n\r", ch);
	    return;
	}

	WAIT_STATE(ch, 24);
	SET_BIT(ch->flag3, AFF3_BLINK_1ST_RD);
	stop_fighting(ch, TRUE);
	stc("You pop out of existance.\n\r", ch);
	act("$n pops out of existance.", ch, NULL, NULL, TO_ROOM);
	ch->blinkykill = victim;
	return;
    }
    WAIT_STATE(ch, 24);
    victim = ch->fighting;
    SET_BIT(ch->flag3, AFF3_BLINK_2ND_RD);
    stop_fighting(ch, TRUE);
    stc("You pop out of existance.\n\r", ch);
    act("$n pops out of existance.", ch, NULL, NULL, TO_ROOM);
    ch->blinkykill = victim;
}

void do_graft(CHAR_DATA *ch, char *argument)
{
    OBJ_DATA *obj;
    char arg[MAX_INPUT_LENGTH];
    argument = one_argument(argument, arg);

    if (IS_NPC(ch)) return; 

	if (!IS_CLASS(ch,CLASS_DEMON))
    {
    send_to_char("Huh?\n\r",ch);
    return;
    }


/*
    if (ch->power[DISC_DAEM_ATTA] < 5)
    {
*/
	if (!IS_DEMPOWER( ch, DEM_GRAFT) && IS_CLASS(ch,CLASS_DEMON))
    {
	stc("You need to get graft first.\n\r",ch);
	return;
    }

    if ( arg[0] == '\0')
    {
	stc("Which limb do you wish to graft on to yourself?\n\r",ch);
	return;
    }

    if ( ( obj = get_obj_carry(ch,arg) ) == NULL )
    {
	stc("You do not have that limb.\n\r",ch);
	return;
    }

    if (!IS_SET(obj->extra_flags2, ITEM_ARM))
    {
	stc("That's not even an arm!\n\r",ch);
	return;
    }

    if (IS_SET(ch->newbits, THIRD_HAND) && IS_SET(ch->newbits, FOURTH_HAND))
    {
	stc("You already have four arms!\n\r",ch);
	return;
    }

    if (!IS_SET(ch->newbits, FOURTH_HAND))
    {
	act("You graft an arm onto your body.",ch,NULL,obj,TO_CHAR);
	act("$n grafts an arm onto $m body.",ch,NULL,obj,TO_ROOM);
	SET_BIT(ch->newbits, FOURTH_HAND);
	SET_TIMER(ch, TIMER_FOURTH_ARM_GOING, dice(ch->generation, 6) );
	WAIT_STATE(ch, 18);
	extract_obj(obj);
	return;    
    }

    if (!IS_SET(ch->newbits, THIRD_HAND))
    {
	act("You graft an arm onto your body.",ch,NULL,obj,TO_CHAR);
	act("$n grafts an arm onto $m body.",ch,NULL,obj,TO_ROOM);
	SET_BIT(ch->newbits, THIRD_HAND);
	SET_TIMER(ch, TIMER_THIRD_ARM_GOING, dice(ch->generation, 6) );
	WAIT_STATE(ch, 18);
	extract_obj(obj);
	return;    
    }    

    return;
}


void do_shadowdemon(CHAR_DATA *ch, char *argument)
{
      char buf[MAX_STRING_LENGTH];
      char arg[MAX_INPUT_LENGTH];
      char *fname;
      int form;

      argument = one_argument(argument, arg);

    if (!IS_CLASS(ch, CLASS_VAMPIRE))
    {
	stc("Huh?\n\r",ch);
	return;
    }

     if (arg[0] == '\0')
      {
	  stc("What demonic form do you wish to mimic?\n\r",ch);
	  return;
      }

      if (!str_cmp(arg, "return") && ch->cur_form == get_normal_form(ch))
      {
	  stc("You are already in your normal demonic form!\n\r",ch);
	  return;
      }

	     if (!str_cmp(arg, "lemure"   )) form = FRM_LEMURE;
      else if (!str_cmp(arg, "nupperibo")) form = FRM_NUPPERIBO;
      else if (!str_cmp(arg, "spinagon" )) form = FRM_SPINAGON;
      else if (!str_cmp(arg, "barbazu"  )) form = FRM_BARBAZU;
      else if (!str_cmp(arg, "abishai"  )) form = FRM_ABISHAI;
      else if (!str_cmp(arg, "osyluth"  )) form = FRM_OSYLUTH;
      else if (!str_cmp(arg, "hamatula" )) form = FRM_HAMATULA;
      else if (!str_cmp(arg, "erinyes"  )) form = FRM_ERINYES;
      else if (!str_cmp(arg, "amnizu"   )) form = FRM_AMNIZU;
      else if (!str_cmp(arg, "cornugon" )) form = FRM_CORNUGON;
      else if (!str_cmp(arg, "gelugon"  )) form = FRM_GELUGON;
      else if (!str_cmp(arg, "return"   )) form = get_normal_form(ch);
      else
      {
	stc("That is an invalid demonic form.\n\r",ch);
	return;
      }

     
     if ((form - 23) <= ch->generation)
      {
	  fname = str_dup(ch->name);
	  stc("Your skin slowly melts away and you form a puddle on the floor.\n\r",ch);
	  act("$n's body slowly melts into a puddle on the ground.",ch,NULL,NULL,TO_ROOM);
	  set_form(ch, form);
	  sprintf(buf,"Your body slowly reforms as %s.",ch->name);
	  stc(buf,ch);
	  sprintf(buf,"%s's body slowly reforms as %s.",fname,ch->name);
	  act(buf,ch,NULL,NULL,TO_ROOM);
	  return;
      }
	  
	
}


void do_dgate( CHAR_DATA *ch, char *argument )
{
    char arg1[MAX_INPUT_LENGTH];
    DESCRIPTOR_DATA *d;
    CHAR_DATA *victim;
	
    argument = one_argument( argument, arg1 );
    
    if (!IS_CLASS(ch, CLASS_DEMON))
    {
	stc("Huh?\n\r",ch);
	return;
    }

    if ( arg1[0] == '\0' )
    {
	send_to_char( "Gate whom?\n\r", ch );
	return;
    }

    if ( !str_cmp( arg1, "all" ) )
    {
	if ( ch->generation < 12 )
	{
	    send_to_char("You do not yet have the power to gate all demons.\n\r",ch);
	}
	else
	{
		for ( d = descriptor_list; d != NULL; d = d->next )
		{
		    if ( d->connected == CON_PLAYING
		    &&   d->character != ch
		    &&   d->character->in_room != NULL
		    &&   can_see( ch, d->character ) 
		    &&   d->character->generation < ch->generation
		    &&   d->character->class == CLASS_DEMON)
		    {
			if ( d->character->fighting != NULL ) stop_fighting( d->character, TRUE );
			    act( "A scaly hand reaches down and drags $n away.", d->character, NULL, NULL, TO_ROOM );
			    char_from_room( d->character );
			    char_to_room( d->character, ch->in_room );
			    act( "You have successfully gated $N.", ch, NULL, d->character, TO_CHAR );
			    act( "$n has successfully gated $N.", ch, NULL, d->character, TO_NOTVICT );
			    if ( ch != d->character )
				act( "$n has pulled you through the demonic void.", ch, NULL, d->character, TO_VICT );
			    do_look( d->character, "auto" );
			    send_to_char( "Ok.\n\r", ch );                      
		    }
		}
	}
	return;
    }

    if ( ( victim = get_char_world( ch, arg1 ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( victim->class != CLASS_DEMON )
    {
	send_to_char( "You may only gate in demons.\n\r", ch );
	return;
    }

    if ( victim->in_room == NULL )
    {
	send_to_char( "They are in limbo.\n\r", ch );
	return;
    }

    if ( victim->generation >= ch->generation )
    {
	send_to_char("You may only gate one of lesser power than yourself.\n\r",ch);
	return;
    }    
    if  (!IS_NPC(victim) && !IS_IMMUNE(victim, IMM_SUMMON) )
{
	 send_to_char("Your powers seem to have failed you.\n\r",ch);
return;
}
    if ( number_range(1, ch->generation) == 1 )
    {
	send_to_char("Your powers seem to have failed you.\n\r",ch);
	send_to_char("You hear demonic chanting in the distance.\n\r",victim);
	return;
    }
    
    if ( victim->fighting != NULL ) stop_fighting( victim, TRUE );
    act( "A scaly hand reaches down and drags $n away.", victim, NULL, NULL, TO_ROOM );
    char_from_room( victim );
    char_to_room( victim, ch->in_room);
    act( "You have successfully gated $N.", ch, NULL, victim, TO_CHAR );
    act( "$n has successfully gated $N.", ch, NULL, victim, TO_NOTVICT );
    if ( ch != victim )
	act( "$n has pulled you through the demonic void.", ch, NULL, victim, TO_VICT );
    do_look( victim, "auto" );
    send_to_char( "Ok.\n\r", ch );
}

void do_frostbreath (CHAR_DATA *ch, char *argument)
{
    CHAR_DATA *victim;
    char arg[MAX_STRING_LENGTH];

    argument = one_argument(argument, arg);

    if (ch->power[DISC_DAEM_GELU] < 2)
    {
	stc("You must obtain level two in Geluge to use Frostbreath.\n\r",ch);
	return;
    }

    if (!TIME_UP(ch, TIMER_CAN_BREATHE_FROST) && ch->level < 12)
    {
	send_to_char("You are out of breath.\n\r", ch);
	return;
    }

    if (arg[0] == '\0')
    {
	send_to_char("Who do you wish to breathe on?\n\r", ch);
	return;
    }

    if (!str_cmp(arg, "all"))
    {
      CHAR_DATA *vch, *vch_next;
      for (vch = ch->in_room->people; vch != NULL; vch = vch_next)
      {
	  vch_next = vch->next_in_room;
	  if (vch == ch) continue;

	  if (is_safe(ch,vch) 
	  &&   (ch->fighting != vch || vch->fighting != ch))
	     continue;

	WAIT_STATE(ch, 24);
	SET_TIMER(ch, TIMER_CAN_BREATHE_FROST, 11 - ch->generation / 2);
	frost_breath(ch, vch, TRUE);
      }
    }

    if ( (victim = get_char_room(ch, arg)) == NULL)
    {
	send_to_char("They aren't here.\n\r", ch);
	return;
    }

    WAIT_STATE(ch, 12);
    SET_TIMER(ch, TIMER_CAN_BREATHE_FROST, 9 - ch->generation / 2);
    frost_breath(ch, victim, FALSE);
}


void cold_effect(void *vo, int level, int dam, int target)
{
    if (target == TARGET_ROOM) /* nail objects on the floor */
    {
	ROOM_INDEX_DATA *room = (ROOM_INDEX_DATA *) vo;
	OBJ_DATA *obj, *obj_next;
 
	for (obj = room->contents; obj != NULL; obj = obj_next)
	{
	    obj_next = obj->next_content;
	    cold_effect(obj,level,dam,TARGET_OBJ);
	}
	return;
    }

    else if (target == TARGET_CHAR) /* whack a character */
    {
	CHAR_DATA *victim = (CHAR_DATA *) vo;
	OBJ_DATA *obj, *obj_next;

	/* chill touch effect */
	    AFFECT_DATA af;

	    af.type      = skill_lookup("chill touch");
	    af.duration  = 6;
	    af.location  = APPLY_STR;
	    af.modifier  = -3;
	    af.bitvector = 0;
	    affect_to_char( victim, &af );

	/* let's toast some gear */
	for (obj = victim->carrying; obj != NULL; obj = obj_next)
	{
	    obj_next = obj->next_content;
	    cold_effect(obj,level,dam,TARGET_OBJ);
	}
	return;
   }

   else if (target == TARGET_OBJ) /* toast an object */
   {
	OBJ_DATA *obj = (OBJ_DATA *) vo;
	int chance;
	char *msg;

	chance = level / 4 + dam / 10;

	if (chance > 25)
	    chance = (chance - 25) / 2 + 25;
	if (chance > 50)
	    chance = (chance - 50) / 2 + 50;

	if (IS_OBJ_STAT(obj,ITEM_BLESS))
	    chance -= 5;

	chance -= obj->level * 2;

	switch(obj->item_type)
	{
	    default:
		return;
	    case ITEM_POTION:
		msg = "$p freezes and shatters!";
		chance += 25;
		break;
	    case ITEM_DRINK_CON:
		msg = "$p freezes and shatters!";
		chance += 5;
		break;
	}

	chance = URANGE(5,chance,95);

	if (number_percent() > chance)
	    return;

	if (IS_SET(obj->quest, QUEST_SPELLPROOF))
	    return;

	if (obj->carried_by != NULL)
	    act(msg,obj->carried_by,obj,NULL,TO_ALL);
	else if (obj->in_room != NULL && obj->in_room->people != NULL)
	    act(msg,obj->in_room->people,obj,NULL,TO_ALL);

	extract_obj(obj);
	return;
    }
}


void frost_breath(CHAR_DATA *ch, CHAR_DATA *victim, bool all)
{
    CHAR_DATA *vch, *vch_next;
    int dam;
    int power;

    if (IS_CLASS(ch, CLASS_DEMON)) power = ch->power[DISC_DAEM_GELU];
    else power = 0;

    if (all)
    {
	dam = (ch->generation + 5 * power+5) * 8;
	
	act("$n breathes forth a stream of frost over you.",ch,NULL,NULL,TO_ROOM);
	act("You breath forth a stream of frost.",ch,NULL,NULL,TO_CHAR);

	for (vch = ch->in_room->people; vch != NULL; vch = vch_next)
	{
	    vch_next = vch->next_in_room;
	    if (vch == ch) continue;

	    if (is_safe(ch,vch) 
	    &&   (ch->fighting != vch || vch->fighting != ch))
		continue;

		cold_effect(vch,ch->explevel,dam,TARGET_CHAR);
		damage(ch,vch,dam,skill_lookup("frost breath"));
	}
	return;
    }

    if (is_safe(ch, victim)) return;
    dam = (ch->generation +3 * power+3) * 20;

    act("$n breathes forth a stream of frost over $N.",ch,NULL,victim,TO_NOTVICT);
    act("$n breathes a stream of frost over you!",ch,NULL,victim,TO_VICT);
    act("You breath forth a stream of frost over $N.",ch,NULL,victim,TO_CHAR);
    
    damage(ch,victim,dam,skill_lookup("frost breath"));
    cold_effect(victim,ch->explevel,dam,TARGET_CHAR);
}



#include <types.h>
#else
#include <sys/types.h>
#endif
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"


/* Gets a mob suitable for a person to kill, randomly */

MOB_INDEX_DATA *get_random_mob( void )
{
    MOB_INDEX_DATA *mob;
    
    for ( ; ; )
    {
        mob = get_mob_index( number_range( 0, 65535 ) );
	
        if ( mob != NULL
	     && mob->vnum > 500
	     && mob->level < 1500 ) break;
    }
        
    return mob;
}

DECLARE_DO_FUN( do_sremove );

/* Fun fun fun fun fun fun forms */
/* name, hitprob, damprob, acmod, hitpointmod, squishable? , size!!!!*/
/* can_cast, can_fly, can_wear, carry_max, max_items, say_word, 
move_word, xp_bonus, polymorph_level, in_room_desc
*/

const struct form_type form_data [MAX_FORMS] =
{

    {"","",                0,      0,      0,      0,      FALSE, 0,
	FALSE, FALSE, FALSE, 0, 0, "","", 0, 0, "","", TRUE},

    /* The demonic forms - 13 of them, oh goody */

    {"lemure","", 0,      0,      0,      20, FALSE,SIZE_MEDIUM,
	TRUE, FALSE, TRUE, -1, -1, "gurgle","slimes", 0, -1,
	 "A slimy misshapen lump of flesh lies here in a pile.", "the lemure",TRUE},
    {"nupperibo","", 0,      0,      0,      20, FALSE,SIZE_MEDIUM,
	TRUE, FALSE, TRUE, -1, -1, "gurgle","slimes", 0, -1,
	 "A foul bloated humanoid is here, infested with maggots.", "the nupperibo",TRUE},
    {"spinagon","", 0,      0,      0,      20, FALSE,SIZE_MEDIUM,
	TRUE, FALSE, TRUE, -1, -1, "growl","flies", 0, -1,
	 "A small imp like creature covered with spines hovers here.", "the spinagon",TRUE},
    {"barbazu","", 0,      0,      0,      20, FALSE,SIZE_MEDIUM,
	TRUE, FALSE, TRUE, -1, -1, "roar","stalks", 0, -1,
	 "A foul, bearded and tall demonic warrior patrolls here.", "the barbazu",TRUE},
    {"abishai","", 0,      0,      0,      20, FALSE,SIZE_MEDIUM,
	TRUE, FALSE, TRUE, -1, -1, "growl","flies", 0, -1,
	 "A red-skinned, gargoyle-like demon flaps its wings here. ", "the abishai",TRUE},
    {"osyluth","", 0,      0,      0,      20, FALSE,SIZE_MEDIUM,
	TRUE, FALSE, TRUE, -1, -1, "growl","clatters", 0, -1,
	 "A proud demonic warrior grins wickedly here. ", "the osyluth",TRUE},
    {"hamatula","", 0,      0,      0,      20, FALSE,SIZE_MEDIUM,
	TRUE, FALSE, TRUE, -1, -1, "growl","stalks", 0, -1,
	 "A tall spiny demonic knight stands here proudly.", "the hamatula",TRUE},
    {"erinyes","", 0,      0,      0,      20, FALSE,SIZE_MEDIUM,
	TRUE, FALSE, TRUE, -1, -1, "say","walks", 0, -1,
	 "A beautiful woman with white feathery wings stands here.", "the erinyes",TRUE},
    {"amnizu","", 0,      0,      0,      20, FALSE,SIZE_SMALL,
	TRUE, FALSE, TRUE, -1, -1, "cough","floats", 0, -1,
	 "A foul little winged, pug-nosed dwarf hovers here, sneering.", "the amnizu",TRUE},
    {"cornugon","", 0,      0,      0,      20, FALSE,SIZE_LARGE,
	TRUE, FALSE, TRUE, -1, -1, "growl","crashes", 0, -1,
	 "A huge red-skinned demon with a spiny tail stands here.", "the cornugon",TRUE},
    {"gelugon","", 0,      0,      0,      20, FALSE,SIZE_LARGE,
	TRUE, FALSE, TRUE, -1, -1, "howl","slimes", 0, -1,
	 "An insect-like frost demon with a long tail stands here.", "the gelugon",TRUE},
    {"pit fiend","", 0,      0,      0,      20, FALSE,SIZE_HUGE,
	TRUE, FALSE, TRUE, -1, -1, "bellow","crashes", 0, -1,
	 "A hulking twelve-foot demon is here, dripping with molten lava.", "the pit fiend",TRUE},
    {"pit lord","", 0,      0,      0,      20, FALSE,SIZE_HUGE,
	TRUE, FALSE, TRUE, -1, -1, "thunder","crashes", 0, -1,
	 "A huge black-skinned demon lord stands here.", "the pit lord",TRUE},

/*
     tree form 

    {"tree","", -20,      -20,     -200,      0, FALSE,SIZE_LARGE,
	FALSE, FALSE, FALSE, -1, -1, "creak","uproots", 0, -1,
	 "A huge gnarled tree stands here.", "the gnarled tree",FALSE},


     dragon forms 

    {"hatchling dragon", "", 0, 0, 0, 0, FALSE, SIZE_MEDIUM,
	TRUE, TRUE, TRUE, -1, -1, "slurp", "crawls", 0, -1,
	"A small %s dragon hatchling is here.", "the %s hatchling",TRUE},

    {"young dragon", "", 0, 0, 0, 0, FALSE, SIZE_MEDIUM,
	TRUE, TRUE, TRUE, -1, -1, "hisses", "crawls", 0, -1,
	"A young %s dragon is here.", "the %s young dragon",TRUE},

    {"juvenile dragon", "", 0, 0, 0, 0, FALSE, SIZE_MEDIUM,
	TRUE, TRUE, TRUE, -1, -1, "hisses", "crawls", 0, -1,
	"A juvenile %s dragon stands here.", "the %s dragon",TRUE},

    {"young adult dragon", "", 0, 0, 0, 0, FALSE, SIZE_LARGE,
	TRUE, TRUE, TRUE, -1, -1, "rumble", "walks", 0, -1,
	"A medium sized %s dragon stands here.", "the %s dragon",TRUE},

    {"mature dragon", "", 0, 0, 0, 0, FALSE, SIZE_LARGE,
	TRUE, TRUE, TRUE, -1, -1, "rumble", "walks", 0, -1,
	"A mature %s dragon stands here.", "the mature %s dragon",TRUE},

    {"adult dragon", "", 0, 0, 0, 0, FALSE, SIZE_LARGE,
	TRUE, TRUE, TRUE, -1, -1, "growl", "strides", 0, -1,
	"A large, adult %s dragon stands here.", "the adult %s dragon",TRUE},

    {"elder dragon", "", 0, 0, 0, 0, FALSE, SIZE_HUGE,
	TRUE, TRUE, TRUE, -1, -1, "growl", "crashes", 0, -1,
	"A huge elder %s dragon is here.", "the elder %s dragon",TRUE},

    {"venerable dragon", "", 0, 0, 0, 0, FALSE, SIZE_HUGE,
	TRUE, TRUE, TRUE, -1, -1, "bellow", "crashes", 0, -1,
	"A venerable %s dragon is here.", "the venerable %s dragon",TRUE},

    {"ancient dragon", "", 0, 0, 0, 0, FALSE, SIZE_GIANT,
	TRUE, TRUE, TRUE, -1, -1, "roar", "crashes", 0, -1,
	"A giant ancient %s dragon is standing here.", "the ancient %s dragon",TRUE},

    {"lesser wyrm", "", 0, 0, 0, 0, FALSE, SIZE_GIANT,
	TRUE, TRUE, TRUE, -1, -1, "roar", "crashes", 0, -1,
	"A giant lesser %s wyrm is standing here.", "the lesser %s wyrm",TRUE},

    {"wyrm", "", 0, 0, 0, 0, FALSE, SIZE_GIANT,
	TRUE, TRUE, TRUE, -1, -1, "roar", "crashes", 0, -1,
	"A giant %s wyrm is here, towering over you.", "the %s wyrm",TRUE},

    {"great wyrm", "", 0, 0, 0, 0, FALSE, SIZE_GIANT,
	TRUE, TRUE, TRUE, -1, -1, "thunder", "crashes", 0, -1,
	"A Great %s Wyrm is here, towering over you.", "the great %s wyrm",TRUE},

    {"supreme dragon", "", 0, 0, 0, 0, FALSE, SIZE_GIANT,
	TRUE, TRUE, TRUE, -1, -1, "thunder", "crashes", 0, -1,
	"The colossal Supreme %s Dragon towers over you.", "the supreme %s dragon",TRUE},

     The alternative were beasties 

    {"wererat","",  60,     60,     -40,    0,    FALSE, SIZE_MEDIUM,
	FALSE,FALSE,TRUE,500,60,"growl","bounds",140,-1,
	"A filthy half-man, half-rat is standing here.", "a filthy wererat",TRUE},
    {"werebear","",  60,     60,     -40,    0,    FALSE, SIZE_LARGE,
	FALSE,FALSE,TRUE,500,60,"boom","lumbers",140,-1,
	"A hulking great half-man, half-bear is standing here.", "a hulking werebear",TRUE},
    {"weretiger","",  60,     60,     -40,    0,    FALSE, SIZE_MEDIUM,
	FALSE,FALSE,TRUE,500,60,"roar","pounces",140,-1,
	"A ferocious half-man, half-tiger is standing here.", "a ferocious weretiger",TRUE},
    {"wereshark","",  60,     60,     -40,    0,    FALSE, SIZE_MEDIUM,
	FALSE,FALSE,TRUE,500,60,"growl","stalks",140,-1,
	"A ravenous half-man, half-shark is standing here.", "a hungry wereshark",TRUE},
    {"stone golem","",  0,     100,     -300,    0,    FALSE, SIZE_MEDIUM,
	FALSE,FALSE,FALSE,500,60,"scrape","lumbers",140,-1,
	"A roughly carved but lifelike humanoid statue stands here.", "a stone golem",TRUE},
    {"pixie","",  20,     1,     -10,    0,    FALSE, SIZE_SMALL,
	TRUE,TRUE,TRUE,500,60,"squeak","flies",140,-1,
	"A little pixie hovers around the room here, flapping its tiny wings.", "a pixie",FALSE},
    {"manticore","",  50,     50,     -90,    1000,    FALSE, SIZE_LARGE,
	TRUE,TRUE,FALSE,500,60,"roar","flies",140,-1,
	"A manticore patrols the area proudly, growling at you.", "a manticore",TRUE},
*/
    {"giant myrlochar","", 0,      0,  0,      0, FALSE,SIZE_LARGE,
        TRUE, TRUE,TRUE, 200, 30, "hisses","creeps", 0, -1,
         "A giant, hairy myrlochar is creeping along here.", "A giant myrlochar", TRUE}

};

/* Fun fun fun fun fun fun forms */
/* name, hitprob, damprob, acmod, hitpointmod, squishable? , size!!!!*/
/* can_cast, can_fly, can_wear, carry_max, max_items, say_word, 
move_word, xp_bonus, polymorph_level, in_room_desc, short_name
*/


int get_normal_form(CHAR_DATA *ch)
{
    if ( IS_CLASS(ch, CLASS_DEMON) )
     return ch->generation;

    return 0;
}

bool is_demonic_form(int form)
{
    if (form >= FRM_LEMURE && form <= FRM_PIT_LORD) return TRUE;
    return FALSE;
}

bool is_vowel(char arg)
{
    if (arg == 'a' || arg == 'e' || arg == 'i'
	|| arg == 'o' || arg == 'u') return TRUE;

    return FALSE;
}

void form_in_room_desc( CHAR_DATA *ch, char *buf )
{
    if (ch->cur_form >= 38 && ch->cur_form <= 50)
    {
	sprintf(buf, form_data[ch->cur_form].in_room_desc, dragon_colour2(ch->dragtype));
	bug(buf, 0);
	bug(dragon_colour2(ch->dragtype), 0);
	return;
    }
    sprintf(buf,form_data[ch->cur_form].in_room_desc);
}

bool is_clan( CHAR_DATA *ch )
{
    return ch->cclan;
}

const char * circlesymbol [7] =
{
	" ",
	"#1*#n",
	"#4~#n",
	"#6=#n",
	"#2###n",
	"#5+#n",
	"#3-#n"
};


int souls_needed( CHAR_DATA *ch )
{
   int souls;
   souls = ch->generation * 5;
   return souls;
}

void do_testform( CHAR_DATA *ch, char *argument )
{
    int form;
    ch->generation = 13;
    ch->class = CLASS_DEMON;
    form = get_normal_form(ch);
    set_form(ch, form);
    return;
}

/* Free hand counter */
bool sremove_obj( CHAR_DATA *ch, int iWear, bool fReplace )
{
    OBJ_DATA *obj;

    if ( ( obj = get_eq_char( ch, iWear ) ) == NULL )
	return TRUE;

    if ( !fReplace )
	return FALSE;

    unequip_char( ch, obj );
    act( "$n stops using $p.", ch, obj, NULL, TO_ROOM );
    act( "You stop using $p.", ch, obj, NULL, TO_CHAR );
    return TRUE;
}


void do_sremove( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;
    

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char( "Remove what?\n\r", ch );
	return;
    }

    if (!str_cmp(arg, "all"))
    {
	OBJ_DATA *obj_next;
	for (obj = ch->carrying; obj != NULL; obj = obj_next)
	{
	    obj_next = obj->next_content;
	    if ( obj->wear_loc != WEAR_NONE && can_see_obj(ch, obj))
		sremove_obj(ch,obj->wear_loc, TRUE);
	}
	return;
    }

    if ( ( obj = get_obj_wear( ch, arg ) ) == NULL )
    {
	send_to_char( "You do not have that item.\n\r", ch );
	return;
    }

    sremove_obj( ch, obj->wear_loc, TRUE );
    return;
}


void set_switchname( CHAR_DATA *ch, char *title )
{
    char buf[MAX_STRING_LENGTH];

    if ( IS_NPC(ch) )
    {
	bug( "Set_switchname: NPC.", 0 );
	return;
    }
    strcpy( buf, title );
    free_string( ch->pcdata->switchname );
    ch->pcdata->switchname = str_dup( buf );
    return;
}

void set_pc_name( CHAR_DATA *ch, char *title )
{
    char buf[MAX_STRING_LENGTH];

    if ( IS_NPC(ch) )
    {
	bug( "Set_pc_name: NPC.", 0 );
	return;
    }
    strcpy( buf, title );
    free_string( ch->name);
    ch->name = str_dup( buf );
    return;
}

void set_enter_room_text( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH]; 

    if ( IS_NPC(ch) )
	return;

    if ( strlen(argument) > 45 )
	argument[45] = '\0';

    smash_tilde( argument );

    strcpy( buf, argument );

    free_string( ch->pcdata->enter_room );
    ch->pcdata->enter_room = str_dup( buf );
    return;

}

const struct clanrank_type clanrank [9][14] =
{
    { /* None */
	{       "",              0   ,"" ,""   },
	{       "",              0   ,"" ,""   },
	{       "",              0   ,"" ,""   },
	{       "",              0   ,"" ,""   },
	{       "",              0   ,"" ,""   },
	{       "",              0   ,"" ,""   },
	{       "",              0   ,"" ,""   },
	{       "",              0   ,"" ,""   },
	{       "",              0   ,"" ,""   },
	{       "",              0   ,"" ,""   },
	{       "",              0   ,"" ,""   },
	{       "",              0   ,"" ,""   },
	{       "",              0   ,"" ,""   },
	{       "",              0   ,"" ,""   }
    },

    { /* Dragon */
	{       " bug - chris you git",  0 ,"",""     },
	{       "Hatchling",       30 ,"Dragon Hatchling","Dragon Hatchling"},
	{       "Young",           34 ,"Young Dragon","Young Dragon"},
	{       "Juvenile",        40 ,"Juvenile Dragon","Juvenile Dragon"},
	{       "Young Adult",     46 ,"Dragon","Dragon"     },
	{       "Mature",          52 ,"Mature Dragon","Mature Dragon"},
	{       "Adult",           58 ,"Adult Dragon","Adult Dragon"},
	{       "Elder",           65 ,"Elder Dragon","Elder Dragon"},
	{       "Venerable",       72 ,"Venerable Dragon","Venerable Dragon"},
	{       "Ancient",         79 ,"Ancient Dragon","Ancient Dragon"},
	{       "Lesser Wyrm",     86  ,"Lesser Wyrm","Lesser Wyrm"    },
	{       "Wyrm",            93  ,"Wyrm","Wyrm"    },
	{       "Great Wyrm",      100 ,"Great Wyrm","Great Wyrm"    },
	{       "Supreme Dragon",  112 ,"Supreme Dragon","Supreme Dragon"}
    },
    { /* Demon */
	{       "  *** BUG ***",         0  ,"bug",""    },
	{       "Lemure",             20  ," the lemure","lemure"    },
	{       "Nupperibo",          25  ," the nupperibo","nupperibo"},
	{       "Spinagon",           31  ," the spinagon","spinagon"},
	{       "Barbazu",            38  ," the barbazu","barbazu"},
	{       "Abishai",            45  ," the abishai","abishai"},
	{       "Osyluth",            52  ," the osyluth","osyluth"},
	{       "Hamatula",           59  ," the hamatula","hamatula"},
	{       "Erinyes",            67  ," the erinyes","erinyes"},
	{       "Amnizu",             75  ," the amnizu","amnizu"    },
	{       "Cornugon",           84  ," the cornugon","cornugon"},
	{       "Gelugon",            93  ," the gelugon","gelugon"},
	{       "Pit Fiend",          102  ," the pit fiend","pit fiend"},
	{       "Pit Lord",           112  ," the pit lord","pit lady"}
    },
    { /* Vampires */
	{       " AARGH bug bzzz",       0   ,"",""   },
	{       " Childe}",             20   ,"Childe Vampire","Childe Vampiress"   },
	{       " Childe}",             25   ,"Childe Vampire","Childe Vampiress"   },
	{       " Neonate}",            31   ,"Neonate Vampire","Neonate Vampiress"   },
	{       " Primogen}",           38   ,"Vampire","Vampiress"   },
	{       " Elder}",              45   ,"Vampire","Vampiress"   },
	{       " Archon}",             52   ,"Vampire","Vampiress"   },
	{       " Justicar}",           59   ,"Vampire","Vampiress"   },
	{       " Prince}",             67   ,"Vampire Prince","Vampire Princess"   },
	{       " of the Inner Circle}",75   ,"Vampire Prince","Vampire Princess"   },
	{       " Methuselah}",         84   ,"Methuselah","Methuselah"},
	{       " Antediluvian}",       93   ,"Antediluvian","Antediluvian"   },
	{       " Inconnu}",       102  ,"Vampire Lord","Vampire Lady"},
	{       " Supreme Vampire}",       112  ,"Son of Caine","Daughter of Caine"   }
    },
    { /* Lupine */
	{       "None ",                 0    ,"",""   },
	{       " Pup)",                 20   ,"Were-pup","Were-pup"   },
	{       " Kid)",                 25   ,"Werewolf","Werewolf"   },
	{       " Adult)",               31   ,"Werewolf","Werewolf"   },
	{       " Mature Adult)",        38   ,"Werewolf","Werewolf"   },
	{       " Tracker)",             45   ,"Werewolf","Werewolf"   }, 
	{       " Hunter)",              52   ,"Werewolf","Werewolf"   },
	{       " Warrior)",             59   ,"Werewolf","Werewolf"   },
	{       " Warlord)",             67   ,"Werewolf Lord","Werewolf Lady"   },
	{       " Shaman)",              75   ,"Werewolf Shaman","Werewolf Shaman"   },
	{       " Tribal Chief)",        84   ,"Werewolf Chief","Werewolf Chief"   },
	{       " War Chief)",           93   ,"Werewolf Prince","Werewolf Princess"   },
	{       " Overlord)",            102  ,"Werewolf Overlord","Werewolf Overlord"   },	
      {       " Deity)",               112  ,"Werewolf Diety","Werewolf Diety"   }
    },
    { /* Eladrin */
	{       "None ",                 0      ,"",""},
	{       " Coure]",              20      ,"Coure","Coure"},
	{       " Coure]",              25      ,"Coure","Coure"},
	{       " Noviere]",            31      ,"Noviere","Noviere"},
	{       " Noviere]",            38      ,"Noviere","Noviere"},
	{       " Bralani]",            45      ,"Bralani","Bralani"},
	{       " Bralani]",            52      ,"Bralani","Bralani"},
	{       " Shiere]",             59      ,"Shiere","Shiere"},
	{       " Firre]",              67      ,"Firre","Firre"},
	{       " Firre]",              75      ,"Firre","Firre"},
	{       " Ghaele]",             84      ,"Ghaele","Ghaele"},
	{       " Ghaele]",             93      ,"Ghaele","Ghaele"},
	{       " Tulani]",             102     ,"Tulani","Tulani" },
	{       " Faerie Lord]",        112     ,"Faerie Prince","Faerie Princess" }
    },
    { /* Warlocks */
	{       "None ",                  0   ,"",""   },
	{       " Student>-",             15  ,"Student Wizard","Student Wizard"    },
	{       " Adept>-",               19  ,"Adept Wizard","Adept Wizard"    },
	{       " Artisan>-",           24   ,"Artisan Wizard","Artisan Wizard"   },
	{       " Master>-",            30   ,"Master Wizard","Lady Wizard"   },
	{       " Conjurer>-",          36   ,"Conjurer","Conjuress"   },
	{       " Enchanter>-",         42   ,"Enchanter","Enchantress" },
	{       " Abjurer>-",           49   ,"Abjurer","Abjuress"   },
	{       " Sorcerer>-",          57   ,"Sorcerer","Sorceress"   },
	{       " Mage>-",              66   ,"Mage","Magi"   },
	{       " Wizard>-",            78   ,"High Wizard","High Wizard" },
	{       " Grand Wizard>-",      93   ,"Grand Wizard","Grand Magi" },
	{       " Archmage>-",          99   ,"Archmage","Archmagi"   },
	{       " Supreme Wizard>-",    112  ,"Supreme Wizard","Supreme Wizard"   }
    },
    { /* Hero */
	{       "None ",                 0   ,"",""   },
	{       " Traveller<>",          15  ,"Adventurer","Adventurer" },
	{       " Journeyman<>",         19  ,"Adventurer","Adventurer" },
	{       " Artisan<>",            24  ,"Adventurer","Adventurer" },
	{       " Master<>",             30  ,"Adventurer","Adventurer" },
	{       " Defender<>",           37  ,"Adventurer","Adventurer" },
	{       " Protector<>",          43  ,"Adventurer","Adventurer" },
	{       " Crusader<>",           50  ,"Crusader","Crusader"     },
	{       " Hero<>",               58  ,"Hero","Heroin"    },
	{       " Legend<>",             68  ,"Hero","Heroin"    },
	{       " Legend<>",             80  ,"Hero","Heroin"    },
	{       " Avatar<>",             93  ,"Avatar","Avatar"    },
	{       " Saviour<>",            102   ,"Avatar","Avatar"  },
	{       " Immortal<>",           112   ,"Immortal","Immortal"  }
    },
    { /* Death Knight */
	{       "None ",                 0   ,"",""   },
	{       " Squire>",             15  ,"death knight","death knight" },
	{       " Squire>",             19  ,"Adventurer","Adventurer" },
	{       " Trainee>",            24  ,"Adventurer","Adventurer" },
	{       " Master>",             30  ,"Adventurer","Adventurer" },
	{       " Lord>",               37  ,"Adventurer","Adventurer" },
	{       " Anti-Hero>",          43  ,"Adventurer","Adventurer" },
	{       " Anti-Hero>",          50  ,"Crusader","Crusader"    },
	{       " Knight>",             58  ,"Hero","Heroin"    },
	{       " Grey Knight>",        68  ,"Hero","Heroin"    },
	{       " Dark Knight>",        80  ,"Dark Knight","Dark Knight" },
	{       " Black Knight>",       93  ,"Black Knight","Black Knight" },
	{       " Death Knight>",       102   ,"Death Knight","Death Knight"  },
	{       " Death Knight>",       112   ,"Death Knight","Death Knight"  }
    }
};

void look_name(CHAR_DATA *ch)
{
	char const * class;
	char buf[MAX_STRING_LENGTH];

	if (IS_NPC(ch))
	return;
	
	class = race_table[ch->race].name;
	
	if (ch->class > 0)
	{
		if (ch->sex != SEX_FEMALE)
		  class = clanrank[ch->class][ch->generation].male_name;
		else
		  class = clanrank[ch->class][ch->generation].female_name;
	}

	    sprintf(buf, " the %s", class);


	set_enter_room_text(ch, buf);
}

/* race table */
const   struct  race_type       race_table      []              =
{
/*
    {
	name,           ishname,      pc_race?,
	act bits,       aff_by bits,    off bits,
	imm,            res,            vuln,
	form,           parts 
    },
*/
    { "unique",   "unique",      FALSE, 0, 0, 0, 0, 0, 0, 0, 0 },

    { 
	"human",  "human",              TRUE, 
	0,              0,              0,
	0,              0,              0,
	0,              0
    },

    {
	"elf",    "elvish",              TRUE,
	0,              0,      0,
	0,              0,      0,
	0,              0
    },

    {
	"half-elf",   "half-elvish",          TRUE,
	0,              0,      0,
	0,              0,      0,
	0,              0
    },

    {
	"gnome",     "gnomish",           TRUE,
	0,              0,           0,
	0,              0,           0,
	0,              0
    },

    {
	NULL, NULL, 0, 0, 0, 0, 0, 0
    }
};

char * dragon_colour (sh_int dragtype)
{
    if (dragtype == DRAGON_RED) return "#1Red#n";
    else if (dragtype == DRAGON_WHITE) return "#7White#n";
    else if (dragtype == DRAGON_BLACK) return "Black";
    else if (dragtype == DRAGON_GREEN) return "#2Green#n";
    else if (dragtype == DRAGON_BLUE) return "#4Blue#n";
    else if (dragtype == DRAGON_SILVER) return "#6Silver#n";
    else if (dragtype == DRAGON_GOLD) return "#3Gold#n";
    else if (dragtype == DRAGON_SHADOW) return "Shadow";
    return "Bug, please inform Jander";
}

char * dragon_colour2 (sh_int dragtype)
{
    if (dragtype == DRAGON_RED) return "red";
    else if (dragtype == DRAGON_WHITE) return "white";
    else if (dragtype == DRAGON_BLACK) return "black";
    else if (dragtype == DRAGON_GREEN) return "green";
    else if (dragtype == DRAGON_BLUE) return "blue";
    else if (dragtype == DRAGON_SILVER) return "silver";
    else if (dragtype == DRAGON_GOLD) return "gold";
    else if (dragtype == DRAGON_SHADOW) return "shadow";
    return "Bug, please inform Jander";
}


void set_form(CHAR_DATA *ch, sh_int form)
{
    char shortdesc[MAX_STRING_LENGTH];
    char name[MAX_STRING_LENGTH];
    int oldform;

/*
    if (form == 0 && ch->secondaryrace == RACE_DRAGON)
    {
        form = 37 + ch->generation;
	if (ch->generation < 1 || ch->generation > 13) form = 0;
    }
*/
/*    oldform = form;
    ch->max_hit  -= form_data[ch->cur_form].hit_mod;
    ch->xhitroll -= form_data[ch->cur_form].hit;
    ch->xdamroll -= form_data[ch->cur_form].dam;
    ch->armor    -= form_data[ch->cur_form].ac;
    ch->cur_form = form;
    ch->max_hit  += form_data[ch->cur_form].hit_mod;
    ch->xhitroll += form_data[ch->cur_form].hit;
    ch->xdamroll += form_data[ch->cur_form].dam;
    ch->armor    += form_data[ch->cur_form].ac;
    ch->size = get_size( ch );
*/
/*
//  if (ch->secondaryrace == RACE_ELADRIN) ch->body_form = 0;
    if (form >= 38 && form <=50)
    {
	if (form_data[form].short_desc != NULL
		&& form_data[form].short_desc[0] != '\0')
	sprintf(shortdesc, form_data[ch->cur_form].short_desc, dragon_colour2(ch->dragtype));
	else shortdesc[0] = 0;
    }
    else
    {
	if (form_data[form].short_desc != NULL
		&& form_data[form].short_desc[0] != '\0')
	sprintf(shortdesc, form_data[ch->cur_form].short_desc);
	else shortdesc[0] = 0;
    }
*/
    if (!IS_CLASS(ch,CLASS_DROW))
    {
    sprintf(name, form_data[ch->cur_form].name);
    set_enter_room_text(ch, name);
    if (ch->cur_form == 0)
    {
	look_name(ch);
	set_pc_name(ch, GET_PROPER_NAME(ch));
    }
    else
	if (shortdesc != NULL
		&& shortdesc[0] != '\0')
	set_pc_name(ch, shortdesc);
    }
    if (IS_CLASS(ch, CLASS_DROW))
    {
    sprintf(name, form_data[ch->cur_form].name);
    set_enter_room_text(ch, name);
    if (ch->cur_form == 0)
    {
        set_pc_name(ch, GET_PROPER_NAME(ch));
    }
    else
        if (shortdesc != NULL
                && shortdesc[0] != '\0')
        set_pc_name(ch, shortdesc);
    }  
	
    if (ch->cur_form != 0 && !form_data[ch->cur_form].can_wear)
    {
	OBJ_DATA *obj;

	do_sremove(ch, "all");
	for (obj = ch->carrying; obj != NULL; obj = obj->next_content)
	{
	    SET_BIT(obj->extra_flags2, ITEM_FORM_MELDED);
	}
    }
    else
    {
	OBJ_DATA *obj;

	for (obj = ch->carrying; obj != NULL; obj = obj->next_content)
	{
	    REMOVE_BIT(obj->extra_flags2, ITEM_FORM_MELDED);
	}
    }

/*
    if (ch->cur_form == FRM_WOLF)
    {
	SET_BIT(ch->flag2, AFF_BITE);
	SET_BIT(ch->flag2, AFF_CLAW);
    }

    else if (!( oldform == 0
	  && ch->cur_form == 0))
    {
	REMOVE_BIT(ch->flag2, AFF_BITE);
	REMOVE_BIT(ch->flag2, AFF_CLAW);
    }
*/

    if (ch->cur_form == 0) ch->size = get_size(ch);

    save_char_obj(ch);
}

int get_size(CHAR_DATA *ch)
{
    if (ch->cur_form != 0) return form_data[ch->cur_form].size;
//    if (ch->secondaryrace == RACE_ELADRIN)
//  {
//	if (ch->generation < 3) return SIZE_SMALL;
//	return SIZE_MEDIUM;
//  }

    else if (ch->class == 0)
    {
	return SIZE_MEDIUM;
    }
/*
    else if (ch->secondaryrace == RACE_DRAGON)
    {
	if (ch->generation > 9) return SIZE_GIANT;
	if (ch->generation > 7) return SIZE_HUGE;
	if (ch->generation > 3) return SIZE_LARGE;
    }
*/
    else if (IS_CLASS(ch, CLASS_DEMON))
    {
	if (ch->generation == 10) return SIZE_LARGE;
	if (ch->generation > 10) return SIZE_HUGE;
    }

    return SIZE_MEDIUM;
}





 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *


 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *


 *                                                                         *


 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *


 *  Chastain, Michael Quan, and Mitchell Tse.                              *


 *                                                                         *


 *  In order to use any part of this Merc Diku Mud, you must comply with   *


 *  both the original Diku license in 'license.doc' as well the Merc       *


 *  license in 'license.txt'.  In particular, you may not remove either of *


 *  these copyright notices.                                               *


 *                                                                         *


 *  Much time and thought has gone into this software and you are          *


 *  benefitting.  We hope that you share your changes too.  What goes      *


 *  around, comes around.                                                  *


 ***************************************************************************/





#if defined(macintosh)


#include <types.h>


#else


#include <sys/types.h>


#endif


#include <ctype.h>


#include <stdio.h>


#include <stdlib.h>


#include <string.h>


#include <time.h>


#include "merc.h"





#if !defined(macintosh)


extern	int	_filbuf		args( (FILE *) );


#endif








/*


 * Globals.


 */
HELP_DATA *		help_first;


HELP_DATA *		help_last;





SHOP_DATA *		shop_first;


SHOP_DATA *		shop_last;





CHAR_DATA *		char_free;


EXTRA_DESCR_DATA *	extra_descr_free;


NOTE_DATA *		note_free;


OBJ_DATA *		obj_free;


PC_DATA *		pcdata_free;





char			bug_buf		[2*MAX_INPUT_LENGTH];


CHAR_DATA *		char_list;


char *			help_greeting;


char			log_buf		[2*MAX_INPUT_LENGTH];


KILL_DATA		kill_table	[MAX_LEVEL];


OBJ_DATA *		object_list;


TIME_INFO_DATA		time_info;


WEATHER_DATA		weather_info;


sh_int			gsn_backstab;


sh_int                  gsn_shred;


sh_int                  gsn_quills;


sh_int 			gsn_cheapshot;


sh_int                  gsn_spit;


sh_int			gsn_venomtong;


sh_int			gsn_spiketail;


sh_int			gsn_badbreath;


sh_int			gsn_magma;


sh_int			gsn_shards;


sh_int			gsn_hide;


sh_int			gsn_peek;


sh_int			gsn_pick_lock;


sh_int			gsn_sneak;


sh_int			gsn_steal;


sh_int			gsn_spiderform;


sh_int			gsn_garotte;


sh_int			gsn_disarm;


sh_int			gsn_tendrils;


sh_int			gsn_berserk;


sh_int			gsn_punch;
sh_int			gsn_headbutt;
sh_int			gsn_shiroken;


sh_int			gsn_inferno;
sh_int			gsn_blinky;
sh_int			gsn_fangs;


sh_int			gsn_buffet;


sh_int			gsn_sweep;


sh_int			gsn_knee;


sh_int                  gsn_rfangs;
sh_int			gsn_thrustkick;
sh_int			gsn_spinkick;
sh_int			gsn_backfist;
sh_int			gsn_elbow;
sh_int			gsn_shinkick;
sh_int			gsn_palmstrike;
sh_int			gsn_lightningkick;
sh_int			gsn_tornadokick;
sh_int			gsn_jumpkick;
sh_int			gsn_spinkick;
sh_int			gsn_monksweep;
sh_int		gsn_circle;


sh_int			gsn_kick;


sh_int			gsn_hurl;


sh_int			gsn_rescue;


sh_int			gsn_track;


sh_int			gsn_polymorph;


sh_int			gsn_web;


sh_int			gsn_drowfire;


sh_int                  gsn_infirmity;


sh_int                  gsn_spew;


sh_int			gsn_blindness;


sh_int			gsn_charm_person;


sh_int			gsn_curse;


sh_int			gsn_invis;


sh_int			gsn_mass_invis;


sh_int			gsn_poison;


sh_int			gsn_sleep;





sh_int			gsn_darkness;


sh_int			gsn_paradox;


sh_int			gsn_laser;
sh_int			gsn_stuntubes;















/*


 * Locals.


 */


MOB_INDEX_DATA *	mob_index_hash		[MAX_KEY_HASH];


OBJ_INDEX_DATA *	obj_index_hash		[MAX_KEY_HASH];


ROOM_INDEX_DATA *	room_index_hash		[MAX_KEY_HASH];


char *			string_hash		[MAX_KEY_HASH];





AREA_DATA *		area_first;


AREA_DATA *		area_last;



CONFIG_DATA *		config_info;
ROOM_INDEX_DATA *	room_list;

HELP_DATA *		first_help;
HELP_DATA *		last_help;




char *			string_space;


char *			top_string;


char			str_empty	[1];





int			top_affect;


int			top_area;


int			top_rt;


int			top_ed;


int			top_exit;


int			top_help;


int			top_mob_index;


int			top_obj_index;


int			top_reset;


int			top_room;


int			top_shop;


int                     top_vnum_room;  /* OLC */
int                     top_vnum_mob;   /* OLC */
int                     top_vnum_obj;   /* OLC */

bool CHAOS = FALSE;
bool VISOR = FALSE;
bool DARKNESS = FALSE;
bool SPEED = FALSE;
bool BRACELET = FALSE;
bool TORC = FALSE;
bool ARMOUR = FALSE;
bool CLAWS = FALSE;






/*


 * Memory management.


 * Increase MAX_STRING if you have too.


 * Tune the others only if you understand what you're doing.





#define			MAX_STRING	1048576





 */





#define			MAX_STRING	1572864


#define			MAX_PERM_BLOCK	131072


#define			MAX_MEM_LIST	11





void *			rgFreeList	[MAX_MEM_LIST];


const int		rgSizeList	[MAX_MEM_LIST]	=


{


    16, 32, 64, 128, 256, 1024, 2048, 4096, 8192, 16384, 32768-64


};





int			nAllocString;


int			sAllocString;


int			nAllocPerm;


int			sAllocPerm;











/*


 * Semi-locals.


 */


bool			fBootDb;


FILE *			fpArea;


char			strArea[MAX_INPUT_LENGTH];











/*


 * Local booting procedures.


 */


void	init_mm		args( ( void ) );





void	load_area	args( ( FILE *fp ) );


void    load_helps      args( ( FILE *fp ) );
void	load_mobiles	args( ( FILE *fp ) );


void	load_objects	args( ( FILE *fp ) );


void	load_resets	args( ( FILE *fp ) );


void	load_rooms	args( ( FILE *fp ) );


void	load_shops	args( ( FILE *fp ) );


void	load_specials	args( ( FILE *fp ) );


void    load_artifacts  args( ( void ) );
void    new_load_area   args( ( FILE *fp ) );   /* OLC */
void    new_load_rooms  args( ( FILE *fp ) );   /* OLC 1.1b */




void	fix_exits	args( ( void ) );





void	reset_area	args( ( AREA_DATA * pArea ) );












/*


 * Big mama top level function.


 */


void boot_db( void )


{


/*	char buf[MAX_STRING_LENGTH];
*/
    /*


     * Init some data space stuff.


     */


    {


	if ( ( string_space = calloc( 1, MAX_STRING ) ) == NULL )


	{


	    bug( "Boot_db: can't alloc %d string space.", MAX_STRING );


	    exit( 1 );


	}


	top_string	= string_space;


	fBootDb		= TRUE;


    }





    /*


     * Init random number generator.


     */


    {


	init_mm( );


    }





    /*


     * Set time and weather.


     */


    {


	long lhour, lday, lmonth;





	lhour		= (current_time - 650336715)


			/ (PULSE_TICK / PULSE_PER_SECOND);


	time_info.hour	= lhour  % 24;


	lday		= lhour  / 24;


	time_info.day	= lday   % 35;


	lmonth		= lday   / 35;


	time_info.month	= lmonth % 17;


	time_info.year	= lmonth / 17;





	     if ( time_info.hour <  5 ) weather_info.sunlight = SUN_DARK;


	else if ( time_info.hour <  6 ) weather_info.sunlight = SUN_RISE;


	else if ( time_info.hour < 19 ) weather_info.sunlight = SUN_LIGHT;


	else if ( time_info.hour < 20 ) weather_info.sunlight = SUN_SET;


	else                            weather_info.sunlight = SUN_DARK;





	weather_info.change	= 0;


	weather_info.mmhg	= 960;


	if ( time_info.month >= 7 && time_info.month <=12 )


	    weather_info.mmhg += number_range( 1, 50 );


	else


	    weather_info.mmhg += number_range( 1, 80 );





	     if ( weather_info.mmhg <=  980 ) weather_info.sky = SKY_LIGHTNING;


	else if ( weather_info.mmhg <= 1000 ) weather_info.sky = SKY_RAINING;


	else if ( weather_info.mmhg <= 1020 ) weather_info.sky = SKY_CLOUDY;


	else                                  weather_info.sky = SKY_CLOUDLESS;





    }

	initialise_config();


    /*
     * Assign gsn's for skills which have them.


     */


    {


	int sn;





	for ( sn = 0; sn < MAX_SKILL; sn++ )


	{


	    if ( skill_table[sn].pgsn != NULL )


		*skill_table[sn].pgsn = sn;


	}


    }





    /*


     * Read in all the area files.


     */


    {


	FILE *fpList;





	if ( ( fpList = fopen( AREA_LIST, "r" ) ) == NULL )


	{


	    perror( AREA_LIST );


	    exit( 1 );


	}





	for ( ; ; )


	{


	    strcpy( strArea, fread_word( fpList ) );


	    if ( strArea[0] == '$' )


		break;





	    if ( strArea[0] == '-' )


	    {


		fpArea = stdin;


	    }


	    else


	    {


/*		sprintf(buf,"loading %s",strArea);
		log_string(buf);*/
		if ( ( fpArea = fopen( strArea, "r" ) ) == NULL )


		{


		    perror( strArea );


		    exit( 1 );


		}


	    }





	    for ( ; ; )


	    {


		char *word;





		if ( fread_letter( fpArea ) != '#' )


		{


		    bug( "Boot_db: # not found.", 0 );


		    exit( 1 );


		}





		word = fread_word( fpArea );





		     if ( word[0] == '$'               )                 break;


		else if ( !str_cmp( word, "AREA"     ) ) load_area(fpArea);


		else if ( !str_cmp( word, "HELPS"    ) ) load_helps   (fpArea);


		else if ( !str_cmp( word, "MOBILES"  ) ) load_mobiles (fpArea);


		else if ( !str_cmp( word, "OBJECTS"  ) ) load_objects (fpArea);


		else if ( !str_cmp( word, "RESETS"   ) ) load_resets  (fpArea);


		else if ( !str_cmp( word, "ROOMS"    ) ) load_rooms   (fpArea);


		else if ( !str_cmp( word, "SHOPS"    ) ) load_shops   (fpArea);


		else if ( !str_cmp( word, "SPECIALS" ) ) load_specials(fpArea);


                else if ( !str_cmp( word, "AREADATA" ) )        /* OLC */
                    new_load_area( fpArea );
                else if ( !str_cmp( word, "ROOMDATA" ) )        /* OLC 1.1b */
                    new_load_rooms( fpArea );

		else


		{


		    bug( "Boot_db: bad section name.", 0 );


		    exit( 1 );


		}


	    }





	    if ( fpArea != stdin )


		fclose( fpArea );


	    fpArea = NULL;


	}


	fclose( fpList );


    }





    /*


     * Fix up exits.


     * Declare db booting over.


     * Reset all areas once.


     * Load up the notes file.


     */


    {


	fix_exits( );


	fBootDb	= FALSE;


	area_update( );


	load_bans();


	load_kingdoms();
	load_boards();
	save_notes();
	load_disabled();


        load_artifacts();
    }

    return;


}













/*
 * Load the Artifacts ( whee ).
 */

void load_artifacts( void )
{
    CHAR_DATA *pMob;
    OBJ_DATA *obj;
/*
    bug( "Loading Artifacts.", 0 );
*/
    /* Gaia */
    pMob = create_mobile( get_mob_index( 70000 ) );
    char_to_room( pMob, get_room_index( 9200 ) );
    obj = create_object( get_obj_index( 29516 ), 0 );
    obj_to_char( obj, pMob );

    /* Zombie Lord - Chaos Axe */
    pMob = create_mobile( get_mob_index( 1212 ) );
    char_to_room( pMob, get_room_index( 3001 ) );
    obj = create_object( get_obj_index( 29503 ), 0 );
    obj_to_char( obj, pMob );

    /* The Master Wizard - Visor of Vision */
    pMob = create_mobile( get_mob_index( 70007 ) );
    char_to_room( pMob, get_room_index( 1498 ) );
    obj = create_object( get_obj_index( 29515 ), 0 );
    obj_to_char( obj, pMob );

    /* Satan - Sword of Darkness */
    pMob = create_mobile( get_mob_index( 70006 ) );
    char_to_room( pMob, get_room_index( 2551 ) );
    obj = create_object( get_obj_index( 29512 ), 0 );
    obj_to_char( obj, pMob );

    /* Lloth the Spider Queen - Bracelet of Lloth */
    pMob = create_mobile( get_mob_index( 70003 ) );
    char_to_room( pMob, get_room_index( 5143 ) );
    obj = create_object( get_obj_index( 29518 ), 0 );
    obj_to_char( obj, pMob );

    /* Allah - Torc of Continual Restoration */
    pMob = create_mobile( get_mob_index( 70002 ) );
    char_to_room( pMob, get_room_index( 951 ) );
    obj = create_object( get_obj_index( 29504 ), 0 );
    obj_to_char( obj, pMob );

    /* Caine - The Armour of Resistance */
    pMob = create_mobile( get_mob_index( 70001 ) );
    char_to_room( pMob, get_room_index( 3475 ) );
    obj = create_object( get_obj_index( 29514 ), 0 );
    obj_to_char( obj, pMob );

    return;
}

/*


 * Snarf an 'area' header line.


 */


void load_area( FILE *fp )


{


    AREA_DATA *pArea;





    pArea		= alloc_perm( sizeof(*pArea) );


    pArea->name		= fread_string( fp );


    pArea->age		= 15;


    pArea->nplayer	= 0;





    pArea->area_flags   = AREA_LOADING;         /* OLC */
    pArea->security     = 3;                    /* OLC */
    pArea->builders     = str_dup( "None" );    /* OLC */
    pArea->lvnum        = 0;                    /* OLC */
    pArea->uvnum        = 0;                    /* OLC */
    pArea->vnum         = top_area;             /* OLC */
    pArea->filename     = str_dup( strArea );   /* OLC */

    if ( area_first == NULL )


	area_first = pArea;


    if ( area_last  != NULL )

 {
	area_last->next = pArea;


	REMOVE_BIT(area_last->area_flags, AREA_LOADING); /* OLC */
	}
    area_last	= pArea;


    pArea->next	= NULL;





    top_area++;


    return;


}










#if defined(KEY)
#undef KEY
#endif
                    
#define KEY( literal, field, value )                \
                if ( !str_cmp( word, literal ) )    \
                {                                   \
                    field  = value;                 \
                    fMatch = TRUE;                  \
                    break;                          \
                }
    
#define SKEY( string, field )                       \
                if ( !str_cmp( word, string ) )     \
                {                                   \
                    free_string( field );           \
                    field = fread_string( fp );     \
                    fMatch = TRUE;                  \
                    break;                          \
                }
  

/* OLC
 * Snarf an 'area' header line.   Check this format.  MUCH better.  Add fields
 * too.             
dv *
 * #AREAFILE
 * Name   { All } Locke    Newbie School~
 * Repop  A teacher pops in the room and says, 'Repop coming!'~
 * Recall 3001   
 * End
 */
void new_load_area( FILE *fp )
{
    AREA_DATA *pArea;
    char      *word;
    bool      fMatch;
    pArea               = alloc_perm( sizeof(*pArea) );
    pArea->age          = 15;
    pArea->nplayer      = 0;
    pArea->filename     = str_dup( strArea );
    pArea->vnum         = top_area;
    pArea->name         = str_dup( "New Area" );
    pArea->builders     = str_dup( "" );
    pArea->security     = 3;
    pArea->lvnum        = 0;
    pArea->uvnum        = 0;
    pArea->area_flags   = 0;
    pArea->recall       = ROOM_VNUM_TEMPLE;
 
    for ( ; ; )
    {
       word   = feof( fp ) ? "End" : fread_word( fp );
       fMatch = FALSE;
 
       switch ( UPPER(word[0]) )
       {
           case 'N':
            SKEY( "Name", pArea->name );
            break;   
           case 'S':
             KEY( "Security", pArea->security, fread_number( fp ) );
            break;
           case 'V':
            if ( !str_cmp( word, "VNUMs" ) )
            {
                pArea->lvnum = fread_number( fp );
                pArea->uvnum = fread_number( fp );
            }
            break;
           case 'E':
             if ( !str_cmp( word, "End" ) )
             {
                 fMatch = TRUE;
                 if ( area_first == NULL ) 
                    area_first = pArea;
                 if ( area_last  != NULL )
                    area_last->next = pArea;
                 area_last   = pArea;
                 pArea->next = NULL;
                 top_area++;
                 return;
            }
            break;  
           case 'B':
            SKEY( "Builders", pArea->builders );
            break;  
           case 'R':
             KEY( "Recall", pArea->recall, fread_number( fp ) );
            break;  
        }
    }
}
                
             
            
/*
 * Sets vnum range for area using OLC protection features.
 */
void assign_area_vnum( int vnum )
{
    if ( area_last->lvnum == 0 || area_last->uvnum == 0 )
        area_last->lvnum = area_last->uvnum = vnum;
    if ( vnum != URANGE( area_last->lvnum, vnum, area_last->uvnum ) )
        if ( vnum < area_last->lvnum )
            area_last->lvnum = vnum;
        else
            area_last->uvnum = vnum;
    return;  
}




/*
 * Returns an uppercase string.
 */
char *strupper( const char *str )
{
    static char strup[MAX_STRING_LENGTH];
    int i;

    for ( i = 0; str[i] != '\0'; i++ )
	strup[i] = UPPER(str[i]);
    strup[i] = '\0';
    return strup;
}


/*
 * Adds a help page to the list if it is not a duplicate of an existing page.
 * Page is insert-sorted by keyword.			-Thoric
 * (The reason for sorting is to keep do_hlist looking nice)
 */
void add_help( HELP_DATA *pHelp )
{
    HELP_DATA *tHelp;
   /* char buf[MAX_STRING_LENGTH];*/
    int match;

    for ( tHelp = first_help; tHelp; tHelp = tHelp->next )
/*
	if ( pHelp->level == tHelp->level
	&&  !strcmp(pHelp->keyword, tHelp->keyword) )
	{
	    sprintf(buf, "Duplicate %s. Deleting Help.\n\r",pHelp->keyword);
	    bug(buf,0);
	    STRFREE( pHelp->text );
	    STRFREE( pHelp->keyword );
	    DISPOSE( pHelp );
	    return;
	}
	else
*/
	if ( (match=strcmp(pHelp->keyword[0]=='\'' ? pHelp->keyword+1 : pHelp->keyword,
			   tHelp->keyword[0]=='\'' ? tHelp->keyword+1 : tHelp->keyword)) < 0
	||   (match == 0 && pHelp->level > tHelp->level) )
	{
	    if ( !tHelp->prev )
		first_help	  = pHelp;
	    else
		tHelp->prev->next = pHelp;
	    pHelp->prev		  = tHelp->prev;
	    pHelp->next		  = tHelp;
	    tHelp->prev		  = pHelp;
	    break;
	}

    if ( !tHelp )
	LINK( pHelp, first_help, last_help, next, prev );

    top_help++;
}


/*
 * Load a help section.
 */
void load_helps( FILE *fp )
{
    HELP_DATA *pHelp;

    for ( ; ; )
    {
	CREATE( pHelp, HELP_DATA, 1 );
	pHelp->level	= fread_number( fp );
	pHelp->keyword	= fread_string( fp );
	if ( pHelp->keyword[0] == '$' )
	    break;
	pHelp->text	= fread_string( fp );
	if ( pHelp->keyword[0] == '\0' )
	{
	    STRFREE( pHelp->text );
	    STRFREE( pHelp->keyword );
	    DISPOSE( pHelp );
	    continue;
	}

	if ( !str_cmp( pHelp->keyword, "greeting" ) )
	    help_greeting = pHelp->text;
	add_help( pHelp );
    }
    return;
}


/*


 * Snarf a mob section.


 */


void load_mobiles( FILE *fp )


{


    MOB_INDEX_DATA *pMobIndex;






    if ( !area_last )   /* OLC */
    {
        bug( "Load_mobiles: no #AREA seen yet.", 0 );
        exit( 1 );
    }
 
    for ( ; ; )


    {


	int vnum;


	char letter;


	int iHash;





	letter				= fread_letter( fp );


	if ( letter != '#' )


	{


	    bug( "Load_mobiles: # not found.", 0 );


	    exit( 1 );


	}





	vnum				= fread_number( fp );


	if ( vnum == 0 )


	    break;





	fBootDb = FALSE;


	if ( get_mob_index( vnum ) != NULL )


	{


	    bug( "Load_mobiles: vnum %d duplicated.", vnum );


	    exit( 1 );


	}


	fBootDb = TRUE;





	pMobIndex			= alloc_perm( sizeof(*pMobIndex) );


	pMobIndex->vnum			= vnum;


        pMobIndex->area                 = area_last;            /* OLC */
	pMobIndex->player_name		= fread_string( fp );


	pMobIndex->short_descr		= fread_string( fp );


	pMobIndex->long_descr		= fread_string( fp );


	pMobIndex->description		= fread_string( fp );





	pMobIndex->long_descr[0]	= UPPER(pMobIndex->long_descr[0]);


	pMobIndex->description[0]	= UPPER(pMobIndex->description[0]);





	pMobIndex->act			= fread_number( fp ) | ACT_IS_NPC;


	pMobIndex->affected_by		= fread_number( fp );


	pMobIndex->itemaffect		= 0;


	pMobIndex->pShop		= NULL;


	pMobIndex->alignment		= fread_number( fp );


	letter				= fread_letter( fp );


	pMobIndex->level		= number_fuzzy( fread_number( fp ) );





	/*


	 * The unused stuff is for imps who want to use the old-style


	 * stats-in-files method.


	 */


	pMobIndex->hitroll		= fread_number( fp );	/* Unused */


	pMobIndex->ac			= fread_number( fp );	/* Unused */


	pMobIndex->hitnodice		= fread_number( fp );	/* Unused */


	/* 'd'		*/		  fread_letter( fp );	/* Unused */


	pMobIndex->hitsizedice		= fread_number( fp );	/* Unused */


	/* '+'		*/		  fread_letter( fp );	/* Unused */


	pMobIndex->hitplus		= fread_number( fp );	/* Unused */


	pMobIndex->damnodice		= fread_number( fp );	/* Unused */


	/* 'd'		*/		  fread_letter( fp );	/* Unused */


	pMobIndex->damsizedice		= fread_number( fp );	/* Unused */


	/* '+'		*/		  fread_letter( fp );	/* Unused */


	pMobIndex->damplus		= fread_number( fp );	/* Unused */


	pMobIndex->gold			= fread_number( fp );	/* Unused */


	/* xp can't be used! */		  fread_number( fp );	/* Unused */


	/* position	*/		  fread_number( fp );	/* Unused */


	/* start pos	*/		  fread_number( fp );	/* Unused */





	/*


	 * Back to meaningful values.


	 */


	pMobIndex->sex			= fread_number( fp );





	if ( letter != 'S' )


	{


	    bug( "Load_mobiles: vnum %d non-S.", vnum );


	    exit( 1 );


	}





	iHash			= vnum % MAX_KEY_HASH;


	pMobIndex->next		= mob_index_hash[iHash];


	mob_index_hash[iHash]	= pMobIndex;


	top_mob_index++;


        top_vnum_mob = top_vnum_mob < vnum ? vnum : top_vnum_mob;  /* OLC */
        assign_area_vnum( vnum );                                  /* OLC */

	kill_table[URANGE(0, pMobIndex->level, MAX_LEVEL-1)].number++;


    }





    return;


}











/*


 * Snarf an obj section.


 */


void load_objects( FILE *fp )


{


    OBJ_INDEX_DATA *pObjIndex;






    if ( !area_last )   /* OLC */
    {
        bug( "Load_objects: no #AREA seen yet.", 0 );
        exit( 1 );
    }

    for ( ; ; )


    {


	int vnum;


	char letter;


	int iHash;





	letter				= fread_letter( fp );


	if ( letter != '#' )


	{


	    bug( "Load_objects: # not found.", 0 );


	    exit( 1 );


	}





	vnum				= fread_number( fp );


	if ( vnum == 0 )


	    break;



/*
	     if ( vnum == 29503 && CHAOS )
	  return;
        else if ( vnum == 29515 && VISOR )
          return;
        else if ( vnum == 29512 && DARKNESS )
          return;
        else if ( vnum == 29505 && SPEED )
          return;
        else if ( vnum == 29518 && BRACELET )
          return;
        else if ( vnum == 29504 && TORC )
          return;
        else if ( vnum == 29514 && ARMOUR )
          return;
        else if ( vnum == 29516 && CLAWS )
          return;
*/

	fBootDb = FALSE;
	if ( get_obj_index( vnum ) != NULL )
	{
	    bug( "Load_objects: vnum %d duplicated.", vnum );
	    exit( 1 );
	}

	fBootDb = TRUE;

	pObjIndex			= alloc_perm( sizeof(*pObjIndex) );
	pObjIndex->vnum			= vnum;
        pObjIndex->area                 = area_last;            /* OLC */
	pObjIndex->name			= fread_string( fp );


	pObjIndex->short_descr		= fread_string( fp );


	pObjIndex->description		= fread_string( fp );


	/* Action description */	  fread_string( fp );





	pObjIndex->short_descr[0]	= LOWER(pObjIndex->short_descr[0]);


	pObjIndex->description[0]	= UPPER(pObjIndex->description[0]);





	pObjIndex->item_type		= fread_number( fp );


	pObjIndex->extra_flags		= fread_number( fp );


	pObjIndex->wear_flags		= fread_number( fp );


	switch (pObjIndex->item_type) {
	case ITEM_WAND:
	case ITEM_STAFF:
		pObjIndex->value[0] = fread_number(fp);
		pObjIndex->value[1] = fread_number(fp);
		pObjIndex->value[2] = fread_number(fp);
		pObjIndex->value[3] = skill_lookup(fread_word(fp));
		break;
	case ITEM_POTION:
	case ITEM_PILL:
	case ITEM_SCROLL:
		pObjIndex->value[0] = fread_number(fp);
		pObjIndex->value[1] = skill_lookup(fread_word(fp));
		pObjIndex->value[2] = skill_lookup(fread_word(fp));
		pObjIndex->value[3] = skill_lookup(fread_word(fp));
		break;
	default:
	pObjIndex->value[0]		= fread_number( fp );


	pObjIndex->value[1]		= fread_number( fp );


	pObjIndex->value[2]		= fread_number( fp );


	pObjIndex->value[3]		= fread_number( fp );


	break;
	}
	pObjIndex->weight		= fread_number( fp );


	pObjIndex->cost			= fread_number( fp );	/* Unused */


	pObjIndex->affected		= NULL;


	pObjIndex->extra_descr		= NULL;


	pObjIndex->chpoweron		= NULL;


	pObjIndex->chpoweroff		= NULL;


	pObjIndex->chpoweruse		= NULL;


	pObjIndex->victpoweron		= NULL;


	pObjIndex->victpoweroff		= NULL;


	pObjIndex->victpoweruse		= NULL;


	pObjIndex->spectype		= 0;


	pObjIndex->specpower		= 0;


	/* Cost per day */		  fread_number( fp );


/*


	if ( pObjIndex->item_type == ITEM_POTION )


	    SET_BIT(pObjIndex->extra_flags, ITEM_NODROP);


*/


	for ( ; ; )


	{


	    char letter;





	    letter = fread_letter( fp );





	    if ( letter == 'A' )


	    {


		AFFECT_DATA *paf;





		paf			= alloc_perm( sizeof(*paf) );


		paf->type		= -1;


		paf->duration		= -1;


		paf->location		= fread_number( fp );


		paf->modifier		= fread_number( fp );


		paf->bitvector		= 0;


		paf->next		= pObjIndex->affected;


		pObjIndex->affected	= paf;


		top_affect++;


	    }





	    else if ( letter == 'E' )


	    {


		EXTRA_DESCR_DATA *ed;





		ed			= alloc_perm( sizeof(*ed) );


		ed->keyword		= fread_string( fp );


		ed->description		= fread_string( fp );


		ed->next		= pObjIndex->extra_descr;


		pObjIndex->extra_descr	= ed;


		top_ed++;


	    }





	    else if ( letter == 'Q' )


	    {


		pObjIndex->chpoweron	= fread_string( fp );


		pObjIndex->chpoweroff	= fread_string( fp );


		pObjIndex->chpoweruse	= fread_string( fp );


		pObjIndex->victpoweron	= fread_string( fp );


		pObjIndex->victpoweroff	= fread_string( fp );


		pObjIndex->victpoweruse	= fread_string( fp );


		pObjIndex->spectype	= fread_number( fp );


		pObjIndex->specpower	= fread_number( fp );


	    }





	    else


	    {


		ungetc( letter, fp );


		break;


	    }


	}





	/*


	 * Translate spell "slot numbers" to internal "skill numbers."


	 */


	switch ( pObjIndex->item_type )


	{


	case ITEM_PILL:


	case ITEM_POTION:


	case ITEM_SCROLL:


	    pObjIndex->value[1] = slot_lookup( pObjIndex->value[1] );


	    pObjIndex->value[2] = slot_lookup( pObjIndex->value[2] );


	    pObjIndex->value[3] = slot_lookup( pObjIndex->value[3] );


	    break;





	case ITEM_STAFF:


	case ITEM_WAND:


	    pObjIndex->value[3] = slot_lookup( pObjIndex->value[3] );


	    break;


	}

	if ( vnum == 29503 )
          CHAOS = TRUE;
        if ( vnum == 29515 )
          VISOR = TRUE;
        if ( vnum == 29512 )
          DARKNESS = TRUE;
        if ( vnum == 29505 )
          SPEED = TRUE;
        if ( vnum == 29518 )
          BRACELET = TRUE;
        if ( vnum == 29504 )
          TORC = TRUE;
        if ( vnum == 29514 )
          ARMOUR = TRUE;
        if ( vnum == 29516 )
	  CLAWS = TRUE;

	iHash			= vnum % MAX_KEY_HASH;


	pObjIndex->next		= obj_index_hash[iHash];


	obj_index_hash[iHash]	= pObjIndex;


	top_obj_index++;


        top_vnum_obj = top_vnum_obj < vnum ? vnum : top_vnum_obj;  /* OLC */
        assign_area_vnum( vnum );                                  /* OLC */
 
    }





    return;


}



/*
 * Adds a reset to a room.  OLC
 * Similar to add_reset in olc.c
 */
void new_reset( ROOM_INDEX_DATA *pR, RESET_DATA *pReset )
{
    RESET_DATA *pr;
     
    if ( !pR )
       return;

    pr = pR->reset_last;
        
    if ( !pr )
    {
        pR->reset_first = pReset;
        pR->reset_last  = pReset;
    }
    else
    {
        pR->reset_last->next = pReset;
        pR->reset_last       = pReset;
        pR->reset_last->next = NULL;
    }   

    top_reset++;
    return;
}


/*   
 * Snarf a reset section.       Changed for OLC.
 */      
void load_resets( FILE *fp )
{
    RESET_DATA  *pReset;
    int         iLastRoom = 0;
    int         iLastObj  = 0;
    
    if ( !area_last )
    {
        bug( "Load_resets: no #AREA seen yet.", 0 );
        exit( 1 );
    }    
  
    for ( ; ; )
    {
        EXIT_DATA       *pexit;
        ROOM_INDEX_DATA *pRoomIndex;
        char             letter;
    
        if ( ( letter = fread_letter( fp ) ) == 'S' )
            break;
     
        if ( letter == '*' )
        {
            fread_to_eol( fp );
            continue;
        }

        pReset          = alloc_perm( sizeof( *pReset ) );
        pReset->command = letter;
        /* if_flag */     fread_number( fp );
        pReset->arg1    = fread_number( fp );
        pReset->arg2    = fread_number( fp );
        pReset->arg3    = ( letter == 'G' || letter == 'R' )
                            ? 0 : fread_number( fp );
                          fread_to_eol( fp );
        
        /*
         * Validate parameters.
         * We're calling the index functions for the side effect.
         */
        switch ( letter )
        {
        default:
            bug( "Load_resets: bad command '%c'.", letter );
            exit( 1 );
            break;
     
        case 'M':
            get_mob_index  ( pReset->arg1 );
            if ( ( pRoomIndex = get_room_index ( pReset->arg3 ) ) )
            {
                new_reset( pRoomIndex, pReset );
                iLastRoom = pReset->arg3;
            }
            break;
        
        case 'O':
            get_obj_index  ( pReset->arg1 ); 
            if ( ( pRoomIndex = get_room_index ( pReset->arg3 ) ) )
            {
                new_reset( pRoomIndex, pReset );
                iLastObj = pReset->arg3;
            }
            break;
         
        case 'P':
            get_obj_index  ( pReset->arg1 );
            if ( ( pRoomIndex = get_room_index ( iLastObj ) ) )
            {   
                new_reset( pRoomIndex, pReset );
            }
            break;
     
        case 'G':
        case 'E':
            get_obj_index  ( pReset->arg1 );
            if ( ( pRoomIndex = get_room_index ( iLastRoom ) ) )
            {
                new_reset( pRoomIndex, pReset );
                iLastObj = iLastRoom;
            }
            break;
        
        case 'D':
            pRoomIndex = get_room_index( pReset->arg1 );
             
            if (   pReset->arg2 < 0
                || pReset->arg2 > 5
                || !pRoomIndex
                || !( pexit = pRoomIndex->exit[pReset->arg2] )
                || !IS_SET( pexit->rs_flags, EX_ISDOOR ) )
            {
                bug( "Load_resets: 'D': exit %d not door.", pReset->arg2 );
                exit( 1 );
            }   
                
            switch ( pReset->arg3 )     /* OLC 1.1b */
            {
                default:
                    bug( "Load_resets: 'D': bad 'locks': %d." , pReset->arg3);
                case 0:
                    break;
                case 1: SET_BIT( pexit->rs_flags, EX_CLOSED );  
                    break;
                case 2: SET_BIT( pexit->rs_flags, EX_CLOSED | EX_LOCKED );
                    break;
            }
            break;
        
        case 'R':
            if ( pReset->arg2 < 0 || pReset->arg2 > 6 ) /* Last Door. */
            {
                bug( "Load_resets: 'R': bad exit %d.", pReset->arg2 );
                exit( 1 );
            }
                
            if ( ( pRoomIndex = get_room_index( pReset->arg1 ) ) )
                new_reset( pRoomIndex, pReset );
                
            break;
        }
    }           
            
            
    return;  
}






/*


 * Snarf a room section.


 */


void load_rooms( FILE *fp )


{


    ROOM_INDEX_DATA *pRoomIndex;





    if ( area_last == NULL )


    {


	bug( "Load_resets: no #AREA seen yet.", 0 );


	exit( 1 );


    }





    for ( ; ; )


    {


	int vnum;


	char letter;


	int door;


	int iHash;





	letter				= fread_letter( fp );


	if ( letter != '#' )


	{


	    bug( "Load_rooms: # not found.", 0 );


	    exit( 1 );


	}





	vnum				= fread_number( fp );


	if ( vnum == 0 )


	    break;





	fBootDb = FALSE;


	if ( get_room_index( vnum ) != NULL )


	{


	    bug( "Load_rooms: vnum %d duplicated.", vnum );


	    exit( 1 );


	}


	fBootDb = TRUE;





	pRoomIndex			= alloc_perm( sizeof(*pRoomIndex) );


	pRoomIndex->people		= NULL;


	pRoomIndex->contents		= NULL;


	pRoomIndex->first_person	= NULL;
	pRoomIndex->last_person		= NULL;
	pRoomIndex->first_content	= NULL;
	pRoomIndex->last_content	= NULL;
	pRoomIndex->extra_descr		= NULL;
	pRoomIndex->first_extradesc	= NULL;
	pRoomIndex->last_extradesc	= NULL;
	pRoomIndex->area		= area_last;


	pRoomIndex->vnum		= vnum;


	pRoomIndex->name		= fread_string( fp );


	pRoomIndex->description		= fread_string( fp );


	/* Area number */		  fread_number( fp );


	pRoomIndex->room_flags		= fread_number( fp );


	pRoomIndex->sector_type		= fread_number( fp );


	pRoomIndex->light		= 0;


	pRoomIndex->blood		= 0;


	pRoomIndex->roomtext		= NULL;


	pRoomIndex->first_exit		= NULL;
	pRoomIndex->last_exit		= NULL;
	for ( door = 0; door <= 4; door++ )


	{


	    pRoomIndex->track[door] 	= str_dup( "" );


	    pRoomIndex->track_dir[door] = 0;
	}
	for ( door = 0; door <= 5; door++ )
	    pRoomIndex->exit[door] = NULL;


	for ( ; ; )


	{


	    letter = fread_letter( fp );





	    if ( letter == 'S' )


		break;





	    if ( letter == 'D' )


	    {


		EXIT_DATA *pexit;


		int locks;





		door = fread_number( fp );


		if ( door < 0 || door > 5 )


		{


		    bug( "Fread_rooms: vnum %d has bad door number.", vnum );


		    exit( 1 );


		}





		pexit			= alloc_perm( sizeof(*pexit) );


		pexit->description	= fread_string( fp );


		pexit->keyword		= fread_string( fp );


		pexit->exit_info	= 0;


                pexit->rs_flags         = 0;                    /* OLC */ 
		locks			= fread_number( fp );


		pexit->key		= fread_number( fp );


		pexit->vnum		= fread_number( fp );





/*		switch ( locks )


		{


		case 1: pexit->exit_info = EX_ISDOOR;                break;


		case 2: pexit->exit_info = EX_ISDOOR | EX_PICKPROOF; break;


		}


*/

                switch ( locks )        /* OLC exit_info to rs_flags. */
                {
                case 1: pexit->rs_flags  = EX_ISDOOR;                    break;
                case 2: pexit->rs_flags  = EX_ISDOOR | EX_PICKPROOF;     break;
                }




		pRoomIndex->exit[door]	= pexit;


		top_exit++;


	    }


	    else if ( letter == 'E' )


	    {


		EXTRA_DESCR_DATA *ed;





		ed			= alloc_perm( sizeof(*ed) );


		ed->keyword		= fread_string( fp );


		ed->description		= fread_string( fp );


		ed->next		= pRoomIndex->extra_descr;


		pRoomIndex->extra_descr	= ed;


		top_ed++;


	    }


	    else if ( letter == 'T' )


	    {


		ROOMTEXT_DATA *rt;





		rt			= alloc_perm( sizeof(*rt) );


		rt->input		= fread_string( fp );


		rt->output		= fread_string( fp );


		rt->choutput		= fread_string( fp );


		rt->name		= fread_string( fp );


		rt->type		= fread_number( fp );


		rt->power		= fread_number( fp );


		rt->mob			= fread_number( fp );


		rt->next		= pRoomIndex->roomtext;


		pRoomIndex->roomtext	= rt;


		top_rt++;


	    }


	    else


	    {


		bug( "Load_rooms: vnum %d has flag not 'DES'.", vnum );


		exit( 1 );


	    }


	}





	iHash			= vnum % MAX_KEY_HASH;


	pRoomIndex->next	= room_index_hash[iHash];


	room_index_hash[iHash]	= pRoomIndex;


	pRoomIndex->next_room	= room_list;
	room_list		= pRoomIndex;
	top_room++;


       top_vnum_room = top_vnum_room < vnum ? vnum : top_vnum_room; /* OLC */
        assign_area_vnum( vnum );                                    /* OLC */

    }





    return;


}



/* OLC 1.1b */
void new_load_rooms( FILE *fp )
{   
    ROOM_INDEX_DATA *pRoomIndex;
    
    if ( !area_last )
    {
        bug( "Load_rooms: no #AREA seen yet.", 0 );
        exit( 1 ); 
    }
        
    for ( ; ; )
    {
        char letter;
        int  vnum;
        int  door;
        int  iHash;
    
        letter                          = fread_letter( fp );
        if ( letter != '#' )
        {
            bug( "Load_rooms: # not found.", 0 );  
            exit( 1 );
        }       

        vnum                            = fread_number( fp );
        if ( vnum == 0 )
            break;
    
        fBootDb = FALSE;
        if ( get_room_index( vnum ) )
        {
            bug( "Load_rooms: vnum %d duplicated.", vnum );
            exit( 1 );
        }
        fBootDb = TRUE;
        
        pRoomIndex                      = alloc_perm( sizeof( *pRoomIndex ) );
        pRoomIndex->people              = NULL;
        pRoomIndex->contents            = NULL;
        pRoomIndex->extra_descr         = NULL;
        pRoomIndex->area                = area_last;
        pRoomIndex->vnum                = vnum;
        pRoomIndex->name                = fread_string( fp );
        pRoomIndex->description         = fread_string( fp );
        /* Area number */                 fread_number( fp );   /* Unused */
        pRoomIndex->room_flags          = fread_number( fp );
        pRoomIndex->sector_type         = fread_number( fp );
        pRoomIndex->light               = 0;
	pRoomIndex->blood		= 0;
	pRoomIndex->roomtext		= NULL;
	for ( door = 0; door <= 4; door++)
	{
		pRoomIndex->track[door]= str_dup("");
		pRoomIndex->track_dir[door] = 0;
	}
        for ( door = 0; door <= 5; door++ )
            pRoomIndex->exit[door] = NULL;
        
        for ( ; ; )
        {
            letter = fread_letter( fp );
        
            if ( letter == 'S' || letter == 's' )
            {
                if ( letter == 's' )
                    bug( "Load_rooms: vnum %d has lowercase 's'", vnum );
                break;
            }
        
            if ( letter == 'D' )
            {
                EXIT_DATA *pexit;
                int        locks;
        
                door = fread_number( fp );
                if ( door < 0 || door > 5 )
                {
                    bug( "Fread_rooms: vnum %d has bad door number.", vnum );
                    exit( 1 );
                }
        
                pexit                   = alloc_perm( sizeof( *pexit ) );
                pexit->description      = fread_string( fp );
                pexit->keyword          = fread_string( fp );
                locks                   = fread_number( fp );
                pexit->exit_info        = locks;
                pexit->rs_flags         = locks;
                pexit->key              = fread_number( fp );
                pexit->vnum             = fread_number( fp );
             
                
                pRoomIndex->exit[door]          = pexit;
                top_exit++;
            }
            else if ( letter == 'E' )
            {
                EXTRA_DESCR_DATA *ed;
                
                ed                      = alloc_perm( sizeof( *ed ) );
                ed->keyword             = fread_string( fp );
                ed->description         = fread_string( fp );
                ed->next                = pRoomIndex->extra_descr;
                pRoomIndex->extra_descr = ed;
                top_ed++;
            }
            else if ( letter == 'T' )
            {
                ROOMTEXT_DATA *rt;

                rt                      = alloc_perm( sizeof(*rt) );
                rt->input               = fread_string( fp );
                rt->output              = fread_string( fp );
                rt->choutput            = fread_string( fp );
                rt->name                = fread_string( fp );
                rt->type                = fread_number( fp );
                rt->power               = fread_number( fp );
                rt->mob                 = fread_number( fp );
                rt->next                = pRoomIndex->roomtext;
                pRoomIndex->roomtext    = rt;
                top_rt++;
            }

            else 
            {
                bug( "Load_rooms: vnum %d has flag not 'DES'.", vnum );  
                exit( 1 );
            }
        }
                
        iHash                   = vnum % MAX_KEY_HASH;
        pRoomIndex->next        = room_index_hash[iHash];
        room_index_hash[iHash]  = pRoomIndex;
        top_room++;
        top_vnum_room = top_vnum_room < vnum ? vnum : top_vnum_room;
        assign_area_vnum( vnum );
    }
             
    return;
}

/*


 * Snarf a shop section.


 */


void load_shops( FILE *fp )


{


    SHOP_DATA *pShop;





    for ( ; ; )


    {


	MOB_INDEX_DATA *pMobIndex;


	int iTrade;





	pShop			= alloc_perm( sizeof(*pShop) );


	pShop->keeper		= fread_number( fp );


	if ( pShop->keeper == 0 )


	    break;


	for ( iTrade = 0; iTrade < MAX_TRADE; iTrade++ )


	    pShop->buy_type[iTrade]	= fread_number( fp );


	pShop->profit_buy	= fread_number( fp );


	pShop->profit_sell	= fread_number( fp );


	pShop->open_hour	= fread_number( fp );


	pShop->close_hour	= fread_number( fp );


				  fread_to_eol( fp );


	pMobIndex		= get_mob_index( pShop->keeper );


	pMobIndex->pShop	= pShop;





	if ( shop_first == NULL )


	    shop_first = pShop;


	if ( shop_last  != NULL )


	    shop_last->next = pShop;





	shop_last	= pShop;


	pShop->next	= NULL;


	top_shop++;


    }





    return;


}











/*


 * Snarf spec proc declarations.


 */


void load_specials( FILE *fp )


{


    for ( ; ; )


    {


	MOB_INDEX_DATA *pMobIndex;


	char letter;





	switch ( letter = fread_letter( fp ) )


	{


	default:


	    bug( "Load_specials: letter '%c' not *MS.", letter );


	    exit( 1 );





	case 'S':


	    return;





	case '*':


	    break;





	case 'M':


	    pMobIndex		= get_mob_index	( fread_number ( fp ) );


	    pMobIndex->spec_fun	= spec_lookup	( fread_word   ( fp ) );


	    if ( pMobIndex->spec_fun == 0 )


	    {


		bug( "Load_specials: 'M': vnum %d.", pMobIndex->vnum );


		exit( 1 );


	    }


	    break;


	}





	fread_to_eol( fp );


    }


}








/*


 * Translate all room exits from virtual to real.


 * Has to be done after all rooms are read in.


 * Check for bad reverse exits.


 */


void fix_exits( void )


{


    extern const sh_int rev_dir [];


    char buf[MAX_STRING_LENGTH];


    ROOM_INDEX_DATA *pRoomIndex;


    ROOM_INDEX_DATA *to_room;


    EXIT_DATA *pexit;


    EXIT_DATA *pexit_rev;


    int iHash;


    int door;





    for ( iHash = 0; iHash < MAX_KEY_HASH; iHash++ )


    {


	for ( pRoomIndex  = room_index_hash[iHash];


	      pRoomIndex != NULL;


	      pRoomIndex  = pRoomIndex->next )


	{


	    bool fexit;





	    fexit = FALSE;


	    for ( door = 0; door <= 5; door++ )


	    {


		if ( ( pexit = pRoomIndex->exit[door] ) != NULL )


		{


		    fexit = TRUE;


		    if ( pexit->vnum <= 0 )


			pexit->to_room = NULL;


		    else


			pexit->to_room = get_room_index( pexit->vnum );


		}


	    }





	    if ( !fexit )


		SET_BIT( pRoomIndex->room_flags, ROOM_NO_MOB );


	}


    }





    for ( iHash = 0; iHash < MAX_KEY_HASH; iHash++ )


    {


	for ( pRoomIndex  = room_index_hash[iHash];


	      pRoomIndex != NULL;


	      pRoomIndex  = pRoomIndex->next )


	{


	    for ( door = 0; door <= 5; door++ )


	    {


		if ( ( pexit     = pRoomIndex->exit[door]       ) != NULL


		&&   ( to_room   = pexit->to_room               ) != NULL


		&&   ( pexit_rev = to_room->exit[rev_dir[door]] ) != NULL


		&&   pexit_rev->to_room != pRoomIndex )


		{


		    sprintf( buf, "Fix_exits: %d:%d -> %d:%d -> %d.",


			pRoomIndex->vnum, door,


			to_room->vnum,    rev_dir[door],


			(pexit_rev->to_room == NULL)


			    ? 0 : pexit_rev->to_room->vnum );


/*		    bug( buf, 0 ); */


		}


	    }


	}


    }





    return;


}











/*


 * Repopulate areas periodically.


 */


void area_update( void )


{


    AREA_DATA *pArea;





    for ( pArea = area_first; pArea != NULL; pArea = pArea->next )


    {


	CHAR_DATA *pch;





	if ( ++pArea->age < 3 )


	    continue;





	/*


	 * Check for PC's.


	 */


	if ( pArea->nplayer > 0 && pArea->age == 15 - 1 )


	{


	    for ( pch = char_list; pch != NULL; pch = pch->next )


	    {


		if ( !IS_NPC(pch)


		&&   IS_AWAKE(pch)


		&&   pch->in_room != NULL


		&&   pch->in_room->area == pArea )


		{


		    send_to_char( "You hear an agonised scream in the distance.\n\r",


			pch );


		}





	    }


	}





	/*


	 * Check age and reset.


	 * Note: Mud School resets every 3 minutes (not 15).


	 */


	if ( pArea->nplayer == 0 || pArea->age >= 15 )


	{


	    ROOM_INDEX_DATA *pRoomIndex;





	    reset_area( pArea );


	    pArea->age = number_range( 0, 3 );


	    pRoomIndex = get_room_index( ROOM_VNUM_SCHOOL );


	    if ( pRoomIndex != NULL && pArea == pRoomIndex->area )


		pArea->age = 15 - 3;


	}


    }





    return;


}



/* OLC
 * Reset one room.  Called by reset_area and olc.
 */
void reset_room( ROOM_INDEX_DATA *pRoom )
{
    RESET_DATA  *pReset;
    CHAR_DATA   *pMob;
    OBJ_DATA    *pObj;
    CHAR_DATA   *LastMob = NULL;
    OBJ_DATA    *LastObj = NULL;
    int iExit;
    int level = 0;
    bool last;
                
    if ( !pRoom )
        return;
   
    pMob        = NULL;
    last        = FALSE;
            
    for ( iExit = 0;  iExit < MAX_DIR;  iExit++ )
    {
        EXIT_DATA *pExit;
        if ( ( pExit = pRoom->exit[iExit] ) )
        {
            pExit->exit_info = pExit->rs_flags;
            if ( ( pExit->to_room != NULL )
              && ( ( pExit = pExit->to_room->exit[rev_dir[iExit]] ) ) )
            {
                /* nail the other side */
                pExit->exit_info = pExit->rs_flags;
            }
        }
    }
    
    for ( pReset = pRoom->reset_first; pReset != NULL; pReset = pReset->next )
    {
        MOB_INDEX_DATA  *pMobIndex;
        OBJ_INDEX_DATA  *pObjIndex;
        OBJ_INDEX_DATA  *pObjToIndex;
        ROOM_INDEX_DATA *pRoomIndex;
   
        switch ( pReset->command )
        {
        default:
                bug( "Reset_room: bad command %c.", pReset->command );
                break;
        
        case 'M':
            if ( !( pMobIndex = get_mob_index( pReset->arg1 ) ) )
            {
                bug( "Reset_room: 'M': bad vnum %d.", pReset->arg1 );
                continue;
            }
             
            /*
             * Some hard coding.
             */
            if ( ( pMobIndex->spec_fun == spec_lookup( "spec_cast_ghost" ) &&
                 ( weather_info.sunlight != SUN_DARK ) ) ) continue;
    
            if ( pMobIndex->count >= pReset->arg2 )
            {
                last = FALSE;
                break;
            }
        
            pMob = create_mobile( pMobIndex );
        
            /*
             * Some more hard coding.
             */
            if ( room_is_dark( pRoom ) )
                SET_BIT(pMob->affected_by, AFF_INFRARED);
        
            /*
             * Pet shop mobiles get ACT_PET set.
             */
            {
                ROOM_INDEX_DATA *pRoomIndexPrev;
             
                pRoomIndexPrev = get_room_index( pRoom->vnum - 1 );
                if ( pRoomIndexPrev
                    && IS_SET( pRoomIndexPrev->room_flags, ROOM_PET_SHOP ) )
                    SET_BIT( pMob->act, ACT_PET);
            }
    
            char_to_room( pMob, pRoom );
             
            LastMob = pMob;  
            level  = URANGE( 0, pMob->level - 2, LEVEL_HERO );
            last = TRUE;
            break;
            
        case 'O':
            if ( !( pObjIndex = get_obj_index( pReset->arg1 ) ) )
            {
                bug( "Reset_room: 'O': bad vnum %d.", pReset->arg1 );
                continue;
            }
        
            if ( !( pRoomIndex = get_room_index( pReset->arg3 ) ) )
            {
                bug( "Reset_room: 'O': bad vnum %d.", pReset->arg3 );
                continue;
            }
             
            if ( pRoom->area->nplayer > 0
              || count_obj_list( pObjIndex, pRoom->contents ) > 0 )
                break;
                    
            pObj = create_object( pObjIndex, number_fuzzy( level ) );
            pObj->cost = 0;
            obj_to_room( pObj, pRoom ); 
            break;
            
        case 'P':
            if ( !( pObjIndex = get_obj_index( pReset->arg1 ) ) )
            {
                bug( "Reset_room: 'P': bad vnum %d.", pReset->arg1 );
                continue;
            }
            if ( !( pObjToIndex = get_obj_index( pReset->arg3 ) ) )  
            {
                bug( "Reset_room: 'P': bad vnum %d.", pReset->arg3 );
                continue;
            }
             
            if ( pRoom->area->nplayer > 0
              || !( LastObj = get_obj_type( pObjToIndex ) )
              || count_obj_list( pObjIndex, LastObj->contains ) > 0 )
                break;
            
            pObj = create_object( pObjIndex, number_fuzzy( level ) );
            obj_to_obj( pObj, LastObj );
                    
            /*
             * Ensure that the container gets reset.    OLC 1.1b
             */
            if ( LastObj->item_type == ITEM_CONTAINER )
            {
                LastObj->value[1] = LastObj->pIndexData->value[1];
            }
            else
            {
                    /* THIS SPACE INTENTIONALLY LEFT BLANK */
            }
            break;
            
        case 'G':
        case 'E':
            if ( !( pObjIndex = get_obj_index( pReset->arg1 ) ) )
            {
                bug( "Reset_room: 'E' or 'G': bad vnum %d.", pReset->arg1 );
                continue;
            }
              
            if ( !last )
                break;
            
            if ( !LastMob )
            {       
                bug( "Reset_room: 'E' or 'G': null mob for vnum %d.",
                    pReset->arg1 );
                last = FALSE;
                break;
            }
                
            if ( LastMob->pIndexData->pShop )   /* Shop-keeper? */
            {   
                int olevel;
                    
                switch ( pObjIndex->item_type )
                { 
                default:                olevel = 0;                      break;
                case ITEM_PILL:         olevel = number_range(  0, 10 ); break;
                case ITEM_POTION:       olevel = number_range(  0, 10 ); break;
                case ITEM_SCROLL:       olevel = number_range(  5, 15 ); break;
                case ITEM_WAND:         olevel = number_range( 10, 20 ); break;
                case ITEM_STAFF:        olevel = number_range( 15, 25 ); break;
                case ITEM_ARMOR:        olevel = number_range(  5, 15 ); break;
                case ITEM_WEAPON:       if ( pReset->command == 'G' )
                                            olevel = number_range( 5, 15 );
                                        else
                                            olevel = number_fuzzy( level );
                  break;
                }
              
		if ( pObjIndex->vnum == 29603 && CHAOS ) return;
		if ( pObjIndex->vnum == 29603 ) CHAOS = TRUE;      

                pObj = create_object( pObjIndex, olevel );
                if ( pReset->command == 'G' )
                    SET_BIT( pObj->extra_flags, ITEM_INVENTORY );
            }
            else
            {   
                pObj = create_object( pObjIndex, number_fuzzy( level ) );
            }   
            obj_to_char( pObj, LastMob );
            if ( pReset->command == 'E' )
                equip_char( LastMob, pObj, pReset->arg3 );
            last = TRUE;
            break;
                
        case 'D':
            break;
                
        case 'R':
/* OLC 1.1b
            if ( !( pRoomIndex = get_room_index( pReset->arg1 ) ) )  
            {
                bug( "Reset_room: 'R': bad vnum %d.", pReset->arg1 );
                continue;
            }
                 
            {       
                EXIT_DATA *pExit;
                int d0;
                int d1;
             
                for ( d0 = 0; d0 < pReset->arg2 - 1; d0++ )
                {
                    d1                   = number_range( d0, pReset->arg2-1 );
                    pExit                = pRoomIndex->exit[d0];
                    pRoomIndex->exit[d0] = pRoomIndex->exit[d1];
                    pRoomIndex->exit[d1] = pExit;
                }
            }
*/
            break;
        }
    }
                
    return;
}


/* OLC
 * Reset one area.
 */
void reset_area( AREA_DATA *pArea )
{
    ROOM_INDEX_DATA *pRoom;
    int  vnum;
             
    for ( vnum = pArea->lvnum; vnum <= pArea->uvnum; vnum++ )
    {
        if ( ( pRoom = get_room_index(vnum) ) )
            reset_room(pRoom);
    }
                    
    return;
}









/*


 * Create an instance of a mobile.


 */


CHAR_DATA *create_mobile( MOB_INDEX_DATA *pMobIndex )


{


    CHAR_DATA *mob;


    int tempvalue;





    if ( pMobIndex == NULL )


    {


	bug( "Create_mobile: NULL pMobIndex.", 0 );


	exit( 1 );


    }





    if ( char_free == NULL )


    {


	mob		= alloc_perm( sizeof(*mob) );


    }


    else


    {


	mob		= char_free;


	char_free	= char_free->next;


    }





    clear_char( mob );


    mob->pIndexData	= pMobIndex;





    mob->hunting	= str_dup( "" );


    mob->lord		= str_dup( "" );


    mob->morph		= str_dup( "" );


    mob->createtime	= str_dup( "" );


    mob->lasttime	= str_dup( "" );


    mob->lasthost	= str_dup( "" );


    mob->powertype	= str_dup( "" );


    mob->poweraction	= str_dup( "" );


    mob->pload		= str_dup( "" );


    mob->prompt		= str_dup( "" );


    mob->cprompt	= str_dup( "" );





    mob->name           = str_dup( pMobIndex->player_name );    /* OLC */
    mob->short_descr    = str_dup( pMobIndex->short_descr );    /* OLC */
    mob->long_descr     = str_dup( pMobIndex->long_descr );     /* OLC */
    mob->description    = str_dup( pMobIndex->description );    /* OLC */



    mob->spec_fun	= pMobIndex->spec_fun;





    mob->home		= 3001;


    mob->form		= 32767;


    mob->level		= number_fuzzy( pMobIndex->level );


    mob->act		= pMobIndex->act;


    mob->affected_by	= pMobIndex->affected_by;


    mob->alignment	= pMobIndex->alignment;


    mob->sex		= pMobIndex->sex;





    mob->armor		= interpolate( mob->level, 100, -100 );





    tempvalue		= mob->level * 8 + number_range(


				mob->level * mob->level / 4,


				mob->level * mob->level );


    if (tempvalue > 100000) mob->max_hit = 100000;


    else mob->max_hit	= tempvalue;





    mob->hit		= mob->max_hit;





    mob->hitroll	= mob->level;


    mob->damroll	= mob->level;


	mob->practice   = mob->level * (number_range(10,20)/10);




     /* Random Forge Objects */

  if (number_percent() < 25)
  {
    if (number_percent() < 2)
    {
	OBJ_DATA *obj;
	obj = create_object( get_obj_index( number_range( 30049,30071 ) ), 0 );
	obj_to_char(obj,mob);
    }
  }
    /*


     * Insert in list.


     */


    mob->next		= char_list;


    char_list		= mob;


    pMobIndex->count++;


    return mob;


}











/*


 * Create an instance of an object.


 */


OBJ_DATA *create_object( OBJ_INDEX_DATA *pObjIndex, int level )


{


    static OBJ_DATA obj_zero;


    OBJ_DATA *obj;





    if ( pObjIndex == NULL )


    {


	bug( "Create_object: NULL pObjIndex.", 0 );


	exit( 1 );


    }





    if ( obj_free == NULL )


    {


	obj		= alloc_perm( sizeof(*obj) );


    }


    else


    {


	obj		= obj_free;


	obj_free	= obj_free->next;


    }





    *obj		= obj_zero;


    obj->pIndexData	= pObjIndex;


    obj->in_room	= NULL;


    obj->level		= level;


    obj->wear_loc	= -1;





    obj->name           = str_dup( pObjIndex->name );           /* OLC */
    obj->short_descr    = str_dup( pObjIndex->short_descr );    /* OLC */
    obj->description    = str_dup( pObjIndex->description );    /* OLC */
 


    if (pObjIndex->chpoweron != NULL)


    {


	obj->chpoweron    = pObjIndex->chpoweron;


	obj->chpoweroff   = pObjIndex->chpoweroff;


	obj->chpoweruse   = pObjIndex->chpoweruse;


	obj->victpoweron  = pObjIndex->victpoweron;


	obj->victpoweroff = pObjIndex->victpoweroff;


	obj->victpoweruse = pObjIndex->victpoweruse;


	obj->spectype     = pObjIndex->spectype;


	obj->specpower    = pObjIndex->specpower;


    }


    else


    {


	obj->chpoweron    = str_dup( "(null)" );


	obj->chpoweroff   = str_dup( "(null)" );


	obj->chpoweruse   = str_dup( "(null)" );


	obj->victpoweron  = str_dup( "(null)" );


	obj->victpoweroff = str_dup( "(null)" );


	obj->victpoweruse = str_dup( "(null)" );


	obj->spectype     = 0;


	obj->specpower    = 0;


    }


    obj->questmaker     = str_dup( "" );


    obj->questowner     = str_dup( "" );





    obj->chobj		= NULL;





    obj->quest		= 0;


    obj->points		= 0;





    obj->item_type	= pObjIndex->item_type;


    obj->extra_flags	= pObjIndex->extra_flags;


    obj->wear_flags	= pObjIndex->wear_flags;


    obj->value[0]	= pObjIndex->value[0];


    obj->value[1]	= pObjIndex->value[1];


    obj->value[2]	= pObjIndex->value[2];


    obj->value[3]	= pObjIndex->value[3];


    obj->weight		= pObjIndex->weight;


    obj->cost		= number_fuzzy( 10 )


			* number_fuzzy( level ) * number_fuzzy( level );





	if (obj->pIndexData->vnum >= 29600 && obj->pIndexData->vnum <= 29625)


	{


	obj->condition = 100;


	obj->toughness = 100;


	SET_BIT(obj->spectype,SITEM_DROW);


	SET_BIT(obj->quest,QUEST_RELIC);


	} else {





    if (obj->pIndexData->vnum >=  29500 && obj->pIndexData->vnum <= 29599)


    {


	SET_BIT(obj->quest, QUEST_ARTIFACT);


    	obj->condition	= 100;


    	obj->toughness	= 100;


    	obj->resistance	= 1;


	obj->level	= 60;


	obj->cost	= 1000000;


    }


    else if (obj->pIndexData->vnum >= 29666 


             && obj->pIndexData->vnum <= 29679


	     && !IS_SET(obj->spectype, SITEM_PDEMONIC))


	{


    SET_BIT(obj->spectype, SITEM_PDEMONIC);


    SET_BIT(obj->quest, QUEST_RELIC);


        obj->condition  = 100;


        obj->toughness  = 100;


        obj->resistance = 1; 


	}


    else if (obj->pIndexData->vnum >= 27650 && obj->pIndexData->vnum <= 29711)


    {


	SET_BIT(obj->quest, QUEST_RELIC);


    	obj->condition	= 100;


    	obj->toughness	= 100;


    	obj->resistance	= 1;


    }


    else


    {


    	obj->condition	= 100;


    	obj->toughness	= 5;


    	obj->resistance	= 25;


    }


}


    /*


     * Mess with object properties.


     */


    switch ( obj->item_type )


    {


    default:


	bug( "Read_object: vnum %d bad type.", pObjIndex->vnum );


	break;





    case ITEM_LIGHT:


    case ITEM_TREASURE:


    case ITEM_FURNITURE:


    case ITEM_TRASH:


    case ITEM_CONTAINER:


    case ITEM_DRINK_CON:


    case ITEM_KEY:


    case ITEM_FOOD:


    case ITEM_BOAT:


    case ITEM_CORPSE_NPC:


    case ITEM_CORPSE_PC:


    case ITEM_FOUNTAIN:


    case ITEM_PORTAL:


    case ITEM_EGG:


    case ITEM_VOODOO:


    case ITEM_STAKE:


    case ITEM_MISSILE:


    case ITEM_AMMO:


    case ITEM_QUEST:


    case ITEM_QUESTCARD:


    case ITEM_QUESTMACHINE:


    case ITEM_SYMBOL:


    case ITEM_BOOK:


    case ITEM_PAGE:


    case ITEM_TOOL:


    case ITEM_COPPER:


    case ITEM_IRON:


    case ITEM_STEEL:


    case ITEM_ADAMANTITE:


    case ITEM_GEMSTONE:


    case ITEM_HILT:


	break;





    case ITEM_SCROLL:


	obj->value[0]	= number_fuzzy( obj->value[0] );


	break;





    case ITEM_WAND:


    case ITEM_STAFF:


	obj->value[0]	= number_fuzzy( obj->value[0] );


	obj->value[1]	= number_fuzzy( obj->value[1] );


	obj->value[2]	= obj->value[1];


	break;





    case ITEM_WEAPON:


	if (!IS_SET(obj->quest, QUEST_ARTIFACT)


	    && !IS_SET(obj->quest, QUEST_RELIC))


	{


	    obj->value[1]	= number_range( 1, 10 );


	    obj->value[2]	= number_range((obj->value[1]+1),(obj->value[1]*2));


	}


	break;





    case ITEM_ARMOR:


	if (!IS_SET(obj->quest, QUEST_ARTIFACT)


	    && !IS_SET(obj->quest, QUEST_RELIC))


	    obj->value[0]	= number_range( 5, 15 );


	break;





    case ITEM_POTION:


    case ITEM_PILL:


	obj->value[0]	= number_fuzzy( number_fuzzy( obj->value[0] ) );


	break;





    case ITEM_MONEY:


	obj->value[0]	= obj->cost;


	break;


    }





    obj->next		= object_list;


    object_list		= obj;


    pObjIndex->count++;





    return obj;


}











/*


 * Clear a new character.


 */


void clear_char( CHAR_DATA *ch )


{


    static CHAR_DATA ch_zero;





    *ch				= ch_zero;


    ch->name			= &str_empty[0];


    ch->short_descr		= &str_empty[0];


    ch->long_descr		= &str_empty[0];


    ch->description		= &str_empty[0];


    ch->lord			= &str_empty[0];


    ch->morph			= &str_empty[0];


    ch->createtime		= &str_empty[0];


    ch->lasthost		= &str_empty[0];


    ch->lasttime		= &str_empty[0];


    ch->powertype		= &str_empty[0];


    ch->poweraction		= &str_empty[0];


    ch->pload			= &str_empty[0];


    ch->prompt			= &str_empty[0];


    ch->cprompt			= &str_empty[0];


    ch->hunting			= &str_empty[0];





    ch->logon			= current_time;


    ch->armor			= 100;


    ch->position		= POS_STANDING;


    ch->practice		= 0;


    ch->hit			= 1000;


    ch->max_hit			= 1000;


    ch->mana			= 1500;


    ch->max_mana		= 1500;


    ch->move			= 1500;


    ch->max_move		= 1500;


    ch->master			= NULL;


    ch->leader			= NULL;


    ch->fighting		= NULL;


    ch->mount			= NULL;


    ch->wizard			= NULL;


    ch->paradox[0]              = 0;        


    ch->paradox[1]              = 0;        


    ch->paradox[2]              = 0;        


    ch->damcap[0]		= 1000;


    ch->damcap[1]		= 0;


    return;


}











/*


 * Free a character.


 */


void free_char( CHAR_DATA *ch )


{


    OBJ_DATA *obj;


    OBJ_DATA *obj_next;


    AFFECT_DATA *paf;


    AFFECT_DATA *paf_next;





    for ( obj = ch->carrying; obj != NULL; obj = obj_next )


    {


	obj_next = obj->next_content;


	extract_obj( obj );


    }





    for ( paf = ch->affected; paf != NULL; paf = paf_next )


    {


	paf_next = paf->next;


	affect_remove( ch, paf );


    }





    free_string( ch->name		);


    free_string( ch->short_descr	);


    free_string( ch->long_descr		);


    free_string( ch->description	);


    free_string( ch->lord 		);


    free_string( ch->morph 		);


    free_string( ch->createtime 	);


    free_string( ch->lasttime 		);


    free_string( ch->lasthost 		);


    free_string( ch->powertype 		);


    free_string( ch->poweraction 	);


    free_string( ch->pload 		);


    free_string( ch->prompt 		);


    free_string( ch->cprompt 		);


    free_string( ch->hunting		);





    if ( ch->pcdata != NULL )


    {


	free_string( ch->pcdata->pwd		);


	free_string( ch->pcdata->bamfin		);


	free_string( ch->pcdata->bamfout	);


	free_string( ch->pcdata->title		);


	free_string( ch->pcdata->conception	);


	free_string( ch->pcdata->parents	);


	free_string( ch->pcdata->cparents	);


	free_string( ch->pcdata->marriage	);


	free_string( ch->pcdata->email		);


	ch->pcdata->next = pcdata_free;


	pcdata_free      = ch->pcdata;


    }





    ch->next	     = char_free;


    char_free	     = ch;


    return;


}











/*


 * Get an extra description from a list.


 */


char *get_extra_descr( char *name, EXTRA_DESCR_DATA *ed )


{


    for ( ; ed != NULL; ed = ed->next )


    {


	if ( is_name( name, ed->keyword ) )


	    return ed->description;


    }


    return NULL;


}











/*


 * Translates mob virtual number to its mob index struct.


 * Hash table lookup.


 */


MOB_INDEX_DATA *get_mob_index( int vnum )


{


    MOB_INDEX_DATA *pMobIndex;





    for ( pMobIndex  = mob_index_hash[vnum % MAX_KEY_HASH];


	  pMobIndex != NULL;


	  pMobIndex  = pMobIndex->next )


    {


	if ( pMobIndex->vnum == vnum )


	    return pMobIndex;


    }





    if ( fBootDb )


    {


	bug( "Get_mob_index: bad vnum %d.", vnum );


	exit( 1 );


    }





    return NULL;


}











/*


 * Translates mob virtual number to its obj index struct.


 * Hash table lookup.


 */


OBJ_INDEX_DATA *get_obj_index( int vnum )


{


    OBJ_INDEX_DATA *pObjIndex;





    for ( pObjIndex  = obj_index_hash[vnum % MAX_KEY_HASH];


	  pObjIndex != NULL;


	  pObjIndex  = pObjIndex->next )


    {


	if ( pObjIndex->vnum == vnum )


	    return pObjIndex;


    }





    if ( fBootDb )


    {


	bug( "Get_obj_index: bad vnum %d.", vnum );


	exit( 1 );


    }





    return NULL;


}











/*


 * Translates mob virtual number to its room index struct.


 * Hash table lookup.


 */


ROOM_INDEX_DATA *get_room_index( int vnum )


{


    ROOM_INDEX_DATA *pRoomIndex;





    for ( pRoomIndex  = room_index_hash[vnum % MAX_KEY_HASH];


	  pRoomIndex != NULL;


	  pRoomIndex  = pRoomIndex->next )


    {


	if ( pRoomIndex->vnum == vnum )


	    return pRoomIndex;


    }





    if ( fBootDb )


    {


	bug( "Get_room_index: bad vnum %d.", vnum );


	exit( 1 );


    }





    return NULL;


}











/*


 * Read a letter from a file.


 */


char fread_letter( FILE *fp )


{


    char c;





    do


    {


	c = getc( fp );


    }


    while ( isspace(c) );





    return c;


}











/*


 * Read a number from a file.


 */


int fread_number( FILE *fp )


{


    int number;


    bool sign;


    char c;





    do


    {


	c = getc( fp );


    }


    while ( isspace(c) );





    number = 0;





    sign   = FALSE;


    if ( c == '+' )


    {


	c = getc( fp );


    }


    else if ( c == '-' )


    {


	sign = TRUE;


	c = getc( fp );


    }





    if ( !isdigit(c) )


    {


	bug( "Fread_number: bad format.", 0 );


	exit( 1 );


    }





    while ( isdigit(c) )


    {


	number = number * 10 + c - '0';


	c      = getc( fp );


    }





    if ( sign )


	number = 0 - number;





    if ( c == '|' )


	number += fread_number( fp );


    else if ( c != ' ' )


	ungetc( c, fp );





    return number;


}











/*


 * Read and allocate space for a string from a file.


  * These strings are read-only and shared.


 * Strings are hashed:


 *   each string prepended with hash pointer to prev string,


 *   hash code is simply the string length.


 * This function takes 40% to 50% of boot-up time.


 */


char *fread_string( FILE *fp )


{


    char *plast;


    char c;





    plast = top_string + sizeof(char *);


    if ( plast > &string_space[MAX_STRING - MAX_STRING_LENGTH] )


    {


	bug( "Fread_string: MAX_STRING %d exceeded.", MAX_STRING );


	exit( 1 );


    }





    /*


     * Skip blanks.


     * Read first char.


     */


    do


    {


	c = getc( fp );


    }


    while ( isspace(c) );





    if ( ( *plast++ = c ) == '~' )


	return &str_empty[0];


    for ( ;; )


    {


	/*


	 * Back off the char type lookup,


	 *   it was too dirty for portability.


	 *   -- Furey


	 */


	switch ( *plast = getc( fp ) )


	{


	default:


	    plast++;


	    break;





	case EOF:


	    bug( "Fread_string: EOF", 0 );


	    exit( 1 );


	    break;





	case '\n':


	    plast++;


	    *plast++ = '\r';


	    break;





	case '\r':


	    break;





	case '~':


	    plast++;


	    {


		union


		{


		    char *	pc;


		    char	rgc[sizeof(char *)];


		} u1;


		int ic;


		int iHash;


		char *pHash;


		char *pHashPrev;


		char *pString;





		plast[-1] = '\0';


		iHash     = UMIN( MAX_KEY_HASH - 1, plast - 1 - top_string );


		for ( pHash = string_hash[iHash]; pHash; pHash = pHashPrev )


		{


		    for ( ic = 0; ic < sizeof(char *); ic++ )


			u1.rgc[ic] = pHash[ic];


		    pHashPrev = u1.pc;


		    pHash    += sizeof(char *);





		    if ( top_string[sizeof(char *)] == pHash[0]


		    &&   !strcmp( top_string+sizeof(char *)+1, pHash+1 ) )


			return pHash;


		}





		if ( fBootDb )


		{


		    pString		= top_string;


		    top_string		= plast;


		    u1.pc		= string_hash[iHash];


		    for ( ic = 0; ic < sizeof(char *); ic++ )


			pString[ic] = u1.rgc[ic];


		    string_hash[iHash]	= pString;





		    nAllocString += 1;


		    sAllocString += top_string - pString;


		    return pString + sizeof(char *);


		}


		else


		{


		    return str_dup( top_string + sizeof(char *) );


		}


	    }


	}


    }


}











/*


 * Read to end of line (for comments).


 */


void fread_to_eol( FILE *fp )


{


    char c;





    do


    {


	c = getc( fp );


    }


    while ( c != '\n' && c != '\r' );





    do


    {


	c = getc( fp );


    }


    while ( c == '\n' || c == '\r' );





    ungetc( c, fp );


    return;


}











/*


 * Read one word (into static buffer).


 */


char *fread_word( FILE *fp )


{


    static char word[MAX_INPUT_LENGTH];


    char *pword;


    char cEnd;





    do


    {


	cEnd = getc( fp );


    }


    while ( isspace( cEnd ) );





    if ( cEnd == '\'' || cEnd == '"' )


    {


	pword   = word;


    }


    else


    {


	word[0] = cEnd;


	pword   = word+1;


	cEnd    = ' ';


    }





    for ( ; pword < word + MAX_INPUT_LENGTH; pword++ )


    {


	*pword = getc( fp );


	if ( cEnd == ' ' ? isspace(*pword) : *pword == cEnd )


	{


	    if ( cEnd == ' ' )


		ungetc( *pword, fp );


	    *pword = '\0';


	    return word;


	}


    }





    bug( "Fread_word: word too long.", 0 );


    exit( 1 );


    return NULL;


}











/*


 * Allocate some ordinary memory,


 *   with the expectation of freeing it someday.


 */


void *alloc_mem( int sMem )


{


    void *pMem;


    int iList;





    for ( iList = 0; iList < MAX_MEM_LIST; iList++ )


    {


	if ( sMem <= rgSizeList[iList] )


	    break;


    }





    if ( iList == MAX_MEM_LIST )


    {


	bug( "Alloc_mem: size %d too large.", sMem );


	exit( 1 );


    }





    if ( rgFreeList[iList] == NULL )


    {


	pMem		  = alloc_perm( rgSizeList[iList] );


    }


    else


    {


	pMem              = rgFreeList[iList];


	rgFreeList[iList] = * ((void **) rgFreeList[iList]);


    }





    return pMem;


}











/*


 * Free some memory.


 * Recycle it back onto the free list for blocks of that size.


 */


void free_mem( void *pMem, int sMem )


{


    int iList;





    for ( iList = 0; iList < MAX_MEM_LIST; iList++ )


    {


	if ( sMem <= rgSizeList[iList] )


	    break;


    }





    if ( iList == MAX_MEM_LIST )


    {


	bug( "Free_mem: size %d too large.", sMem );


	exit( 1 );


    }





    * ((void **) pMem) = rgFreeList[iList];


    rgFreeList[iList]  = pMem;





    return;


}











/*


 * Allocate some permanent memory.


 * Permanent memory is never freed,


 *   pointers into it may be copied safely.


 */


void *alloc_perm( int sMem )


{


    static char *pMemPerm;


    static int iMemPerm;


    void *pMem;





    while ( sMem % sizeof(long) != 0 )


	sMem++;


    if ( sMem > MAX_PERM_BLOCK )


    {


	bug( "Alloc_perm: %d too large.", sMem );


	exit( 1 );


    }





    if ( pMemPerm == NULL || iMemPerm + sMem > MAX_PERM_BLOCK )


    {


	iMemPerm = 0;


	if ( ( pMemPerm = calloc( 1, MAX_PERM_BLOCK ) ) == NULL )


	{


	    perror( "Alloc_perm" );


	    exit( 1 );


	}


    }





    pMem        = pMemPerm + iMemPerm;


    iMemPerm   += sMem;


    nAllocPerm += 1;


    sAllocPerm += sMem;


    return pMem;


}











/*


 * Duplicate a string into dynamic memory.


 * Fread_strings are read-only and shared.


 */


char *str_dup( const char *str )


{


    char *str_new;





    if ( str[0] == '\0' )


	return &str_empty[0];





    if ( str >= string_space && str < top_string )


	return (char *) str;





    str_new = alloc_mem( strlen(str) + 1 );


    strcpy( str_new, str );


    return str_new;


}











/*


 * Free a string.


 * Null is legal here to simplify callers.


 * Read-only shared strings are not touched.


 */


void free_string( char *pstr )


{


    if ( pstr == NULL


    ||   pstr == &str_empty[0]


    || ( pstr >= string_space && pstr < top_string ) )


	return;





    free_mem( pstr, strlen(pstr) + 1 );


    return;


}













void do_areas( CHAR_DATA *ch, char *argument )


{


    char buf[MAX_STRING_LENGTH];


    AREA_DATA *pArea1;


    AREA_DATA *pArea2;


    int iArea;


    int iAreaHalf;


    WAIT_STATE(ch,10);


    iAreaHalf = (top_area + 1) / 2;


    pArea1    = area_first;


    pArea2    = area_first;


    for ( iArea = 0; iArea < iAreaHalf; iArea++ )


	pArea2 = pArea2->next;





    


   for ( iArea = 0; iArea < iAreaHalf; iArea++ )


    {


	sprintf( buf, "%-39s%-39s\n\r",


	    pArea1->name, (pArea2 != NULL) ? pArea2->name : "" );


	send_to_char( buf, ch );


	pArea1 = pArea1->next;


	if ( pArea2 != NULL )


	    pArea2 = pArea2->next;


    }





    return;


}











void do_memory( CHAR_DATA *ch, char *argument )


{


    char buf[MAX_STRING_LENGTH];





    sprintf( buf, "Affects %5d\n\r", top_affect    ); send_to_char( buf, ch );


    sprintf( buf, "Areas   %5d\n\r", top_area      ); send_to_char( buf, ch );


    sprintf( buf, "RmTxt   %5d\n\r", top_rt        ); send_to_char( buf, ch );


    sprintf( buf, "ExDes   %5d\n\r", top_ed        ); send_to_char( buf, ch );


    sprintf( buf, "Exits   %5d\n\r", top_exit      ); send_to_char( buf, ch );


    sprintf( buf, "Helps   %5d\n\r", top_help      ); send_to_char( buf, ch );


    sprintf( buf, "Mobs    %5d\n\r", top_mob_index ); send_to_char( buf, ch );


    sprintf( buf, "Objs    %5d\n\r", top_obj_index ); send_to_char( buf, ch );


    sprintf( buf, "Resets  %5d\n\r", top_reset     ); send_to_char( buf, ch );


    sprintf( buf, "Rooms   %5d\n\r", top_room      ); send_to_char( buf, ch );


    sprintf( buf, "Shops   %5d\n\r", top_shop      ); send_to_char( buf, ch );





    sprintf( buf, "Strings %5d strings of %7d bytes (max %d).\n\r",


	nAllocString, sAllocString, MAX_STRING );


    send_to_char( buf, ch );





    sprintf( buf, "Perms   %5d blocks  of %7d bytes.\n\r",


	nAllocPerm, sAllocPerm );


    send_to_char( buf, ch );





    return;


}











/*


 * Stick a little fuzz on a number.


 */


int number_fuzzy( int number )


{


    switch ( number_bits( 2 ) )


    {


    case 0:  number -= 1; break;


    case 3:  number += 1; break;


    }





    return UMAX( 1, number );


}











/*


 * Generate a random number.


 */


int number_range( int from, int to )


{


    int power;


    int number;





    if ( ( to = to - from + 1 ) <= 1 )


	return from;





    for ( power = 2; power < to; power <<= 1 )


	;





    while ( ( number = number_mm( ) & (power - 1) ) >= to )


	;





    return from + number;


}











/*


 * Generate a percentile roll.


 */


int number_percent( void )


{


    int percent;





    while ( ( percent = number_mm( ) & (128-1) ) > 99 )


	;





    return 1 + percent;


}











/*


 * Generate a random door.


 */


int number_door( void )


{


    int door;





    while ( ( door = number_mm( ) & (8-1) ) > 5 )


	;





    return door;


}











int number_bits( int width )


{


    return number_mm( ) & ( ( 1 << width ) - 1 );


}











/*


 * I've gotten too many bad reports on OS-supplied random number generators.


 * This is the Mitchell-Moore algorithm from Knuth Volume II.


 * Best to leave the constants alone unless you've read Knuth.


 * -- Furey


 */


static	int	rgiState[2+55];





void init_mm( )


{


    int *piState;


    int iState;





    piState	= &rgiState[2];





    piState[-2]	= 55 - 55;


    piState[-1]	= 55 - 24;





    piState[0]	= ((int) current_time) & ((1 << 30) - 1);


    piState[1]	= 1;


    for ( iState = 2; iState < 55; iState++ )


    {


	piState[iState] = (piState[iState-1] + piState[iState-2])


			& ((1 << 30) - 1);


    }


    return;


}











int number_mm( void )


{


    int *piState;


    int iState1;


    int iState2;


    int iRand;





    piState		= &rgiState[2];


    iState1	 	= piState[-2];


    iState2	 	= piState[-1];


    iRand	 	= (piState[iState1] + piState[iState2])


			& ((1 << 30) - 1);


    piState[iState1]	= iRand;


    if ( ++iState1 == 55 )


	iState1 = 0;


    if ( ++iState2 == 55 )


	iState2 = 0;


    piState[-2]		= iState1;


    piState[-1]		= iState2;


    return iRand >> 6;


}











/*


 * Roll some dice.


 */


int dice( int number, int size )


{


    int idice;


    int sum;





    switch ( size )


    {


    case 0: return 0;


    case 1: return number;


    }





    for ( idice = 0, sum = 0; idice < number; idice++ )


	sum += number_range( 1, size );





    return sum;


}











/*


 * Simple linear interpolation.


 */


int interpolate( int level, int value_00, int value_32 )


{


    return value_00 + level * (value_32 - value_00) / 32;


}











/*


 * Removes the tildes from a string.


 * Used for player-entered strings that go into disk files.


 */


void smash_tilde( char *str )


{


    for ( ; *str != '\0'; str++ )


    {


	if ( *str == '~' )


	    *str = '-';


    }





    return;


}











/*


 * Compare strings, case insensitive.


 * Return TRUE if different


 *   (compatibility with historical functions).


 */


bool str_cmp( const char *astr, const char *bstr )
{
    if ( astr == NULL )
    {
	bug( "Str_cmp: null astr.", 0 );
	return TRUE;
    }

    if ( bstr == NULL )
    {
	bug( "Str_cmp: null bstr.", 0 );
	return TRUE;
    }

    for ( ; *astr || *bstr; astr++, bstr++ )
    {
	if ( LOWER(*astr) != LOWER(*bstr) )
	    return TRUE;
    }

    return FALSE;
}



/*


 * Compare strings, case insensitive, for prefix matching.


 * Return TRUE if astr not a prefix of bstr


 *   (compatibility with historical functions).


 */


bool str_prefix( const char *astr, const char *bstr )


{


    if ( astr == NULL )


    {


	bug( "Strn_cmp: null astr.", 0 );


	return TRUE;


    }





    if ( bstr == NULL )


    {


	bug( "Strn_cmp: null bstr.", 0 );


	return TRUE;


    }





    for ( ; *astr; astr++, bstr++ )


    {


	if ( LOWER(*astr) != LOWER(*bstr) )


	    return TRUE;


    }





    return FALSE;


}











/*


 * Compare strings, case insensitive, for match anywhere.


 * Returns TRUE is astr not part of bstr.


 *   (compatibility with historical functions).


 */


bool str_infix( const char *astr, const char *bstr )


{


    int sstr1;


    int sstr2;


    int ichar;


    char c0;





    if ( ( c0 = LOWER(astr[0]) ) == '\0' )


	return FALSE;





    sstr1 = strlen(astr);


    sstr2 = strlen(bstr);





    for ( ichar = 0; ichar <= sstr2 - sstr1; ichar++ )


    {


	if ( c0 == LOWER(bstr[ichar]) && !str_prefix( astr, bstr + ichar ) )


	    return FALSE;


    }





    return TRUE;


}











/*


 * Compare strings, case insensitive, for suffix matching.


 * Return TRUE if astr not a suffix of bstr


 *   (compatibility with historical functions).


 */


bool str_suffix( const char *astr, const char *bstr )


{


    int sstr1;


    int sstr2;





    sstr1 = strlen(astr);


    sstr2 = strlen(bstr);


    if ( sstr1 <= sstr2 && !str_cmp( astr, bstr + sstr2 - sstr1 ) )


	return FALSE;


    else


	return TRUE;


}











/*


 * Returns an initial-capped string.


 */


char *capitalize( const char *str )


{


    static char strcap[MAX_STRING_LENGTH];


    int i;





    for ( i = 0; str[i] != '\0'; i++ )


	strcap[i] = LOWER(str[i]);


    strcap[i] = '\0';


    strcap[0] = UPPER(strcap[0]);


    return strcap;


}











/*


 * Append a string to a file.


 */


void append_file( CHAR_DATA *ch, char *file, char *str )


{


    FILE *fp;





    if ( IS_NPC(ch) || str[0] == '\0' )


	return;





    fclose( fpReserve );


    if ( ( fp = fopen( file, "a" ) ) == NULL )


    {


	perror( file );


	send_to_char( "Could not open the file!\n\r", ch );


    }


    else


    {


	fprintf( fp, "[%5d] %s: %s\n",


	    ch->in_room ? ch->in_room->vnum : 0, ch->name, str );


	fclose( fp );


    }





    fpReserve = fopen( NULL_FILE, "r" );


    return;


}











/*


 * Reports a bug.


 */


void bug( const char *str, int param )


{


    char buf[MAX_STRING_LENGTH];


    FILE *fp;





    if ( fpArea != NULL )


    {


	int iLine;


	int iChar;





	if ( fpArea == stdin )


	{


	    iLine = 0;


	}


	else


	{


	    iChar = ftell( fpArea );


	    fseek( fpArea, 0, 0 );


	    for ( iLine = 0; ftell( fpArea ) < iChar; iLine++ )


	    {


		while ( getc( fpArea ) != '\n' )


		    ;


	    }


	    fseek( fpArea, iChar, 0 );


	}





	sprintf( buf, "[*****] FILE: %s LINE: %d", strArea, iLine );


	log_string( buf );





	if ( ( fp = fopen( "shutdown.txt", "a" ) ) != NULL )


	{


	    fprintf( fp, "[*****] %s\n", buf );


	    fclose( fp );


	}


    }





    strcpy( buf, "[*****] BUG: " );


    sprintf( buf + strlen(buf), str, param );


    log_string( buf );





    fclose( fpReserve );


    if ( ( fp = fopen( BUG_FILE, "a" ) ) != NULL )


    {


	fprintf( fp, "%s\n", buf );


	fclose( fp );


    }


    fpReserve = fopen( NULL_FILE, "r" );





    return;


}











/*


 * Writes a string to the log.


 */


void log_string( const char *str )


{


    char *strtime;


    char logout [MAX_STRING_LENGTH];





    strtime                    = ctime( &current_time );


    strtime[strlen(strtime)-1] = '\0';


    fprintf( stderr, "%s :: %s\n", strtime, str );


    strcpy ( logout, str );


    logchan( logout );


    return;


}













/*


 * This function is here to aid in debugging.


 * If the last expression in a function is another function call,


 *   gcc likes to generate a JMP instead of a CALL.


 * This is called "tail chaining."


 * It hoses the debugger call stack for that call.


 * So I make this the last call in certain critical functions,


 *   where I really need the call stack to be right for debugging!


 *


 * If you don't understand this, then LEAVE IT ALONE.


 * Don't remove any calls to tail_chain anywhere.


 *


 * -- Furey


 */


void tail_chain( void )


{


    return;


}





6650201550  10435

 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
 *                                                                         *
 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
 *  Chastain, Michael Quan, and Mitchell Tse.                              *
 *                                                                         *
 *  In order to use any part of this Merc Diku Mud, you must comply with   *
 *  both the original Diku license in 'license.doc' as well the Merc       *
 *  license in 'license.txt'.  In particular, you may not remove either of *
 *  these copyright notices.                                               *
 *                                                                         *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 ***************************************************************************/

#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"
#include "player.h"

/*
 * Local functions.
 */

void do_notravel( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];

    one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if (IS_IMMUNE(ch, IMM_TRAVEL))
    {
	REMOVE_BIT(ch->immune, IMM_TRAVEL);
	send_to_char("You can now be the target of travel or burrow.\n\r",
ch);
	return;
    }
    else if (!IS_IMMUNE(ch, IMM_TRAVEL)) 
    {
	SET_BIT(ch->immune, IMM_TRAVEL);
	send_to_char("You can no longer be the target of travel or burrow.\n\r", ch);
	return;
    }
    else
	send_to_char( "Excuse you?\n\r", ch );
    return;
}



void do_warps( CHAR_DATA *ch, char *argument )
{
    char lin   [MAX_STRING_LENGTH];
 
 
    if (IS_NPC(ch)) return;
    if (!IS_CLASS(ch, CLASS_DEMON))
    {
    send_to_char("Huh?\n\r",ch);
    return;
    }
    sprintf( lin,
"-=(**)=-=(**)=-=(**)=-=(**)=-=(**)=-=(**)=-=(**)=-=(**)=-=(**)=-=(**)=-=(**)=-\n\r");
    send_to_char( lin,ch);
    send_to_char(
"                      -=(**)=- Attained Warps -=(**)=-\n\r",ch);
send_to_char(lin,ch);
if (IS_SET(ch->warp, WARP_CBODY      )) send_to_char("Your body is protected by a indestructable crystal shell.\n\r",ch);
if (IS_SET(ch->warp, WARP_SBODY      )) send_to_char("Your skin is as hard as steel.\n\r",ch);
if (IS_SET(ch->warp, WARP_STRONGARMS )) send_to_char("Your arms are incredibly strong.\n\r",ch);
if (IS_SET(ch->warp, WARP_STRONGLEGS )) send_to_char("Your legs are incredibly strong.\n\r",ch);
if (IS_SET(ch->warp, WARP_VENOMTONG  )) send_to_char("Your tongue is long and venomous.\n\r",ch);
if (IS_SET(ch->warp, WARP_SPIKETAIL  )) send_to_char("Your tail fires deadly spikes during combat.\n\r",ch);
if (IS_SET(ch->warp, WARP_BADBREATH  )) send_to_char("Your breath is putrid and deadly.\n\r",ch);
if (IS_SET(ch->warp, WARP_QUICKNESS  )) send_to_char("You have incredible speed.\n\r",ch);
if (IS_SET(ch->warp, WARP_STAMINA    )) send_to_char("You have increased stamina, reducing the damage you take.\n\r",ch);
if (IS_SET(ch->warp, WARP_HUNT       )) send_to_char("Your heightened senses enable you to hunt people.\n\r",ch);
if (IS_SET(ch->warp, WARP_DEVOUR     )) send_to_char("You have the ability to devour your opponents, sending them into the pits of Hell.\n\r",ch);
if (IS_SET(ch->warp, WARP_TERROR     )) send_to_char("Your features are so horrid that they may stun those who look at you.\n\r",ch);
if (IS_SET(ch->warp, WARP_REGENERATE )) send_to_char("Your body has the ability to regenerate incredibly fast.\n\r",ch);
if (IS_SET(ch->warp, WARP_STEED      )) send_to_char("Your mounts transform into hideous Demons.\n\r",ch);
if (IS_SET(ch->warp, WARP_WEAPON     )) send_to_char("You have the power to transform into a deadly battle axe.\n\r",ch);
if (IS_SET(ch->warp, WARP_INFIRMITY  )) send_to_char("Your body has been afflicted by a terrible infirmity.\n\r",ch);
if (IS_SET(ch->warp, WARP_GBODY      )) send_to_char("Your skin is made of a fragile glass.\n\r",ch);
if (IS_SET(ch->warp, WARP_SCARED     )) send_to_char("You are incredibly scared of combat.\n\r",ch);
if (IS_SET(ch->warp, WARP_MAGMA      )) send_to_char("Your body is composed of deadly magma.\n\r",ch);
if (IS_SET(ch->warp, WARP_WEAK       )) send_to_char("Your muscles are severely weakened.\n\r",ch);
if (IS_SET(ch->warp, WARP_SLOW       )) send_to_char("Your body moves very slowly.\n\r",ch);
if (IS_SET(ch->warp, WARP_VULNER     )) send_to_char("Your skin is very vulnerable to magic.\n\r",ch);
if (IS_SET(ch->warp, WARP_SHARDS     )) send_to_char("Your skin is covered with shards of ice.\n\r",ch);
if (IS_SET(ch->warp, WARP_WINGS      )) send_to_char("A pair of leathery wings protrude from your back.\n\r",ch);
if (IS_SET(ch->warp, WARP_CLUMSY     )) send_to_char("You are incredibly clumsy, enabling you to be disarmed.\n\r",ch);
if (IS_SET(ch->warp, WARP_STUPID     )) send_to_char("Your intelligence is extremely low, preventing you from casting spells.\n\r",ch);
if (IS_SET(ch->warp, WARP_SPOON      )) send_to_char("There is a spoon stuck on your ear.\n\r",ch);
if (IS_SET(ch->warp, WARP_FORK       )) send_to_char("You have a fork stuck in your nose.\n\r",ch);
if (IS_SET(ch->warp, WARP_KNIFE      )) send_to_char("You have a knife hanging out of your ear.\n\r",ch);
if (IS_SET(ch->warp, WARP_SALADBOWL  )) send_to_char("Your head is made out of a salad bowl.\n\r",ch);
if (ch->warp < 1) send_to_char("You haven't obtained any warp powers.\n\r",ch);
send_to_char(lin,ch);
return;
}


void do_redeem( CHAR_DATA *ch, char *argument )
{

    int           warpnum = number_range(1,19);
    int	      newwarp = 0;
    if (IS_NPC(ch)) return;

	if ( !IS_CLASS(ch, CLASS_DEMON))
	{
	send_to_char("Huh?\n\r", ch);
	return;
	}

    if (ch->pcdata->stats[DEMON_TOTAL] < 10000 || 
	ch->pcdata->stats[DEMON_CURRENT] < 10000)
    {
	send_to_char("You need 10000 demon points to redeem
warps!\n\r",ch);
	return;
    }
    {
             if (warpnum == 1) newwarp = WARP_CBODY;
        else if (warpnum == 2) newwarp = WARP_SBODY;
	else if (warpnum == 3) newwarp = WARP_STRONGARMS;
	else if (warpnum == 4) newwarp = WARP_STRONGLEGS;
	else if (warpnum == 5) newwarp = WARP_VENOMTONG;
	else if (warpnum == 6) newwarp = WARP_SPIKETAIL;
	else if (warpnum == 7) newwarp = WARP_BADBREATH;
	else if (warpnum == 8) newwarp = WARP_QUICKNESS;
	else if (warpnum == 9) newwarp = WARP_STAMINA;
	else if (warpnum == 11) newwarp = WARP_HUNT;
	else if (warpnum == 12) newwarp = WARP_DEVOUR;
	else if (warpnum == 13) newwarp = WARP_TERROR;
	else if (warpnum == 14) newwarp = WARP_REGENERATE;
	else if (warpnum == 15) newwarp = WARP_STEED;
	else if (warpnum == 16) newwarp = WARP_WEAPON;
        else if (warpnum == 17) newwarp = WARP_SHARDS;
	else if (warpnum == 18) newwarp = WARP_WINGS;
	else if (warpnum == 19) newwarp = WARP_MAGMA;
    }

	if (ch->warp==12877823)
	newwarp = 0;

	if (IS_SET(ch->warp, newwarp) && ch->warp != 12877823)
    {
      do_redeem(ch,"");
	return;
    }
	
    {
	if (IS_SET(ch->warp, WARP_INFIRMITY))
	{
	   REMOVE_BIT(ch->warp, WARP_INFIRMITY);
	   SET_BIT(ch->warp, newwarp);
	   ch->pcdata->stats[DEMON_CURRENT] -= 10000;
	   send_to_char("You pray to Satan and a warp is cleansed.\n\r",ch);
    	   save_char_obj(ch);
    	   return;
	}
	else if (IS_SET(ch->warp, WARP_GBODY))
	{
	   REMOVE_BIT(ch->warp, WARP_GBODY);
	   SET_BIT(ch->warp, newwarp);
	   ch->pcdata->stats[DEMON_CURRENT] -= 10000;
	   send_to_char("You pray to Satan and a warp is cleansed.\n\r",ch);
    	   save_char_obj(ch);
    	   return;
	}
	else if (IS_SET(ch->warp, WARP_SCARED))
	{
	   REMOVE_BIT(ch->warp, WARP_SCARED);
	   SET_BIT(ch->warp, newwarp);
	   ch->pcdata->stats[DEMON_CURRENT] -= 10000;
	   send_to_char("You pray to Satan and a warp is cleansed.\n\r",ch);
    	   save_char_obj(ch);
    	   return;
	}
	else if (IS_SET(ch->warp, WARP_WEAK))
	{
	   REMOVE_BIT(ch->warp, WARP_WEAK);
	   SET_BIT(ch->warp, newwarp);
	   ch->pcdata->stats[DEMON_CURRENT] -= 10000;
	   send_to_char("You pray to Satan and a warp is cleansed.\n\r",ch);
    	   save_char_obj(ch);
    	   return;
	}
	else if (IS_SET(ch->warp, WARP_SLOW))
	{
	   REMOVE_BIT(ch->warp, WARP_SLOW);
	   SET_BIT(ch->warp, newwarp);
	   ch->pcdata->stats[DEMON_CURRENT] -= 10000;
	   send_to_char("You pray to Satan and a warp is cleansed.\n\r",ch);
    	   save_char_obj(ch);
    	   return;
	}
	else if (IS_SET(ch->warp, WARP_VULNER))
	{
	   REMOVE_BIT(ch->warp, WARP_VULNER);
	   SET_BIT(ch->warp, newwarp);
	   ch->pcdata->stats[DEMON_CURRENT] -= 10000;
	   send_to_char("You pray to Satan and a warp is cleansed.\n\r",ch);
    	   save_char_obj(ch);
    	   return;
	}
	else if (IS_SET(ch->warp, WARP_CLUMSY))
	{
	   REMOVE_BIT(ch->warp, WARP_CLUMSY);
	   SET_BIT(ch->warp, newwarp);
	   ch->pcdata->stats[DEMON_CURRENT] -= 10000;
	   send_to_char("You pray to Satan and a warp is cleansed.\n\r",ch);
    	   save_char_obj(ch);
    	   return;
	}
	else if (IS_SET(ch->warp, WARP_STUPID))
	{
	   REMOVE_BIT(ch->warp, WARP_STUPID);
	   SET_BIT(ch->warp, newwarp);
	   ch->pcdata->stats[DEMON_CURRENT] -= 10000;
	   send_to_char("You pray to Satan and a warp is cleansed.\n\r",ch);
    	   save_char_obj(ch);
    	   return;
	}
	else if (IS_SET(ch->warp, WARP_SPOON))
	{
	   REMOVE_BIT(ch->warp, WARP_SPOON);
	   SET_BIT(ch->warp, newwarp);
	   ch->pcdata->stats[DEMON_CURRENT] -= 10000;
	   send_to_char("You pray to Satan and a warp is cleansed.\n\r",ch);
    	   save_char_obj(ch);
    	   return;
	}
	else if (IS_SET(ch->warp, WARP_FORK))
	{
	   REMOVE_BIT(ch->warp, WARP_FORK);
	   SET_BIT(ch->warp, newwarp);
	   ch->pcdata->stats[DEMON_CURRENT] -= 10000;
	   send_to_char("You pray to Satan and a warp is cleansed.\n\r",ch);
    	   save_char_obj(ch);
    	   return;
	}
	else if (IS_SET(ch->warp, WARP_KNIFE))
	{
	   REMOVE_BIT(ch->warp, WARP_KNIFE);
	   SET_BIT(ch->warp, newwarp);
	   ch->pcdata->stats[DEMON_CURRENT] -= 10000;
	   send_to_char("You pray to Satan and a warp is cleansed.\n\r",ch);
    	   save_char_obj(ch);
    	   return;
	}
      else send_to_char("You have no evil warps to redeem!\n\r",ch);
    }	
  return;
}


void do_obtain( CHAR_DATA *ch, char *argument )
{
    int       newwarp = 0;
    int       warpnum = number_range(1,30);

    if (IS_NPC(ch)) return;

	if ( !IS_CLASS(ch, CLASS_DEMON))
	{
	send_to_char("Huh?\n\r", ch);
	return;
	}

    if (ch->pcdata->stats[DEMON_TOTAL] < 15000 || 
	ch->pcdata->stats[DEMON_CURRENT] < 15000)
    {
	send_to_char("You need 15000 demon points to obtain a new warp!\n\r",ch);
	return;
    }

        if (ch->warpcount >= 18)
        {
	    send_to_char("You have already obtained as many warps as possible.\n\r",ch);
	    return;
	}

             if (warpnum == 1) newwarp = WARP_CBODY;
        else if (warpnum == 2) newwarp = WARP_SBODY;
	else if (warpnum == 3) newwarp = WARP_STRONGARMS;
	else if (warpnum == 4) newwarp = WARP_STRONGLEGS;
	else if (warpnum == 5) newwarp = WARP_VENOMTONG;
	else if (warpnum == 6) newwarp = WARP_SPIKETAIL;
	else if (warpnum == 7) newwarp = WARP_BADBREATH;
	else if (warpnum == 8) newwarp = WARP_QUICKNESS;
	else if (warpnum == 9) newwarp = WARP_STAMINA;
	else if (warpnum == 11) newwarp = WARP_HUNT;
	else if (warpnum == 12) newwarp = WARP_DEVOUR;
	else if (warpnum == 13) newwarp = WARP_TERROR;
	else if (warpnum == 14) newwarp = WARP_REGENERATE;
	else if (warpnum == 15) newwarp = WARP_STEED;
	else if (warpnum == 16) newwarp = WARP_WEAPON;
	else if (warpnum == 17) newwarp = WARP_INFIRMITY;
	else if (warpnum == 18) newwarp = WARP_GBODY;
	else if (warpnum == 19) newwarp = WARP_SCARED;
	else if (warpnum == 20) newwarp = WARP_MAGMA;
	else if (warpnum == 21) newwarp = WARP_WEAK;
	else if (warpnum == 22) newwarp = WARP_SLOW;
	else if (warpnum == 23) newwarp = WARP_VULNER;
	else if (warpnum == 24) newwarp = WARP_SHARDS;
	else if (warpnum == 25) newwarp = WARP_WINGS;
	else if (warpnum == 26) newwarp = WARP_CLUMSY;
	else if (warpnum == 27) newwarp = WARP_STUPID;
	else if (warpnum == 28) newwarp = WARP_SPOON;
	else if (warpnum == 29) newwarp = WARP_FORK;
	else if (warpnum == 30) newwarp = WARP_KNIFE;

    if (IS_SET(ch->warp, newwarp))
    {
      do_obtain(ch,"");
	return;
    }

    SET_BIT(ch->warp, newwarp);
    ch->pcdata->stats[DEMON_CURRENT] -= 15000;
    ch->warpcount += 1;
    send_to_char("You have obtained a new warp!\n\r",ch);
    save_char_obj(ch);
    return;
}

void do_inpart( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char      arg1 [MAX_INPUT_LENGTH];
    char      arg2 [MAX_INPUT_LENGTH];
    int       inpart = 0;
    int       cost = 0;

    smash_tilde(argument);
    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if (IS_NPC(ch)) return;

	if ( !IS_CLASS(ch, CLASS_DEMON))
	{
	send_to_char("Huh?\n\r", ch);
	return;
	}

    if ( arg1[0] == '\0' || arg2[0] == '\0' )
    {
	send_to_char( "Syntax: Inpart <person> <power>\n\r", ch );
	send_to_char(" Fangs        [ 2500] Claws        [ 2500] Tail        [ 5000]\n\r",ch);
        send_to_char(" Horns        [ 2500] Hooves       [ 1500] Graft       [20000]\n\r",ch);
	send_to_char(" NightSight   [ 3000] Wings        [ 1000] Might       [ 7500]\n\r",ch);
        send_to_char(" Toughness    [ 7500] Speed        [ 7500] Travel      [ 1500]\n\r",ch);
	send_to_char(" Scry         [ 7500] Truesight    [ 7500] Move        [  500]\n\r",ch);
	send_to_char(" Leap         [  500] Magic        [ 1000] Lifespan    [  100]\n\r",ch);
	send_to_char(" Shield       [20000] Longsword    [    0] Shortsword  [    0]\n\r",ch);
	send_to_char(" Immolate     [ 2500] Inferno      [20000] Caust       [ 3000]\n\r",ch);
	send_to_char(" Unnerve      [ 5000] Freezeweapon [ 3000] Entomb      [20000]\n\r",ch);
	send_to_char(" Leech	      [15000] Demonform    [25000] Blink       [15000]\n\r",ch);
	return;
    }

    if ( ( victim = get_char_world( ch, arg1 ) ) == NULL )
    {
	send_to_char( "Nobody by that name.\n\r", ch );
	return;
    }


    if ( IS_NPC(victim) )
    {
	send_to_char( "Not on NPC's.\n\r", ch );
	return;
    }

/*
    if ( victim->level != LEVEL_AVATAR || 
	(victim != ch && !IS_SET(victim->special, SPC_CHAMPION)))
    {
	send_to_char( "Only on a champion.\n\r", ch );
	return;
    }

    if ( victim != ch && str_cmp(victim->lord, ch->name) && 
	str_cmp(victim->lord, ch->lord) && strlen(victim->lord) > 1 )
    {
	send_to_char( "They are not your champion.\n\r", ch );
	return;
    }
*/

    if (!str_cmp(arg2,"longsword"))
    {
	send_to_char("You have been granted the power to transform into a demonic longsword!\n\r",victim);
	send_to_char("You grant them the power to transform into a demonic longsword.\n\r",ch);
	victim->pcdata->powers[DPOWER_OBJ_VNUM] = 29662;
	save_char_obj(victim);
	return;
    }

    if (!str_cmp(arg2,"fangs")) 
	{inpart = DEM_FANGS; cost = 2500;}
    else if (!str_cmp(arg2,"immolate"))
	{inpart = DEM_IMMOLATE; cost = 2500;}
    else if (!str_cmp(arg2,"inferno"))
	{inpart = DEM_INFERNO; cost = 20000;}
    else if (!str_cmp(arg2,"caust"))
	{inpart = DEM_CAUST; cost = 3000;}
    else if (!str_cmp(arg2,"freezeweapon"))
	{inpart = DEM_FREEZEWEAPON; cost = 3000;}
    else if (!str_cmp(arg2,"unnerve"))
	{inpart = DEM_UNNERVE; cost = 5000;}
    else if (!str_cmp(arg2,"entomb"))
	{inpart = DEM_ENTOMB; cost = 20000;}
    else if (!str_cmp(arg2,"claws")) 
	{inpart = DEM_CLAWS; cost = 2500;}
    else if (!str_cmp(arg2,"horns")) 
	{inpart = DEM_HORNS; cost = 2500;}
   else if (!str_cmp(arg2, "demonform"))
	{inpart = DEM_FORM; cost = 25000;} 
   else if (!str_cmp(arg2,"tail")) 
	{inpart = DEM_TAIL; cost = 5000;}
    else if (!str_cmp(arg2,"hooves")) 
	{inpart = DEM_HOOVES; cost = 1500;}
    else if (!str_cmp(arg2,"shield")) 
	{inpart = DEM_SHIELD; cost = 20000;}
    else if (!str_cmp(arg2,"nightsight")) 
	{inpart = DEM_EYES; cost = 3000;}
    else if (!str_cmp(arg2,"wings")) 
	{inpart = DEM_WINGS; cost = 1000;}
    else if (!str_cmp(arg2,"might")) 
	{inpart = DEM_MIGHT; cost = 7500;}
    else if (!str_cmp(arg2,"toughness")) 
	{inpart = DEM_TOUGH; cost = 7500;}
    else if (!str_cmp(arg2,"speed"))
	{inpart = DEM_SPEED; cost = 7500;}
    else if (!str_cmp(arg2,"travel")) 
	{inpart = DEM_TRAVEL; cost = 1500;}
    else if (!str_cmp(arg2,"scry")) 
	{inpart = DEM_SCRY; cost = 7500;}
    else if (!str_cmp(arg2,"move")) 
	{inpart = DEM_MOVE; cost = 500;}
    else if (!str_cmp(arg2,"leap")) 
	{inpart = DEM_LEAP; cost = 500;}
    else if (!str_cmp(arg2,"magic")) 
	{inpart = DEM_MAGIC; cost = 1000;}
    else if (!str_cmp(arg2,"truesight"))
        {inpart = DEM_TRUESIGHT; cost = 7500;}
    else if (!str_cmp(arg2,"graft"))
	{inpart = DEM_GRAFT; cost = 20000;}
    else if (!str_cmp(arg2,"leech"))
	{inpart = DEM_LEECH; cost = 15000;}
    else if (!str_cmp(arg2,"blink"))
        {inpart = DEM_BLINK; cost = 15000;}
    else if (!str_cmp(arg2,"lifespan")) 
	{inpart = DEM_LIFESPAN; cost = 100;}
    else
    {
	do_inpart(ch,"");
	return;
    }
    if (IS_DEMPOWER(victim, inpart))
    {
	send_to_char("They have already got that power.\n\r",ch);
	return;
    }
    if (ch->pcdata->stats[DEMON_TOTAL] < cost || 
	ch->pcdata->stats[DEMON_CURRENT] < cost)
    {
	send_to_char("You have insufficient power to inpart that gift.\n\r",ch);
	return;
    }
    SET_BIT(victim->pcdata->powers[DPOWER_FLAGS], inpart);
    ch->pcdata->stats[DEMON_CURRENT] -= cost;
    if (victim != ch) send_to_char("You have been granted a demonic gift from your patron!\n\r",victim);
    send_to_char("Ok.\n\r",ch);
    if (victim != ch) save_char_obj(ch);
    save_char_obj(victim);
    return;
}

void do_demonarmour( CHAR_DATA *ch, char *argument )
{
    OBJ_INDEX_DATA *pObjIndex;
    OBJ_DATA *obj;
    char arg[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    int vnum = 0;

    argument = one_argument( argument, arg );
    argument = one_argument( argument, arg2 );

    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch, CLASS_DEMON))
    {
	send_to_char("Huh?\n\r", ch );
	return;
    }
    
    if (arg[0] == '\0')
    {
    send_to_char("Command: demonarmor <black/red> <piece>.\n\r", ch);
    return;
    }

    if (arg2[0] == '\0')
    {
	send_to_char("Please specify which piece of demon armor you wish to make: Ring Collar\n\rPlate Helmet Leggings Boots Gauntlets Sleeves Cape Belt Bracer Visor.\n\r",ch);
	return;
    }

    if      (!str_cmp(arg2,"ring"     ) && !str_cmp(arg,"black")) vnum = 29650;
    else if (!str_cmp(arg2,"collar"   ) && !str_cmp(arg,"black")) vnum = 29651;
    else if (!str_cmp(arg2,"plate"    ) && !str_cmp(arg,"black")) vnum = 29652;
    else if (!str_cmp(arg2,"helmet"   ) && !str_cmp(arg,"black")) vnum = 29653;
    else if (!str_cmp(arg2,"leggings" ) && !str_cmp(arg,"black")) vnum = 29654;
    else if (!str_cmp(arg2,"boots"    ) && !str_cmp(arg,"black")) vnum = 29655;
    else if (!str_cmp(arg2,"gauntlets") && !str_cmp(arg,"black")) vnum = 29656;
    else if (!str_cmp(arg2,"sleeves"  ) && !str_cmp(arg,"black")) vnum = 29657;
    else if (!str_cmp(arg2,"cape"     ) && !str_cmp(arg,"black")) vnum = 29658;
    else if (!str_cmp(arg2,"belt"     ) && !str_cmp(arg,"black")) vnum = 29659;
    else if (!str_cmp(arg2,"bracer"   ) && !str_cmp(arg,"black")) vnum = 29660;
    else if (!str_cmp(arg2,"visor"    ) && !str_cmp(arg,"black")) vnum = 29661;
    else if (!str_cmp(arg2,"ring"     ) && !str_cmp(arg,"red")) vnum = 27650;
    else if (!str_cmp(arg2,"collar"   ) && !str_cmp(arg,"red")) vnum = 27651;
    else if (!str_cmp(arg2,"plate"    ) && !str_cmp(arg,"red")) vnum = 27652;
    else if (!str_cmp(arg2,"helmet"   ) && !str_cmp(arg,"red")) vnum = 27653;
    else if (!str_cmp(arg2,"leggings" ) && !str_cmp(arg,"red")) vnum = 27654;
    else if (!str_cmp(arg2,"boots"    ) && !str_cmp(arg,"red")) vnum = 27655;
    else if (!str_cmp(arg2,"gauntlets") && !str_cmp(arg,"red")) vnum = 27656;
    else if (!str_cmp(arg2,"sleeves"  ) && !str_cmp(arg,"red")) vnum = 27657;
    else if (!str_cmp(arg2,"cape"     ) && !str_cmp(arg,"red")) vnum = 27658;
    else if (!str_cmp(arg2,"belt"     ) && !str_cmp(arg,"red")) vnum = 27659;
    else if (!str_cmp(arg2,"bracer"   ) && !str_cmp(arg,"red")) vnum = 27660;
    else if (!str_cmp(arg2,"visor"    ) && !str_cmp(arg,"red")) vnum = 27661;
    else if (!str_cmp(arg2,"longsword") && !str_cmp(arg,"red")) vnum = 29662;
    else if (!str_cmp(arg2,"shortsword") && !str_cmp(arg,"red")) vnum = 29663;
    else
    {
	send_to_char("Please specify which piece of demon armor you wish to make: Ring Collar\n\rPlate Helmet Leggings Boots Gauntlets Sleeves Cape Belt Bracer Visor.\n\r",ch);
	return;
    }
    if ( (ch->pcdata->stats[DEMON_TOTAL] < 5000 || ch->pcdata->stats[DEMON_CURRENT] < 5000)
         && !str_cmp(arg,"black"))
    {
	send_to_char("It costs 5000 points of power to create a piece of black demon
armour.\n\r",ch);
	return;
    }
    else if ( (ch->pcdata->stats[DEMON_TOTAL] < 15000 ||
ch->pcdata->stats[DEMON_CURRENT] <
15000)
         && !str_cmp(arg,"red"))
    {
     send_to_char("It costs 15000 points of power to create a piece of red
demon
armour.\n\r",ch);
     return;
    }

    if ( vnum == 0 || (pObjIndex = get_obj_index( vnum )) == NULL)
    {
	send_to_char("Missing object, please inform KaVir.\n\r",ch);
	return;
    }
    if ( !str_cmp(arg,"black") )
    {
    ch->pcdata->stats[DEMON_TOTAL]   -= 5000;
    ch->pcdata->stats[DEMON_CURRENT] -= 5000;
    }
    else if ( !str_cmp(arg,"red") )
    {
    ch->pcdata->stats[DEMON_TOTAL]   -= 15000;
    ch->pcdata->stats[DEMON_CURRENT] -= 15000;
    }
    obj = create_object(pObjIndex, 50);
    obj_to_char(obj, ch);
    act("$p appears in your hands in a blast of flames.",ch,obj,NULL,TO_CHAR);
    act("$p appears in $n's hands in a blast of flames.",ch,obj,NULL,TO_ROOM);
    return;
}

void do_travel( CHAR_DATA *ch, char *argument )
{
    char      arg [MAX_INPUT_LENGTH];
    CHAR_DATA *victim;

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if (IS_CLASS(ch, CLASS_DEMON) || IS_SET(ch->special, SPC_CHAMPION))
    {
	if (!IS_DEMPOWER( ch, DEM_TRAVEL))
	{
	    send_to_char("You haven't been granted the gift of travel.\n\r",ch);
	    return;
	}
    }
    else
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }

    if ( ( victim = get_char_world( ch, arg ) ) == NULL )
    {
	send_to_char( "Nobody by that name.\n\r", ch );
	return;
    }

    if ( IS_NPC(victim) )
    {
	send_to_char( "Not on NPC's.\n\r", ch );
	return;
    }

    if (IS_IMMUNE(victim, IMM_TRAVEL))
    {
	send_to_char("I don't think they want you to do that.\n\r",ch);
	return;
    }   

    if ( victim == ch ) {
		send_to_char( "Nothing happens.\n\r", ch);
		return; }

    if ( victim->level != LEVEL_AVATAR || 
	(!IS_SET(victim->special, SPC_CHAMPION) && !IS_CLASS(victim, CLASS_DEMON)))
    {
	send_to_char( "Nothing happens.\n\r", ch );
	return;
    }
/*
    if ( IS_CLASS(victim, CLASS_DEMON) && str_cmp(ch->lord, victim->name) )
    {
	send_to_char( "Nothing happens.\n\r", ch );
	return;
    }
    else if ( IS_SET(victim->special, SPC_CHAMPION) &&
	(str_cmp(victim->lord, ch->name) && str_cmp(victim->lord, ch->lord) ))
    {
	send_to_char( "Nothing happens.\n\r", ch );
	return;
    }
*/
    if (victim->in_room == NULL)
    {
	send_to_char( "Nothing happens.\n\r", ch );
	return;
    }

/*
    if ( victim->position != POS_STANDING )
    {
	send_to_char( "You are unable to focus on their location.\n\r", ch );
	return;
    }
*/
    send_to_char("You sink into the ground.\n\r",ch);
    act("$n sinks into the ground.",ch,NULL,NULL,TO_ROOM);
    char_from_room(ch);
    char_to_room(ch,victim->in_room);
    do_look(ch,"");
    send_to_char("You rise up out of the ground.\n\r",ch);
    act("$n rises up out of the ground.",ch,NULL,NULL,TO_ROOM);
    return;
}

void do_horns( CHAR_DATA *ch, char *argument )
{
    char      arg [MAX_INPUT_LENGTH];

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch,CLASS_VAMPIRE) && !IS_CLASS(ch, CLASS_DEMON) 
    && !IS_SET(ch->special,SPC_CHAMPION))
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }
    if (!IS_DEMPOWER( ch, DEM_HORNS) && IS_CLASS(ch,CLASS_DEMON))
    {
	send_to_char("You haven't been granted the gift of horns.\n\r",ch);
	return;
    }
    else if (IS_CLASS(ch,CLASS_VAMPIRE) && !IS_VAMPAFF(ch,VAM_VICISSITUDE) )
    {
	send_to_char("You have not mastered the Vicissitude discipline.\n\r", ch);
	return;
    }

    if (IS_DEMAFF(ch,DEM_HORNS) )
    {
	send_to_char("Your horns slide back into your head.\n\r",ch);
	act("$n's horns slide back into $s head.", ch, NULL, NULL, TO_ROOM);
	REMOVE_BIT(ch->pcdata->powers[DPOWER_CURRENT], DEM_HORNS);
	return;
    }
    send_to_char("Your horns extend out of your head.\n\r",ch);
    act("A pair of pointed horns extend from $n's head.", ch, NULL, NULL, TO_ROOM);
    SET_BIT(ch->pcdata->powers[DPOWER_CURRENT], DEM_HORNS);
    return;
}
void do_tail( CHAR_DATA *ch, char *argument )
{
    char      arg [MAX_INPUT_LENGTH];

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch, CLASS_DEMON))
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }
    if (!IS_DEMPOWER( ch, DEM_TAIL))
    {
	send_to_char("You haven't been granted the gift of a tail.\n\r",ch);
	return;
    }

    if (IS_DEMAFF(ch,DEM_TAIL) )
    {
	send_to_char("Your tail slides back into your back.\n\r",ch);
	act("$n's tail slides back into $s back.", ch, NULL, NULL, TO_ROOM);
	REMOVE_BIT(ch->pcdata->powers[DPOWER_CURRENT], DEM_TAIL);
	return;
    }

    send_to_char("Your tail slides out of your back side.\n\r",ch);
    act("A huge tail extends from $n's back.", ch, NULL, NULL, TO_ROOM);
    SET_BIT(ch->pcdata->powers[DPOWER_CURRENT], DEM_TAIL);
    return;
}

/*moved*/
void do_hooves( CHAR_DATA *ch, char *argument )
{
    char      arg [MAX_INPUT_LENGTH];

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch, CLASS_DEMON))
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }
    if (!IS_DEMPOWER( ch, DEM_HOOVES))
    {
	send_to_char("You haven't been granted the gift of horns.\n\r",ch);
	return;
    }

    if (IS_DEMAFF(ch,DEM_HOOVES) )
    {
	send_to_char("Your hooves transform into feet.\n\r",ch);
	act("$n's hooves transform back into $s feet.", ch, NULL,NULL,TO_ROOM);
	REMOVE_BIT(ch->pcdata->powers[DPOWER_CURRENT], DEM_HOOVES);
	return;
    }
    send_to_char("Your feet transform into hooves.\n\r",ch);
    act("$n's feet transform into hooves.", ch, NULL, NULL, TO_ROOM);
    SET_BIT(ch->pcdata->powers[DPOWER_CURRENT], DEM_HOOVES);
    return;
}

void do_wings( CHAR_DATA *ch, char *argument )
{
    char      arg [MAX_INPUT_LENGTH];

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch, CLASS_DEMON) && !IS_SET(ch->special, SPC_CHAMPION))
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }
    if (!IS_DEMPOWER( ch, DEM_WINGS))
    {
	send_to_char("You haven't been granted the gift of wings.\n\r",ch);
	return;
    }

    if (arg[0] != '\0')
    {
	if (!IS_DEMAFF(ch,DEM_WINGS) )
	{
	    send_to_char("First you better get your wings out!\n\r",ch);
	    return;
	}
	if (!str_cmp(arg,"unfold") || !str_cmp(arg,"u"))
	{
	    if (IS_DEMAFF(ch,DEM_UNFOLDED) )
	    {
		send_to_char("But your wings are already unfolded!\n\r",ch);
		return;
	    }
	    send_to_char("Your wings unfold from behind your back.\n\r",ch);
	    act("$n's wings unfold from behind $s back.", ch, NULL, NULL, TO_ROOM);
	    SET_BIT(ch->pcdata->powers[DPOWER_CURRENT], DEM_UNFOLDED);
	    return;
	}
	else if (!str_cmp(arg,"fold") || !str_cmp(arg,"f"))
	{
	    if (!IS_DEMAFF(ch,DEM_UNFOLDED) )
	    {
		send_to_char("But your wings are already folded!\n\r",ch);
		return;
	    }
	    send_to_char("Your wings fold up behind your back.\n\r",ch);
	    act("$n's wings fold up behind $s back.", ch, NULL, NULL, TO_ROOM);
	    REMOVE_BIT(ch->pcdata->powers[DPOWER_CURRENT], DEM_UNFOLDED);
	    return;
	}
	else
	{
	    send_to_char("Do you want to FOLD or UNFOLD your wings?\n\r",ch);
	    return;
	}
    }

    if (IS_DEMAFF(ch,DEM_WINGS) )
    {
	if (IS_DEMAFF(ch,DEM_UNFOLDED) )
	{
	    send_to_char("Your wings fold up behind your back.\n\r",ch);
	    act("$n's wings fold up behind $s back.", ch, NULL, NULL, TO_ROOM);
	    REMOVE_BIT(ch->pcdata->powers[DPOWER_CURRENT], DEM_UNFOLDED);
	}
	send_to_char("Your wings slide into your back.\n\r",ch);
	act("$n's wings slide into $s back.", ch, NULL, NULL, TO_ROOM);
	REMOVE_BIT(ch->pcdata->powers[DPOWER_CURRENT], DEM_WINGS);
	return;
    }
    send_to_char("Your wings extend from your back.\n\r",ch);
    act("A pair of wings extend from $n's back.", ch, NULL, NULL, TO_ROOM);
    SET_BIT(ch->pcdata->powers[DPOWER_CURRENT], DEM_WINGS);
    return;
}

void do_lifespan( CHAR_DATA *ch, char *argument )
{
    char      arg [MAX_INPUT_LENGTH];
    OBJ_DATA *obj;

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch,CLASS_DEMON) && !IS_SET(ch->special,SPC_CHAMPION))
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }

    if (!IS_DEMPOWER( ch, DEM_LIFESPAN))
    {
	send_to_char("You haven't been granted the gift of lifespan.\n\r",ch);
	return;
    }

    if ( ( obj = ch->pcdata->chobj ) == NULL )
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }

    if ( obj->chobj == NULL || obj->chobj != ch )
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }

    if (!IS_HEAD(ch,LOST_HEAD))
    {
	send_to_char("You cannot change your lifespan in this form.\n\r",ch);
	return;
    }

         if (!str_cmp(arg,"l") || !str_cmp(arg,"long" )) obj->timer = 0;
    else if (!str_cmp(arg,"s") || !str_cmp(arg,"short")) obj->timer = 1;
    else
    {
	send_to_char("Do you wish to have a long or short lifespan?\n\r",ch);
	return;
    }
    send_to_char("Ok.\n\r",ch);

    return;
}

void do_pact( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char      arg [MAX_INPUT_LENGTH];
    bool      can_sire = FALSE;

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch, CLASS_DEMON) && !IS_SET(ch->special, SPC_CHAMPION))
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }

    if (IS_CLASS(ch, CLASS_DEMON)) can_sire = TRUE;

    if (!can_sire)
    {
	send_to_char("You are not able to make a pact.\n\r",ch);
	return;
    }

    if ( arg[0] == '\0' )
    {
	send_to_char( "Make a pact with whom?\n\r", ch );
	return;
    }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( IS_NPC(victim) )
    {
	send_to_char( "Not on NPC's.\n\r", ch );
	return;
    }

    if ( ch == victim )
    {
	send_to_char( "You cannot make a pact with yourself.\n\r", ch );
	return;
    }

	if (victim->class != 0) {
	send_to_char("Not on them!\n\r", ch );
	return;}

    if ( victim->level != LEVEL_AVATAR && !IS_IMMORTAL(victim) )
    {
	send_to_char( "You can only make pacts with avatars.\n\r", ch );
	return;
    }

    if (!IS_IMMUNE(victim,IMM_DEMON))
    {
	send_to_char( "You cannot make a pact with an unwilling person.\n\r", ch );
	return;
    }

    if (ch->exp < 666)
    {
	send_to_char("You cannot afford the 666 exp to make a pact.\n\r",ch);
	return;
    }

	if (!IS_EVIL(victim)) {
	send_to_char("They must be evil!\n\r", ch );
		return;}

    ch->exp = ch->exp - 666;
    act("You make $N a demonic champion!", ch, NULL, victim, TO_CHAR);
    act("$n makes $N a demonic champion!", ch, NULL, victim, TO_NOTVICT);
    act("$n makes you a demonic champion!", ch, NULL, victim, TO_VICT);
    victim->class=0;
    victim->class=CLASS_DEMON;
    SET_BIT(victim->special, SPC_CHAMPION);

    if (IS_CLASS(victim, CLASS_VAMPIRE)) do_mortalvamp(victim,"");
    REMOVE_BIT(victim->act, PLR_HOLYLIGHT);
    REMOVE_BIT(victim->act, PLR_WIZINVIS);
    victim->pcdata->stats[UNI_RAGE] = 0;

    free_string(victim->morph);

    save_char_obj(ch);
    save_char_obj(victim);
    return;
}

void do_offersoul( CHAR_DATA *ch, char *argument )
{
    char      arg [MAX_INPUT_LENGTH];
    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if (!IS_IMMUNE(ch, IMM_DEMON))
    {
/*
	send_to_char("That would be a very bad idea...\n\r",ch);
	return;
*/
	send_to_char("You will now allow demons to buy your soul.\n\r",ch);
	SET_BIT(ch->immune, IMM_DEMON);
	return;
  
    }
    send_to_char("You will no longer allow demons to buy your soul.\n\r",ch);
    REMOVE_BIT(ch->immune, IMM_DEMON);
    return;
}

void do_weaponform( CHAR_DATA *ch, char *argument )
{
    OBJ_DATA *obj;
    if (IS_NPC(ch)) return;
    if (!IS_CLASS(ch, CLASS_DEMON) && !IS_SET(ch->special, SPC_CHAMPION))
    {
	send_to_char( "Huh?\n\r", ch);
	return;
    }
    else if (IS_AFFECTED(ch,AFF_POLYMORPH))
    {
	send_to_char( "You cannot do this while polymorphed.\n\r", ch);
	return;
    }
   

    if (IS_SET(ch->warp, WARP_WEAPON))
	ch->pcdata->powers[DPOWER_OBJ_VNUM] = OBJ_VNUM_KHORNE;

    if (ch->pcdata->powers[DPOWER_OBJ_VNUM] < 1)
    {
	send_to_char( "You don't have the ability to change into a weapon.\n\r", ch);
	return;
    }
    if ((obj = create_object(get_obj_index(ch->pcdata->powers[DPOWER_OBJ_VNUM]),60)) == NULL)
    {
	send_to_char( "You don't have the ability to change into a weapon.\n\r", ch);
	return;
    }
    if (IS_AFFECTED(ch,AFF_WEBBED))
    {
	send_to_char( "Not with all this sticky webbing on.\n\r", ch);
	return;
    }
    obj_to_room(obj,ch->in_room);
    act("$n transforms into $p and falls to the ground.",ch,obj,NULL,TO_ROOM);
    act("You transform into $p and fall to the ground.",ch,obj,NULL,TO_CHAR);
    ch->pcdata->obj_vnum = ch->pcdata->powers[DPOWER_OBJ_VNUM];
    obj->chobj = ch;
    ch->pcdata->chobj = obj;
    SET_BIT(ch->affected_by, AFF_POLYMORPH);
    SET_BIT(ch->extra, EXTRA_OSWITCH);
    free_string(ch->morph);
    ch->morph = str_dup(obj->short_descr);
    return;
}

void do_humanform( CHAR_DATA *ch, char *argument )
{
    OBJ_DATA *obj;

    if (IS_NPC(ch)) return;
    if ( ( obj = ch->pcdata->chobj ) == NULL )
    {
	send_to_char("You are already in human form.\n\r",ch);
	return;
    }

    ch->pcdata->obj_vnum = 0;
    obj->chobj = NULL;
    ch->pcdata->chobj = NULL;
    REMOVE_BIT(ch->affected_by, AFF_POLYMORPH);
    REMOVE_BIT(ch->extra, EXTRA_OSWITCH);
    free_string(ch->morph);
    ch->morph = str_dup("");
    act("$p transforms into $n.",ch,obj,NULL,TO_ROOM);
    act("Your reform your human body.",ch,obj,NULL,TO_CHAR);
    extract_obj(obj);
    if (ch->in_room->vnum == ROOM_VNUM_IN_OBJECT)
    {
	char_from_room(ch);
	char_to_room(ch,get_room_index(ROOM_VNUM_HELL));
    }
    return;
}

void do_champions( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    char lord[MAX_INPUT_LENGTH];
    CHAR_DATA *gch;

    one_argument( argument, arg );

    if (IS_NPC(ch)) return;
    if (!IS_CLASS(ch, CLASS_DEMON) && !IS_SET(ch->special, SPC_CHAMPION) )
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }

    if (strlen(ch->lord) < 2 && !IS_CLASS(ch, CLASS_DEMON) )
    {
	send_to_char("But you don't follow any demon!\n\r",ch);
	return;
    }

    if (IS_CLASS(ch, CLASS_DEMON)) strcpy(lord,ch->name);
	else strcpy(lord,ch->lord);
    sprintf( buf, "The champions of %s:\n\r", lord );
    send_to_char( buf, ch );
    send_to_char("[      Name      ] [ Hits ] [ Mana ] [ Move ] [  Exp  ] [       Power
]\n\r", ch );
    for ( gch = char_list; gch != NULL; gch = gch->next )
    {
	if ( IS_NPC(gch) ) continue;
	if ( !IS_CLASS(gch, CLASS_DEMON) && !IS_SET(gch->special, SPC_CHAMPION) ) 
	    continue;
	if ( !str_cmp(ch->lord,lord) || !str_cmp(ch->name,lord))
	{
	    sprintf( buf,
	    "[%-16s] [%-6d] [%-6d] [%-6d] [%7d] [ %-9d%9d ]\n\r",
		capitalize( gch->name ),
		gch->hit,gch->mana,gch->move,
		gch->exp, gch->pcdata->stats[DEMON_CURRENT], gch->pcdata->stats[DEMON_TOTAL]);
		send_to_char( buf, ch );
	}
    }
    return;
}


void do_eyespy( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    CHAR_DATA *familiar;

    if (IS_HEAD(ch,LOST_EYE_L) && IS_HEAD(ch,LOST_EYE_R))
    {
	send_to_char( "But you don't have any more eyes to pluck out!\n\r", ch );
	return;
    }
    if (!IS_HEAD(ch,LOST_EYE_L) && number_range(1,2) == 1)
    {
	act( "You pluck out your left eyeball and throw it to the ground.", ch, NULL, NULL, TO_CHAR );
	act( "$n plucks out $s left eyeball and throws it to the ground.", ch, NULL, NULL, TO_ROOM );
    }
    else if (!IS_HEAD(ch,LOST_EYE_R))
    {
	act( "You pluck out your right eyeball and throw it to the ground.", ch, NULL, NULL, TO_CHAR );
	act( "$n plucks out $s right eyeball and throws it to the ground.", ch, NULL, NULL, TO_ROOM );
    }
    else
    {
	act( "You pluck out your left eyeball and throw it to the ground.", ch, NULL, NULL, TO_CHAR );
	act( "$n plucks out $s left eyeball and throws it to the ground.", ch, NULL, NULL, TO_ROOM );
    }
    if ( ( familiar = ch->pcdata->familiar ) != NULL ) 
    {
	make_part(ch,"eyeball");
	return;
    }

    victim = create_mobile( get_mob_index( MOB_VNUM_EYE ) );
    if (victim == NULL)
    {send_to_char("Error - please inform KaVir.\n\r",ch); return;}

    char_to_room( victim, ch->in_room );

    ch->pcdata->familiar = victim;
    victim->wizard = ch;
    return;
}


/*
void do_gifts( CHAR_DATA *ch, char *argument )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    int improve;
    int cost;
    int max;

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch, CLASS_DEMON))
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }

    if (arg1[0] == '\0' && arg2[0] == '\0')
    {
	sprintf(buf,"Gifts: Strength of Satan, Speed of Satan, Stake, Cone of fire, True Form\n\r");
	send_to_char(buf,ch);
	return;
    }
    if (arg2[0] == '\0')
    {
	if (!str_cmp(arg1,"Strength"))
	{
	    send_to_char("Strength of Satan: You are as strong as your creator.\n\r",ch);
	    return;
	}
	else if (!str_cmp(arg1,"Speed"))
	{
	    send_to_char("Speed: The Speed of satan you dodge most attacks wth incredible speed.\n\r",ch);
	    return;
	}
	else if (!str_cmp(arg1,"Stake"))
	{
	    send_to_char("Stake: You have the ability to make a silver stake.\n\r",ch);
	    return;
	}
	else if (!str_cmp(arg1,"Cone"))
	{
	    send_to_char("Cone: You have the power to breath a cone fo fire.\n\r",ch);
	    return;
	}
	else if (!str_cmp(arg1,"Form"))
	{
	    send_to_char("Form: The power to go into true demon form.\n\r",ch);
	    return;
	}
	
	sprintf(buf,"Gifts: Strength of Satan, Speed of Satan, Stake, Cone of fire, True Form\n\r");
        send_to_char(buf,ch);
	return;
    }
    if (!str_cmp(arg2,"improve"))
    {
	     if (!str_cmp(arg1,"strength"   )) {improve = DEM_STRENGTH;max=1;}
	else if (!str_cmp(arg1,"speed"   )) {improve = DEM_SPEEDY;max=1;}
	else if (!str_cmp(arg1,"stake"   )) {improve = DEM_STAKE;max=1;}
	else if (!str_cmp(arg1,"cone"    )) {improve = DEM_CONE;max=1;}
	else if (!str_cmp(arg1,"form" )) {improve = DEM_FORM;max=1;}
	else
	{
	    send_to_char("You can improve: Strength Speed Stake Cone Form\n\r",ch);
	    return;
	}
	cost = (ch->pcdata->powers[improve]+1) * 50;
	arg1[0] = UPPER(arg1[0]);
	if ( ch->pcdata->powers[improve] >= max )
	{
	    sprintf(buf,"You have already gained this gift.\n\r");
	    send_to_char(buf,ch);
	    return;
	}
	if ( cost > ch->practice )
	{
	    sprintf(buf,"It costs you %d primal to improve your gifts.\n\r", cost);
	    send_to_char(buf,ch);
	    return;
	}
       ch->pcdata->powers[improve] += 1;
       ch->practice -= cost;
       sprintf(buf,"You improve your gifts.\n\r");
       send_to_char(buf,ch);
      }
}
*/

void do_cone( CHAR_DATA *ch, char *argument ) {
    CHAR_DATA *victim;
    char arg [MAX_INPUT_LENGTH];
    int sn;
    int level;
    int spelltype;

    argument = one_argument( argument, arg );
    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch, CLASS_DEMON))
    {
        send_to_char("Huh?\n\r",ch);
        return;
    }

    if ( arg[0] == '\0' )
    {
    send_to_char("Cone who?\n\r", ch);
    return;
    }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
	if ((victim = ch->fighting) == NULL)
    {
        send_to_char( "They aren't here.\n\r", ch );
        return;
    }
	if (ch->mana < 100) {
		send_to_char("You don't have enough mana.\n\r", ch);
		return;}

    if ( ( sn = skill_lookup( "cone" ) ) < 0 ) return;
    spelltype = skill_table[sn].target;
    level = ch->spl[spelltype] * 1.0;
	level = level * 1.0;
	act("You Blast $N with a cone of fire.",ch,NULL,victim,TO_CHAR);
	act("$n Blasts you with a cone of fire.",ch,NULL,victim,TO_VICT);
    (*skill_table[sn].spell_fun) ( sn, level, ch, victim );
    WAIT_STATE( ch, 10 );
	ch->mana = ch->mana - 100;
    return;
}

void do_dstake( CHAR_DATA *ch, char *argument )

{
OBJ_DATA *obj;

if (IS_NPC(ch)) return;

if (!IS_CLASS(ch, CLASS_DEMON))
    {

send_to_char("Huh?\n\r",ch);
return;
}

if ( 60 > ch->practice)
{
send_to_char("It costs 60 points of primal to create a stake.\n\r",ch);
return;
}
ch->practice   -= 60;
obj = create_object(get_obj_index(OBJ_VNUM_STAKE)  ,0 );
if (IS_SET(obj->quest, QUEST_ARTIFACT))
REMOVE_BIT(obj->quest, QUEST_ARTIFACT);
obj_to_char(obj, ch);
act("A Stake appears in your hands in a flash of
light.",ch,NULL,NULL,TO_CHAR);
act("A Stake appears in $n's hands in a flash of
light.",ch,NULL,NULL,TO_ROOM);
return;
}




 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
 *                                                                         *
 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
 *  Chastain, Michael Quan, and Mitchell Tse.                              *
 *                                                                         *
 *  In order to use any part of this Merc Diku Mud, you must comply with   *
 *  both the original Diku license in 'license.doc' as well the Merc       *
 *  license in 'license.txt'.  In particular, you may not remove either of *
 *  these copyright notices.                                               *
 *                                                                         *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 ***************************************************************************/

#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"
#include "player.h"

/*
 * Local functions.
 */

void do_grant( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char      arg1 [MAX_INPUT_LENGTH];
    char      arg2 [MAX_INPUT_LENGTH];
    int       inpart = 0;
    int       cost = 0;

    smash_tilde(argument);
    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch, CLASS_DROW))
    {
	    send_to_char("Huh?\n\r",ch);
	    return;
    }

    if ( arg1[0] == '\0' || arg2[0] == '\0' )
    {
	send_to_char( "Syntax: Grant <person> <power>\n\r", ch );
	send_to_char("Drowfire (2500),  Darkness (7500),  Drowpoison (2500).\n\r",ch);
	send_to_char("Drowsight (5000),  Drowshield (5000),  Levitation (1000).\n\r", ch );
	send_to_char("Shadowwalk (10000),  Garotte (5000),  Spiderarms (7500).\n\r", ch );
	send_to_char("Drowhate (10000),  Spiderform (15000),  Web (5000).\n\r",ch );
	send_to_char("Dgarotte (2500),  Confuse (2500),  Glamour (5000).\n\r", ch );
	send_to_char("Earthshatter (7500),  Speed (7500),  Toughskin (7500).\n\r", ch );
	send_to_char("Warrior (0), Mage (0), Cleric (0).\n\r", ch );
	return;
    }

    if ( ( victim = get_char_world( ch, arg1 ) ) == NULL )
    {
	send_to_char( "Nobody by that name.\n\r", ch );
	return;
    }

    if ( IS_NPC(victim) )
    {
	send_to_char( "Not on NPC's.\n\r", ch );
	return;
    }


    if (!str_cmp(arg2,"mage") || !str_cmp(arg2,"warrior") || !str_cmp(arg2, "cleric" ))
    {
	if (victim->generation < 3 )
	{	send_to_char("Not on them!\n\r", ch );
		return;}

	if (!IS_CLASS(victim, CLASS_DROW)) {
		send_to_char("Only on drows.\n\r", ch );
		return;}

	if (IS_SET(victim->special, SPC_DROW_WAR) ||
	IS_SET(victim->special, SPC_DROW_MAG) ||
	IS_SET(victim->special, SPC_DROW_CLE))
  {		send_to_char( "They already have a profession.\n\r", ch );
		return;}
	if (!str_cmp(arg2, "mage"))
		SET_BIT(victim->special, SPC_DROW_MAG);
	else if (!str_cmp(arg2, "cleric"))
		SET_BIT(victim->special, SPC_DROW_CLE);
	else if (!str_cmp(arg2, "warrior"))
		SET_BIT(victim->special, SPC_DROW_WAR);
	send_to_char("You give them a profession.\n\r", ch );
	send_to_char("You have been given a profession.\n\r", victim);
	save_char_obj(victim);
	return;
    }


    if (!str_cmp(arg2,"drowfire")) 
	{inpart = DPOWER_DROWFIRE; cost = 2500;}
    else if (!str_cmp(arg2,"darkness"))
	{inpart = DPOWER_DARKNESS; cost= 7500;}
    else if (!str_cmp(arg2,"drowsight"))
	{inpart = DPOWER_DROWSIGHT; cost= 5000;}
    else if (!str_cmp(arg2,"spiderarms"))
	{inpart = DPOWER_ARMS; cost = 7500;}
    else if (!str_cmp(arg2,"web"))
	{inpart = DPOWER_WEB; cost = 5000;}
    else if (!str_cmp(arg2,"spiderform"))
	{inpart = DPOWER_SPIDERFORM; cost = 15000;}
    else if (!str_cmp(arg2,"drowhate"))
	{inpart = DPOWER_DROWHATE; cost = 10000;}
    else if (!str_cmp(arg2,"drowshield"))
     	{inpart = DPOWER_DROWSHIELD; cost = 5000;}
    else if (!str_cmp(arg2,"levitation"))
	{inpart = DPOWER_LEVITATION; cost = 1000;}
    else if (!str_cmp(arg2,"shadowwalk"))
	{inpart = DPOWER_SHADOWWALK; cost = 10000;}
    else if (!str_cmp(arg2,"garotte")) 
	{inpart = DPOWER_GAROTTE; cost = 5000;}
    else if (!str_cmp(arg2,"dgarotte"))
	{inpart = DPOWER_DGAROTTE; cost = 2500;}
    else if (!str_cmp(arg2,"drowpoison"))
	{inpart = DPOWER_DROWPOISON; cost = 2500;}
    else if (!str_cmp(arg2,"glamour"))
	{inpart = DPOWER_GLAMOUR; cost = 5000;}
    else if (!str_cmp(arg2,"confuse"))
	{inpart = DPOWER_CONFUSE; cost = 2500;}
    else if (!str_cmp(arg2,"earthshatter"))
	{inpart = DPOWER_EARTHSHATTER; cost = 7500;}
    else if (!str_cmp(arg2,"speed"))
	{inpart = DPOWER_SPEED; cost = 7500;}
   else if (!str_cmp(arg2,"toughskin"))
	{inpart = DPOWER_TOUGHSKIN; cost =7500;}
    else
    {
	send_to_char("Please select a power from:\n\r",ch);
        send_to_char("Drowfire (2500),  Darkness (7500),  Drowpoison  (1000).\n\r",ch);
	send_to_char("Drowsight (5000),  Drowshield (5000),  Levitation (1000).\n\r", ch );
	send_to_char("Shadowwalk (10000),  Garotte (5000),  Spiderarms (7500).\n\r", ch );
	send_to_char("Drowhate (10000),  Spiderform (15000),  Web (5000).\n\r",ch );
	send_to_char("Dgarotte (2500),  Confuse (2500),  Glamour (5000).\n\r", ch);
	send_to_char("Earthshatter (7500),  Speed (7500),  Toughskin (7500).\n\r", ch );

        if (ch->generation < 3) {
        send_to_char("Warrior (0), Mage (0), Cleric (0).\n\r", ch );}
	return;
    }
    if (IS_SET(victim->pcdata->powers[1], inpart))
    {
	send_to_char("They have already got that power.\n\r",ch);
	return;
    }
    if (ch->pcdata->stats[DROW_POWER] < cost) 
    {
	send_to_char("You have insufficient power to grant that gift.\n\r",ch);
	return;
    }
    SET_BIT(victim->pcdata->powers[1], inpart);
    ch->pcdata->stats[DROW_POWER]   -= cost;
    if (victim != ch) send_to_char("You have been granted a gift from your matron!\n\r",victim);
    send_to_char("Ok.\n\r",ch);
    if (victim != ch) save_char_obj(ch);
    save_char_obj(victim);
    return; 
}

void do_chaosblast(CHAR_DATA *ch, char *argument) {

    CHAR_DATA *victim;
    char arg [MAX_INPUT_LENGTH];
    int sn;
    int level;
    int spelltype;

    argument = one_argument( argument, arg );
    if (IS_NPC(ch)) return;

	if (!IS_CLASS(ch, CLASS_DROW) || (!IS_SET(ch->special,
	SPC_DROW_MAG) && ch->generation > 2)) {
		send_to_char("Huh?\n\r", ch);
		return;}

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
        if ((victim = ch->fighting) == NULL)
    {
        send_to_char( "They aren't here.\n\r", ch );
        return;
    }
        if (ch->mana < 100) {
                send_to_char("You don't have enough mana.\n\r", ch);
                return;}

    if ( ( sn = skill_lookup( "chaos blast" ) ) < 0 ) return;
    spelltype = skill_table[sn].target;
    level = ch->spl[spelltype]*3/2;
        act("You concentrate your power on $N.",ch,NULL,victim,TO_CHAR);
        act("$n concentrates $s power on you.",ch,NULL,victim,TO_VICT);
    (*skill_table[sn].spell_fun) ( sn, level, ch, victim );
    WAIT_STATE( ch, 12 );
        ch->mana = ch->mana - 100;
    return;
}


void do_drowcreate( CHAR_DATA *ch, char *argument )
{
    OBJ_INDEX_DATA *pObjIndex;
    OBJ_DATA *obj;
    char arg[MAX_INPUT_LENGTH];
    int vnum = 0;

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch, CLASS_DROW))
    {
	    send_to_char("Huh?\n\r",ch);
	    return;
    }

    if (arg[0] == '\0')
    {
	send_to_char("Please specify what kind of equipment you want to create.\n\r", ch );
	send_to_char("Whip, Dagger, Ring, Amulet, Armor, Helmet,\n\r", ch);
	send_to_char("Leggings, Boots, Gauntlets, Sleeves,\n\r", ch );
	send_to_char("Belt, Bracer, Mask, Cloak.\n\r", ch);
	return;
    }
    if      (!str_cmp(arg,"whip"     )) vnum = 29600;
    else if (!str_cmp(arg,"cloak"   )) vnum = 29613;
    else if (!str_cmp(arg,"armor"    )) vnum = 29604;
    else if (!str_cmp(arg,"boots"   )) vnum = 29607;
    else if (!str_cmp(arg,"gauntlets")) vnum = 29608;
    else if (!str_cmp(arg,"sleeves")) vnum = 29609;
    else if (!str_cmp(arg,"belt"))   vnum = 29610;
    else if (!str_cmp(arg,"helmet"))	vnum = 29605;
    else if (!str_cmp(arg,"leggings"))	vnum = 29606;
    else if (!str_cmp(arg,"mask" )) vnum = 29612;
    else if (!str_cmp(arg,"bracer"    )) vnum = 29611;
    else if (!str_cmp(arg,"dagger"	)) vnum = 29601;
    else if (!str_cmp(arg, "ring"))	vnum = 29602;
    else if (!str_cmp(arg, "amulet"))	vnum = 29603;

    else
    {
	send_to_char("That is an invalid type.\n\r", ch );
	return;
    }
    if ( ch->pcdata->stats[DROW_POWER] < 10000)
    {
	send_to_char("It costs 10000 points of power to create a piece of drow armour.\n\r",ch);
	return;
    }
    if ( vnum == 0 || (pObjIndex = get_obj_index( vnum )) == NULL)
    {
	send_to_char("Missing object, please inform KaVir.\n\r",ch);
	return;
    }
    ch->pcdata->stats[DROW_POWER] -= 10000;
    obj = create_object(pObjIndex, 50);
    obj_to_char(obj, ch);
    act("$p appears in your hands.",ch,obj,NULL,TO_CHAR);
    act("$p appears in $n's hands.",ch,obj,NULL,TO_ROOM);
    return;
}

void do_favor( CHAR_DATA *ch, char *argument )
{
    char      buf [MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    char      arg [MAX_INPUT_LENGTH];

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch, CLASS_DROW)) 
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }

    if ( arg[0] == '\0' )
    {
	send_to_char( "Give Lloth's favor to whom?\n\r", ch );
	return;
    }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( IS_NPC(victim) )
    {
	send_to_char( "Not on NPC's.\n\r", ch );
	return;
    }

    if ( ch == victim )
    {
	send_to_char("Not on yourself.\n\r", ch );
	return;
    }

    if (victim->class != 0 || IS_SET(victim->special, SPC_CHAMPION)) {
	send_to_char("You can't make a classed person a Drow.\n\r", ch);
	return;}

    if ( victim->level != LEVEL_AVATAR && !IS_IMMORTAL(victim) )
    {
	send_to_char( "Only on avatars.\n\r", ch );
	return;
    }

    if (!IS_IMMUNE(victim,IMM_DEMON))
    {
	send_to_char( "Not on an unwilling person.\n\r", ch);
	return;
    }

    if (ch->exp < 10000)
    {
	send_to_char("You cannot afford the 10,000 exp.\n\r",ch);
	return;
    }

    ch->exp = ch->exp - 10000;
    act("You make $N a drow!", ch, NULL, victim, TO_CHAR);
    act("$n makes $N a drow!", ch, NULL, victim, TO_NOTVICT);
    act("$n makes you a drow!", ch, NULL, victim, TO_VICT);
    victim->class=0;
    victim->class=CLASS_DROW;
    victim->special=0;

    if (IS_CLASS(victim, CLASS_VAMPIRE)) do_mortalvamp(victim,"");
    REMOVE_BIT(victim->act, PLR_HOLYLIGHT);
    REMOVE_BIT(victim->act, PLR_WIZINVIS);
    REMOVE_BIT(victim->special, SPC_SIRE);
    REMOVE_BIT(victim->special, SPC_ANARCH);
    victim->rage = 0;
    victim->generation = ch->generation + 1;
	victim->special = 0;
    free_string(victim->morph);
    victim->morph=str_dup("");

    free_string(victim->lord);
    if (ch->generation == 1)
        victim->lord=str_dup(ch->name);
    else
    {
        sprintf(buf,"%s %s",ch->lord,ch->name);
        victim->lord=str_dup(buf);
    }
 
    save_char_obj(ch);
    save_char_obj(victim);
    return;
}

void do_drowfire( CHAR_DATA *ch, char *argument ) {

    CHAR_DATA *victim;
    char arg [MAX_INPUT_LENGTH];
    int sn;
    int level;
    int spelltype;

	argument = one_argument(argument, arg);

	if (IS_NPC(ch)) return;

	if(!IS_CLASS(ch, CLASS_DROW) ||
!IS_SET(ch->pcdata->powers[1],DPOWER_DROWFIRE)) {
		send_to_char("Huh?\n\r", ch );
		return;}

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
        send_to_char( "They aren't here.\n\r", ch );
        return;
    }

    if ( ch == victim )
    {
        send_to_char( "Not on yourself.\n\r", ch );
        return;
    }

	if (ch->mana < 100) {
	send_to_char("You don't have enough mana.\n\r", ch );
		return;}

    if ( ( sn = skill_lookup( "drowfire" ) ) < 0 ) return;
    spelltype = skill_table[sn].target;
    level = ch->spl[spelltype] * 0.5;
    (*skill_table[sn].spell_fun) ( sn, level, ch, victim );
    WAIT_STATE( ch, 12 );
	ch->mana = ch->mana - 100;
    return;
}
void do_heal ( CHAR_DATA *ch, char *argument ) 
{
        if (IS_NPC(ch)) return;

	if (!IS_CLASS(ch, CLASS_DROW) || (!IS_SET(ch->special,SPC_DROW_CLE) && ch->generation > 2)) 
            {
		send_to_char("Huh?\n\r", ch );
		return;
            }

	if (ch->mana < 100) {
		send_to_char("You don't have enough mana.\n\r", ch );
		return;}

	ch->mana = ch->mana - 100;
	ch->hit = ch->hit + ch->spl[BLUE_MAGIC]*3/2;
	if (ch->hit > ch->max_hit) ch->hit = ch->max_hit;
	send_to_char("Lloth heals you.\n\r",ch);
	act("$n is healed by Lloth.",ch,NULL,NULL,TO_ROOM);
	WAIT_STATE(ch, 12);
	return;
}

void do_shadowwalk(CHAR_DATA *ch, char *argument)
{
	char arg[MAX_INPUT_LENGTH];
	ROOM_INDEX_DATA *location;
	CHAR_DATA *victim;

	one_argument (argument, arg);

	if (IS_NPC(ch)) return;

	if (!IS_CLASS(ch, CLASS_DROW) || !IS_SET(ch->pcdata->powers[1],DPOWER_SHADOWWALK)) {
	send_to_char("Huh?\n\r", ch );
	return;}

	if ((victim = get_char_world(ch, arg)) == NULL) {
	send_to_char("Shadowwalk to whom?\n\r", ch );
	return;}

	location = victim->in_room;

	if (ch->move < 250) {
	send_to_char("You are too tired to go shadowwalking.\n\r", ch );
	return;}

	if (!IS_NPC(victim)) {
	send_to_char("You failed.\n\r", ch );
	return;}

	if (!IS_SET(victim->in_room->room_flags, ROOM_DARK) && 
	!IS_SET(victim->in_room->room_flags, ROOM_TOTAL_DARKNESS)) {
	send_to_char("You failed.\n\r", ch );
	return;}

	act("You walk into the shadows.", ch, NULL, NULL, TO_CHAR);
	act("$n walks into the shadows.", ch, NULL, NULL, TO_ROOM);
	ch->move -= 250;
	char_from_room(ch);
	char_to_room(ch, location);
	do_look(ch, "auto");	
	act("You walk out of the shadows.", ch, NULL, NULL, TO_CHAR);
	act("$n walks out of the shadows.", ch, NULL, NULL, TO_CHAR);

	return;
}

void do_drowhate(CHAR_DATA *ch, char *argument)
{
	if (IS_NPC(ch)) return;

	if (!IS_CLASS(ch, CLASS_DROW) || !IS_SET(ch->pcdata->powers[1], DPOWER_DROWHATE))
	{send_to_char("Huh?\n\r", ch );
	return;}

	if (IS_SET(ch->newbits, NEW_DROWHATE)) {
	send_to_char("You calm your hatred.\n\r", ch );
	REMOVE_BIT(ch->newbits, NEW_DROWHATE);
	}
	else {
	send_to_char("You invoke your hatred for others.\n\r", ch );
	SET_BIT(ch->newbits, NEW_DROWHATE);
	}

	return;
}

void do_spiderform( CHAR_DATA *ch, char *argument ) 
{
	char arg[MAX_INPUT_LENGTH];
	char buf[MAX_STRING_LENGTH];
 
	argument = one_argument(argument,arg);

	if (IS_NPC(ch)) return;

	if (!IS_CLASS(ch, CLASS_DROW) || !IS_SET(ch->pcdata->powers[1], DPOWER_SPIDERFORM))
	{send_to_char("Huh?\n\r", ch );
	return;}

	if (IS_AFFECTED(ch, AFF_POLYMORPH)) 
      {
	send_to_char("You can't spiderform while changed.\n\r", ch );
	return;
      }

      if (ch->cur_form != get_normal_form(ch))
      {
	sprintf(buf, "$n morphs back into %s.", GET_PROPER_NAME(ch));
        act(buf, ch, NULL, NULL, TO_ROOM);
        stc("You return to your normal form.\n\r", ch);
        set_form(ch, get_normal_form(ch) );
        WAIT_STATE(ch, 7);
        return;   
      }

	if (ch->move < 500) {
	send_to_char("You don't have the energy to change.\n\r", ch );
	return;}


      if (ch->cur_form == get_normal_form(ch))
      {
	ch->move -= 500;
	
	act("You mutate into a giant spider.",ch,NULL,NULL,TO_CHAR);
        act("$n mutates into a giant spider.",ch,NULL,NULL,TO_ROOM);
        set_form(ch, FRM_DROWSPIDER);
	return;
    }

	return;
}


void do_drowsight(CHAR_DATA *ch, char *argument)
{
	if (IS_NPC(ch)) return;
	
	if (!IS_CLASS(ch, CLASS_DROW) || !IS_SET(ch->pcdata->powers[1],DPOWER_DROWSIGHT)) {
	send_to_char("Huh?\n\r", ch );
	return;}

    if ( IS_SET(ch->act, PLR_HOLYLIGHT) )
    {   
        REMOVE_BIT(ch->act, PLR_HOLYLIGHT);
        send_to_char( "Your senses return to normal.\n\r", ch );
    }
    else
    {
        SET_BIT(ch->act, PLR_HOLYLIGHT);
        send_to_char( "Your senses increase to incredible proportions.\n\r", ch);
    }

	return;
}

void do_drowshield(CHAR_DATA *ch, char *argument)
{

	if (IS_NPC(ch)) return;

	if (!IS_CLASS(ch, CLASS_DROW) || !IS_SET(ch->pcdata->powers[1], DPOWER_DROWSHIELD)) {
	send_to_char("Huh?\n\r", ch );
	return;}

    if (!IS_IMMUNE(ch,IMM_SHIELDED) )
    {
        send_to_char("You shield your aura from those around you.\n\r",ch);
        SET_BIT(ch->immune, IMM_SHIELDED);
        return;
    }
    send_to_char("You stop shielding your aura.\n\r",ch);
    REMOVE_BIT(ch->immune, IMM_SHIELDED);


	return;
}


void do_drowpowers(CHAR_DATA *ch,char *argument)
{
	char buf[MAX_STRING_LENGTH];

	if (IS_NPC(ch)) return;

	if (!IS_CLASS(ch, CLASS_DROW))  {
	send_to_char("Huh?\n\r", ch );
	return;}

	send_to_char("#6The powers Lloth has bestowed upon you...#n\n\r", ch );
	send_to_char("#4-----------------------------------------#n\n\r", ch );

	if (IS_SET(ch->pcdata->powers[1], DPOWER_SPEED))
	send_to_char("You move quite quickly.\n\r", ch );

	if (IS_SET(ch->pcdata->powers[1], DPOWER_TOUGHSKIN))
	send_to_char("Your skin has been toughened.\n\r", ch );

	if (IS_SET(ch->pcdata->powers[1], DPOWER_DROWFIRE))
	send_to_char("You can call Drowfire upon your enemies.\n\r", ch );

	if (IS_SET(ch->pcdata->powers[1], DPOWER_DARKNESS))
	send_to_char("You can summon a globe of darkness.\n\r", ch );

	if (IS_SET(ch->pcdata->powers[1], DPOWER_DROWSIGHT))
	send_to_char("You can use enhanced sight.\n\r", ch );

	if (IS_SET(ch->pcdata->powers[1], DPOWER_LEVITATION))
	send_to_char("You can levitate in the air.\n\r", ch );

	if (IS_SET(ch->pcdata->powers[1], DPOWER_DROWSHIELD))
	send_to_char("You can shield your aura.\n\r", ch );

	if (IS_SET(ch->pcdata->powers[1], DPOWER_DROWPOISON))
	send_to_char("You have control over deadly poisons.\n\r", ch );

	if (IS_SET(ch->pcdata->powers[1], DPOWER_SHADOWWALK))
	send_to_char("You can walk through the shadows.\n\r", ch );

	if (IS_SET(ch->pcdata->powers[1], DPOWER_GAROTTE)) 
	send_to_char("You have mastered the art of garotte.\n\r", ch );

	if (IS_SET(ch->pcdata->powers[1], DPOWER_DGAROTTE))
	send_to_char("You have dark-enhanced garotte.\n\r", ch );

	if (IS_SET(ch->pcdata->powers[1], DPOWER_ARMS))
	send_to_char("You have extra spidery arms.\n\r", ch );

	if (IS_SET(ch->pcdata->powers[1], DPOWER_DROWHATE))
	send_to_char("You can invoke the hatred of the Drow.\n\r", ch );

	if (IS_SET(ch->pcdata->powers[1], DPOWER_SPIDERFORM))
	send_to_char("You can mutate into a large spider.\n\r", ch );

	if (IS_SET(ch->pcdata->powers[1], DPOWER_WEB))
	send_to_char("You can shoot a spidery web at opponents.\n\r", ch);

	if (IS_SET(ch->pcdata->powers[1], DPOWER_GLAMOUR))
	send_to_char("You can glamourosly change the appearance of items.\n\r", ch );

	if (IS_SET(ch->pcdata->powers[1], DPOWER_CONFUSE))
	send_to_char("You can confuse your enemies during battle.\n\r", ch );

	if (IS_SET(ch->pcdata->powers[1], DPOWER_EARTHSHATTER))
	send_to_char("You can shatter the earth under your feet.\n\r", ch );

	send_to_char("\n\r", ch);
	
	if (ch->generation == 1)
	send_to_char("You are Lloth's Avatar.\n\r", ch );
	
	if (ch->generation == 2)
	send_to_char("You are a Drow Matron.\n\r", ch );
	
	if (IS_SET(ch->special, SPC_DROW_WAR))
	send_to_char("You are a Drow Warrior.\n\r", ch);

	if (IS_SET(ch->special, SPC_DROW_MAG))
	send_to_char("You are a Drow Mage.\n\r", ch );

	if (IS_SET(ch->special, SPC_DROW_CLE))
	send_to_char("You are a Drow Cleric.\n\r", ch );

        sprintf( buf, "You have %d drow power points!.\n\r",
        ch->pcdata->stats[DROW_POWER] );
        send_to_char( buf, ch );

        sprintf( buf, "You have %d points of magic resistance.\n\r", 
        ch->pcdata->stats[DROW_MAGIC] );
        send_to_char( buf, ch );

        if (weather_info.sunlight == SUN_DARK)
        send_to_char("You feel strong in the night.\n\r", ch );

	send_to_char("\n\r", ch );
	
	return;
}


void do_darkness(CHAR_DATA *ch, char *argument) 
{
	bool blah = FALSE;

	if (IS_NPC(ch)) return;

	if (!IS_CLASS(ch, CLASS_DROW) || !IS_SET(ch->pcdata->powers[1], DPOWER_DARKNESS)) {
	do_vampdarkness(ch,argument);
	return;}

	if (IS_SET(ch->newbits, NEW_DARKNESS)) {
	send_to_char("You banish your globe of darkness.\n\r", ch );
	act("The globe of darkness around $n disappears.",ch,NULL,NULL,TO_ROOM);
	REMOVE_BIT(ch->newbits, NEW_DARKNESS);
	if (ch->in_room != NULL)
	if (IS_SET(ch->in_room->room_flags, ROOM_TOTAL_DARKNESS))
	REMOVE_BIT(ch->in_room->room_flags, ROOM_TOTAL_DARKNESS);
	return;
	}

	if (ch->mana < 500) {
	send_to_char("You don't have enough mana to summon the darkness.\n\r",ch );
	return;}

	send_to_char("You summon a globe of darkness.\n\r", ch );
	act("$n summons a globe of darkness.",ch,NULL,NULL,TO_ROOM);
	ch->mana -= 500;
	if (IS_SET(ch->extra, TIED_UP)) {
		REMOVE_BIT(ch->extra, TIED_UP);
		blah = TRUE;}

	if (IS_AFFECTED(ch, AFF_WEBBED)) {
		REMOVE_BIT(ch->affected_by, AFF_WEBBED);
		blah = TRUE;}

	if (blah) send_to_char("The darkness sets you free.\n\r", ch );		

	SET_BIT(ch->newbits, NEW_DARKNESS);
	if (!IS_SET(ch->in_room->room_flags, ROOM_TOTAL_DARKNESS))
	SET_BIT(ch->in_room->room_flags, ROOM_TOTAL_DARKNESS);


	return;
}

void do_glamour(CHAR_DATA *ch, char *argument)
{

	char arg1[MAX_STRING_LENGTH];
	char arg2[MAX_STRING_LENGTH];
	OBJ_DATA *obj;

	argument=one_argument(argument,arg1);
	strcpy(arg2,argument);

	if (IS_NPC(ch)) return;
	if (!IS_CLASS(ch,CLASS_DROW) || !IS_SET(ch->pcdata->powers[1],DPOWER_GLAMOUR)) {
	send_to_char("Huh?\n\r", ch );
	return;}

	if (arg1 == NULL || arg2 == NULL)
	{send_to_char("Syntax: Glamour (item) (description)\n\r",ch);
	return;}

	if ((obj=get_obj_carry(ch,arg1)) == NULL)
	{send_to_char("You dont have that item.\n\r",ch);
	return;}

	if (strlen(arg2) > 40 || strlen(arg2) < 3)
	{send_to_char("From 3 to 40 characters please.\n\r",ch);
	return;}

	free_string(obj->name);
	obj->name = str_dup(arg2);
	free_string(obj->short_descr);
	obj->short_descr=str_dup(arg2);
	send_to_char("Ok.\n\r",ch);

	return;
}


void do_confuse(CHAR_DATA *ch, char *argument) {

	CHAR_DATA *victim;

	if (IS_NPC(ch)) return;

	if (!IS_CLASS(ch, CLASS_DROW) || !IS_SET(ch->pcdata->powers[1], DPOWER_CONFUSE)) {
	send_to_char("Huh?\n\r",  ch);
	return;}

	if ((victim = ch->fighting) == NULL) {
	send_to_char("You are not fighting anyone.\n\r",  ch);
	return;}

	if (ch->move < 75) {
	send_to_char("You need 75 move to confuse your opponent.\n\r",ch);
	return;}

	act("$n attempts to confuse you.",ch,NULL,victim,TO_VICT);
	act("You attempt to confuse $N.",ch,NULL,victim,TO_CHAR);
	act("$n attempts to confuse $N.",ch,NULL,victim,TO_NOTVICT);

	ch->move -=75;

	if ( number_percent() > 25 ) {
	send_to_char("You failed.\n\r", ch );
	return;}

	else {
		do_flee(victim,"");	
	WAIT_STATE(ch, 16);
	return;	}

	return;
}


void do_earthshatter( CHAR_DATA *ch, char *argument)
{
    CHAR_DATA *vch;
    CHAR_DATA *vch_next;
    int dam;
    int level;
    

	if (IS_NPC(ch)) return;

	if (!IS_CLASS(ch, CLASS_DROW) || !IS_SET(ch->pcdata->powers[1], DPOWER_EARTHSHATTER)) {
	send_to_char("Huh?\n\r", ch );
	return;}

	if (ch->mana < 150) {
	send_to_char("You need more mana.\n\r", ch );
	return;}

	level = ch->spl[PURPLE_MAGIC];
	ch->mana -= 150;

	send_to_char("You summon the power of the underworld, shattering the earth.\n\r", ch );
	act("$n causes the earth to shatter",ch,NULL,NULL,TO_ROOM);

    for ( vch = ch->in_room->people; vch != NULL; vch = vch_next )
    {
        vch_next = vch->next_in_room;

	if (vch == ch) continue;
            dam  = dice(level, 7 );
            if ( saves_spell( level, vch ) )
                dam /= 2;
            damage( ch, vch, dam, skill_lookup("earthquake"));
    }
	WAIT_STATE(ch, 12);
    return;
}
/* Drow hand-crossbow quarrels, by Zaphonite */
/* Disabled till i finish
void do_dartcreate( CHAR_DATA *ch, char *argument )
{
   char  arg[MAX_INPUT_LENGTH];
   int   cost = 0;
   argument=one_argument(argument,arg);

   if (( arg[0] == '\0' ))
   {
	send_to_char("Please select type of dart.\n\r",ch);
	stc("Poison (1000), Electrical(1500), Paralysis(2000), Flaming(2500).\n\r",ch);
	stc("Explosive(3000), */



/***************************************************************************
 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
 *                                                                         *
 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
 *  Chastain, Michael Quan, and Mitchell Tse.                              *
 *                                                                         *
 *  In order to use any part of this Merc Diku Mud, you must comply with   *
 *  both the original Diku license in 'license.doc' as well the Merc       *
 *  license in 'license.txt'.  In particular, you may not remove either of *
 *  these copyright notices.                                               *
 *                                                                         *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 ***************************************************************************/

#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"

#define MONK_AUTODROP 11


/*
 * Local functions.
 */
void    autodrop        args( ( CHAR_DATA *ch) );
bool    check_dodge     args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dt ) );
void    check_killer    args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
bool    check_parry     args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dt ) );
void    dam_message     args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dam, int dt ) );
void    death_cry       args( ( CHAR_DATA *ch ) );
void    group_gain      args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
int     xp_compute      args( ( CHAR_DATA *gch, CHAR_DATA *victim ) );
void    set_fighting    args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
bool    can_counter     args( ( CHAR_DATA *ch) );
bool    can_bypass      args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
int     number_attacks  args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
int     dambonus        args( ( CHAR_DATA *ch, CHAR_DATA *victim, 
                            int dam, int stance) );
void    update_damcap   args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
void    check_arena     args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
void    check_wrestle   args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );

/*
 * Control the fights going on.
 * Called periodically by update_handler.
 */
void violence_update( void )
{
    CHAR_DATA *ch;
    CHAR_DATA *ch_next;
    CHAR_DATA *emb;
    CHAR_DATA *victim;
    CHAR_DATA *rch;
    CHAR_DATA *rch_next;
    CHAR_DATA *mount;
    //OBJ_DATA  *obj;
  
    for ( ch = char_list; ch != NULL; ch = ch->next )
    {
        victim = ch->blinkykill; 

        if (victim == NULL) continue;

        if (IS_SET(ch->flag3, AFF3_BLINK_1ST_RD))
        {
            REMOVE_BIT(ch->flag3, AFF3_BLINK_1ST_RD);
            SET_BIT(ch->flag3, AFF3_BLINK_2ND_RD);
        }
        else if (IS_SET(ch->flag3, AFF3_BLINK_2ND_RD))
        {

            REMOVE_BIT(ch->flag3, AFF3_BLINK_2ND_RD);
            REMOVE_BIT(ch->flag3, AFF3_BLINK_1ST_RD);

            /* Has the victim left? */
            if (victim->in_room != ch->in_room)
            {
                victim = NULL;
                act("$n pops back into existence.", ch, NULL, NULL, TO_ROOM);
                stc("You pop back into existence.\n\r", ch);
                stc("Your victim is no longer in the room.\n\r", ch);
                break;
            }


            act("$n pops back into existence next to $N.", ch,
NULL,victim, TO_NOTVICT);
            act("You pop back into existence next to $N.", ch, NULL,
victim, TO_CHAR);
            act("$n pops back into existence next to you.", ch, NULL,
victim, TO_VICT);
            set_fighting(ch, victim);
            do_say(ch, "Muhahahahahaha");
            victim = NULL;
            multi_hit(ch, victim, gsn_blinky);
            multi_hit(ch, victim, gsn_blinky);
            if (IS_SET(ch->newbits, THIRD_HAND) && get_eq_char(ch, WEAR_THIRD) != NULL )
            multi_hit(ch, victim, gsn_blinky);
            if (IS_SET(ch->newbits, FOURTH_HAND) && get_eq_char(ch, WEAR_FOURTH) != NULL)
            multi_hit(ch, victim, gsn_blinky);
            update_pos(victim);
        }
    }


    for ( ch = char_list; ch != NULL; ch = ch->next )
    {
        ch_next = ch->next;

        if (ch->fight_timer > 0)
                ch->fight_timer--;

        if (ch->rage > 0 && IS_CLASS(ch, CLASS_DEMON))
            ch->rage--;

        if ( ch->embracing != NULL )
        {
          emb = ch->embracing;
          if ( emb == NULL ) ch->embracing = NULL;
          if ( ch->in_room != emb->in_room )
          {
            if ( emb->embraced != NULL )
            {
              emb->embraced = NULL;
              ch->embracing = NULL;
            }
            else
              ch->embracing = NULL;
          }
        }

        if ( ch->embraced != NULL )
        {
          emb = ch->embraced;
          if ( emb == NULL ) ch->embraced = NULL;
          if ( ch->in_room != emb->in_room )
          {
            if ( emb->embracing != NULL )
            {
              emb->embracing = NULL;
              ch->embraced   = NULL;
            }
            else
              ch->embraced = NULL;
          }
        }  
  
        if ( IS_SET(ch->monkstuff, MONK_DEATH) )
        {
          if ( ch->hit > (ch->max_hit /2 ) )
          {
              ch->hit -=  number_range( 50,200 );
              stc("Your writhe in agony as magical energies tear you asunder.\n\r",ch);
              act("$n writhes in agony as magical forces tear apart $s body.",ch,NULL,NULL,TO_ROOM);
          }               
          else
          {
              if ( number_range( 1,2 ) == 1 )
              {
                 stc("You feel the magical forces leave your body.\n\r",ch);
                 act("The magical forces leave $n's body.",ch,NULL,NULL,TO_ROOM);
                 REMOVE_BIT(ch->monkstuff, MONK_DEATH);
            }
              else
              {
                  ch->hit -=  number_range( 50,200 );
                  stc("Your writhe in agony as magical energies tear you asunder.\n\r",ch);
                  act("$n writhes in agony as magical forces tear apart $s body.",ch,NULL,NULL,TO_ROOM); 
              }
           }
        }

        if ( IS_SET(ch->monkstuff, MONK_HEAL) )
        {
          if ( ch->hit < (ch->max_hit /2 ) )
          {
            if ( ch->hit < ch->max_hit )
              ch->hit +=  number_range( 200,400 );
            if ( ch->move < ch->max_move )
              ch->move += number_range( 175,400 );
              stc("Your body emits glowing sparks.\n\r",ch);
              act("$n's body emits glowing sparks and fizzes.",ch,NULL,NULL,TO_ROOM);
          }               
          else
          {
              if ( number_range( 1,2 ) == 1 )
              {
                 stc("The sparks fizzle and die.\n\r",ch);
                 act("The sparks around $n's body fizzle and die.",ch,NULL,NULL,TO_ROOM);
                 REMOVE_BIT(ch->monkstuff, MONK_HEAL);
              }
              else
              {
               if ( ch->hit < ch->max_hit )
                 ch->hit +=  number_range( 200,400 );
               if ( ch->move < ch->max_move )
                 ch->move += number_range( 175,400 );
                 stc("Your body emits glowing sparks.\n\r",ch);
                 act("$n's body emits glowing sparks and fizzes.",ch,NULL,NULL,TO_ROOM);
              }
           }
        }

/*
        if ( ( victim = ch->fighting ) == NULL || ch->in_room == NULL )
            continue;

        if (!IS_NPC(ch) && !IS_NPC(victim) && !is_safe(ch, victim) &&
!is_safe(victim,ch))
                ch->fight_timer = 10;
*/

        if (IS_CLASS(ch, CLASS_MONK)
          && ch->level < 7 && IS_SET(ch->act, PLR_WIZINVIS) )
        REMOVE_BIT(ch->act, PLR_WIZINVIS);

/*        if (!IS_CLASS(ch, CLASS_DEMON) && ch->alignment > 0
                && !IS_NPC(ch) && ch->level > 2)
        {
            OBJ_DATA *obj_next;

            for ( obj = ch->in_room->contents; obj != NULL; obj = obj_next )
            {
                obj_next = obj->next_content;
                if (IS_OBJ_STAT2(obj, ITEM_ATTACK_GOOD) && number_range(1, 3) == 1)
                {
                act("$p jumps into the air and slams into $n.", ch, obj, NULL, TO_ROOM);
                act("$p jumps into the air and slams into you.", ch, obj, NULL, TO_CHAR);
                    ch->hit -= number_range( 40, 60 );
                update_pos( ch );
                }
            }
        }
*/
        if ( IS_SET(ch->newbits, NEW_POWER) )
        {
           if ( ch->move < 75 )
             do_spiritpower(ch,"");
           else
             ch->move -= 15;
        }


      if ( ch->chi[CURRENT] > 0 )
      {
        if ( IS_CLASS(ch, CLASS_MONK) && ch->move > ( 500 - ch->chi[CURRENT] * 20 ))
            ch->move -= ch->chi[CURRENT] * 20;
        else
        {
          if ( ch->chi[CURRENT] > 0 )
          {
            stc("You feel exhausted, and lose control of your ch'i.\n\r",ch);
            ch->chi[CURRENT] -= 1;
          }
        }
      }

       if ( ( victim = ch->fighting ) == NULL || ch->in_room == NULL )
            continue;

        if (!IS_NPC(ch) && !IS_NPC(victim) && !is_safe(ch, victim) &&
!is_safe(victim,ch))
                ch->fight_timer = 10; 

        if ( IS_AWAKE(ch) && IS_AWAKE(victim) && 
                ch->in_room == victim->in_room ) 
        {
            multi_hit( ch, victim, TYPE_UNDEFINED );
        if (IS_CLASS(ch, CLASS_DROW) && ch->cur_form == FRM_DROWSPIDER
        && IS_SET(ch->pcdata->powers[1], DPOWER_ARMS))
            multi_hit(ch, victim, gsn_spiderform);
        } 
        else
            stop_fighting( ch, FALSE );

        if ( ( victim = ch->fighting ) == NULL )
            continue;

        /*
         * Fun for the whole family!
         */
        for ( rch = ch->in_room->people; rch != NULL; rch = rch_next )
        {
            rch_next = rch->next_in_room;

            if ( IS_AWAKE(rch) && rch->fighting == NULL )
            {
                /*
                 * Mount's auto-assist their riders and vice versa.
                 */
                if ( (mount = rch->mount) != NULL )
                {
                    if (mount == ch) multi_hit( rch, victim, TYPE_UNDEFINED );
                    continue;
                }
                /*
                 * PC's auto-assist others in their group.
                 */
                if ( !IS_NPC(ch) || IS_AFFECTED(ch, AFF_CHARM) )
                {
                    if ( ( !IS_NPC(rch) || IS_AFFECTED(rch, AFF_CHARM) )
                    &&   is_same_group(ch, rch) )
                        multi_hit( rch, victim, TYPE_UNDEFINED );
                    continue;
                }

                /*
                 * NPC's assist NPC's of same type or 12.5% chance regardless.
                 */
                if ( IS_NPC(rch) && !IS_AFFECTED(rch, AFF_CHARM) )
                {
                    if ( rch->pIndexData == ch->pIndexData
                    ||   number_bits( 3 ) == 0 )
                    {
                        CHAR_DATA *vch;
                        CHAR_DATA *target;
                        int number;

                        target = NULL;
                        number = 0;
                        for ( vch = ch->in_room->people; vch; vch = vch->next )
                        {
                            if ( can_see( rch, vch )
                            &&   is_same_group( vch, victim )
                            &&   number_range( 0, number ) == 0 )
                            {
                                target = vch;
                                number++;
                            }
                        }

                        if ( target != NULL )
                            multi_hit( rch, target, TYPE_UNDEFINED );
                    }
                }
            }
        }
    }

    

    return;
}



/*
 * Do one group of attacks.
 */
void multi_hit( CHAR_DATA *ch, CHAR_DATA *victim, int dt )
{
    OBJ_DATA *wield;
    OBJ_DATA *wield1;
    OBJ_DATA *wield2;
    OBJ_DATA *wield3;
    OBJ_DATA *wield4;
    char buf[MAX_STRING_LENGTH];
    int       sn;
    int       level;
    int       chance;
    int       unarmed;
    int       wieldorig = 0;
    int       wieldtype = 0;
    int       maxcount;
    int       countup;
    int         x;
    int       wieldie;

    if ( ch->position < POS_SLEEPING ) return;

    if ( IS_CREATOR(ch) || IS_CLASS(ch, CLASS_MONK) )
    {
        if (!IS_NPC(ch) && wieldorig == 0)
        {
            if      (countup == 0) unarmed = number_range(0,3);
            else if (countup == 1) unarmed = number_range(4,7);
            else                   unarmed = number_range(0,7);
            if ( !IS_NPC(ch) && ch->cmbt[unarmed] != 0 && wieldorig == 0 )
            {
                fightaction(ch,victim,ch->cmbt[unarmed], dt, wieldtype);
            }
        } 
    }

    if ( dt == gsn_headbutt )
    {
        one_hit( ch, victim, dt, 1 );
        return;
    }

        if (dt == gsn_shiroken) 
        {one_hit(ch, victim, dt, 1);
        return;}

    if ( dt == gsn_spiderform ) {
        for (x = 1; x < 4; x++)
        one_hit(ch,victim,dt,0);
    }

    if ( dt == gsn_fangs )
    {
        one_hit( ch, victim, dt, 1 );
        return;
    } 
    if ( dt== gsn_quills)
    {
         one_hit(ch,victim,dt,1);
         return;
    }
    if ( dt==gsn_venomtong)
    {
          one_hit(ch,victim,dt,1);
          return;
    }
    if ( dt==gsn_spiketail)
    {
            one_hit(ch,victim,dt,1);
            return;
    }  
    if ( dt==gsn_badbreath)
    {
            one_hit(ch,victim,dt,1);
            return;
    }  
    if ( dt==gsn_magma)
    {
            one_hit(ch,victim,dt,1);
            return;
    }  
    if ( dt==gsn_shards)
    {
            one_hit(ch,victim,dt,1);
            return;
    }  
    if ( dt==gsn_laser)
    {
	one_hit(ch,victim,dt,1);
	return;
    }
    if ( dt==gsn_cheapshot)
    {
            send_to_char("You stun them with a shoulder charge!\n\r",ch);
            send_to_char("You are stunned by a shoulder charge!\n\r",victim);
          /*victim->position=POS_STUNNED;*/
            one_hit(ch,victim,dt,1);    
           /* victim->position=POS_STUNNED;
            one_hit(ch,victim,dt,1);*/
            one_hit(ch,victim,dt,1);
            one_hit(ch,victim,dt,1);
            return;
    } 
    if ( dt == gsn_buffet )
    {
        one_hit( ch, victim, dt, 1 );
        return;
    } 

    if ( dt == gsn_sweep )
    {
          one_hit( ch, victim, dt, 1 );
          return;
    }
    if ( dt == gsn_rfangs )
    {
         one_hit( ch, victim, dt, 1);
         return;
    }

   /* if (!IS_NPC(ch) && IS_AFFECTED(ch, AFF_PEACE))
    {
        send_to_char( "You are unable to attack them.\n\r", ch );
        return;
    }*/

    if (!IS_NPC(victim) && IS_AFFECTED(victim, AFF_PEACE))
    {
        send_to_char( "You can't seem to attack them.\n\r", ch );
        return;
    }


   /* if (!IS_NPC(ch) && IS_ITEMAFF(ch, ITEMA_PEACE))
    {
        send_to_char( "You are unable to attack them.\n\r", ch );
        return;
    }*/

    if (!IS_NPC(victim) && IS_ITEMAFF(victim, ITEMA_PEACE))
    {
        send_to_char( "You can't seem to attack them.\n\r", ch );
        return;
    }

    wield1 = get_eq_char( ch, WEAR_WIELD );
    wield2 = get_eq_char( ch, WEAR_HOLD );
    wield3 = get_eq_char( ch, WEAR_THIRD );
    wield4 = get_eq_char( ch, WEAR_FOURTH);
    if ( wield1 != NULL && wield1->item_type == ITEM_WEAPON ) wieldorig  = 1;
    if ( wield2 != NULL && wield2->item_type == ITEM_WEAPON ) wieldorig += 2;
    if ( wield3 != NULL && wield3->item_type == ITEM_WEAPON ) wieldorig += 4;
    if ( wield4 != NULL && wield4->item_type == ITEM_WEAPON ) wieldorig += 8;
    wieldtype = wieldorig;
    wieldie = number_range(1,4);

    if ( wieldorig == 15 ) 
    { 
        if (wieldie == 2) 
          wieldtype = 8; 
        else
          wieldtype = 4;
    }
    if ( wieldorig == 14 )
    {
        if (wieldie == 2)
          wieldtype = 8;
        else if (wieldie == 1)
          wieldtype = 4;
        else if (wieldie == 3)
          wieldtype = 2;
        else
          wieldtype = 1;
    }
    if ( wieldorig == 13 )
    {
        if ( wieldie == 1)
         wieldtype = 8;
        else if (wieldie == 2)
         wieldtype = 4;
        else wieldtype = 1;
    }
    if ( wieldorig == 12 )
    {
        if ( wieldie == 1 )
          wieldtype = 8;
        else
          wieldtype = 4;
    }
    if ( wieldorig == 11 )
    {
        if ( wieldie == 1 )
         wieldtype = 8;
        if ( wieldie == 2 )
         wieldtype = 2;
        else wieldtype = 1;
    }
    if ( wieldorig == 10 )
    {
        if ( wieldie == 1 )
         wieldtype = 8;
        else wieldtype = 2;
    }
    if ( wieldorig == 9 )
    {
        if ( wieldie == 1 )
          wieldtype = 8;
        else wieldtype = 1;
    }
    if ( wieldorig == 8 )
        wieldtype = 8;
    if ( wieldorig == 7 )
    {
        if ( wieldie == 1 )
          wieldtype = 4;
        else if ( wieldie == 2 )
          wieldtype = 2;
        else wieldtype = 1;
    }
    if ( wieldorig == 6 )
    {
       if ( wieldie == 1 || wieldie == 2)
         wieldtype = 2;
       else wieldtype = 4;
    } 
    if ( wieldorig == 5 )
    {
        if ( wieldie == 1)
          wieldtype = 4;
        else wieldtype = 1;
    }
    if ( wieldorig == 4 )
        wieldtype = 4;
    if ( wieldorig == 3 )
    {
        if ( wieldie == 2 || wieldie == 4)
          wieldtype = 2;
        else wieldtype = 1;
    }
    if ( wieldorig == 2 )
        wieldtype = 2;
    if ( wieldorig == 1 )
        wieldtype = 1;
        

         if ( wieldtype == 8 ) wield = wield4;
    else if ( wieldtype == 4 ) wield = wield3;
    else if ( wieldtype == 2 ) wield = wield2;
    else                       wield = wield1;

    if (!IS_NPC(ch) && ch->stance[0] > 0 && number_percent() == 5)
    {
        int stance = ch->stance[0];
        if (ch->stance[stance] >= 200)
        {
            special_move(ch,victim);
            return;
        }
    }

    unarmed = 0;
/*
    if (!IS_NPC(ch) && wieldorig == 0)
        {
            if      (countup == 0) unarmed = number_range(0,3);
            else if (countup == 1) unarmed = number_range(4,7);
            else                   unarmed = number_range(0,7);
            if ( !IS_NPC(ch) && !IS_AFFECTED(ch, AFF_POLYMORPH) &&
                ch->cmbt[unarmed] != 0 && wieldorig == 0 )
            {
                fightaction(ch,victim,ch->cmbt[unarmed], dt, wieldtype);
            }
        }
    else
*/

    if ( IS_SET( ch->flag2, VAMP_OBJMASK) )
    {
      act("You return to your normal form.",ch,NULL,NULL,TO_CHAR);
      sprintf(buf,"%s reforms as %s.\n\r",ch->morph, ch->name );
      act(buf,ch,NULL,NULL,TO_ROOM);
      free_string(ch->morph);
      free_string(ch->objdesc);
      ch->long_descr = str_dup("");
      REMOVE_BIT(ch->flag2, VAMP_OBJMASK);
      REMOVE_BIT(ch->affected_by, AFF_POLYMORPH);
    }

        one_hit( ch, victim, dt, wieldtype );

    if ( victim == NULL || victim->position != POS_FIGHTING ) return;

    /* Only want one spell per round from spell weapons...otherwise it's 
     * too powerful, and would unbalance player killing (as this is a PK mud).
     */

    if ( dt == TYPE_UNDEFINED )
    {
        dt = TYPE_HIT;
        if ( wield != NULL && wield->item_type == ITEM_WEAPON )
        {
            dt += wield->value[3];
            if (wield->value[0] >= 1)
            {
                /* Look, just don't ask...   KaVir */
                if (wield->value[0] >= 1000)
                    sn = wield->value[0] - ((wield->value[0] / 1000) * 1000);
                else
                    sn = wield->value[0];
                if (sn != 0 && victim->position == POS_FIGHTING)
                    (*skill_table[sn].spell_fun) (sn,wield->level,ch,victim);
            }
        }
    }

    if ( victim == NULL || victim->position != POS_FIGHTING ) return;

    if ( ch->fighting != victim || dt == gsn_backstab || dt == gsn_shiroken 
        || dt == gsn_garotte || dt == gsn_headbutt || dt == gsn_circle )
        return;


    maxcount = number_attacks(ch, victim);
    if (!IS_NPC(ch))
    {
        chance = 0;
        if (wield != NULL && wield->item_type == ITEM_WEAPON)
        {
            int tempnum = wield->value[3];
            chance = (ch->wpn[tempnum]) * 0.5;
        }
        else chance = (ch->wpn[0]) * 0.5;
        if (number_percent() <= chance) maxcount += 1;
    }
    if (wieldorig == 3) maxcount += 1;
    for (countup = 0; countup <= maxcount; countup++)
    {
/*
        if (!IS_NPC(ch) && wieldorig == 0)
        {
            if      (countup == 0) unarmed = number_range(0,3);
            else if (countup == 1) unarmed = number_range(4,7);
            else                   unarmed = number_range(0,7);
            if ( !IS_NPC(ch) && !IS_AFFECTED(ch, AFF_POLYMORPH) &&
                ch->cmbt[unarmed] != 0 && wieldorig == 0 )
            {
                fightaction(ch,victim,ch->cmbt[unarmed], dt, wieldtype);
                continue;
            }
        }
*/
        wieldtype = wieldorig;
        if ( wieldorig == 15 ) 
    { 
        if (wieldie == 2) 
          wieldtype = 8; 
        else
          wieldtype = 4;
    }
    if ( wieldorig == 14 )
    {
        if (wieldie == 2)
          wieldtype = 8;
        else if (wieldie == 1)
          wieldtype = 4;
        else if (wieldie == 3)
          wieldtype = 2;
        else
          wieldtype = 1;
    }
    if ( wieldorig == 13 )
    {
        if ( wieldie == 1)
         wieldtype = 8;
        else if (wieldie == 2)
         wieldtype = 4;
        else wieldtype = 1;
    }
    if ( wieldorig == 12 )
    {
        if ( wieldie == 1 )
          wieldtype = 8;
        else
          wieldtype = 4;
    }
    if ( wieldorig == 11 )
    {
        if ( wieldie == 1 )
         wieldtype = 8;
        if ( wieldie == 2 )
         wieldtype = 2;
        else wieldtype = 1;
    }
    if ( wieldorig == 10 )
    {
        if ( wieldie == 1 )
         wieldtype = 8;
        else wieldtype = 2;
    }
    if ( wieldorig == 9 )
    {
        if ( wieldie == 1 )
          wieldtype = 8;
        else wieldtype = 1;
    }
    if ( wieldorig == 7 )
    {
        if ( wieldie == 1 )
          wieldtype = 4;
        else if ( wieldie == 2 )
          wieldtype = 2;
        else wieldtype = 1;
    }
    if ( wieldorig == 6 )
    {
       if ( wieldie == 1 || wieldie == 2)
         wieldtype = 2;
       else wieldtype = 4;
    } 
    if ( wieldorig == 5 )
    {
        if ( wieldie == 1)
          wieldtype = 4;
        else wieldtype = 1;
    }
    if ( wieldorig == 3 )
    {
        if ( wieldie == 2 || wieldie == 4)
          wieldtype = 2;
        else wieldtype = 1;
    }
        one_hit( ch, victim, -1, wieldtype );
        if ( victim == NULL || victim->position != POS_FIGHTING ) return;
        if ( ch->fighting != victim ) return;
    }

    if (!IS_NPC(ch) && IS_VAMPAFF(ch,VAM_FANGS))
        one_hit( ch, victim, ( TYPE_HIT + 10 ), 0 );
    if ( victim == NULL || victim->position != POS_FIGHTING ) return;
    if (!IS_NPC(ch))
    {
        if (IS_VAMPAFF(ch,VAM_HORNS) 
                && number_range(1,3) == 1)
        multi_hit( ch, victim, gsn_headbutt );
    }
        if (IS_CLASS(ch, CLASS_DEMON)  && IS_DEMAFF(ch,DEM_HORNS) 
                && number_range(1,3) == 1)
        multi_hit( ch, victim, gsn_headbutt );

        if (IS_CLASS(ch, CLASS_DEMON)  && IS_DEMAFF(ch, DEM_TAIL)
                && number_range(1,2) == 2)
        multi_hit( ch, victim, gsn_sweep );

        if (!IS_NPC(ch))
        if (IS_CLASS(ch, CLASS_NINJA) && ch->pcdata->powers[NPOWER_NINGENNO] >=4 && number_range(1,4) != 1)
        multi_hit(ch, victim, gsn_shiroken);


    if (!IS_NPC(ch))
    {
        if (IS_VAMPAFF(ch,VAM_TAIL)
                && number_range(1,2) == 1)
        multi_hit( ch, victim, gsn_sweep );
    }          

    if (!IS_NPC(ch))
    {
        if (IS_VAMPAFF(ch,VAM_HEAD)
                && number_range(1,2) == 1)
        multi_hit( ch, victim, gsn_fangs );
    }        
   if (!IS_NPC(ch))
  {
   if (IS_SET(ch->newbits,NEW_QUILLS))
       multi_hit(ch,victim,gsn_quills);
    }

   if (!IS_NPC(ch)&& IS_CLASS(ch,CLASS_WEREWOLF))
   {
   if (IS_SET(ch->newbits,NEW_SLAM) && number_range(1,
ch->power[DISC_WERE_BEAR]/3)==1)
   multi_hit(ch,victim,gsn_cheapshot);
  }
    if (!IS_NPC(ch))
    {
        if (IS_VAMPAFF(ch,VAM_WINGS)
                && number_range(1,2) == 1)
        multi_hit( ch, victim, gsn_buffet );
    }        
    if (!IS_NPC(ch) && IS_CLASS(ch,CLASS_WEREWOLF)
                    && ch->power[DISC_WERE_RAPT] > 0)
    {
     multi_hit(ch,victim,gsn_rfangs);
    }
                    
    if ( victim == NULL || victim->position != POS_FIGHTING ) return;

    if (!IS_NPC(ch) && IS_CLASS(ch, CLASS_VAMPIRE) && IS_VAMPAFF(ch, VAM_SERPENTIS))
        spell_poison( gsn_poison, (ch->level*number_range(5,10)),ch,victim );
    else if (!IS_NPC(ch) && IS_CLASS(ch, CLASS_WEREWOLF) && ch->power[DISC_WERE_SPID] > 0)
        spell_poison( gsn_poison, (ch->level*number_range(5,10)),ch,victim );
    else if (!IS_NPC(ch) && IS_CLASS(ch, CLASS_DROW) && IS_SET(ch->pcdata->powers[1], DPOWER_DROWPOISON))
        spell_poison(gsn_poison,(ch->level*number_range(10,20)),ch,victim);
        else if (!IS_NPC(ch) && IS_CLASS(ch, CLASS_NINJA) &&
        ch->pcdata->powers[NPOWER_NINGENNO] >=5)
        spell_poison(gsn_poison,(ch->level*number_range(5,10)),ch,victim);

   if (victim->itemaffect < 1) return;
    if (IS_NPC(victim) || victim->spl[1] < 4) level = victim->level;
    else level = (victim->spl[1] * 0.25);
    
    if (IS_SET(victim->newbits, NEW_MONKFLAME) && !IS_AFFECTED(ch, AFF_FLAMING))
    {
        if (number_percent() > 95)
        {
        SET_BIT(ch->affected_by, AFF_FLAMING);
    if (!IS_CLASS(ch, CLASS_WEREWOLF))
    {
    act("Your flaming hands catch $n on fire!", ch, NULL, victim, TO_VICT);
    act("$N's flaming hands catch $n on fire!", ch, NULL, victim, TO_NOTVICT);
    act("$N's flaming hands catch you on fire!.", ch, NULL, victim, TO_CHAR);
    }
    else
    {
    act("Your flaming claws catch $n on fire!", ch, NULL, victim, TO_VICT);
    act("$N's flaming claws catch $n on fire!", ch, NULL, victim, TO_NOTVICT);
    act("$N's flaming claws catch you on fire!.", ch, NULL, victim, TO_CHAR);
    }
   }
    else
        {
         return;
        }
    }

    if (IS_ITEMAFF(victim, ITEMA_SHOCKSHIELD) && ch->position == POS_FIGHTING)
        if ( (sn = skill_lookup( "lightning bolt" ) ) > 0)
            (*skill_table[sn].spell_fun) (sn,level,victim,ch);
    if (IS_ITEMAFF(victim, ITEMA_FIRESHIELD) && ch->position == POS_FIGHTING)
        if ( (sn = skill_lookup( "fireball" ) ) > 0)
            (*skill_table[sn].spell_fun) (sn,level,victim,ch);
    if (IS_ITEMAFF(victim, ITEMA_ICESHIELD) && ch->position == POS_FIGHTING)
        if ( (sn = skill_lookup( "chill touch" ) ) > 0)
            (*skill_table[sn].spell_fun) (sn,level,victim,ch);
    if (IS_ITEMAFF(victim, ITEMA_ACIDSHIELD) && ch->position == POS_FIGHTING)
        if ( (sn = skill_lookup( "acid blast" ) ) > 0)
            (*skill_table[sn].spell_fun) (sn,level,victim,ch);
    if (IS_ITEMAFF(victim, ITEMA_CHAOSSHIELD) && ch->position == POS_FIGHTING)
        if ( (sn = skill_lookup( "chaos blast" ) )
> 0)
            (*skill_table[sn].spell_fun) (sn,level,victim,ch);
    return;
}


int number_attacks( CHAR_DATA *ch, CHAR_DATA *victim )
{
    int count = 1;

    if ( IS_NPC(ch) )
    {
        if (ch->level >= 50) count += 1;
        if (ch->level >= 100) count += 1;
        return count;
    }

 if (IS_NPC(victim))
 {
    if ( IS_STANCE(ch, STANCE_VIPER) && number_percent() > 
        ch->stance[STANCE_VIPER] * 0.5) count += 1;
    else if ( IS_STANCE(ch, STANCE_MANTIS) && number_percent() > 
        ch->stance[STANCE_MANTIS] * 0.5) count += 1;
    else if ( IS_STANCE(ch, STANCE_TIGER) && number_percent() > 
        ch->stance[STANCE_TIGER] * 0.5) count += 1;
    else if ( IS_STANCE(ch, STANCE_WOLF) && number_percent() >
       ch->stance[STANCE_WOLF] * .5) count += 2;
    else if ( IS_STANCE(ch, STANCE_KOZUDO) && number_percent() >
       ch->stance[STANCE_KOZUDO] * 1) count += 4;
    if (!IS_NPC(ch))
    {   
        if ( IS_CLASS(ch, CLASS_VAMPIRE) && ch->power[DISC_VAMP_CELE] > 0)
                count += .5;
        else if ( IS_CLASS(ch, CLASS_VAMPIRE) && ch->power[DISC_VAMP_CELE] > 5)
                count += .5;
        else if ( IS_CLASS(ch, CLASS_VAMPIRE) && ch->power[DISC_VAMP_CELE] > 7)
                count += .5;
        else if ( IS_CLASS(ch, CLASS_VAMPIRE) && ch->power[DISC_VAMP_CELE] > 9)
                count += .5;
        else if (IS_CLASS(ch, CLASS_WEREWOLF) && ch->power[DISC_WERE_LYNX] > 2 )
                count += 2;
        else if ( !IS_NPC(ch) && IS_CLASS(ch, CLASS_DEMON) && IS_DEMPOWER( ch, DEM_SPEED) )
                count += 2;     
        else if (IS_CLASS(ch, CLASS_DROW) && (IS_SET(ch->special, SPC_DROW_WAR) || ch->generation < 3))
                count += 1;
    }

        if (!IS_NPC(ch) && IS_CLASS(ch, CLASS_DROW) && 
        IS_SET(ch->pcdata->powers[1],DPOWER_SPEED))
        count += 1;

    if ( !IS_NPC(ch) && IS_CLASS(ch,CLASS_WEREWOLF) && ch->power[DISC_WERE_BOAR] > 6)
    {
    count += ch->move/2000;
    }
        if (!IS_NPC(ch) && IS_CLASS(ch, CLASS_NINJA) && ch->pcdata->powers[NPOWER_CHIKYU] >= 3)
                count += 2;

    if ( IS_ITEMAFF(ch, ITEMA_SPEED) ) count += 2;
  }

  else
  {
    if ( IS_STANCE(ch, STANCE_VIPER) && number_percent() > 
        ch->stance[STANCE_VIPER] * 0.5) count += 1;
    else if ( IS_STANCE(ch, STANCE_MANTIS) && number_percent() > 
        ch->stance[STANCE_MANTIS] * 0.5) count += 1;
    else if ( IS_STANCE(ch, STANCE_TIGER) && number_percent() > 
        ch->stance[STANCE_TIGER] * 0.5) count += 1;
    else if ( IS_STANCE(ch, STANCE_KOZUDO) && number_percent() >
        ch->stance[STANCE_KOZUDO] * 0.5) count += 1;
    

    if (!IS_NPC(ch))
    {   
           if ( IS_CLASS(ch, CLASS_VAMPIRE) && ch->power[DISC_VAMP_CELE] > 0)
            count += 1;
      else if ( IS_CLASS(ch, CLASS_VAMPIRE) && ch->power[DISC_VAMP_CELE] > 5)
            count += 1;
        else if ( IS_CLASS(ch, CLASS_VAMPIRE) && ch->power[DISC_VAMP_CELE] > 7)
                count += 1;
        else if ( IS_CLASS(ch, CLASS_VAMPIRE) && ch->power[DISC_VAMP_CELE] > 9)
                count += 1;
        else if ( IS_CLASS(ch, CLASS_MONK) && ch->monkab[COMBAT] > 0 )
                count += ch->monkab[COMBAT];
        else if (IS_CLASS(ch, CLASS_WEREWOLF) && ch->power[DISC_WERE_LYNX] > 2 )
                count += 1;
        else if (ch->power[DISC_DAEM_ATTA] > 0)
                count += ch->power[DISC_DAEM_ATTA] / 2;
        else if (IS_CLASS(ch, CLASS_DROW) && (IS_SET(ch->special, SPC_DROW_WAR) || ch->generation < 3))
                count += 1;

    }

    if ( !IS_NPC(ch) && IS_CLASS(ch,CLASS_WEREWOLF) && ch->power[DISC_WERE_BOAR] > 6)
    {
    count += ch->move/4000;
    }

    if ( IS_ITEMAFF(ch, ITEMA_SPEED) ) count += 1;

    if (victim->power[DISC_VAMP_CELE] >= 3)
        count -= victim->power[DISC_VAMP_CELE] / 3;
    if (victim->power[DISC_WERE_MANT] >= 3)
          count -= victim->power[DISC_WERE_MANT] / 3;
    if (victim->power[DISC_DAEM_ATTA] > 0)
        count -= victim->power[DISC_DAEM_ATTA] /2;
    if (number_range(1,4) == 2)
        count -= 1;
 }
    if ( count < 1)
       count = 1;


    return count;
}


/*
 * Hit one guy once.
 */
void one_hit( CHAR_DATA *ch, CHAR_DATA *victim, int dt, int handtype)
{

    OBJ_DATA *wield;
//  OBJ_DATA *gloves;
    char buf[MAX_STRING_LENGTH];
    int victim_ac;
    int thac0;
    int thac0_00;
    int thac0_32;
    int dam, wdam;
    int diceroll;
    int level;
    int attack_modify;
//  int stance;
    int right_hand;

    /*
     * Can't beat a dead char!
     * Guard against weird room-leavings.
     */
    if ( victim->position == POS_DEAD || ch->in_room != victim->in_room )
        return;

    if ( !IS_NPC(ch) )
    {
        if (IS_AFFECTED( ch, AFF_PEACE) && ch->fighting != NULL)
        REMOVE_BIT(ch->affected_by, AFF_PEACE);
    }
    
    if ( !IS_NPC(victim) )
    {
        if (IS_AFFECTED(victim, AFF_PEACE) && victim->fighting != NULL)
        REMOVE_BIT(victim->affected_by, AFF_PEACE);
    }

    if (!IS_NPC(ch) && IS_AFFECTED(ch, AFF_PEACE))
    {
        send_to_char( "You are unable to attack them.\n\r", ch );
        return;
    }

    if (!IS_NPC(victim) && IS_AFFECTED(victim, AFF_PEACE))
    {
        send_to_char( "You can't seem to attack them.\n\r", ch );
        return;
    }


    if (!IS_NPC(ch) && IS_ITEMAFF(ch, ITEMA_PEACE))
    {
        send_to_char( "You are unable to attack them.\n\r", ch );
        return;
    }

    if (!IS_NPC(victim) && IS_ITEMAFF(victim, ITEMA_PEACE))
    {
        send_to_char( "You can't seem to attack them.\n\r", ch );
        return;
    }

    if (ch->power[DISC_DAEM_HELL] > 3 && number_range(1, 50-ch->generation) == 1
        && ch->fighting != NULL)
    {
        wdam = dice(ch->generation + 5, 20);
        sprintf(buf,"#1%s breathes out a cloud of fire at you#n.[%d]", ch->name, wdam);
        sprintf(buf,"#1%s breathes out a cloud of fire at %s#n.",ch->name,victim->name );
        sprintf(buf,"#1You breathe out a cloud of fire at %s#n.[%d]",victim->name, wdam );
        victim->hit -= wdam;
        update_pos(victim);
    }

    /*
     * Figure out the type of damage message.
     */
    if (handtype == 8)
    {
        wield = get_eq_char( ch, WEAR_FOURTH );
        right_hand = 8;
    }
    else if (handtype == 4)
    {
        wield = get_eq_char( ch, WEAR_THIRD );
        right_hand = 4;
    }
    else if (handtype == 2)
    {
        wield = get_eq_char( ch, WEAR_HOLD );
        right_hand = 2;
    }
    else if (handtype == 0) 
    {
        wield = NULL;
        right_hand = 0;
    }
    else
    {
        wield = get_eq_char( ch, WEAR_WIELD );
        right_hand = 1;
    }

    if ( dt == TYPE_UNDEFINED )
    {
        dt = TYPE_HIT;
        if ( wield != NULL && wield->item_type == ITEM_WEAPON )
            dt += wield->value[3];
    }

    if (ch->wpn[dt-1000] > 5) level = (ch->wpn[dt-1000] / 5);
    else level = 1;
    if (level > 40) level = 40;

    /*
     * Calculate to-hit-armor-class-0 versus armor.
     */
    if ( IS_NPC(ch) )
    {
        thac0_00 = 20;
        thac0_32 =  0;
    }
    else
    {
        thac0_00 = SKILL_THAC0_00;
        thac0_32 = SKILL_THAC0_32;
    }
    thac0     = interpolate( level, thac0_00, thac0_32 ) - char_hitroll(ch);
    victim_ac = UMAX( -100, char_ac(victim) / 10 );
    if ( !can_see( ch, victim ) )
        victim_ac -= 4;

    /*
     * The moment of excitement!
     */
    while ( ( diceroll = number_bits( 5 ) ) >= 20 )
        ;

    if ( diceroll == 0
    || ( diceroll != 19 && diceroll < thac0 - victim_ac ) )
    {
        /* Miss. */
        damage( ch, victim, 0, dt );
        tail_chain( );
        if (!is_safe(ch,victim))
        {
            improve_wpn(ch,dt,right_hand);
            improve_stance(ch);
        }
        return;
    }

    /*
     * Hit.
     * Calc damage.
     */
    if ( IS_NPC(ch) )
    {
        dam = number_range( ch->level / 2, ch->level * 3 / 2 );
        if ( wield != NULL )
            dam += dam * 0.5;
    }
    else
    {
        if ( IS_VAMPAFF(ch, VAM_CLAWS) && IS_GAR1(ch, WOLF_RAZORCLAWS))
            dam = dice( 25, 35 ); 
        else if ( IS_VAMPAFF(ch,VAM_CLAWS) && wield == NULL)
            dam = dice( 10, 20 );
        else if ( IS_SET(ch->newbits, NEW_MONKADAM))
            dam = dice( 10, 25 );
        else if ( wield != NULL && wield->item_type == ITEM_WEAPON )
            dam = dice( wield->value[1], wield->value[2] );
        else
            dam = dice( 1, 4 );
    }

    /*
     * Bonuses.
     */
    dam += char_damroll(ch);
    if ( !IS_AWAKE(victim) )
        dam *= 2;


    if ( !IS_NPC(ch) && dt >= TYPE_HIT)
        dam = dam + (dam * ((ch->wpn[dt-1000]+1) / 60));


    /* Other Resistances */
   
    if (IS_ITEMAFF(victim, ITEMA_RESISTANCE))
            dam /= 2;
       
    /* damage reduction */
    if ( dam > 1000)
        dam = (dam - 1000)/2 + 312;
    if ( dam > 1500)
        dam = (dam - 1500)/2 + 427;


    if ( dam <= 0 )
        dam = 1;

    if ( !IS_NPC(ch) && IS_CLASS(ch, CLASS_DEMON) && 
                IS_DEMPOWER(ch, DEM_MIGHT) )
        dam *= 1.1;

    if (!IS_NPC(ch) && IS_CLASS(ch, CLASS_WEREWOLF)
        && ch->power[DISC_WERE_BEAR] > 5)
       dam *= 1.2;
     
    if (!IS_NPC(victim) && IS_CLASS(victim, CLASS_WEREWOLF)
        && ch->power[DISC_WERE_LUNA] > 9)
       {
        int luna;
        luna = number_range(1,50);
        if (luna == 10 || luna == 20 || luna == 30 || luna == 40 || luna == 50)
        {
        stc("#3You absorb your opponents damage#n.\n\r",victim);
        stc("#3Your opponent absorbs your damage#n.\n\r",ch);
        dam = 0;
        }
       }

 if (!IS_NPC(ch) && wield != NULL)
 {

    if (number_range(1,6) == 2)
    {
        if (ch->fighting == victim && IS_WEAP(wield,WEAPON_VAMPIRIC))
        {
            wdam = number_range(1,wield->level / 5 + 1);
            act("$p draws life from $n.",victim,wield,NULL,TO_ROOM);
            act("You feel $p drawing your life away.",
                victim,wield,NULL,TO_CHAR);
            victim->hit -= wdam;
            update_pos( victim );
            ch->alignment = UMAX(-1000,ch->alignment - 1);
            ch->hit += wdam/2;
        }

        if (ch->fighting == victim && (IS_WEAP(wield,WEAPON_FLAMING)
                || IS_WEAP(wield, WEAPON_ELE_FLAME) )  )
        {
            wdam = number_range(1,wield->level / 4 + 1);
            act("$n is burned by $p.",victim,wield,NULL,TO_ROOM);
            act("$p sears your flesh.",victim,wield,NULL,TO_CHAR);
            fire_effect( (void *) victim,wield->level/2,wdam,TARGET_CHAR);
            victim->hit -= wdam;
            update_pos( victim );
        }

        if (ch->fighting == victim && (IS_WEAP(wield,WEAPON_FROST)
                || IS_WEAP(wield, WEAPON_ELE_WATER) ) )
        {
            wdam = number_range(1,wield->level / 6 + 2);
            act("$p freezes $n.",victim,wield,NULL,TO_ROOM);
            act("The cold touch of $p surrounds you with ice.",
                victim,wield,NULL,TO_CHAR);
            cold_effect(victim,wield->level/2,wdam,TARGET_CHAR);
            victim->hit -= wdam;
            update_pos( victim );
        }

        if (ch->fighting == victim && IS_WEAP(wield, WEAPON_ELE_EARTH) )
        {
            wdam = number_range(1,wield->level / 5 + 2);
            act("$p covers $n in acid.",victim,wield,NULL,TO_ROOM);
            act("The corrosive touch of $p surrounds you with acid.",
                victim,wield,NULL,TO_CHAR);
            acid_effect(victim,wield->level/2,wdam,TARGET_CHAR);
            victim->hit -= wdam;
            update_pos( victim );
        }

        if (ch->fighting == victim && (IS_WEAP(wield,WEAPON_SHOCKING)
                || IS_WEAP(wield, WEAPON_ELE_AIR) ) )
        {
            wdam = number_range(1,wield->level/5 + 2);
            act("$n is struck by lightning from $p.",victim,wield,NULL,TO_ROOM);
            act("You are shocked by $p.",victim,wield,NULL,TO_CHAR);
            shock_effect(victim,wield->level/2,wdam,TARGET_CHAR);
            victim->hit -= wdam;
            update_pos( victim );
      }

        if (ch->fighting == victim && IS_WEAP(wield, WEAPON_SUNBLADE))
        {
            wdam = number_range(wield->level/2, wield->level+1);
            if (victim->alignment > -100)
                wdam = 0;
            if (victim->alignment > -300)
                wdam = wdam / 2;
            if (victim->alignment == -1000)
                wdam *= 2;
            if (victim->class == CLASS_VAMPIRE)
                wdam *= 4;
            if (wdam > 0)
            {
            act("$n's flesh is seared by the radiant aura of $p.",victim,wield,NULL,TO_ROOM);
            act("Your flesh is seared by the radiant aura of $p.",victim,wield,NULL,TO_CHAR);
            victim->hit -= wdam;
            update_pos( victim );
            ch->alignment = UMAX(-1000,ch->alignment + 1);
            }
        }

        if (ch->fighting == victim 
                && IS_WEAP(wield, WEAPON_DRAGONLANCE))
        {
            wdam = number_range(wield->level/2, wield->level+1)*4;
                wdam = 0;
            if (wdam > 0)
            {
            act("$n's flesh is torn apart by $p.",victim,wield,NULL,TO_ROOM);
            act("Your flesh is torn apart by $p.",victim,wield,NULL,TO_CHAR);
            victim->hit -= wdam;
            update_pos( victim );
            }
        }

        if ( ch->fighting == victim && IS_CLASS(ch, CLASS_MONK)
          && !IS_NPC(ch) && ch->monkab[BODY] > 3 )
        {
            wdam = number_range( (ch->chi[CURRENT]*6),(ch->chi[CURRENT]*10) );
            if ( victim->alignment < 0 )
             wdam *= 1.5;
            act("$n's hands glow with a heavenly aura.",ch,NULL,victim,TO_VICT);
            act("$n's aura sears your flesh!",ch,NULL,victim,TO_VICT);
            act("Your heavenly aura sears $N's flesh.",ch,NULL,victim,TO_CHAR);
            act("$n's hands' heavenly aura sears $N's flesh.",ch,NULL,victim,TO_NOTVICT);
            victim->hit -= wdam;
            update_pos( victim );
        }
     }
  }

    if ( number_range( 1,5 ) == 3 )
    {
        if ( ch->fighting == victim && IS_CLASS(ch, CLASS_MONK)
          && !IS_NPC(ch) && ch->monkab[BODY] > 3 )
        {
            wdam = number_range( (ch->chi[CURRENT]*6),(ch->chi[CURRENT]*10) );
            if ( victim->alignment < 0 )
             wdam *= 1.5;
            act("$n's hands glow with a heavenly aura.",ch,NULL,victim,TO_VICT);
            act("$n's aura sears your flesh!",ch,NULL,victim,TO_VICT);
            act("Your heavenly aura sears $N's flesh.",ch,NULL,victim,TO_CHAR);
            act("$n's hands' heavenly aura sears $N's flesh.",ch,NULL,victim,TO_NOTVICT);
            victim->hit -= wdam;
            update_pos( victim );
        }
    }

  if ( !IS_NPC(ch) && IS_CLASS(ch, CLASS_MONK) )
  {
    if (ch->chi[CURRENT] > 0 && ch->chi[CURRENT] < 3 )
        dam *= 1.3;
    if (ch->chi[CURRENT] > 2 && ch->chi[CURRENT] < 7 )
        dam *= ((ch->chi[CURRENT]) / 2);
  }

    if ( dt == gsn_garotte )
        dam *= (number_range(3,5));
   
    if ( dt == gsn_backstab ) 
        if (IS_CLASS(ch, CLASS_NINJA) && !IS_NPC(ch) && ch->pcdata->powers[NPOWER_NINGENNO] >=2)
        dam *= number_range(4,8);
        else
        dam *= number_range(2,4);

        if (dt == gsn_circle)
        dam *= number_range(2,4);

    dam = cap_dam(ch,victim,dam);       
    attack_modify = dice(1, 100);
    randomize_damage(ch,dam,attack_modify);
    damage( ch, victim, dam, dt );

    if (IS_SET(victim->newbits, NEW_LWRATH) && dt != gsn_garotte)
    {
    act("You absorb the damage and $n is struck by Luna's Wrath!", ch, NULL, victim, TO_VICT);
    act("$N absorbs $n's hit and $n is struck by Luna's Wrath!", ch, NULL, victim, TO_NOTVICT);
       if (!IS_NPC(ch))
    act("$n absorbs your damage and you are struck by Luna's Wrath!", ch, NULL, victim, TO_CHAR);
      ch->hit -= 250;
      victim->hit += 500;
     if (victim->hit > victim->max_hit)
      victim->hit = victim->max_hit;
      REMOVE_BIT(victim->newbits, NEW_LWRATH);
    }


    tail_chain( );
    if (!is_safe(ch,victim))
    {
        improve_wpn(ch,dt,right_hand);
        improve_stance(ch);
    }
 
}

int randomize_damage( CHAR_DATA *ch, int dam, int am )
{
    dam = dam * (am + 50) / 100;
    return dam;
}

int cap_dam(CHAR_DATA *ch, CHAR_DATA *victim, int dam)
{
    
    if (is_safe(ch, victim))
        return 0;

    if (dam > 80)
        dam = (dam - 80) / 2 + 80;

    if (!IS_NPC(victim) && victim->pcdata->condition[COND_DRUNK] > 10)
        dam /= 2;
        
        if (!IS_NPC(victim) && IS_CLASS(victim, CLASS_DROW)) {
        if (IS_SET(victim->pcdata->powers[1], DPOWER_TOUGHSKIN))
        dam /= 2;
        }

    /* Vampire protean 7 (flesh of lava) reduces damage */
    if (victim->power[DISC_VAMP_PROT] >= 10)
    {
        dam *= 2;
        dam /= 3;
    }

    /* body of stone */
    if (victim->monkab[BODY] >= 2 )
    {
        dam *= 2;
        dam /= 3;
    }

    /* Monk Chi */
    if (victim->chi[CURRENT] > 0 )
    {
        dam *= (100 - (victim->chi[CURRENT] * 8) );
        dam /= 100;
    }

    if (victim->power[DISC_DAEM_IMMU] > 0)
    {
        dam *= (100 - (victim->power[DISC_DAEM_IMMU] * 3.7));
        dam /= 100;
    }

    /* Vampire fortitude reduces damage */
    if (victim->power[DISC_VAMP_FORT] > 0)
    {
        dam *= (100 - (victim->power[DISC_VAMP_FORT] * 8));
        dam /= 100;
    }

        if (!IS_NPC(victim))
        if (victim->pcdata->powers[NPOWER_CHIKYU] >= 1 && IS_CLASS(victim,CLASS_NINJA))
        {
        dam /= 2;
        }

        
        if (!IS_NPC(victim))
        if (victim->pcdata->powers[NPOWER_CHIKYU] >= 1 && IS_CLASS(victim,CLASS_MAGE))
        {
        dam /= 2;
        }       

        else if ( !IS_NPC(victim) && IS_CLASS(victim, CLASS_DEMON) 
                 && IS_DEMPOWER( victim, DEM_TOUGH))
        {
          dam *= 50;
          dam /= 100;
        }

    if (victim->power[DISC_WERE_BOAR] > 2)
    {
        dam *= 50;
        dam /= 100;
    }

    if ( IS_GAR1(victim, WOLF_COCOON) )
        dam /= 1.5;

    /* Vampires should be tougher at night and weaker during the day. */
    if ( !IS_NPC(ch) && IS_CLASS(ch, CLASS_VAMPIRE) )
    {
        if (weather_info.sunlight == SUN_LIGHT && dam > 1)
            dam /= 1.5;
        else if (weather_info.sunlight == SUN_DARK)
            dam *= 1.5;
    }

    if (dam >= 2000)
        dam = dam - (dam / number_range(3,10) + number_range(10,30));

    if (!IS_NPC(victim))
    {
        dam = dam + (dam / number_range(2,5) + number_range(10,50));
        dam *= (number_range(2,4) * number_range(2,3) / number_range(4,6));
    }

    if (dam <= 0)
        dam = 1;
                                                                               
    if (dam > 30000) dam = 30000;                                               

    if ( dam > ch->damcap[DAM_CAP] )
      dam = number_range( (ch->damcap[DAM_CAP] - 200), (ch->damcap[DAM_CAP] + 100) );

    if ( IS_AFFECTED(victim, AFF_SANCTUARY ) ) dam *= 0.5;

    return dam;
}

bool can_counter( CHAR_DATA *ch)
{
    if (!IS_NPC(ch) && IS_STANCE(ch, STANCE_MONKEY)) return TRUE;
    return FALSE;
}

bool can_bypass( CHAR_DATA *ch, CHAR_DATA *victim )
{
    if (IS_NPC(ch) || IS_NPC(victim)) return FALSE;
    else if (IS_STANCE(ch, STANCE_VIPER)) return TRUE;
    else if (IS_STANCE(ch, STANCE_MANTIS)) return TRUE;
    else if (IS_STANCE(ch, STANCE_TIGER)) return TRUE;
    else if (IS_STANCE(ch, STANCE_WOLF)) return TRUE;
    else if (IS_STANCE(ch, STANCE_KOZUDO)) return TRUE;
    return FALSE;
}

void update_damcap( CHAR_DATA *ch, CHAR_DATA *victim )
{
int max_dam = 1000;


    if (!IS_NPC(ch))
    {

        if (IS_CLASS(ch, CLASS_DROW))
        {
                if (weather_info.sunlight == SUN_DARK)
                max_dam += 500;
                
                if (IS_SET(ch->newbits, NEW_DROWHATE))
                max_dam += 750;
        }
else if ((IS_CLASS(ch, CLASS_DEMON) || IS_SET(ch->special,
SPC_CHAMPION)) &&
            ch->in_room != NULL)
        {
            if (ch->in_room->vnum == 30000) max_dam = 10000; /* was5000Rotain*/
            max_dam += (ch->pcdata->stats[DEMON_POWER] * 20);
        }       

        if (IS_CLASS(ch, CLASS_MONK))
            max_dam +=  (ch->monkab[COMBAT] * 100);
        if (IS_CLASS(ch, CLASS_MONK) && ch->chi[CURRENT] > 0 )
            max_dam += ch->chi[CURRENT] * 200;

        else if (IS_CLASS(ch, CLASS_VAMPIRE))
        {
             max_dam = 1500;

            max_dam += (ch->rage * 10);
            if (ch->power[DISC_VAMP_POTE] > 0) 
                 max_dam += (ch->power[DISC_VAMP_POTE] * 125 * 2);
            if (ch->pcdata->rank == AGE_METHUSELAH) max_dam += 400;
            else if (ch->pcdata->rank == AGE_ELDER) max_dam += 250;
            else if (ch->pcdata->rank == AGE_ANCILLA) max_dam += 125;
        
        if (ch->generation == 13)
          max_dam += 75;
         else if (ch->generation ==12)
          max_dam += 100;
         else if (ch->generation ==11)          
         max_dam += 150;
          else if (ch->generation == 10)
          max_dam += 200;
          else if (ch->generation == 9)
          max_dam += 250;
        else if (ch->generation == 8)
          max_dam += 300;
          else if (ch->generation == 7)
          max_dam += 350;
        else if (ch->generation == 6)
          max_dam += 400;
        else if (ch->generation == 5)
          max_dam += 450;
        else if (ch->generation  == 4)
          max_dam += 500;
        else if (ch->generation  == 3)
          max_dam += 550;
        else if (ch->generation  == 2)
          max_dam += 600;


        }
        else if (IS_CLASS(ch, CLASS_NINJA)) 
        {
        max_dam += (ch->rage * 5);
        if(ch->pcdata->powers[NPOWER_CHIKYU] >=6 &&
        ch->pcdata->powers[HARA_KIRI] > 0) 
        max_dam += 500;
        if (ch->pcdata->powers[NPOWER_CHIKYU] >=2)
        max_dam += 500;
        }
        else if (IS_SET(ch->special, SPC_WOLFMAN))
        {
            if      (ch->generation < 2) max_dam = 2000;
            else if (ch->generation < 3) max_dam = 1900;
            else if (ch->generation < 4) max_dam = 1800;
            else                      max_dam = 1700;

            max_dam += ch->rage;

          if (ch->power[DISC_WERE_LUNA] > 6
            && (weather_info.sunlight == SUN_DARK))
            max_dam += 400;
        }

	else if (IS_CLASS(ch, CLASS_CYBORG))
	{
	if ((ch->pcdata->powers[CYBORG_LIMBS] > 0)) max_dam += 1500;
	if ((ch->pcdata->powers[CYBORG_LIMBS] > 2)) max_dam += 2000;
	}
        
        else if (IS_CLASS(ch, CLASS_DEMON)) max_dam += 500;
        else if (IS_SET(ch->special, SPC_CHAMPION)) max_dam += 250;
        
        if (ch->pcdata->souls >= 10)
        max_dam += 500;

        
        if ( ch->generation > 0 && IS_CLASS(ch, CLASS_DEMON))
        {
          max_dam += (ch->generation * 20);
        }

        else if (IS_CLASS(ch, CLASS_HIGHLANDER) && (get_eq_char(ch, WEAR_WIELD) != NULL))
        {
            int wpn = ch->wpn[1];
                    max_dam += wpn;
                max_dam += ch->race*40;
        }
   }
        if (IS_ITEMAFF(ch, ITEMA_ARTIFACT)) max_dam += 500;

        if (IS_ITEMAFF(victim, ITEMA_ARTIFACT)) max_dam += 500;

        if (IS_NPC(victim) || victim->stance[0] != STANCE_MONKEY )
        {
            if      (ch->stance[0] == STANCE_BULL)   max_dam += 250;
            else if (ch->stance[0] == STANCE_DRAGON) max_dam += 300;
            else if (ch->stance[0] == STANCE_WOLF)   max_dam += 500;
            else if (ch->stance[0] == STANCE_TIGER)  max_dam += 350;
            else if (ch->stance[0] == STANCE_KOZUDO) max_dam += 750;
        }

    /* Max Dam Reductions */
    /* Werewolves */

    if (!IS_NPC(victim))
    {
        int silver_tol = (victim->siltol * 2.5);
        if (IS_CLASS(victim, CLASS_WEREWOLF) && 
            IS_ITEMAFF(ch, ITEMA_RIGHT_SILVER))
            max_dam += (250 - silver_tol);
        if (IS_CLASS(victim, CLASS_WEREWOLF) && 
            IS_ITEMAFF(ch, ITEMA_LEFT_SILVER))
            max_dam += (250 - silver_tol);
        
        /* Vampies */
        if (!IS_NPC(ch) && (IS_CLASS(victim, CLASS_VAMPIRE)))
            max_dam -= (victim->power[DISC_VAMP_FORT] * 100); 

        if (IS_NPC(ch) || ch->stance[0] != STANCE_MONKEY)
        {
            if      (victim->stance[0] == STANCE_CRAB)    max_dam -= 250;
            else if (victim->stance[0] == STANCE_DRAGON)  max_dam -= 250;
            else if (victim->stance[0] == STANCE_SWALLOW) max_dam -= 250;
        }

if ((IS_CLASS(victim,CLASS_DEMON) || IS_SET(victim->special,SPC_CHAMPION)) 
            && victim->in_room != NULL && victim->in_room->vnum == 30000)
            max_dam *= 0.2;
}

    if (max_dam < 3000) max_dam = 3000;
    if (ch->level >= LEVEL_BUILDER)
    max_dam = 30000;
    ch->damcap[DAM_CAP] = max_dam;
    ch->damcap[DAM_CHANGE] = 0;
    return;
}

int check_immune(CHAR_DATA *ch, int dam_type)
{
    int immune, def;
    int bit;

    immune = -1;
    def = IS_NORMAL;

    if (dam_type == DAM_NONE)
        return immune;

    /* Firstly, dDo the backbone for each race, and then do the powers,
        which are not at all race specific - so that ie, eladrin can
        learn protean and be immune to fire! */

    /* Eladrin aura deals with itself, as it is switched on and off
        and removes and sets the bits in both */

    if (ch->class == CLASS_VAMPIRE)
    {
        /* They are resistant to cold */
        if (dam_type == DAM_COLD) immune = IS_RESISTANT;
        /* They are vulnerable to drowning */
        if (dam_type == DAM_DROWNING) immune = IS_VULNERABLE;
        /* They are vulnerable to fire */
        if (dam_type == DAM_FIRE) immune = IS_VULNERABLE;
    }

    /* Firstly, we'll do flesh of lava! */
    if (ch->power[DISC_VAMP_PROT] >= 7
        && dam_type == DAM_FIRE) immune = IS_RESISTANT;

    /* The corruption discipline */
    if (dam_type == DAM_POISON && ch->power[DISC_DAEM_CORR] >= 3)
        immune = IS_DIMMUNE;
    if (dam_type == DAM_POISON && ch->power[DISC_DAEM_CORR] >= 1)
        immune = IS_RESISTANT;

    /* The hellfire discipline */
    if (dam_type == DAM_FIRE && ch->power[DISC_DAEM_HELL] >= 2)
        immune = IS_DIMMUNE;
    if (dam_type == DAM_FIRE && ch->power[DISC_DAEM_HELL] >= 1)
        immune = IS_RESISTANT;

    /* The geluge discipline */
    if (dam_type == DAM_COLD && ch->power[DISC_DAEM_GELU] >= 4)
        immune = IS_DIMMUNE;
    if (dam_type == DAM_COLD && ch->power[DISC_DAEM_GELU] >= 1)
        immune = IS_RESISTANT;

    /* Fortitude level 1 for vampires */
    if (dam_type == DAM_POISON && ch->power[DISC_VAMP_FORT] >= 1)
        immune = IS_RESISTANT;

    /* Returns immune if it has been changed at all ! */
    if (immune != -1) return immune;

    
    /* set bits to check -- VULN etc. must ALL be the same or this will
fail */
    switch (dam_type)
    {
        case(DAM_BASH):         bit = DIMM_BASH;         break;
        case(DAM_PIERCE):       bit = DIMM_PIERCE;       break;
        case(DAM_SLASH):        bit = DIMM_SLASH;        break;
        case(DAM_FIRE):         bit = DIMM_FIRE;         break;
        case(DAM_COLD):         bit = DIMM_COLD;         break;
        case(DAM_LIGHTNING):    bit = DIMM_LIGHTNING;    break;
        case(DAM_ACID):         bit = DIMM_ACID;         break;
        case(DAM_POISON):       bit = DIMM_POISON;       break;
        case(DAM_NEGATIVE):     bit = DIMM_NEGATIVE;     break;
        case(DAM_HOLY):         bit = DIMM_HOLY;         break;
        case(DAM_ENERGY):       bit = DIMM_ENERGY;       break;
        case(DAM_MENTAL):       bit = DIMM_MENTAL;       break;
        case(DAM_DISEASE):      bit = DIMM_DISEASE;      break;
        case(DAM_DROWNING):     bit = DIMM_DROWNING;     break;
        case(DAM_LIGHT):        bit = DIMM_LIGHT;        break;
        case(DAM_CHARM):        bit = DIMM_CHARM;        break;
        case(DAM_SOUND):        bit = DIMM_SOUND;        break;
        default:                return def;
    }


    if (immune == -1)
        return def;
    else
        return immune;
}


/*
 * Inflict damage from a hit.
 */
bool damage_old( CHAR_DATA *ch, CHAR_DATA *victim, int dam, int dt, int dam_type, bool show ) 
{
    OBJ_DATA *corpse;
    bool immune;


    if ( victim->position == POS_DEAD )
        return FALSE;
    
    /* damage reduction */
    if ( dam > 35)
        dam = (dam - 35)/2 + 35; 
    if ( dam > 80)
        dam = (dam - 80)/2 + 80; 
   
    if ( victim != ch )
    {
        /*
         * Certain attacks are forbidden.
         * Most other attacks are returned.
         */
        if ( is_safe( ch, victim ) )
            return FALSE;

        if ( victim->position > POS_STUNNED )
        {
            /*
             * If victim is charmed, ch might attack victim's master.
             */
            if ( IS_NPC(ch)         
            &&   IS_NPC(victim)
            &&   IS_AFFECTED(victim, AFF_CHARM)
            &&   victim->master != NULL
            &&   victim->master->in_room == ch->in_room
            &&   number_bits( 3 ) == 0 )
            {
                stop_fighting( ch, FALSE );
                
                set_fighting( ch, victim->master);
                return FALSE;
            }
        }

        /*
         * More charm stuff.
         */
        if ( victim->master == ch )
            stop_follower( victim );
    }

    /*
     * Inviso attacks ... not.
     */
    if ( IS_AFFECTED(ch, AFF_INVISIBLE) )
    {
        affect_strip( ch, gsn_invis );
        affect_strip( ch, gsn_mass_invis );
        REMOVE_BIT( ch->affected_by, AFF_INVISIBLE );
        act( "$n fades into existence.", ch, NULL, NULL, TO_ROOM );
    }

    /*
     * Damage modifiers.
     */

    if ( dam > 1 && !IS_NPC(victim)
    &&   victim->pcdata->condition[COND_DRUNK]  > 10 )
        dam = 9 * dam / 10;
 
    immune = FALSE;


    switch(check_immune(victim,dam_type))
    {
        case(IS_DIMMUNE):
            immune = TRUE;
            dam = 0;
            break;
        case(IS_RESISTANT):     
            dam -= dam/3;
            break;
        case(IS_VULNERABLE):
            dam += dam/2;
            break;
    }

    if (show)
        dam_message( ch, victim, dam, dt);

    if (dam == 0)
        return FALSE;

    /*
     * Hurt the victim.
     * Inform the victim of his new state.
     */
    victim->hit -= dam;
    if ( !IS_NPC(victim)
    &&   victim->level >= LEVEL_IMMORTAL
    &&   victim->hit < 1 )
        victim->hit = 1;
    update_pos( victim );

    switch( victim->position )

    {
    case POS_MORTAL:
        act( "$n is mortally wounded, and will die soon, if not aided.",
            victim, NULL, NULL, TO_ROOM );
        send_to_char( 
            "You are mortally wounded, and will die soon, if not aided.\n\r",
            victim );
        break;

    case POS_INCAP:
        act( "$n is incapacitated and will slowly die, if not aided.",
            victim, NULL, NULL, TO_ROOM );
        send_to_char(
            "You are incapacitated and will slowly die, if not aided.\n\r",
            victim );
        break;

    case POS_STUNNED:
        act( "$n is stunned, but will probably recover.",
            victim, NULL, NULL, TO_ROOM );
        send_to_char("You are stunned, but will probably recover.\n\r",
            victim );
        break;

    case POS_DEAD:
        act( "$n is DEAD!!", victim, 0, 0, TO_ROOM );
        send_to_char( "You have been KILLED!!\n\r\n\r", victim );
        stop_fighting(ch, TRUE);
        break;

    default:
        if ( dam > victim->max_hit / 4 )
            send_to_char( "That really did HURT!\n\r", victim );
        if ( victim->hit < victim->max_hit / 4 )
            send_to_char( "#1You sure are BLEEDING!\n\r", victim );
        break;
    }

    /*
     * Sleep spells and extremely wounded folks.
     */
    if (victim->position == POS_DEAD && !IS_NPC(victim) && victim->class !=0 )
    {
        stop_fighting(victim, TRUE);
        return TRUE;
    }
    else
    {
        update_pos(victim);
    }

    if ( !IS_AWAKE(victim) )
        stop_fighting( victim, FALSE );

    /*
     * Payoff for killing things.
     */

    if ( victim->position == POS_DEAD && victim->class==0)
    {
        
        group_gain( ch, victim );

        if (IS_NPC(victim) && !IS_NPC(ch) )
            ch->mkill += 1;     


        if ( !IS_NPC(victim) )
        {    
            if (IS_NPC(ch))
                victim->mdeath += 1;
            sprintf( log_buf, "%s killed by %s at %d",
                victim->name,
                (IS_NPC(ch) ? ch->short_descr : ch->name),
                victim->in_room->vnum );
            log_string( log_buf );
        }
        
        sprintf( log_buf, "%s got crapped upon by %s at %s [room %d]",
            (IS_NPC(victim) ? victim->short_descr : victim->name),
            (IS_NPC(ch) ? ch->short_descr : ch->name),
            ch->in_room->name, ch->in_room->vnum);
                    
        raw_kill(victim);

/*      if (!IS_NPC(ch) && !IS_NPC(victim) && victim->pcdata->bounty > 0)
        {
        sprintf(buf,"You recive a %d QP bounty, for killing %s.\n\r",
        victim->pcdata->bounty, victim->name);
        send_to_char(buf, ch);
        ch->pcdata->quest += victim->pcdata->bounty;
        victim->pcdata->bounty =0;      
        }*/

        if ( !IS_NPC(ch) && IS_NPC(victim) )
        {
            corpse = get_obj_list( ch, "corpse", ch->in_room->contents );
         
            if ( IS_SET(ch->act, PLR_AUTOLOOT) &&
                 corpse && corpse->contains) /* exists and not empty */
                do_get( ch, "all corpse" );
      
              if ( IS_SET(ch->act,PLR_AUTOLOOT) && corpse && corpse->contains)
                return TRUE;  /* leave if corpse has treasure */
              else
                do_sacrifice( ch, "corpse" );
        }

        return TRUE;
     }

    if ( victim == ch )
        return TRUE;

    /*
     * Wimp out?
     */

    if ( !IS_NPC(victim)
    &&   victim->hit > 0
    &&   victim->hit <= victim->wimpy
    &&   victim->wait < PULSE_VIOLENCE / 2 )
        do_flee( victim, "" );

    tail_chain( );
    return TRUE;
}

/*
 * Inflict damage from a hit.
 */
void damage( CHAR_DATA *ch, CHAR_DATA *victim, int dam, int dt )
{
    CHAR_DATA *emb;

    if ( victim->position == POS_DEAD )
        return;

    if ( ch->embracing != NULL )
    {
      if ( ( emb = ch->embracing ) != NULL ) stop_embrace(ch,emb);
    else stop_embrace(ch,NULL);
    }

    /*
     * Stop up any residual loopholes.
     */

    if (ch->damcap[DAM_CHANGE] == 1) update_damcap(ch,victim);


    if (IS_NPC(victim) && dam > 2750)
          dam = number_range( 2600, 2900 );

    if ( victim != ch )
    {
        /*
         * Certain attacks are forbidden.
         * Most other attacks are returned.
         */
        if ( is_safe( ch, victim ) )
            return;
        check_killer( ch, victim );

        if ( victim->position > POS_STUNNED )
        {
            if ( victim->fighting == NULL )
                set_fighting( victim, ch );
            victim->position = POS_FIGHTING;
        }

        if ( victim->position > POS_STUNNED )
        {
            if ( ch->fighting == NULL )
                set_fighting( ch, victim );

            /*
             * If victim is charmed, ch might attack victim's master.
             */
            if ( IS_NPC(ch)
            &&   IS_NPC(victim)
            &&   IS_AFFECTED(victim, AFF_CHARM)
            &&   victim->master != NULL
            &&   victim->master->in_room == ch->in_room
            &&   number_bits( 3 ) == 0 )
            {
                stop_fighting( ch, FALSE );
                multi_hit( ch, victim->master, TYPE_UNDEFINED );
                return;
            }
        }

        /*
         * More charm stuff.
         */
        if ( victim->master == ch )
            stop_follower( victim );

        /*
         * Damage modifiers.
         */
        if ( IS_AFFECTED(ch, AFF_HIDE) )
        {
            if (!can_see(victim,ch)) {dam *= 1.5;
                send_to_char("You use your concealment to get a surprise attack!\n\r",ch);}
            REMOVE_BIT( ch->affected_by, AFF_HIDE );
            act( "$n leaps from $s concealment.", ch, NULL, NULL, TO_ROOM );
        }

        if ( IS_AFFECTED(victim, AFF_PROTECT) && IS_EVIL(ch) && dam > 1  )
            dam -= dam * 0.25;

        if ( dam < 0 )
            dam = 0;

        /*
         * Check for disarm, trip, parry, and dodge.
         */
        if ( dt >= TYPE_HIT )
        {
            if ( IS_NPC(ch) && number_percent( ) < ch->level * 0.5 )
                disarm( ch, victim );
            if ( IS_NPC(ch) && number_percent( ) < ch->level * 0.5 )
                trip( ch, victim );
            if ( check_parry( ch, victim, dt ) )
                return;
            if ( !IS_NPC(victim) && IS_STANCE(victim, STANCE_CRANE) && 
                victim->stance[STANCE_CRANE] > 100 && !can_counter(ch)
                && !can_bypass(ch,victim) && check_parry( ch, victim, dt ))
                return;
            else if ( !IS_NPC(victim) && IS_STANCE(victim, STANCE_MANTIS) && 
                victim->stance[STANCE_MANTIS] > 100 && !can_counter(ch)
                && !can_bypass(ch,victim) && check_parry( ch, victim, dt ))
                return;
            if ( check_dodge( ch, victim, dt ) )
                return;
            if ( !IS_NPC(victim) && IS_STANCE(victim, STANCE_MONGOOSE) && 
                victim->stance[STANCE_MONGOOSE] > 100 && !can_counter(ch)
                && !can_bypass(ch,victim) && check_dodge( ch, victim, dt ))
                return;
            else if ( !IS_NPC(victim) && IS_STANCE(victim, STANCE_SWALLOW) && 
                victim->stance[STANCE_SWALLOW] > 100 && !can_counter(ch)
                && !can_bypass(ch,victim) && check_dodge( ch, victim, dt ))
                return;
        }

        dam_message( ch, victim, dam, dt );
    }
    if ( IS_CLASS( victim, CLASS_MONK ) && victim->monkab[SPIRIT] >= 2 )
    {
        if (IS_SET(victim->newbits, NEW_NATURAL))
        {
          stc("You absorb the natural imbalances of your opponent.\n\r",victim);
          act("$n absorbs the natural imbalances of you attack.",victim,NULL,ch,TO_VICT);
          if ( dam > 2000 ) dam /= 2;
          victim->hit += dam;
          REMOVE_BIT(victim->newbits, NEW_NATURAL);
          return;
        }
    }

    hurt_person(ch,victim,dam);
    return;
}

void adv_damage( CHAR_DATA *ch, CHAR_DATA *victim, int dam )
{
    if ( victim->position == POS_DEAD )
        return;

    if ( dam > 1000 ) dam = 1000;

    if ( victim != ch )
    {
        if ( is_safe( ch, victim ) )
            return;
        check_killer( ch, victim );

        if ( victim->position > POS_STUNNED )
        {
            if ( victim->fighting == NULL )
                set_fighting( victim, ch );
            victim->position = POS_FIGHTING;
        }

        if ( victim->position > POS_STUNNED )
        {
            if ( ch->fighting == NULL )
                set_fighting( ch, victim );

            /*
             * If victim is charmed, ch might attack victim's master.
             */
            if ( IS_NPC(ch)
            &&   IS_NPC(victim)
            &&   IS_AFFECTED(victim, AFF_CHARM)
            &&   victim->master != NULL
            &&   victim->master->in_room == ch->in_room
            &&   number_bits( 3 ) == 0 )
            {
                stop_fighting( ch, FALSE );
                multi_hit( ch, victim->master, TYPE_UNDEFINED );
                return;
            }
        }

        if ( victim->master == ch )
            stop_follower( victim );

        if ( IS_AFFECTED(victim, AFF_PROTECT) && IS_EVIL(ch) && dam > 1  )
            dam -= dam / 4;
        if (!IS_NPC(victim) && !IS_NPC(ch)) dam = dam *2/3;

        if ( dam < 0 )
            dam = 0;
    }
    return;
}


void hurt_person( CHAR_DATA *ch, CHAR_DATA *victim, int dam )
{
    char buf[MAX_STRING_LENGTH];
    bool is_npc = FALSE;
    int vnum;

    /*
     * Hurt the victim.
     * Inform the victim of his new state.
     */
    victim->hit -= dam;
    if ( !IS_NPC(victim)
    &&   victim->level >= LEVEL_IMMORTAL
    &&   victim->hit < 1 )
        victim->hit = 1;

    if ( !IS_NPC(victim)
    &&   IS_SET(victim->newbits, NEW_CLOAK)
    &&   victim->hit < 1 )
      {
          victim->hit += (victim->max_hit * .25);
          REMOVE_BIT(victim->newbits, NEW_CLOAK);
      }

    if ( !IS_NPC(victim) && IS_CLASS(ch, CLASS_DROW)
    &&    IS_SET(victim->newbits, NEW_DARKNESS)
    &&    victim->hit < 1 )
    {
        if (IS_SET(victim->in_room->room_flags, ROOM_TOTAL_DARKNESS))
        REMOVE_BIT(victim->in_room->room_flags, ROOM_TOTAL_DARKNESS);
    }

    if (victim->hit < 0 && IS_SET(victim->in_room->room_flags, ROOM_ARENA))
      check_arena(ch, victim);
    update_pos( victim );
    if (victim->hit < 0 && victim->in_room->vnum == 40001)
      check_wrestle(ch, victim);

    switch( victim->position )
    {
    case POS_MORTAL:
        act( "$n is mortally wounded, and spraying blood everywhere.",
            victim, NULL, NULL, TO_ROOM );
        send_to_char( 
            "You are mortally wounded, and spraying blood everywhere.\n\r",
            victim );
        break;

    case POS_INCAP:
        act( "$n is incapacitated, and bleeding badly.",
            victim, NULL, NULL, TO_ROOM );
        send_to_char(
            "You are incapacitated, and bleeding badly.\n\r",
            victim );
        break;

    case POS_STUNNED:
        act( "$n is stunned, but will soon recover.",
            victim, NULL, NULL, TO_ROOM );
        send_to_char("You are stunned, but will soon recover.\n\r",
            victim );
        break;

    case POS_DEAD:
        act( "$n is DEAD!!", victim, 0, 0, TO_ROOM );
        send_to_char( "You have been KILLED!!\n\r\n\r", victim );
        break;

    default:
        if ( dam > victim->max_hit / 4 )
            send_to_char( "That really did HURT!\n\r", victim );
        if ( victim->hit < victim->max_hit / 4 && dam > 0 )
        {
            if (!IS_NPC(victim) && IS_CLASS(victim, CLASS_VAMPIRE)
                && number_percent() < victim->beast)
                vamp_rage(victim);
            else
                send_to_char( "You sure are BLEEDING!\n\r", victim );
        }
        break;
    }

    /*
     * Sleep spells and extremely wounded folks.
     */
    if ( !IS_AWAKE(victim) )
        stop_fighting( victim, FALSE );


    /*
     * Payoff for killing things.
     */
    if ( victim->position == POS_DEAD )
    {
        group_gain( ch, victim );

        if ( !IS_NPC(victim) )
        {
            sprintf( log_buf, "%s killed by %s at %d",
                victim->name,
                (IS_NPC(ch) ? ch->short_descr : ch->name),
                victim->in_room->vnum );
            log_string( log_buf );
        

            /*
             * Dying penalty:
             * 1/2 your current exp.
             */
            if ( victim->exp > 0 )
                victim->exp = victim->exp / 2;
        }

        if (IS_NPC(victim) && !IS_NPC(ch))
        {
            ch->mkill += 1;
        
            if (IS_CLASS(ch, CLASS_DEMON) || IS_SET(ch->special, SPC_CHAMPION)
                || IS_CLASS(ch, CLASS_DROW) || IS_CLASS(ch,CLASS_WEREWOLF)
		|| IS_CLASS(ch, CLASS_CYBORG))
            {
                if ((vnum = victim->pIndexData->vnum) > 29000)
                {
                    switch (vnum)
                    {
                    default:
                        if (IS_CLASS(ch, CLASS_DEMON) || IS_SET(ch->special,SPC_CHAMPION)) {
                        ch->pcdata->stats[DEMON_CURRENT] +=victim->level*2;
                        ch->pcdata->stats[DEMON_TOTAL] +=victim->level*2;}
                        else if (IS_CLASS(ch, CLASS_DROW)) ch->pcdata->stats[DROW_POWER] += victim->level*2;
			else if (IS_CLASS(ch, CLASS_CYBORG)) ch->pcdata->stats[CYBORG_POWER] += victim->level*2;
/*
                else if (IS_CLASS(ch,CLASS_WEREWOLF))
                {
                int amount = 0;
                int amount2 = 0;
                int total = 0; 
		if ((ch->pcdata->ww_researching != 0))
		{
                if ((ch->pcdata->ww_researching == 1)) {amount = ((ch->power[DISC_WERE_BEAR] + 2) * 10);}
                else if ((ch->pcdata->ww_researching == 2)) {amount = ((ch->power[DISC_WERE_LYNX]+ 2) * 10);}
                else if ((ch->pcdata->ww_researching == 3)) {amount = ((ch->power[DISC_WERE_BOAR]+ 2) * 10);}
                else if ((ch->pcdata->ww_researching == 4)) {amount = ((ch->power[DISC_WERE_OWL]+ 2) * 10);}
                else if ((ch->pcdata->ww_researching == 5)) {amount = ((ch->power[DISC_WERE_SPID]+ 2) * 10);}
                else if ((ch->pcdata->ww_researching == 6)) {amount = ((ch->power[DISC_WERE_WOLF]+ 2) * 10);}
                else if ((ch->pcdata->ww_researching == 7)) {amount = ((ch->power[DISC_WERE_HAWK]+ 2) * 10);}
                else if ((ch->pcdata->ww_researching == 8)) {amount = ((ch->power[DISC_WERE_MANT]+ 2) * 10);}
                else if ((ch->pcdata->ww_researching == 9)) {amount = ((ch->power[DISC_WERE_RAPT]+ 2) * 10);}
                else if ((ch->pcdata->ww_researching == 10)) {amount = ((ch->power[DISC_WERE_LUNA]+ 2) * 10);}
                else if ((ch->pcdata->ww_researching == 11)) {amount = ((ch->power[DISC_WERE_PAIN]+ 2) * 10);}
                else if ((ch->pcdata->ww_researching == 12)) {amount = ((ch->power[DISC_WERE_CONG]+ 2) * 10);}
                else amount = 100;
                    
                if (victim->level < 50) amount2 = 100;
                else if (victim->level < 150) amount2 = 200;
                else if (victim->level < 250) amount2 = 400;
                else if (victim->level < 350) amount2 = 500;
                else if (victim->level < 450) amount2 = 600;
                else if (victim->level < 550) amount2 = 700;
                else if (victim->level < 650) amount2 = 800;
                else if (victim->level < 750) amount2 = 900;
                else amount2 = 1000;
                
                total = (amount2/amount);
                }
                ch->pcdata->ww_completed[AMOUNT_COMPLETED] += (amount2 / amount);
                }
*/
                        break;
                    case 29600:
                    case 30001:
                    case 30006:
                    case 30007:
                    case 30008:
                    case 30009:
                case 30000:
                        break;
                    }
                }

                else if (IS_NPC(victim) && !IS_SET(victim->act, ACT_NOEXP))
                {
                if (IS_CLASS(ch, CLASS_DEMON) || IS_SET(ch->special,SPC_CHAMPION)) {
                    ch->pcdata->stats[DEMON_CURRENT] += victim->level*2;
                    ch->pcdata->stats[DEMON_TOTAL] += victim->level*2;}
                else if (IS_CLASS(ch, CLASS_DROW))
                    ch->pcdata->stats[DROW_POWER] += victim->level*2;
		else if (IS_CLASS(ch, CLASS_CYBORG))
			ch->pcdata->stats[CYBORG_POWER] += victim->level*2;
/*                else if (IS_CLASS(ch,CLASS_WEREWOLF))
                {
                int amount;
                int amount2;
                int total;
		if ((ch->pcdata->ww_researching != 0))
		{
                if ((ch->pcdata->ww_researching == 1)) {amount = ((ch->power[DISC_WERE_BEAR] + 2) * 10);}
                else if ((ch->pcdata->ww_researching == 2)) {amount = ((ch->power[DISC_WERE_LYNX]+ 2) * 10);}
                else if ((ch->pcdata->ww_researching == 3)) {amount = ((ch->power[DISC_WERE_BOAR]+ 2) * 10);}
                else if ((ch->pcdata->ww_researching == 4)) {amount = ((ch->power[DISC_WERE_OWL]+ 2) * 10);}
                else if ((ch->pcdata->ww_researching == 5)) {amount = ((ch->power[DISC_WERE_SPID]+ 2) * 10);}
                else if ((ch->pcdata->ww_researching == 6)) {amount = ((ch->power[DISC_WERE_WOLF]+ 2) * 10);}
                else if ((ch->pcdata->ww_researching == 7)) {amount = ((ch->power[DISC_WERE_HAWK]+ 2) * 10);}
                else if ((ch->pcdata->ww_researching == 8)) {amount = ((ch->power[DISC_WERE_MANT]+ 2) * 10);}
                else if ((ch->pcdata->ww_researching == 9)) {amount = ((ch->power[DISC_WERE_RAPT]+ 2) * 10);}
                else if ((ch->pcdata->ww_researching == 10)) {amount = ((ch->power[DISC_WERE_LUNA]+ 2) * 10);}
                else if ((ch->pcdata->ww_researching == 11)) {amount = ((ch->power[DISC_WERE_PAIN]+ 2) * 10);}
                else if ((ch->pcdata->ww_researching == 12)) {amount = ((ch->power[DISC_WERE_CONG]+ 2) * 10);}
		else amount = 100;

                if (victim->level < 50) amount2 = 100;
                else if (victim->level < 150) amount2 = 200;
                else if (victim->level < 250) amount2 = 400;
                else if (victim->level < 350) amount2 = 500;
                else if (victim->level < 450) amount2 = 600;
                else if (victim->level < 550) amount2 = 700;
                else if (victim->level < 650) amount2 = 800;
                else if (victim->level < 750) amount2 = 900;
                else amount2 = 1000;

                total = (amount2/amount);
                }
                ch->pcdata->ww_completed[AMOUNT_COMPLETED] += (amount2 / amount);
                }
*/
                }
            }
            if (ch->level == 1 && ch->mkill > 4)
            {
                ch->level = 2;
                do_save(ch,"");
            }
        }
        if (!IS_NPC(victim) && IS_NPC(ch)) 
        {
           victim->mdeath = victim->mdeath + 1;
        }

        raw_kill( victim );

/*      if (!IS_NPC(ch) && !IS_NPC(victim) && victim->pcdata->bounty > 0)
        {
        sprintf(buf,"You recive a %d QP bounty, for killing %s.\n\r",
        victim->pcdata->bounty, victim->name);
        send_to_char(buf, ch);
        ch->pcdata->quest += victim->pcdata->bounty;
        victim->pcdata->bounty =0;      
        }*/

        if ( IS_SET(ch->act, PLR_AUTOLOOT) )
            do_get( ch, "all corpse" );
        else
            do_look( ch, "in corpse" );

        if ( !IS_NPC(ch) && is_npc )
        {
            if ( IS_SET(ch->act, PLR_AUTOSAC) )
                do_sacrifice( ch, "corpse" );
        }

        return;
    }

    if ( victim == ch )
        return;


    if ( !IS_NPC(victim) && victim->desc == NULL )
    {
        if ( number_range( 0, victim->wait ) == 0 )
        {
            do_recall( victim, "" );
            return;
        }
    }

/*
    if ( IS_NPC(victim) && dam > 0 )
    {
        if ( ( IS_SET(victim->act, ACT_WIMPY) && number_bits( 1 ) == 0
        &&   victim->hit < victim->max_hit / 2 )
        ||   ( IS_AFFECTED(victim, AFF_CHARM) && victim->master != NULL
        &&     victim->master->in_room != victim->in_room ) )
            do_flee( victim, "" );
    }
*/

    if ( !IS_NPC(victim)
    &&   victim->hit > 0
    &&   victim->hit <= victim->wimpy
    &&   victim->wait == 0 )
        do_flee( victim, "" );

    tail_chain( );
    return;
}



bool is_safe( CHAR_DATA *ch, CHAR_DATA *victim )
{

  if (!IS_NPC(victim) && !IS_NPC(ch))
  {
    if ( !CAN_PK(ch) || !CAN_PK(victim) )
    {
        send_to_char( "Both players must be avatars to fight.\n\r", ch );
        return TRUE;
    }  
  }
        if (victim->fight_timer > 0) return FALSE;

     if ( !IS_NPC(ch ) )
     {
        if (IS_AFFECTED(ch, AFF_PEACE) && ch->fighting != NULL)
        REMOVE_BIT(ch->affected_by, AFF_PEACE);
     }
     if ( !IS_NPC(victim) )
     {
        if (IS_AFFECTED(victim, AFF_PEACE) && victim->fighting != NULL)
        REMOVE_BIT(victim->affected_by, AFF_PEACE);
     }

    /* Ethereal people can only attack other ethereal people */
    if ( IS_AFFECTED(ch, AFF_ETHEREAL) && !IS_AFFECTED(victim, AFF_ETHEREAL) )
    {
        send_to_char( "You cannot while ethereal.\n\r", ch );
        return TRUE;
    }
    if ( !IS_AFFECTED(ch, AFF_ETHEREAL) && IS_AFFECTED(victim, AFF_ETHEREAL) )
    {
        send_to_char( "You cannot fight an ethereal person.\n\r", ch );
        return TRUE;
    }

    /* You cannot attack across planes */
    if ( IS_AFFECTED(ch, AFF_SHADOWPLANE) && !IS_AFFECTED(victim, AFF_SHADOWPLANE) )
    {
        act( "You are too insubstantial!", ch, NULL, victim, TO_CHAR );
        return TRUE;
    }
    if ( !IS_AFFECTED(ch, AFF_SHADOWPLANE) && IS_AFFECTED(victim, AFF_SHADOWPLANE) )
    {
        act( "$E is too insubstantial!", ch, NULL, victim, TO_CHAR );
        return TRUE;
    }

    if ( IS_SET(ch->in_room->room_flags,ROOM_SAFE) )
    {
        send_to_char( "You cannot fight in a safe room.\n\r", ch );
        return TRUE;
    }

    /* ARENA room checking */
    if (  IS_SET(ch->in_room->room_flags,ROOM_ARENA)
       && IS_SET(victim->in_room->room_flags,ROOM_ARENA) )
        return FALSE;


    if ( IS_HEAD(ch,LOST_HEAD) || IS_EXTRA(ch,EXTRA_OSWITCH) )
    {
        send_to_char( "Objects cannot fight!\n\r", ch );
        return TRUE;
    }
    else if ( IS_HEAD(victim,LOST_HEAD) || IS_EXTRA(victim,EXTRA_OSWITCH))
    {
        send_to_char( "You cannot attack an object.\n\r", ch );
        return TRUE;
    }

    if ( IS_NPC(ch) || IS_NPC(victim) )
        return FALSE;

    /* Thx Josh! */
    if ( victim->fighting == ch )
        return FALSE;

    if (IS_AFFECTED(ch, AFF_PEACE))
    {
        send_to_char( "You are unable to attack them.\n\r", ch );
        return TRUE;
    }

    if (IS_AFFECTED(victim, AFF_PEACE))
    {
        send_to_char( "You can't seem to attack them.\n\r", ch );
        return TRUE;
    }

    if (IS_ITEMAFF(ch, ITEMA_PEACE))
    {
        send_to_char( "You are unable to attack them.\n\r", ch );
        return TRUE;
    }

    if (IS_ITEMAFF(victim, ITEMA_PEACE))
    {
        send_to_char( "You can't seem to attack them.\n\r", ch );
        return TRUE;
    }
        return FALSE;
}

bool no_attack( CHAR_DATA *ch, CHAR_DATA *victim )
{


  if (!IS_NPC(ch) && !IS_NPC(victim))
  {
    if ( !CAN_PK(ch) || !CAN_PK(victim) )
    {
        send_to_char( "Both players must be avatars to fight.\n\r", ch );
        return TRUE;
    }     
  }
    if (victim->fight_timer > 0)
        return FALSE;

    /* Ethereal people can only attack other ethereal people */
    if ( IS_AFFECTED(ch, AFF_ETHEREAL) && !IS_AFFECTED(victim, AFF_ETHEREAL) )
    {
        send_to_char( "You cannot while ethereal.\n\r", ch );
        return TRUE;
    }
    if ( !IS_AFFECTED(ch, AFF_ETHEREAL) && IS_AFFECTED(victim, AFF_ETHEREAL) )
    {
        send_to_char( "You cannot fight an ethereal person.\n\r", ch );
        return TRUE;
    }

    /* You cannot attack across planes */
    if ( IS_AFFECTED(ch, AFF_SHADOWPLANE) && !IS_AFFECTED(victim, AFF_SHADOWPLANE) )
    {
        act( "You are too insubstantial!", ch, NULL, victim, TO_CHAR );
        return TRUE;
    }
    if ( !IS_AFFECTED(ch, AFF_SHADOWPLANE) && IS_AFFECTED(victim, AFF_SHADOWPLANE) )
    {
        act( "$E is too insubstantial!", ch, NULL, victim, TO_CHAR );
        return TRUE;
    }

    if ( IS_SET(ch->in_room->room_flags,ROOM_SAFE) )
    {
        send_to_char( "You cannot fight in a safe room.\n\r", ch );
        return TRUE;
    }

    if ( IS_HEAD(ch,LOST_HEAD) || IS_EXTRA(ch,EXTRA_OSWITCH) )
    {
        send_to_char( "Objects cannot fight!\n\r", ch );
        return TRUE;
    }
    else if ( IS_HEAD(victim,LOST_HEAD) || IS_EXTRA(victim,EXTRA_OSWITCH) )
    {
        send_to_char( "You cannot attack objects.\n\r", ch );
        return TRUE;
    }

    return FALSE;
}



/*
 * See if an attack justifies a KILLER flag.
 */
void check_killer( CHAR_DATA *ch, CHAR_DATA *victim )
{
    /*
     * Follow charm thread to responsible character.
     * Attacking someone's charmed char is hostile!
     */
    while ( IS_AFFECTED(victim, AFF_CHARM) && victim->master != NULL )
        victim = victim->master;

    /*
     * NPC's are fair game.
     * So are killers and thieves.
     */
    if ( IS_NPC(victim) )
        return;

    /*
     * Charm-o-rama.
     */
    if ( IS_SET(ch->affected_by, AFF_CHARM) )
    {
        if ( ch->master == NULL )
        {
            affect_strip( ch, gsn_charm_person );
            REMOVE_BIT( ch->affected_by, AFF_CHARM );
            return;
        }
        stop_follower( ch );
        return;
    }
    return;
}



/*
 * Check for parry.
 */
bool check_parry( CHAR_DATA *ch, CHAR_DATA *victim, int dt )
{
    OBJ_DATA *obj = NULL;
    int chance = 0;
    bool claws = FALSE;

    if ( !IS_AWAKE(victim) )
        return FALSE;

    if ( IS_NPC(victim) )
        obj = NULL;
    else if ( IS_CLASS(victim, CLASS_WEREWOLF)  && 
        victim->power[DISC_WERE_BEAR] > 2       && 
        IS_VAMPAFF(victim, VAM_CLAWS)           &&
        get_eq_char(victim, WEAR_WIELD) == NULL &&
        get_eq_char(victim, WEAR_HOLD) == NULL)
    {
        obj = NULL;
        claws = TRUE;
    }
    else if ( IS_CLASS(victim, CLASS_MONK) &&
              IS_SET(victim->newbits, NEW_MONKADAM) &&
              get_eq_char(victim, WEAR_WIELD) == NULL &&
              get_eq_char(victim, WEAR_HOLD) == NULL)
    {
        obj = NULL;
        claws = TRUE;
    }

    else
    {
        if ( ( obj = get_eq_char( victim, WEAR_WIELD ) ) == NULL 
                || obj->item_type != ITEM_WEAPON )
        {
            if ( ( obj = get_eq_char( victim, WEAR_HOLD ) ) == NULL 
                || obj->item_type != ITEM_WEAPON ) return FALSE;
        }
    }

    if (dt < 1000 || dt > 1012) return FALSE;
    if (!IS_NPC(ch))   chance -= (ch->wpn[dt-1000] * 0.1);
        else             chance -= (ch->level * 0.2);
    if (!IS_NPC(victim)) chance += (victim->wpn[dt-1000] * 0.5);
        else               chance += victim->level;

    if (!IS_NPC(victim) && IS_STANCE(victim, STANCE_CRANE) &&
        victim->stance[STANCE_CRANE] > 0 && !can_counter(ch) &&
        !can_bypass(ch,victim))
        chance += (victim->stance[STANCE_CRANE] * 0.25);

    else if (!IS_NPC(victim) && IS_STANCE(victim, STANCE_MANTIS) &&
        victim->stance[STANCE_MANTIS] > 0 && !can_counter(ch) &&
        !can_bypass(ch,victim))
        chance += (victim->stance[STANCE_MANTIS] * 0.25);

      chance -= (char_hitroll(ch) * 0.1);

    if (claws) 
    {
            if (victim->power[DISC_WERE_LYNX] > 3)
               chance += (char_hitroll(victim) * 0.1);
            else
               chance += (char_hitroll(victim) * 0.075);
    }


    if (!IS_NPC(ch))
    {
           if (IS_CLASS(ch, CLASS_VAMPIRE))
           {
                 if (ch->power[DISC_VAMP_CELE] > 0)
               chance -= (ch->power[DISC_VAMP_CELE]*4);
           }
        if (IS_CLASS(ch, CLASS_NINJA)  && ch->pcdata->powers[NPOWER_CHIKYU] >= 6
        && ch->pcdata->powers[HARA_KIRI] > 0) 
        chance -= 25;
        if (ch->pcdata->powers[NPOWER_CHIKYU] >= 5 && IS_CLASS(ch, CLASS_NINJA))
        chance -= 25;
        else if (IS_CLASS(ch, CLASS_DEMON) && IS_DEMPOWER(ch, DEM_SPEED) )
            chance -= 25;
        if ( IS_CLASS(ch, CLASS_MONK) && ch->chi[CURRENT] > 0 )
            chance -= (ch->chi[CURRENT] * 7);
        if (IS_CLASS(ch, CLASS_DROW) && IS_SET(ch->pcdata->powers[1], DPOWER_ARMS))
                chance -= 30;
        if (IS_SET(ch->newbits, NEW_MONKFLAME))
            chance -= 3;
        if (IS_CLASS(ch, CLASS_WEREWOLF) &&
            ch->power[DISC_WERE_MANT] < 11 )
            chance -= (ch->power[DISC_WERE_MANT] * 4);
    }

    if (!IS_NPC(victim))
    {
        if (victim->pcdata->powers[NPOWER_CHIKYU] >= 5 && IS_CLASS(victim, CLASS_NINJA))
        chance += 25;
        if (victim->power[DISC_VAMP_CELE] > 0 && 
            IS_CLASS(victim, CLASS_VAMPIRE)) 
            chance += (victim->power[DISC_VAMP_CELE]*4);
        if (IS_CLASS(victim, CLASS_DROW) && IS_SET(victim->pcdata->powers[1], DPOWER_ARMS))
                chance += 30;
        if (IS_CLASS(victim, CLASS_MONK) && ch->chi[CURRENT] > 0 )
                chance += (ch->chi[CURRENT] * 8);
        else if (IS_CLASS(ch, CLASS_DEMON) && IS_DEMPOWER(ch, DEM_SPEED) )
            chance -= 25;
        if (IS_SET(victim->newbits, NEW_MONKFLAME))
           chance += 4;
    }

    if      (chance > 80) chance = 80;
    else if (chance < 20) chance = 20;

    if (!IS_NPC(ch) && ch->power[DISC_VAMP_CELE] > 0 && IS_CLASS(ch, CLASS_VAMPIRE))
    {
        if (ch->pcdata->rank == AGE_METHUSELAH) chance -= 15;
        else if (ch->pcdata->rank == AGE_ELDER) chance -= 10;
        else if (ch->pcdata->rank == AGE_ANCILLA) chance -= 5;
    }

    if (!IS_NPC(victim) && victim->power[DISC_VAMP_CELE] > 0 && 
        IS_CLASS(victim, CLASS_VAMPIRE))
    {
        if (victim->pcdata->rank == AGE_METHUSELAH) chance += 15;
        else if (victim->pcdata->rank == AGE_ELDER) chance += 10;
        else if (victim->pcdata->rank == AGE_ANCILLA) chance += 5;
    }

    if ( !IS_NPC(victim) && IS_CLASS(victim, CLASS_MONK) )
    {
     if ( victim->monkblock / 4 > 0 )
        chance += victim->monkblock / 4;
    }

    if ( !IS_NPC(victim) && IS_CLASS(victim, CLASS_CYBORG))
    {
	if ((victim->pcdata->powers[CYBORG_LIMBS] > 1)) chance += 35;
	else chance += 10;
    }

    if ( !IS_NPC(ch) && IS_CLASS(ch, CLASS_CYBORG))
    {
        if ((ch->pcdata->powers[CYBORG_LIMBS] > 1)) chance += 35;
        else chance += 10;
    }
    if ( number_percent( ) < 100 && number_percent( ) >= chance )
        return FALSE;

    if (claws)
    {
        if (IS_NPC(victim) || !IS_SET(victim->act, PLR_BRIEF))
        {
          if (IS_CLASS(victim, CLASS_WEREWOLF))
            act( "You parry $n's blow with your claws.",  ch, NULL, victim, TO_VICT );
        else
            act( "You parry $n's blow with your Adamantium hands.", ch,NULL,victim, TO_VICT);
        }
            if (!IS_NPC(victim) && IS_CLASS(victim, CLASS_MONK)
                 && victim->monkblock < 150 )
              victim->monkblock++;
        
        if (IS_NPC(ch) || !IS_SET(ch->act, PLR_BRIEF))
        {
          if (IS_CLASS(victim, CLASS_WEREWOLF))
            act( "$N parries your blow with $S claws.", ch, NULL, victim, TO_CHAR );
        else
            act( "$N parries your blow with $S Adamantium claws.", ch,NULL,victim, TO_CHAR);
        }
        return TRUE;
    }
    if (!IS_NPC(victim) && obj != NULL && obj->item_type == ITEM_WEAPON &&
        obj->value[3] >= 0 && obj->value[3] <= 12)
    {
        if (IS_NPC(victim) || !IS_SET(victim->act, PLR_BRIEF))
            act( "You parry $n's blow with $p.",  ch, obj, victim, TO_VICT );
        if (IS_NPC(ch) || !IS_SET(ch->act, PLR_BRIEF))
            act( "$N parries your blow with $p.", ch, obj, victim, TO_CHAR );
        return TRUE;
    }
    if (IS_NPC(victim) || !IS_SET(victim->act, PLR_BRIEF))
        act( "You parry $n's attack.",  ch, NULL, victim, TO_VICT    );
    if (IS_NPC(ch) || !IS_SET(ch->act, PLR_BRIEF))
        act( "$N parries your attack.", ch, NULL, victim, TO_CHAR    );
    return TRUE;
}



/*
 * Check for dodge.
 */
bool check_dodge( CHAR_DATA *ch, CHAR_DATA *victim, int dt )
{
    int chance = 0;

    if ( !IS_AWAKE(victim) )
        return FALSE;

    if (!IS_NPC(ch))     chance -= (ch->wpn[dt-1000] * 0.1);
        else               chance -= (ch->level * 0.2);
    if (!IS_NPC(victim)) chance += (victim->wpn[0] * 0.5);
        else               chance += victim->level;

    if (!IS_NPC(victim) && IS_STANCE(victim, STANCE_MONGOOSE) &&
        victim->stance[STANCE_MONGOOSE] > 0 && !can_counter(ch) &&
        !can_bypass(ch,victim))
        (chance += victim->stance[STANCE_MONGOOSE] * 0.25);

    if (!IS_NPC(victim) && IS_STANCE(victim, STANCE_SWALLOW) &&
        victim->stance[STANCE_SWALLOW] > 0 && !can_counter(ch) &&
        !can_bypass(ch,victim))
        (chance += victim->stance[STANCE_SWALLOW] * 0.25);

    if (!IS_NPC(ch))
    {
        if (IS_CLASS(ch, CLASS_NINJA)  && ch->pcdata->powers[NPOWER_CHIKYU] >= 6
        && ch->pcdata->powers[HARA_KIRI] > 0)
        chance -= 25;
        if (ch->pcdata->powers[NPOWER_CHIKYU] >= 5 && IS_CLASS(ch, CLASS_NINJA))
        chance -= 25;
        if (ch->power[DISC_VAMP_CELE] > 0 && IS_CLASS(ch, CLASS_VAMPIRE)) 
            chance -= (ch->power[DISC_VAMP_CELE]*4);
        else if (IS_CLASS(ch, CLASS_DEMON) && IS_DEMPOWER( ch, DEM_SPEED) )
            chance -= 25;
        else if (IS_CLASS(ch, CLASS_WEREWOLF) &&
            ch->power[DISC_WERE_MANT] < 11 )
            chance -= (ch->power[DISC_WERE_MANT] * 4);
        else if (IS_CLASS(ch, CLASS_DROW) &&
        IS_SET(ch->pcdata->powers[1], DPOWER_SPEED))
        chance -= 25;
    }
    if (!IS_NPC(victim))
    {
        if (victim->pcdata->powers[NPOWER_CHIKYU] >= 5 && IS_CLASS(victim, CLASS_NINJA))
        chance += 30;
        if (victim->power[DISC_VAMP_CELE] > 0 && IS_CLASS(victim, CLASS_VAMPIRE)) 
            chance += (victim->power[DISC_VAMP_CELE]*4);
        else if (IS_CLASS(victim, CLASS_DEMON) && IS_DEMPOWER( victim, DEM_SPEED) )
            chance += 25;
      else if (IS_CLASS(victim, CLASS_WEREWOLF) && victim->power[DISC_WERE_MANT] < 11)
            chance += (victim->power[DISC_WERE_MANT] * 5);
        else if (IS_CLASS(victim, CLASS_DROW) && 
        IS_SET(victim->pcdata->powers[1], DPOWER_SPEED))
        chance += 25;
    }

    if      (chance > 80) chance = 80;
    else if (chance < 20) chance = 20;

    if (!IS_NPC(ch) && IS_CLASS(ch, CLASS_VAMPIRE))
    {
        if (ch->pcdata->rank == AGE_METHUSELAH) chance -= 10;
        else if (ch->pcdata->rank == AGE_ELDER) chance -= 7;
        else if (ch->pcdata->rank == AGE_ANCILLA) chance -= 3;
    }
    if (!IS_NPC(victim) && IS_CLASS(victim, CLASS_VAMPIRE))
    {
        if (victim->pcdata->rank == AGE_METHUSELAH) chance += 10;
        else if (victim->pcdata->rank == AGE_ELDER) chance += 7;
        else if (victim->pcdata->rank == AGE_ANCILLA) chance += 3;
    }

    if (!IS_NPC(victim) && IS_CLASS(victim, CLASS_MONK) 
        && ( victim->monkblock / 4 > 0 ) )
    chance += (victim->monkblock / 4);

    if ( number_percent( ) < 100 && number_percent( ) >= chance )
        return FALSE;

    if (IS_NPC(victim) || !IS_SET(victim->act, PLR_BRIEF))
        act( "You dodge $n's attack.", ch, NULL, victim, TO_VICT );
    if (IS_NPC(ch) || !IS_SET(ch->act, PLR_BRIEF))
        act( "$N dodges your attack.", ch, NULL, victim, TO_CHAR );
    return TRUE;
}



/*
 * Set position of a victim.
 */
void update_pos( CHAR_DATA *victim )
{
    CHAR_DATA *mount;
    if ( victim->hit > 0 )
    {
        if ( victim->position <= POS_STUNNED )
        {
            bool gm_stance = FALSE;
            victim->position = POS_STANDING;
            if (!IS_NPC(victim) && victim->stance[0] > 0)
            {
                int stance = victim->stance[0];
                if (victim->stance[stance] >= 200) gm_stance = TRUE;
            }
            if (IS_NPC(victim) || victim->max_hit * 0.25 > victim->hit || 
                !gm_stance)
            {
                act( "$n clambers back to $s feet.", victim, NULL, NULL, TO_ROOM);
                act( "You clamber back to your feet.", victim, NULL, NULL, TO_CHAR);
            }
            else
            {
                act( "$n flips back up to $s feet.", victim, NULL, NULL, TO_ROOM);
                act( "You flip back up to your feet.", victim, NULL, NULL, TO_CHAR);
            }
        }
        return;
    }
    else if ( (mount = victim->mount) != NULL)
    {
        if (victim->mounted == IS_MOUNT)
        {
            act("$n rolls off $N.",mount,NULL,victim,TO_ROOM);
            act("You roll off $N.",mount,NULL,victim,TO_CHAR);
        }
        else if (victim->mounted == IS_RIDING)
        {
            act("$n falls off $N.",victim,NULL,mount,TO_ROOM);
            act("You fall off $N.",victim,NULL,mount,TO_CHAR);
        }
        mount->mount    = NULL;
        victim->mount   = NULL;
        mount->mounted  = IS_ON_FOOT;
        victim->mounted = IS_ON_FOOT;
    }

    if (!IS_NPC(victim) && victim->hit <=-11 && IS_HERO(victim))
    {
        victim->hit = -10;
        if (victim->position == POS_FIGHTING) 
           stop_fighting(victim,TRUE);
        return;
    }

    if ( IS_NPC(victim) || victim->hit <= -11 )
    {
        victim->position = POS_DEAD;
        return;
    }

         if ( victim->hit <= -6 ) victim->position = POS_MORTAL;
    else if ( victim->hit <= -3 ) victim->position = POS_INCAP;
    else                          victim->position = POS_STUNNED;

    return;
}



/*
 * Start fights.
 */
void set_fighting( CHAR_DATA *ch, CHAR_DATA *victim )
{
    if ( ch->fighting != NULL )
    {
//      bug( "Set_fighting: already fighting", 0 );
        return;
    }

    if ( IS_AFFECTED(ch, AFF_SLEEP) )
        affect_strip( ch, gsn_sleep );

    ch->fighting = victim;
    ch->position = POS_FIGHTING;
    ch->damcap[DAM_CHANGE] = 1;

        autodrop(ch);
        autodrop(victim);

    return;
}



/*
 * Stop fights.
 */
void stop_embrace( CHAR_DATA *ch, CHAR_DATA *victim )
{
  if ( victim == NULL)
  {
    ch->embracing=NULL;
    return;
  }

  victim->embraced=NULL;
  ch->embracing=NULL;
  return;
}

void stop_fighting( CHAR_DATA *ch, bool fBoth )
{
    CHAR_DATA *fch;

    for ( fch = char_list; fch != NULL; fch = fch->next )
    {
        if ( fch == ch || ( fBoth && fch->fighting == ch ) )
        {
            fch->fighting       = NULL;
            fch->position       = POS_STANDING;
            update_pos( fch );
        }
    }

    return;
}



/*
 * Make a corpse out of a character.
 */
void make_corpse( CHAR_DATA *ch )
{
    char buf[MAX_STRING_LENGTH];
    OBJ_DATA *corpse;
    OBJ_DATA *obj;
    OBJ_DATA *obj_next;
    char *name;

    
   if ( IS_NPC(ch) )
    {
        name            = ch->short_descr;
        corpse          = create_object(get_obj_index(OBJ_VNUM_CORPSE_NPC), 0);
        corpse->timer   = number_range( 4, 8 );
        corpse->value[2]= ch->pIndexData->vnum;
        if ( ch->gold > 0 )
        {
            obj_to_obj( create_money( ch->gold ), corpse );
            ch->gold = 0;
        }
    }
    else
    {
        name            = ch->name;
        corpse          = create_object(get_obj_index(OBJ_VNUM_CORPSE_PC), 0);
        corpse->timer   = number_range( 25, 40 );
        /* Why should players keep their gold? */
        if ( ch->gold > 0 )
        {
            obj = create_money( ch->gold );
            if (IS_AFFECTED(ch,AFF_SHADOWPLANE) &&
                (!IS_SET(obj->extra_flags, ITEM_SHADOWPLANE) ) )
                SET_BIT(obj->extra_flags, ITEM_SHADOWPLANE);
            obj_to_obj( obj, corpse );
            ch->gold = 0;
        }
    }
if (IS_SET(ch->extra, EXTRA_ZOMBIE))
{
SET_BIT(corpse->quest, QUEST_ZOMBIE);
}

    sprintf( buf, corpse->short_descr, name );
    free_string( corpse->short_descr );
    corpse->short_descr = str_dup( buf );

    sprintf( buf, corpse->description, name );
    free_string( corpse->description );
    corpse->description = str_dup( buf );
   
    for ( obj = ch->carrying; obj != NULL; obj = obj_next )
    {
        obj_next = obj->next_content;

        obj_from_char( obj );
        if ( IS_SET( obj->extra_flags, ITEM_VANISH ) )
            extract_obj( obj );
        else
        {
            if (IS_AFFECTED(ch,AFF_SHADOWPLANE) &&
                (!IS_SET(obj->extra_flags, ITEM_SHADOWPLANE) ) )
                SET_BIT(obj->extra_flags, ITEM_SHADOWPLANE);
            obj_to_obj( obj, corpse );
        }
    }

    /* If you die in the shadowplane, your corpse should stay there */
    if (IS_AFFECTED(ch, AFF_SHADOWPLANE))
        SET_BIT(corpse->extra_flags, ITEM_SHADOWPLANE);

    obj_to_room( corpse, ch->in_room );
    return;
}



void death_cry( CHAR_DATA *ch )
{
    ROOM_INDEX_DATA *was_in_room;
    char *msg;
    int door;

    if ( IS_NPC(ch) )
        msg = "You hear something's death cry.";
    else
        msg = "You hear someone's death cry.";

    was_in_room = ch->in_room;
    for ( door = 0; door <= 5; door++ )
    {
        EXIT_DATA *pexit;

        if ( ( pexit = was_in_room->exit[door] ) != NULL
        &&   pexit->to_room != NULL
        &&   pexit->to_room != was_in_room )
        {
            ch->in_room = pexit->to_room;
            act( msg, ch, NULL, NULL, TO_ROOM );
        }
    }
    ch->in_room = was_in_room;
    return;
}

void make_part( CHAR_DATA *ch, char *argument )
{
    char  arg [MAX_INPUT_LENGTH];
    int vnum;

    argument = one_argument(argument,arg);
    vnum = 0;

    if (arg[0] == '\0') return;
    if (!str_cmp(arg,"head")) vnum = OBJ_VNUM_SEVERED_HEAD;
    else if (!str_cmp(arg,"arm")) vnum = OBJ_VNUM_SLICED_ARM;
    else if (!str_cmp(arg,"leg")) vnum = OBJ_VNUM_SLICED_LEG;
    else if (!str_cmp(arg,"heart")) vnum = OBJ_VNUM_TORN_HEART;
    else if (!str_cmp(arg,"turd")) vnum = OBJ_VNUM_TORN_HEART;
    else if (!str_cmp(arg,"entrails")) vnum = OBJ_VNUM_SPILLED_ENTRAILS;
    else if (!str_cmp(arg,"brain")) vnum = OBJ_VNUM_QUIVERING_BRAIN;
    else if (!str_cmp(arg,"eyeball")) vnum = OBJ_VNUM_SQUIDGY_EYEBALL;
    else if (!str_cmp(arg,"blood")) vnum = OBJ_VNUM_SPILT_BLOOD;
    else if (!str_cmp(arg,"face")) vnum = OBJ_VNUM_RIPPED_FACE;
    else if (!str_cmp(arg,"windpipe")) vnum = OBJ_VNUM_TORN_WINDPIPE;
    else if (!str_cmp(arg,"cracked_head")) vnum = OBJ_VNUM_CRACKED_HEAD;
    else if (!str_cmp(arg,"ear")) vnum = OBJ_VNUM_SLICED_EAR;
    else if (!str_cmp(arg,"nose")) vnum = OBJ_VNUM_SLICED_NOSE;
    else if (!str_cmp(arg,"tooth")) vnum = OBJ_VNUM_KNOCKED_TOOTH;
    else if (!str_cmp(arg,"tongue")) vnum = OBJ_VNUM_TORN_TONGUE;
    else if (!str_cmp(arg,"hand")) vnum = OBJ_VNUM_SEVERED_HAND;
    else if (!str_cmp(arg,"foot")) vnum = OBJ_VNUM_SEVERED_FOOT;
    else if (!str_cmp(arg,"thumb")) vnum = OBJ_VNUM_SEVERED_THUMB;
    else if (!str_cmp(arg,"index")) vnum = OBJ_VNUM_SEVERED_INDEX;
    else if (!str_cmp(arg,"middle")) vnum = OBJ_VNUM_SEVERED_MIDDLE;
    else if (!str_cmp(arg,"ring")) vnum = OBJ_VNUM_SEVERED_RING;
    else if (!str_cmp(arg,"little")) vnum = OBJ_VNUM_SEVERED_LITTLE;
    else if (!str_cmp(arg,"toe")) vnum = OBJ_VNUM_SEVERED_TOE;

    if ( vnum != 0 )
    {
        char buf[MAX_STRING_LENGTH];
        OBJ_DATA *obj;
        char *name;

        name            = IS_NPC(ch) ? ch->short_descr : ch->name;
        obj             = create_object( get_obj_index( vnum ), 0 );
        if (IS_NPC(ch))   obj->timer = number_range(2,5);
        else              obj->timer = -1;
        if (!str_cmp(arg,"head") && IS_NPC(ch))
            obj->value[1] = ch->pIndexData->vnum;
        else if (!str_cmp(arg,"head") && !IS_NPC(ch))
            {ch->pcdata->chobj = obj; obj->chobj = ch;obj->timer = number_range(2,3); obj->item_type = ITEM_HEAD;}
        else if (!str_cmp(arg,"arm"))
            SET_BIT(obj->extra_flags2, ITEM_ARM);
        else if (!str_cmp(arg,"brain") && !IS_NPC(ch) && 
        IS_AFFECTED(ch,AFF_POLYMORPH) && IS_HEAD(ch, LOST_HEAD))
        {
            if (ch->pcdata->chobj != NULL) ch->pcdata->chobj->chobj = NULL;
            ch->pcdata->chobj = obj;
            obj->chobj = ch;
            obj->timer = number_range(2,3);
            obj->item_type = ITEM_HEAD;
        }

        /* For blood :) KaVir */
        if (vnum == OBJ_VNUM_SPILT_BLOOD) obj->timer = 2;

        /* For voodoo dolls - KaVir */
        if (!IS_NPC(ch))
        {
            sprintf( buf, obj->name, name );
            free_string( obj->name );
            obj->name = str_dup( buf );
        }
        else
        {
            sprintf( buf, obj->name, "mob" );
            free_string( obj->name );
            obj->name = str_dup( buf );
        }

        sprintf( buf, obj->short_descr, name );
        free_string( obj->short_descr );
        obj->short_descr = str_dup( buf );

        sprintf( buf, obj->description, name );
        free_string( obj->description );
        obj->description = str_dup( buf );

        if (IS_AFFECTED(ch, AFF_SHADOWPLANE))
            SET_BIT(obj->extra_flags, ITEM_SHADOWPLANE);

        obj_to_room( obj, ch->in_room );
    }
    return;
}



void raw_kill( CHAR_DATA *victim )
{
    CHAR_DATA *mount;
    stop_fighting( victim, TRUE );
    death_cry( victim );
    make_corpse( victim );

    if ( (mount = victim->mount) != NULL)
    {
        if (victim->mounted == IS_MOUNT)
        {
            act("$n rolls off the corpse of $N.",mount,NULL,victim,TO_ROOM);
            act("You roll off the corpse of $N.",mount,NULL,victim,TO_CHAR);
        }
        else if (victim->mounted == IS_RIDING)
        {
            act("$n falls off $N.",victim,NULL,mount,TO_ROOM);
            act("You fall off $N.",victim,NULL,mount,TO_CHAR);
        }
        mount->mount    = NULL;
        victim->mount   = NULL;
        mount->mounted  = IS_ON_FOOT;
        victim->mounted = IS_ON_FOOT;
    }
 
    if ( IS_NPC(victim) )
    {
        victim->pIndexData->killed++;
        kill_table[URANGE(0, victim->level, MAX_LEVEL-1)].killed++;
        extract_char( victim, TRUE );
        return;
    }

    extract_char( victim, FALSE );
    while ( victim->affected )
        affect_remove( victim, victim->affected );
    if (IS_AFFECTED(victim,AFF_POLYMORPH) && IS_AFFECTED(victim,AFF_ETHEREAL))
    {
        victim->affected_by     = AFF_POLYMORPH + AFF_ETHEREAL;
    }
    else if (IS_AFFECTED(victim,AFF_POLYMORPH))
        victim->affected_by     = AFF_POLYMORPH;
    else if (IS_AFFECTED(victim,AFF_ETHEREAL))
        victim->affected_by     = AFF_ETHEREAL;
    else
        victim->affected_by     = 0;

    REMOVE_BIT(victim->immune, IMM_STAKE);
    REMOVE_BIT(victim->extra, TIED_UP);
    REMOVE_BIT(victim->extra, GAGGED);
    REMOVE_BIT(victim->extra, BLINDFOLDED);
    REMOVE_BIT(victim->extra, EXTRA_PREGNANT);
    REMOVE_BIT(victim->extra, EXTRA_LABOUR);
    victim->pcdata->stats[DEMON_POWER] = 0;

    victim->itemaffect   = 0;
    victim->loc_hp[0]    = 0;
    victim->loc_hp[1]    = 0;
    victim->loc_hp[2]    = 0;
    victim->loc_hp[3]    = 0;
    victim->loc_hp[4]    = 0;
    victim->loc_hp[5]    = 0;
    victim->loc_hp[6]    = 0;
    victim->armor        = 100;
    victim->position     = POS_RESTING;
    victim->hit          = UMAX( 1, victim->hit  );
    victim->mana         = UMAX( 1, victim->mana );
    victim->move         = UMAX( 1, victim->move );
    victim->hitroll      = 0;
    victim->damroll      = 0;
    victim->saving_throw = 0;
    victim->carry_weight = 0;
    victim->carry_number = 0;
    do_call(victim,"all");
    save_char_obj( victim );
    return;
}


void behead( CHAR_DATA *victim )
{
    char buf [MAX_STRING_LENGTH];
    ROOM_INDEX_DATA *location;

    if (IS_NPC(victim)) return;

    location = victim->in_room;

    stop_fighting( victim, TRUE );

    make_corpse( victim );

    extract_char( victim, FALSE );

    char_from_room(victim);
    char_to_room(victim,location);

    if (victim == NULL)
    {bug( "Behead: Victim no longer exists.", 0 );return;}

    make_part( victim, "head" );

    while ( victim->affected )
        affect_remove( victim, victim->affected );
    if (IS_AFFECTED(victim,AFF_POLYMORPH) && IS_AFFECTED(victim,AFF_ETHEREAL))
    {
        victim->affected_by     = AFF_POLYMORPH + AFF_ETHEREAL;
    }
    else if (IS_AFFECTED(victim,AFF_POLYMORPH))
        victim->affected_by     = AFF_POLYMORPH;
    else if (IS_AFFECTED(victim,AFF_ETHEREAL))
        victim->affected_by     = AFF_ETHEREAL;
    else
        victim->affected_by     = 0;

    REMOVE_BIT(victim->immune, IMM_STAKE);
    REMOVE_BIT(victim->extra, TIED_UP);
    REMOVE_BIT(victim->extra, GAGGED);
    REMOVE_BIT(victim->extra, BLINDFOLDED);
    REMOVE_BIT(victim->extra, EXTRA_PREGNANT);
    REMOVE_BIT(victim->extra, EXTRA_LABOUR);
    victim->pcdata->stats[DEMON_POWER] = 0;

    victim->itemaffect   = 0;
    victim->loc_hp[0]    = 0;
    victim->loc_hp[1]    = 0;
    victim->loc_hp[2]    = 0;
    victim->loc_hp[3]    = 0;
    victim->loc_hp[4]    = 0;
    victim->loc_hp[5]    = 0;
    victim->loc_hp[6]    = 0;
    victim->affected_by  = 0;
    victim->armor        = 100;
    victim->position     = POS_STANDING;
    victim->hit          = 1;
    victim->mana         = UMAX( 1, victim->mana );
    victim->move         = UMAX( 1, victim->move );
    victim->hitroll      = 0;
    victim->damroll      = 0;
    victim->saving_throw = 0;
    victim->carry_weight = 0;
    victim->carry_number = 0;

    if (victim->cur_form != get_normal_form(victim))
    {
        set_form(victim, get_normal_form(victim));
        stc("Your body reverts to it's normal form.\n\r",victim);
    }

    SET_BIT(victim->loc_hp[0],LOST_HEAD);
    SET_BIT(victim->affected_by,AFF_POLYMORPH);
    sprintf(buf,"the severed head of %s",victim->name);
    free_string(victim->morph);
    victim->morph = str_dup(buf);
    do_call(victim,"all");
    save_char_obj( victim );
    return;
}



void group_gain( CHAR_DATA *ch, CHAR_DATA *victim )
{
    char buf[MAX_STRING_LENGTH];
    CHAR_DATA *gch;
    CHAR_DATA *lch;
    CHAR_DATA *mount;
    int xp;
    int members;

    /*
     * Monsters don't get kill xp's or alignment changes.
     * P-killing doesn't help either.
     * Dying of mortal wounds or poison doesn't give xp to anyone!
     */
    if ( (IS_NPC(ch) && (mount = ch->mount) == NULL) || victim == ch )
        return;
    
    members = 0;
    for ( gch = ch->in_room->people; gch != NULL; gch = gch->next_in_room )
    {
        if ( is_same_group( gch, ch ) )
            members++;
    }

    if ( members == 0 )
    {
        bug( "Group_gain: members.", members );
        members = 1;
    }

    lch = (ch->leader != NULL) ? ch->leader : ch;

    for ( gch = ch->in_room->people; gch != NULL; gch = gch->next_in_room )
    {
        OBJ_DATA *obj;
        OBJ_DATA *obj_next;

        if ( !is_same_group( gch, ch ) )
            continue;

        xp = xp_compute( gch, victim )*1.2 / members;
        sprintf( buf, "You receive %d experience points.\n\r", xp );
        send_to_char( buf, gch );
        if ((mount = gch->mount) != NULL) send_to_char( buf, mount );
        gain_exp( gch, xp );

        for ( obj = ch->carrying; obj != NULL; obj = obj_next )
        {
            obj_next = obj->next_content;
            if ( obj->wear_loc == WEAR_NONE )
                continue;

            if ( ( IS_OBJ_STAT(obj, ITEM_ANTI_EVIL)    && IS_EVIL(ch)    )
            ||   ( IS_OBJ_STAT(obj, ITEM_ANTI_GOOD)    && IS_GOOD(ch)    )
            ||   ( IS_OBJ_STAT(obj, ITEM_ANTI_NEUTRAL) && IS_NEUTRAL(ch) ) )
            {
                act( "You are zapped by $p.", ch, obj, NULL, TO_CHAR );
                act( "$n is zapped by $p.",   ch, obj, NULL, TO_ROOM );
                obj_from_char( obj );
                obj_to_room( obj, ch->in_room );
            }
        }
    }

    return;
}



/*
 * Compute xp for a kill.
 * Also adjust alignment of killer.
 * Edit this function to change xp computations.
 */
/*
int xp_compute( CHAR_DATA *gch, CHAR_DATA *victim )
{
    int align;
    int xp;

    int vnum;
    int victim_level; 

    xp    = 300 - URANGE( -3, 3 - (victim->level*5/3), 6 ) * 50;
    align = gch->alignment - victim->alignment;

    if (victim->level > 1000 )
        victim_level = 1000;
    else
        victim_level = victim->level;

    if (IS_HERO(gch))
    {
        
        gch->alignment  = gch->alignment;
    }


     
    if (IS_NPC(victim) && (vnum = victim->pIndexData->vnum) > 29000)
    {
        switch (vnum)
        {
        default:
            break;
        case 29600:
        case 30001:
        case 30006:
        case 30007:
        case 30008:
        case 30009:
        case 30000:
            return 0;
        }
    }

    if (IS_NPC(victim) && (IS_SET(victim->act, ACT_NOEXP) || IS_IMMORTAL(gch))) 
        return 0;

    xp    -= xp * number_range( -2, 2 ) / 8;

    xp     = number_range( xp * 3 / 4, xp * 5 / 4 );
    xp     = UMAX( 0, xp );
    xp     = (xp * (victim_level+1) * 0.65);
//  xp     = xp / 2; 


    if (!IS_NPC(gch))
    {
        gch->pcdata->score[SCORE_TOTAL_LEVEL] += victim->level;
        if (victim->level > gch->pcdata->score[SCORE_HIGH_LEVEL])
            gch->pcdata->score[SCORE_HIGH_LEVEL] += victim->level;
        if (victim->level > 950) return 0;
        gch->pcdata->score[SCORE_TOTAL_XP] += xp;
        if (xp > gch->pcdata->score[SCORE_HIGH_XP])
            gch->pcdata->score[SCORE_HIGH_XP] += xp;
    }
    
   
    if (!IS_NPC(gch) && xp > 499
        && gch->pcdata->disc_points != 666
        && gch->pcdata->disc_research != -1)
    {
        stc("You gained a discipline point.\n\r", gch);
        gain_disc_points(gch, 1);
    }
    
    xp *= 5/3;
    return xp;
}

*/


/*
 * Compute xp for a kill.
 * Also adjust alignment of killer.
 * Edit this function to change xp computations.
 */
int xp_compute( CHAR_DATA *gch, CHAR_DATA *victim )
{
    int align;
    int xp;
    int extra;
    int level;
    int number;
    int vnum;
    int victim_level; /* put to stop mass exp give outs Rotain */

    xp    = 300 - URANGE( -3, 3 - (victim->level*5/3), 6 ) * 50;
    align = gch->alignment - victim->alignment;

                if (IS_NPC(victim) && IS_CLASS(gch, CLASS_WEREWOLF) && !IS_SET(victim->act, ACT_NOEXP))
                {
                int amount = 0;
                int amount2 = 0;
                int total = 0;
                if ((gch->pcdata->ww_researching[TOTEM_RESEARCHING] != 0))
                {
                if ((gch->pcdata->ww_researching[TOTEM_RESEARCHING] == 1)) {amount = ((gch->power[DISC_WERE_BEAR] + 2) * 10);}
                else if ((gch->pcdata->ww_researching[TOTEM_RESEARCHING] == 2)) {amount = ((gch->power[DISC_WERE_LYNX]+ 2) * 10);}
                else if ((gch->pcdata->ww_researching[TOTEM_RESEARCHING] == 3)) {amount = ((gch->power[DISC_WERE_BOAR]+ 2) * 10);}
                else if ((gch->pcdata->ww_researching[TOTEM_RESEARCHING] == 4)) {amount = ((gch->power[DISC_WERE_OWL]+ 2) * 10);}
                else if ((gch->pcdata->ww_researching[TOTEM_RESEARCHING] == 5)) {amount = ((gch->power[DISC_WERE_SPID]+ 2) * 10);}
                else if ((gch->pcdata->ww_researching[TOTEM_RESEARCHING] == 6)) {amount = ((gch->power[DISC_WERE_WOLF]+ 2) * 10);}
                else if ((gch->pcdata->ww_researching[TOTEM_RESEARCHING] == 7)) {amount = ((gch->power[DISC_WERE_HAWK]+ 2) * 10);}
                else if ((gch->pcdata->ww_researching[TOTEM_RESEARCHING] == 8)) {amount = ((gch->power[DISC_WERE_MANT]+ 2) *  10);}
                else if ((gch->pcdata->ww_researching[TOTEM_RESEARCHING] == 9)) {amount = ((gch->power[DISC_WERE_RAPT]+ 2) * 10);}
                else if ((gch->pcdata->ww_researching[TOTEM_RESEARCHING] == 10)) {amount = ((gch->power[DISC_WERE_LUNA]+ 2) * 10);}
                else if ((gch->pcdata->ww_researching[TOTEM_RESEARCHING] == 11)) {amount = ((gch->power[DISC_WERE_PAIN]+ 2) * 10);}
                else if ((gch->pcdata->ww_researching[TOTEM_RESEARCHING] == 12)) {amount = ((gch->power[DISC_WERE_CONG]+ 2) * 10);}
                else amount = 100;
      
                if (victim->level < 50) amount2 = 100;
                else if (victim->level < 150) amount2 = 200;
                else if (victim->level < 250) amount2 = 400;
                else if (victim->level < 350) amount2 = 500;
                else if (victim->level < 450) amount2 = 600;
                else if (victim->level < 550) amount2 = 700;
                else if (victim->level < 650) amount2 = 800;
                else if (victim->level < 750) amount2 = 900;
                else amount2 = 1000;
        
                total = (amount2/amount);
        
                gch->pcdata->ww_completed[AMOUNT_COMPLETED] += (amount2 / amount);
                }  
                if ((gch->pcdata->ww_completed[AMOUNT_COMPLETED] > 100))
                gch->pcdata->ww_completed[AMOUNT_COMPLETED] = 100;
                }

    if (victim->level > 1000 )
        victim_level = 1000;
    else
        victim_level = victim->level;

    if (IS_HERO(gch))
    {
        /* Avatars shouldn't be able to change their alignment */
        gch->alignment  = gch->alignment;
    }
    else if ( align >  500 )
    {
        gch->alignment  = UMIN( gch->alignment + (align-500)/4,  1000 );
        xp = 5 * xp / 4;
    }
    else if ( align < -500 )
    {
        gch->alignment  = UMAX( gch->alignment + (align+500)/4, -1000 );
    }
    else
    {
        gch->alignment -= gch->alignment / 4;
        xp = 3 * xp / 4;
    }

     /* 
      * Put in mob vnum that you don't want players to gain exp for
      * Rotain
      */
    if (IS_NPC(victim) && (vnum = victim->pIndexData->vnum) > 29000)
    {
        switch (vnum)
        {
        default:
            break;
        case 29600:
        case 30001:
        case 30006:
        case 30007:
        case 30008:
        case 30009:
        case 30000:
            return 0;
        }
    }

/*                if (IS_NPC(victim) && IS_CLASS(gch, CLASS_WEREWOLF) && !IS_SET(victim->act, ACT_NOEXP))
                {
                int amount = 0;
                int amount2 = 0;
                int total = 0;
                if ((gch->pcdata->ww_researching != 0))
                {
                if ((gch->pcdata->ww_researching == 1)) {amount = ((gch->power[DISC_WERE_BEAR] + 2) * 10);}
                else if ((gch->pcdata->ww_researching == 2)) {amount = ((gch->power[DISC_WERE_LYNX]+ 2) * 10);}
                else if ((gch->pcdata->ww_researching == 3)) {amount = ((gch->power[DISC_WERE_BOAR]+ 2) * 10);}
                else if ((gch->pcdata->ww_researching == 4)) {amount = ((gch->power[DISC_WERE_OWL]+ 2) * 10);}
                else if ((gch->pcdata->ww_researching == 5)) {amount = ((gch->power[DISC_WERE_SPID]+ 2) * 10);}
                else if ((gch->pcdata->ww_researching == 6)) {amount = ((gch->power[DISC_WERE_WOLF]+ 2) * 10);}
                else if ((gch->pcdata->ww_researching == 7)) {amount = ((gch->power[DISC_WERE_HAWK]+ 2) * 10);}
                else if ((gch->pcdata->ww_researching == 8)) {amount = ((gch->power[DISC_WERE_MANT]+ 2) * 10);}
                else if ((gch->pcdata->ww_researching == 9)) {amount = ((gch->power[DISC_WERE_RAPT]+ 2) * 10);}
                else if ((gch->pcdata->ww_researching == 10)) {amount = ((gch->power[DISC_WERE_LUNA]+ 2) * 10);}
                else if ((gch->pcdata->ww_researching == 11)) {amount = ((gch->power[DISC_WERE_PAIN]+ 2) * 10);}
                else if ((gch->pcdata->ww_researching == 12)) {amount = ((gch->power[DISC_WERE_CONG]+ 2) * 10);}
                else amount = 100;

                if (victim->level < 50) amount2 = 100;
                else if (victim->level < 150) amount2 = 200;
                else if (victim->level < 250) amount2 = 400;
                else if (victim->level < 350) amount2 = 500;
                else if (victim->level < 450) amount2 = 600;
                else if (victim->level < 550) amount2 = 700;
                else if (victim->level < 650) amount2 = 800;
                else if (victim->level < 750) amount2 = 900;
                else amount2 = 1000;

                total = (amount2/amount);
                
                gch->pcdata->ww_completed[AMOUNT_COMPLETED] += (amount2 / amount);
		}
		if ((gch->pcdata->ww_completed[AMOUNT_COMPLETED] > 100))
		gch->pcdata->ww_completed[AMOUNT_COMPLETED] = 100;
                }*/

    if (IS_NPC(victim) && (IS_SET(victim->act, ACT_NOEXP) || IS_IMMORTAL(gch))) 
        return .40;

    /*
     * Adjust for popularity of target:
     *   -1/8 for each target over  'par' (down to -100%)
     *   +1/8 for each target under 'par' (  up to + 25%)
     */
    level  = URANGE( 0, victim_level, MAX_LEVEL - 1 );
    number = UMAX( 1, kill_table[level].number );
    extra  = victim->pIndexData->killed - kill_table[level].killed / number;
/*  xp    -= xp * URANGE( -2, extra, 8 ) / 8;
    xp    -= xp * URANGE( -2, extra, 6 ) / 8; */

    xp    -= xp * number_range( -2, 2 ) / 8;

    xp     = number_range( xp * 3 / 4, xp * 5 / 4 );
    xp     = UMAX( 0, xp );
    xp     = (xp * (victim_level+1) * 0.60);
    xp     = xp / 2; /* Put in cause players compaling to much exp :P */

    if (!IS_NPC(gch))
    {
        gch->pcdata->score[SCORE_TOTAL_LEVEL] += victim->level;
        if (victim->level > gch->pcdata->score[SCORE_HIGH_LEVEL])
            gch->pcdata->score[SCORE_HIGH_LEVEL] += victim->level;
        if (victim->level > 950) return 0;
        gch->pcdata->score[SCORE_TOTAL_XP] += xp;
        if (xp > gch->pcdata->score[SCORE_HIGH_XP])
            gch->pcdata->score[SCORE_HIGH_XP] += xp;
    }
        xp = xp *4/3;
    return xp;
}



void dam_message( CHAR_DATA *ch, CHAR_DATA *victim, int dam, int dt )
{
    static char * const attack_table[] =
    {
        "hit",
        "slice",  "stab",  "slash", "whip", "claw",
        "blast",  "pound", "crush", "grep", "bite",
        "pierce", "suck"
    };
    static char * const attack_table2[] =
    {
        "hits",
        "slices",  "stabs",  "slashes", "whips", "claws",
        "blasts",  "pounds", "crushes", "greps", "bites",
        "pierces", "sucks"
    };

    char buf1[512], buf2[512], buf3[512];
    const char *vs;
    const char *vp;
    const char *attack;
    const char *attack2;
    int damp;
    int bodyloc;
    int recover;
    bool critical = FALSE;
    char punct;

if (!IS_NPC(ch) && IS_SET(ch->newbits,NEW_REND)&& dam>0
        && number_range(1,7) == 5) critical=TRUE;
         if ( dam ==   0 ) { vs = " miss";      vp = " misses";         }
    else if ( dam <=  50 ) { vs = " lightly";   vp = " lightly";        }
    else if ( dam <= 100 ) { vs = "";           vp = "";                }
    else if ( dam <= 250 ) { vs = " hard";      vp = " hard";           }
    else if ( dam <= 500 ) { vs = " very hard"; vp = " very hard";      }
    else if ( dam <= 750 ) { vs = " extremely hard"; vp = " extremely hard";}
    else if ( dam <= 1250 ) { vs = " incredibly hard";vp = " incredibly hard";} 
    else if ( dam <= 2000 ) { vs = " insanely hard";vp= " insanely hard";}
    else                   { vs = " unbelievably hard";vp = " unbelievably hard";}

    /* If victim's hp are less/equal to 'damp', attacker gets a death blow */
    if (IS_NPC(victim)) damp = 0;
    else                damp = -10;
    if ( (victim->hit - dam > damp ) || (dt >= 0 && dt < MAX_SKILL) ||
        (IS_NPC(victim) && IS_SET(victim->act, ACT_NOPARTS)) )
    {
        punct   = (dam <= 250) ? '.' : '!';

        if ( dt == TYPE_HIT && !IS_NPC(ch) && !IS_VAMPAFF(ch,VAM_CLAWS) )
        {
            if (dam == 0)
            {
                sprintf( buf1, "$n%s $N%c[%d]",  vp, punct, dam );
                sprintf( buf2, "You%s $N%c[%d]", vs, punct, dam );
                sprintf( buf3, "$n%s you%c", vp, punct );
            }
            else
            {
                sprintf( buf1, "$n hits $N%s%c[%d]",  vp, punct, dam );
                sprintf( buf2, "You hit $N%s%c[%d]", vs, punct, dam );
                sprintf( buf3, "$n hits you%s%c[%d]", vp, punct, dam );
                critical = TRUE;
            }
        }

        else if ( dt == TYPE_HIT && !IS_NPC(ch) && IS_SET(ch->newbits, NEW_MONKFLAME))
        {
            if (dam >= 1)
            {
              if (!IS_CLASS(ch, CLASS_WEREWOLF))
              {
                sprintf( buf1, "$n's flaming hands hit $N%s%c[%d]", vp, punct, dam );
                sprintf( buf2, "Your flaming hands hit $N%s%c[%d]", vs, punct, dam );
                sprintf( buf3, "$n's flaming hands hit you%s%c[%d]", vp, punct, dam );
              }
              else
              {
                sprintf( buf1, "$n's flaming claws hit $N%s%c[%d]", vp, punct, dam );
                sprintf( buf2, "Your flaming claws hit $N%s%c[%d]", vs, punct, dam );
                sprintf( buf3, "$n's flaming claws hit you%s%c[%d]", vp, punct, dam );
              }
            }
            else 
            {
                sprintf( buf1, "$n's hit%s $N%c[%d]",  vp, punct, dam );
                sprintf( buf2, "Your hit%s $N%c[%d]", vs, punct, dam );
                sprintf( buf3, "$n hit%s you%c[%d]", vp, punct, dam );
                critical = TRUE;
            }
        }
        else
        {
            if ( dt == TYPE_HIT && !IS_NPC(ch) && IS_VAMPAFF(ch,VAM_CLAWS))
            {
                attack  = attack_table[dt - TYPE_HIT + 5];
                attack2 = attack_table2[dt - TYPE_HIT + 5];
            }
            else if ( dt >= 0 && dt < MAX_SKILL )
            {
                attack = skill_table[dt].noun_damage;
                attack2 = skill_table[dt].noun_damage;
            }
            else if ( dt >= TYPE_HIT
            && dt < TYPE_HIT + sizeof(attack_table)/sizeof(attack_table[0]) )
            {
                attack  = attack_table[dt - TYPE_HIT];
                attack2 = attack_table2[dt - TYPE_HIT];
            }
            else
            {/*
                bug( "Dam_message: bad dt %d.", dt );
               */ dt  = TYPE_HIT;
                attack  = attack_table[0];
                attack2 = attack_table2[0];
            }

            if (dam == 0)
            {
                sprintf( buf1, "$n's %s%s $N%c[%d]",  attack, vp, punct, dam );
                sprintf( buf2, "Your %s%s $N%c[%d]",  attack, vp, punct, dam );
                sprintf( buf3, "$n's %s%s you%c[%d]", attack, vp, punct, dam );
            }

            else if (IS_SET(ch->newbits, NEW_MONKFLAME) && (dam == 0))
            {
                sprintf( buf1, "$n's flaming %s%s $N%c[%d]", attack2, vp, punct, dam );
                sprintf( buf2, "Your flaming %s%s $N%c[%d]",  attack, vp, punct, dam );
                sprintf( buf3, "$n's flaming %s%s you%c[%d]", attack2, vp, punct, dam );
            }
       

            else
            {
                if ( dt >= 0 && dt < MAX_SKILL )
                {
                    sprintf( buf1, "$n's %s strikes $N%s%c[%d]",  attack2, vp, punct, dam );
                    sprintf( buf2, "Your %s strikes $N%s%c[%d]",  attack, vp, punct, dam );
                    sprintf( buf3, "$n's %s strikes you%s%c[%d]", attack2, vp, punct, dam );
                }

                else if (IS_SET(ch->newbits, NEW_MONKFLAME))
            {
                sprintf( buf1, "$n's flaming %s hits $N%s%c[%d]", attack2, vp, punct, dam);
                sprintf( buf2, "Your flaming %s hits $N%s%c[%d]", attack, vp, punct, dam);
                sprintf( buf3, "$n's flaming %s hits you%s%c[%d]", attack2, vp, punct, dam);
            }
       

                else
                {
                    sprintf( buf1, "$n %s $N%s%c[%d]",  attack2, vp, punct, dam );
                    sprintf( buf2, "You %s $N%s%c[%d]",  attack, vp, punct, dam );
                    sprintf( buf3, "$n %s you%s%c[%d]", attack2, vp, punct, dam );
                    critical = TRUE;
                }
            }

            recover = 0;

            if (!IS_NPC(victim) && IS_SET(victim->newbits,NEW_SKIN) &&
                 (attack=="slash" || attack == "slice" || attack ==
                  "pierce" || attack == "stab"))
           recover=number_range(1,dam);           
            /* Check for weapon resistance - KaVir */
            if ( !IS_NPC(victim) && IS_IMMUNE(victim, IMM_SLASH) &&
                (attack == "slash" || attack == "slice") && dam > 0 )
                recover = number_range(1,dam);
            if ( !IS_NPC(victim) && IS_IMMUNE(victim, IMM_STAB) &&
                (attack == "stab" || attack == "pierce") && dam > 0 )
                recover = number_range(1,dam);
            if ( !IS_NPC(victim) && IS_IMMUNE(victim, IMM_SMASH) &&
                (attack == "blast" || attack == "pound" || attack == "crush") && dam > 0 )
                recover = number_range(1,dam);
            if ( !IS_NPC(victim) && IS_IMMUNE(victim, IMM_ANIMAL) &&
                (attack == "bite" || attack == "claw") && dam > 0 )
                recover = number_range(1,dam);
            if ( !IS_NPC(victim) && IS_IMMUNE(victim, IMM_MISC) &&
                (attack == "grep" || attack == "suck" || attack == "whip") && dam > 0 )
                recover = number_range(1,dam);
            
        }
        act( buf1, ch, NULL, victim, TO_NOTVICT );
        act( buf2, ch, NULL, victim, TO_CHAR );
        act( buf3, ch, NULL, victim, TO_VICT );
        if (critical) critical_hit(ch,victim,dt,dam);
        return;
    }

    if ( dt == TYPE_HIT && !IS_NPC( ch ) && !IS_VAMPAFF(ch,VAM_CLAWS) 
        &&!IS_VAMPAFF(ch,VAM_FANGS))
    {
        damp=number_range(1,5);
        if ( damp == 1 )
        {
            act("You ram your fingers into $N's eye sockets and rip $S face off.", ch, NULL, victim, TO_CHAR);
            act("$n rams $s fingers into $N's eye sockets and rips $S face off.", ch, NULL, victim, TO_NOTVICT);
            act("$n rams $s fingers into your eye sockets and rips your face off.", ch, NULL, victim, TO_VICT);
            make_part(victim,"face");
        }
        else if ( damp == 2 )
        {
            act("You grab $N by the throat and tear $S windpipe out.", ch, NULL, victim, TO_CHAR);
            act("$n grabs $N by the throat and tears $S windpipe out.", ch, NULL, victim, TO_NOTVICT);
            act("$n grabs you by the throat and tears your windpipe out.", ch, NULL, victim, TO_VICT);
            make_part(victim,"windpipe");
        }
        else if ( damp == 3 )
        {
            act("You punch your fist through $N's stomach and rip out $S entrails.", ch, NULL, victim, TO_CHAR);
            act("$n punches $s fist through $N's stomach and rips out $S entrails.", ch, NULL, victim, TO_NOTVICT);
            act("$n punches $s fist through your stomach and rips out your entrails.", ch, NULL, victim, TO_VICT);
            make_part(victim,"entrails");
        }
        else if ( damp == 4 )
        {
            if (!IS_BODY(victim,BROKEN_SPINE))
                SET_BIT(victim->loc_hp[1],BROKEN_SPINE);
            act("You hoist $N above your head and slam $M down upon your knee.\n\rThere is a loud cracking sound as $N's spine snaps.", ch, NULL, victim, TO_CHAR);
            act("$n hoists $N above $s head and slams $M down upon $s knee.\n\rThere is a loud cracking sound as $N's spine snaps.", ch, NULL, victim, TO_NOTVICT);
            act("$n hoists you above $s head and slams you down upon $s knee.\n\rThere is a loud cracking sound as your spine snaps.", ch, NULL, victim, TO_VICT);
        }
        else if ( damp == 5 )
        {
            act("You lock your arm around $N's head, and give it a vicious twist.", ch, NULL, victim, TO_CHAR);
            act("$n locks $s arm around $N's head, and gives it a vicious twist.", ch, NULL, victim, TO_NOTVICT);
            act("$n locks $s arm around your head, and gives it a vicious twist.", ch, NULL, victim, TO_VICT);
            if (!IS_BODY(victim,BROKEN_NECK))
            {
                act("There is a loud snapping noise as your neck breaks.", victim, NULL, NULL, TO_CHAR);
                act("There is a loud snapping noise as $n's neck breaks.", victim, NULL, NULL, TO_ROOM);
                SET_BIT(victim->loc_hp[1],BROKEN_NECK);
            }
        }
        return;
    }
    if ( dt >= 0 && dt < MAX_SKILL )
        attack = skill_table[dt].noun_damage;
    else if ( dt >= TYPE_HIT
    && dt < TYPE_HIT + sizeof(attack_table)/sizeof(attack_table[0]) )
        attack = attack_table[dt - TYPE_HIT];
    else
    {
        dt  = TYPE_HIT;
        attack  = attack_table[0];
    }

    if ( attack == "slash" || attack == "slice" )
    {
        damp=number_range(1,8);
        if ( damp == 1 )
        {
            act("You swing your blade in a low arc, rupturing $N's abdominal cavity.\n\r$S entrails spray out over a wide area.", ch, NULL, victim, TO_CHAR);
            act("$n swings $s blade in a low arc, rupturing $N's abdominal cavity.\n\r$S entrails spray out over a wide area.", ch, NULL, victim, TO_NOTVICT);
            act("$n swings $s blade in a low arc, rupturing your abdominal cavity.\n\rYour entrails spray out over a wide area.", ch, NULL, victim, TO_VICT);
            make_part(victim,"entrails");
        }
        else if ( damp == 2 )
        {
            act("You thrust your blade into $N's mouth and twist it viciously.\n\rThe end of your blade bursts through the back of $S head.", ch, NULL, victim, TO_CHAR);
            act("$n thrusts $s blade into $N's mouth and twists it viciously.\n\rThe end of the blade bursts through the back of $N's head.", ch, NULL, victim, TO_NOTVICT);
            act("$n thrusts $s blade into your mouth and twists it viciously.\n\rYou feel the end of the blade burst through the back of your head.", ch, NULL, victim, TO_VICT);
        }
        else if ( damp == 3 )
        {
            if (!IS_BODY(victim,CUT_THROAT))
                SET_BIT(victim->loc_hp[1],CUT_THROAT);
            if (!IS_BLEEDING(victim,BLEEDING_THROAT))
                SET_BIT(victim->loc_hp[6],BLEEDING_THROAT);
            act("Your blow slices open $N's carotid artery, spraying blood everywhere.", ch, NULL, victim, TO_CHAR);
            act("$n's blow slices open $N's carotid artery, spraying blood everywhere.", ch, NULL, victim, TO_NOTVICT);
            act("$n's blow slices open your carotid artery, spraying blood everywhere.", ch, NULL, victim, TO_VICT);
            make_part(victim,"blood");
        }
        else if ( damp == 4 )
        {
            if (!IS_BODY(victim,CUT_THROAT))
                SET_BIT(victim->loc_hp[1],CUT_THROAT);
            if (!IS_BLEEDING(victim,BLEEDING_THROAT))
                SET_BIT(victim->loc_hp[6],BLEEDING_THROAT);
            act("You swing your blade across $N's throat, showering the area with blood.", ch, NULL, victim, TO_CHAR);
            act("$n swings $s blade across $N's throat, showering the area with blood.", ch, NULL, victim, TO_NOTVICT);
            act("$n swings $s blade across your throat, showering the area with blood.", ch, NULL, victim, TO_VICT);
            make_part(victim,"blood");
        }
        else if ( damp == 5 )
        {
            if (!IS_HEAD(victim,BROKEN_SKULL))
            {
                act("You swing your blade down upon $N's head, splitting it open.\n\r$N's brains pour out of $S forehead.", ch, NULL, victim, TO_CHAR);
                act("$n swings $s blade down upon $N's head, splitting it open.\n\r$N's brains pour out of $S forehead.", ch, NULL, victim, TO_NOTVICT);
                act("$n swings $s blade down upon your head, splitting it open.\n\rYour brains pour out of your forehead.", ch, NULL, victim, TO_VICT);
                make_part(victim,"brain");
                SET_BIT(victim->loc_hp[0],BROKEN_SKULL);
            }
            else
            {
                act("You plunge your blade deep into $N's chest.", ch, NULL, victim, TO_CHAR);
                act("$n plunges $s blade deep into $N's chest.", ch, NULL, victim, TO_NOTVICT);
                act("$n plunges $s blade deep into your chest.", ch, NULL, victim, TO_VICT);
            }
        }
        else if ( damp == 6 )
        {
            act("You swing your blade between $N's legs, nearly splitting $M in half.", ch, NULL, victim, TO_CHAR);
            act("$n swings $s blade between $N's legs, nearly splitting $M in half.", ch, NULL, victim, TO_NOTVICT);
            act("$n swings $s blade between your legs, nearly splitting you in half.", ch, NULL, victim, TO_VICT);
        }
        else if ( damp == 7 )
        {
            if (!IS_ARM_L(victim,LOST_ARM))
            {
                act("You swing your blade in a wide arc, slicing off $N's arm.", ch, NULL, victim, TO_CHAR);
                act("$n swings $s blade in a wide arc, slicing off $N's arm.", ch, NULL, victim, TO_NOTVICT);
                act("$n swings $s blade in a wide arc, slicing off your arm.", ch, NULL, victim, TO_VICT);
                make_part(victim,"arm");
                SET_BIT(victim->loc_hp[2],LOST_ARM);
                if (!IS_BLEEDING(victim,BLEEDING_ARM_L))
                    SET_BIT(victim->loc_hp[6],BLEEDING_ARM_L);
                if (IS_BLEEDING(victim,BLEEDING_HAND_L))
                    REMOVE_BIT(victim->loc_hp[6],BLEEDING_HAND_L);
            }
            else if (!IS_ARM_R(victim,LOST_ARM))
            {
                act("You swing your blade in a wide arc, slicing off $N's arm.", ch, NULL, victim, TO_CHAR);
                act("$n swings $s blade in a wide arc, slicing off $N's arm.", ch, NULL, victim, TO_NOTVICT);
                act("$n swings $s blade in a wide arc, slicing off your arm.", ch, NULL, victim, TO_VICT);
                make_part(victim,"arm");
                SET_BIT(victim->loc_hp[3],LOST_ARM);
                if (!IS_BLEEDING(victim,BLEEDING_ARM_R))
                    SET_BIT(victim->loc_hp[6],BLEEDING_ARM_R);
                if (IS_BLEEDING(victim,BLEEDING_HAND_R))
                    REMOVE_BIT(victim->loc_hp[6],BLEEDING_HAND_R);
            }
            else
            {
                act("You plunge your blade deep into $N's chest.", ch, NULL, victim, TO_CHAR);
                act("$n plunges $s blade deep into $N's chest.", ch, NULL, victim, TO_NOTVICT);
                act("$n plunges $s blade deep into your chest.", ch, NULL, victim, TO_VICT);
            }
        }
        else if ( damp == 8 )
        {
            if (!IS_LEG_L(victim,LOST_LEG))
            {
                act("You swing your blade in a low arc, slicing off $N's leg at the hip.", ch, NULL, victim, TO_CHAR);
                act("$n swings $s blade in a low arc, slicing off $N's leg at the hip.", ch, NULL, victim, TO_NOTVICT);
                act("$n swings $s blade in a wide arc, slicing off your leg at the hip.", ch, NULL, victim, TO_VICT);
                make_part(victim,"leg");
                SET_BIT(victim->loc_hp[4],LOST_LEG);
                if (!IS_BLEEDING(victim,BLEEDING_LEG_L))
                    SET_BIT(victim->loc_hp[6],BLEEDING_LEG_L);
                if (IS_BLEEDING(victim,BLEEDING_FOOT_L))
                    REMOVE_BIT(victim->loc_hp[6],BLEEDING_FOOT_L);
            }
            else if (!IS_LEG_R(victim,LOST_LEG))
            {
                act("You swing your blade in a low arc, slicing off $N's leg at the hip.", ch, NULL, victim, TO_CHAR);
                act("$n swings $s blade in a low arc, slicing off $N's leg at the hip.", ch, NULL, victim, TO_NOTVICT);
                act("$n swings $s blade in a wide arc, slicing off your leg at the hip.", ch, NULL, victim, TO_VICT);
                make_part(victim,"leg");
                SET_BIT(victim->loc_hp[5],LOST_LEG);
                if (!IS_BLEEDING(victim,BLEEDING_LEG_R))
                    SET_BIT(victim->loc_hp[6],BLEEDING_LEG_R);
                if (IS_BLEEDING(victim,BLEEDING_FOOT_R))
                    REMOVE_BIT(victim->loc_hp[6],BLEEDING_FOOT_R);
            }
            else
            {
                act("You plunge your blade deep into $N's chest.", ch, NULL, victim, TO_CHAR);
                act("$n plunges $s blade deep into $N's chest.", ch, NULL, victim, TO_NOTVICT);
                act("$n plunges $s blade deep into your chest.", ch, NULL, victim, TO_VICT);
            }
        }
    }
    else if ( attack == "stab" || attack == "pierce" )
    {
        damp=number_range(1,5);
        if ( damp == 1 )
        {
            act("You defty invert your weapon and plunge it point first into $N's chest.\n\rA shower of blood sprays from the wound, showering the area.", ch, NULL, victim, TO_CHAR);
            act("$n defty inverts $s weapon and plunge it point first into $N's chest.\n\rA shower of blood sprays from the wound, showering the area.", ch, NULL, victim, TO_NOTVICT);
            act("$n defty inverts $s weapon and plunge it point first into your chest.\n\rA shower of blood sprays from the wound, showering the area.", ch, NULL, victim, TO_VICT);
            make_part(victim,"blood");
        }
        else if ( damp == 2 )
        {
            act("You thrust your blade into $N's mouth and twist it viciously.\n\rThe end of your blade bursts through the back of $S head.", ch, NULL, victim, TO_CHAR);
            act("$n thrusts $s blade into $N's mouth and twists it viciously.\n\rThe end of the blade bursts through the back of $N's head.", ch, NULL, victim, TO_NOTVICT);
            act("$n thrusts $s blade into your mouth and twists it viciously.\n\rYou feel the end of the blade burst through the back of your head.", ch, NULL, victim, TO_VICT);
        }
        else if ( damp == 3 )
        {
            act("You thrust your weapon up under $N's jaw and through $S head.", ch, NULL, victim, TO_CHAR);
            act("$n thrusts $s weapon up under $N's jaw and through $S head.", ch, NULL, victim, TO_NOTVICT);
            act("$n thrusts $s weapon up under your jaw and through your head.", ch, NULL, victim, TO_VICT);
        }
        else if ( damp == 4 )
        {
            act("You ram your weapon through $N's body, pinning $M to the ground.", ch, NULL, victim, TO_CHAR);
            act("$n rams $s weapon through $N's body, pinning $M to the ground.", ch, NULL, victim, TO_NOTVICT);
            act("$n rams $s weapon through your body, pinning you to the ground.", ch, NULL, victim, TO_VICT);
        }
        else if ( damp == 5 )
        {
            act("You stab your weapon into $N's eye and out the back of $S head.", ch, NULL, victim, TO_CHAR);
            act("$n stabs $s weapon into $N's eye and out the back of $S head.", ch, NULL, victim, TO_NOTVICT);
            act("$n stabs $s weapon into your eye and out the back of your head.", ch, NULL, victim, TO_VICT);
            if (!IS_HEAD(victim,LOST_EYE_L) && number_percent() < 50)
                SET_BIT(victim->loc_hp[0],LOST_EYE_L);
            else if (!IS_HEAD(victim,LOST_EYE_R))
                SET_BIT(victim->loc_hp[0],LOST_EYE_R);
            else if (!IS_HEAD(victim,LOST_EYE_L))
                SET_BIT(victim->loc_hp[0],LOST_EYE_L);
        }
    }
    else if ( attack == "blast" || attack == "pound" || attack == "crush" )
    {
        damp=number_range(1,3);
        bodyloc = 0;
        if ( damp == 1)
        {
            act("Your blow smashes through $N's chest, caving in half $S ribcage.", ch, NULL, victim, TO_CHAR);
            act("$n's blow smashes through $N's chest, caving in half $S ribcage.", ch, NULL, victim, TO_NOTVICT);
            act("$n's blow smashes through your chest, caving in half your ribcage.", ch, NULL, victim, TO_VICT);
            if (IS_BODY(victim,BROKEN_RIBS_1 )) {bodyloc += 1;
                REMOVE_BIT(victim->loc_hp[1],BROKEN_RIBS_1);}
            if (IS_BODY(victim,BROKEN_RIBS_2 )) {bodyloc += 2;
                REMOVE_BIT(victim->loc_hp[1],BROKEN_RIBS_2);}
            if (IS_BODY(victim,BROKEN_RIBS_4 )) {bodyloc += 4;
                REMOVE_BIT(victim->loc_hp[1],BROKEN_RIBS_4);}
            if (IS_BODY(victim,BROKEN_RIBS_8 )) {bodyloc += 8;
                REMOVE_BIT(victim->loc_hp[1],BROKEN_RIBS_8);}
            if (IS_BODY(victim,BROKEN_RIBS_16)) {bodyloc += 16;
                REMOVE_BIT(victim->loc_hp[1],BROKEN_RIBS_16);}
            bodyloc += number_range(1,3);
            if (bodyloc > 24) bodyloc = 24;
            if (bodyloc >= 16) {bodyloc -= 16;
                SET_BIT(victim->loc_hp[1],BROKEN_RIBS_16);}
            if (bodyloc >= 8) {bodyloc -= 8;
                SET_BIT(victim->loc_hp[1],BROKEN_RIBS_8);}
            if (bodyloc >= 4) {bodyloc -= 4;
                SET_BIT(victim->loc_hp[1],BROKEN_RIBS_4);}
            if (bodyloc >= 2) {bodyloc -= 2;
                SET_BIT(victim->loc_hp[1],BROKEN_RIBS_2);}
            if (bodyloc >= 1) {bodyloc -= 1;
                SET_BIT(victim->loc_hp[1],BROKEN_RIBS_1);}
        }
        else if ( damp == 2)
        {
            act("Your blow smashes $N's spine, shattering it in several places.", ch, NULL, victim, TO_CHAR);
            act("$n's blow smashes $N's spine, shattering it in several places.", ch, NULL, victim, TO_NOTVICT);
            act("$n's blow smashes your spine, shattering it in several places.", ch, NULL, victim, TO_VICT);
            if (!IS_BODY(victim,BROKEN_SPINE))
                SET_BIT(victim->loc_hp[1],BROKEN_SPINE);
        }
        else if ( damp == 3)
        {
            if (!IS_HEAD(victim,BROKEN_SKULL))
            {
                act("You swing your weapon down upon $N's head.\n\r$N's head cracks open like an overripe melon, leaking out brains.", ch, NULL, victim, TO_CHAR);
                act("$n swings $s weapon down upon $N's head.\n\r$N's head cracks open like an overripe melon, covering you with brains.", ch, NULL, victim, TO_NOTVICT);
                act("$n swings $s weapon down upon your head.\n\rYour head cracks open like an overripe melon, spilling your brains everywhere.", ch, NULL, victim, TO_VICT);
                make_part(victim,"brain");
                SET_BIT(victim->loc_hp[0],BROKEN_SKULL);
            }
            else
            {
                act("You hammer your weapon into $N's side, crushing bone.", ch, NULL, victim, TO_CHAR);
                act("$n hammers $s weapon into $N's side, crushing bone.", ch, NULL, victim, TO_NOTVICT);
                act("$n hammers $s weapon into your side, crushing bone.", ch, NULL, victim, TO_VICT);
            }
        }
    }
    else if ( !IS_NPC( ch ) && (attack == "bite" ||IS_VAMPAFF(ch,VAM_FANGS)))
    {
        act("You sink your teeth into $N's throat and tear out $S jugular vein.\n\rYou wipe the blood from your chin with one hand.", ch, NULL, victim, TO_CHAR);
        act("$n sink $s teeth into $N's throat and tears out $S jugular vein.\n\r$n wipes the blood from $s chin with one hand.", ch, NULL, victim, TO_NOTVICT);
        act("$n sink $s teeth into your throat and tears out your jugular vein.\n\r$n wipes the blood from $s chin with one hand.", ch, NULL, victim, TO_VICT);
        make_part(victim,"blood");
        if (!IS_BODY(victim,CUT_THROAT))
            SET_BIT(victim->loc_hp[1],CUT_THROAT);
        if (!IS_BLEEDING(victim,BLEEDING_THROAT))
            SET_BIT(victim->loc_hp[6],BLEEDING_THROAT);
    }
    else if ( !IS_NPC(ch) && (attack == "claw" || IS_VAMPAFF(ch,VAM_CLAWS)))
    {
        damp=number_range(1,2);
        if ( damp == 1 )
        {
            act("You tear out $N's throat, showering the area with blood.", ch, NULL, victim, TO_CHAR);
            act("$n tears out $N's throat, showering the area with blood.", ch, NULL, victim, TO_NOTVICT);
            act("$n tears out your throat, showering the area with blood.", ch, NULL, victim, TO_VICT);
            make_part(victim,"blood");
            if (!IS_BODY(victim,CUT_THROAT))
                SET_BIT(victim->loc_hp[1],CUT_THROAT);
            if (!IS_BLEEDING(victim,BLEEDING_THROAT))
                SET_BIT(victim->loc_hp[6],BLEEDING_THROAT);
        }
        if ( damp == 2 )
        {
            if (!IS_HEAD(victim,LOST_EYE_L) && number_percent() < 50)
            {
                act("You rip an eyeball from $N's face.", ch, NULL, victim, TO_CHAR);
                act("$n rips an eyeball from $N's face.", ch, NULL, victim, TO_NOTVICT);
                act("$n rips an eyeball from your face.", ch, NULL, victim, TO_VICT);
                make_part(victim,"eyeball");
                SET_BIT(victim->loc_hp[0],LOST_EYE_L);
            }
            else if (!IS_HEAD(victim,LOST_EYE_R))
            {
                act("You rip an eyeball from $N's face.", ch, NULL, victim, TO_CHAR);
                act("$n rips an eyeball from $N's face.", ch, NULL, victim, TO_NOTVICT);
                act("$n rips an eyeball from your face.", ch, NULL, victim, TO_VICT);
                make_part(victim,"eyeball");
                SET_BIT(victim->loc_hp[0],LOST_EYE_R);
            }
            else if (!IS_HEAD(victim,LOST_EYE_L))
            {
                act("You rip an eyeball from $N's face.", ch, NULL, victim, TO_CHAR);
                act("$n rips an eyeball from $N's face.", ch, NULL, victim, TO_NOTVICT);
                act("$n rips an eyeball from your face.", ch, NULL, victim, TO_VICT);
                make_part(victim,"eyeball");
                SET_BIT(victim->loc_hp[0],LOST_EYE_L);
            }
            else
            {
                act("You claw open $N's chest.", ch, NULL, victim, TO_CHAR);
                act("$n claws open $N's chest.", ch, NULL, victim, TO_NOTVICT);
                act("$n claws open $N's chest.", ch, NULL, victim, TO_VICT);
            }
        }
    }
    else if ( attack == "whip" )
    {
        act("You entangle $N around the neck, and squeeze out $S life.", ch, NULL, victim, TO_CHAR);
        act("$n entangles $N around the neck, and squeezes out $S life.", ch, NULL, victim, TO_NOTVICT);
        act("$n entangles you around the neck, and squeezes the life out of you.", ch, NULL, victim, TO_VICT);
        if (!IS_BODY(victim,BROKEN_NECK))
            SET_BIT(victim->loc_hp[1],BROKEN_NECK);
    }
    else if ( attack == "suck" || attack == "grep" )
    {
        act("You place your weapon on $N's head and suck out $S brains.", ch, NULL, victim, TO_CHAR);
        act("$n places $s weapon on $N's head and suck out $S brains.", ch, NULL, victim, TO_NOTVICT);
        act("$n places $s weapon on your head and suck out your brains.", ch, NULL, victim, TO_VICT);
    }
    else
    {
        /*bug( "Dam_message: bad dt %d.", dt );*/
    }
    return;
}



/*
 * Disarm a creature.
 * Caller must check for successful attack.
 */
void disarm( CHAR_DATA *ch, CHAR_DATA *victim )
{
    OBJ_DATA *obj;
    char buf [MAX_STRING_LENGTH];

    /* I'm fed up of being disarmed every 10 seconds - KaVir */
    if (IS_NPC(ch) && victim->level > 2 && number_percent() > 5)
        return;

    if (!IS_IMMUNE(ch, IMM_DISARM))
        return;

/*
    if ( ( (obj = get_eq_char( ch, WEAR_WIELD ) == NULL) || obj->item_type != ITEM_WEAPON )
    &&   ( (obj = get_eq_char( ch, WEAR_HOLD  ) == NULL) || obj->item_type != ITEM_WEAPON ) )
        return;
*/
    if ( ( (obj = get_eq_char( victim, WEAR_WIELD ) ) == NULL) || obj->item_type != ITEM_WEAPON )
    {
        if ( ( (obj = get_eq_char( victim, WEAR_HOLD ) ) == NULL) || obj->item_type != ITEM_WEAPON )
        return;
    }

    sprintf(buf,"$n disarms you!");
    ADD_COLOUR(ch,buf,WHITE);
    act( buf, ch, NULL, victim, TO_VICT    );
    sprintf(buf,"You disarm $N!");
    ADD_COLOUR(ch,buf,WHITE);
    act( buf,  ch, NULL, victim, TO_CHAR    );
    sprintf(buf,"$n disarms $N!");
    ADD_COLOUR(ch,buf,WHITE);
    act( buf,  ch, NULL, victim, TO_NOTVICT );

    obj_from_char( obj );

    /* Loyal weapons come back ;)  KaVir */
    if (IS_SET(obj->extra_flags, ITEM_LOYAL) && ( !IS_NPC(victim) ) )
    {
        act( "$p leaps back into your hand!", victim, obj, NULL, TO_CHAR );
        act( "$p leaps back into $n's hand!",  victim, obj, NULL, TO_ROOM );
        obj_to_char( obj, victim );
        do_wear( victim, obj->name);
    }
    else if ( IS_NPC(victim) )
        obj_to_char( obj, victim );
    else
        obj_to_room( obj, victim->in_room );

    return;
}



/*
 * Trip a creature.
 * Caller must check for successful attack.
 */
void trip( CHAR_DATA *ch, CHAR_DATA *victim )
{
    char buf [MAX_STRING_LENGTH];

    if (IS_AFFECTED(victim,AFF_FLYING))
        return;

    if (IS_NPC(ch) && victim->level > 2 && number_percent() > 5)
        return;

    if (!IS_NPC(victim))
    {
        if (IS_CLASS(victim, CLASS_VAMPIRE) && IS_VAMPAFF(victim,VAM_FLYING))
            return;
        if (IS_CLASS(victim, CLASS_DEMON) && IS_DEMAFF(victim, DEM_UNFOLDED))
            return;
        if (IS_SET(victim->special, SPC_CHAMPION) && IS_DEMAFF(victim,DEM_UNFOLDED))
            return;
        if (IS_CLASS(victim, CLASS_DROW) && IS_SET(victim->pcdata->powers[1], DPOWER_LEVITATION)) return;
    }
    if ( victim->wait == 0)
    {
        sprintf(buf,"$n trips you and you go down!");
        ADD_COLOUR(ch,buf,WHITE);
        act( buf, ch, NULL, victim, TO_VICT    );
        sprintf(buf,"You trip $N and $E goes down!");
        ADD_COLOUR(ch,buf,WHITE);
        act( buf,  ch, NULL, victim, TO_CHAR    );
        sprintf(buf,"$n trips $N and $E goes down!");
        ADD_COLOUR(ch,buf,WHITE);
        act( buf,  ch, NULL, victim, TO_NOTVICT );

        WAIT_STATE( ch,     2 * PULSE_VIOLENCE );
        WAIT_STATE( victim, 2 * PULSE_VIOLENCE );
        victim->position = POS_RESTING;
    }

    return;
}



void do_kill( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
        send_to_char( "Kill whom?\n\r", ch );
        return;
    }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
        send_to_char( "They aren't here.\n\r", ch );
        return;
    }

    if ( victim == ch )
    {
        send_to_char( "You cannot kill yourself!\n\r", ch );
        return;
    }

          if ( is_safe( ch, victim ) )
        return;

    if ( IS_AFFECTED(ch, AFF_CHARM) && ch->master == victim )
    {
        act( "$N is your beloved master.", ch, NULL, victim, TO_CHAR );
        return;
    }

        
    if ( ch->position == POS_FIGHTING )
    {
        send_to_char( "You do the best you can!\n\r", ch );
        return;
    }

        /* Autostancing - Loki *
    if (!IS_NPC(victim) && IS_SET(victim->extra, EXTRA_STANCE) )
    {
      if ( victim->stance[11] == STANCE_VIPER )
        do_stance(victim,"viper");
      else if ( victim->stance[11] == STANCE_CRANE )
        do_stance(victim,"crane");
      else if ( victim->stance[11] == STANCE_CRAB )
        do_stance(victim,"crab");
      else if ( victim->stance[11] == STANCE_MONGOOSE )
        do_stance(victim,"mongoose");
      else if ( victim->stance[11] == STANCE_BULL )
        do_stance(victim,"bull");
      else if ( victim->stance[11] == STANCE_MANTIS )
        do_stance(victim,"mantis");
      else if ( victim->stance[11] == STANCE_DRAGON )
        do_stance(victim,"dragon");
      else if ( victim->stance[11] == STANCE_TIGER )
        do_stance(victim,"tiger");
      else if ( victim->stance[11] == STANCE_MONKEY )
        do_stance(victim,"monkey");
      else if ( victim->stance[11] == STANCE_KOZUDO )
        do_stance(victim,"kozudo");
      else if ( victim->stance[11] == STANCE_SWALLOW )
        do_stance(victim,"swallow");
    }

    if (!IS_NPC(ch) && IS_SET(ch->extra, EXTRA_STANCE) )
    {
      if ( ch->stance[11] == STANCE_VIPER )
        do_stance(ch,"viper");
      else if ( ch->stance[11] == STANCE_CRANE )
        do_stance(ch,"crane");
      else if ( ch->stance[11] == STANCE_CRAB )
        do_stance(ch,"crab");
      else if ( ch->stance[11] == STANCE_MONGOOSE )
        do_stance(ch,"mongoose");
      else if ( ch->stance[11] == STANCE_BULL )
        do_stance(ch,"bull");
      else if ( ch->stance[11] == STANCE_MANTIS )
        do_stance(ch,"mantis");
      else if ( ch->stance[11] == STANCE_DRAGON )
        do_stance(ch,"dragon");
      else if ( ch->stance[11] == STANCE_TIGER )
        do_stance(ch,"tiger");
      else if ( ch->stance[11] == STANCE_MONKEY )
        do_stance(ch,"monkey");
      else if ( victim->stance[11] == STANCE_KOZUDO )
        do_stance(victim,"kozudo");
      else if ( ch->stance[11] == STANCE_SWALLOW )
        do_stance(ch,"swallow");
    }
*/

    WAIT_STATE( ch, 1 * PULSE_VIOLENCE );
    check_killer( ch, victim );
    if (!IS_NPC(ch) && IS_CLASS(ch, CLASS_WEREWOLF) && number_range(1,3) == 1
        && ch->power[DISC_WERE_BOAR] > 1 && victim->position == POS_STANDING)
    {

        act("You charge into $N, knocking $M from $S feet.",ch,NULL,victim,TO_CHAR);
        act("$n charge into $N, knocking $M from $S feet.",ch,NULL,victim,TO_NOTVICT);
        act("$n charge into you, knocking you from your feet.",ch,NULL,victim,TO_VICT);
        victim->position = POS_STUNNED;
        multi_hit( ch, victim, TYPE_UNDEFINED );
        multi_hit( ch, victim, TYPE_UNDEFINED );
        return;
    }
    multi_hit( ch, victim, TYPE_UNDEFINED );
    return;
}


void do_backstab( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    OBJ_DATA *obj;

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
        send_to_char( "Backstab whom?\n\r", ch );
        return;
    }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
        send_to_char( "They aren't here.\n\r", ch );
        return;
    }

    if ( victim == ch )
    {
        send_to_char( "How can you sneak up on yourself?\n\r", ch );
        return;
    }

    if ( is_safe( ch, victim ) )
      return;

    if ( ( ( obj = get_eq_char( ch, WEAR_WIELD ) ) == NULL
    ||   obj->value[3] != 11 )
    &&   ( ( obj = get_eq_char( ch, WEAR_HOLD ) ) == NULL
    ||   obj->value[3] != 11 ) )
    {
        send_to_char( "You need to wield a piercing weapon.\n\r", ch );
        return;
    }

    if ( victim->fighting != NULL )
    {
        send_to_char( "You can't backstab a fighting person.\n\r", ch );
        return;
    }

    if ( victim->hit < victim->max_hit )
    {
        act( "$N is hurt and suspicious ... you can't sneak up.",
            ch, NULL, victim, TO_CHAR );
        return;
    }

    check_killer( ch, victim );
    WAIT_STATE( ch, skill_table[gsn_backstab].beats );
    if ( !IS_NPC(victim) 
          && IS_IMMUNE(victim, IMM_BACKSTAB)
          && ch->power[DISC_VAMP_QUIE] < 10 &&
        (!IS_CLASS(ch, CLASS_NINJA) || ch->pcdata->powers[NPOWER_NINGENNO] < 2))
        damage( ch, victim, 0, gsn_backstab );
    else if ( !IS_AWAKE(victim)
    ||   IS_NPC(ch)
    ||   number_percent( ) < ch->pcdata->learned[gsn_backstab] )
        multi_hit( ch, victim, gsn_backstab );
    else
        damage( ch, victim, 0, gsn_backstab );

    return;
}



void do_flee( CHAR_DATA *ch, char *argument )
{
    ROOM_INDEX_DATA *was_in;
    ROOM_INDEX_DATA *now_in;
    CHAR_DATA *victim;
    char buf[MAX_STRING_LENGTH];    
    int attempt;

    if ( ( victim = ch->fighting ) == NULL )
    {
        if ( ch->position == POS_FIGHTING )
            ch->position = POS_STANDING;
        send_to_char( "You aren't fighting anyone.\n\r", ch );
        return;
    }
        if(ch->move <= 0)
        {
           send_to_char("You can't find the energy to leave.\n\r",ch);
           return;
        }

    if (IS_AFFECTED(ch, AFF_WEBBED))
    {
        send_to_char("You are unable to move with all this sticky webbing on.\n\r",ch);
        return;
    }

    if ( IS_SET(ch->flag2, AFF_TOTALBLIND) )
    {
        stc("You are unable to see anything, let alone flee!\n\r",victim);
        return;
    }

   if (IS_CLASS(victim, CLASS_VAMPIRE) &&

IS_SET(victim->newbits,NEW_COIL) && number_percent( ) > 15)
{
sprintf(buf,"Not with %s coiled around you!",victim->name);
send_to_char(buf,ch);
act("$n cant escape with $N coiled around them.",ch,NULL,victim,TO_ROOM);
return;
}

 if (IS_CLASS(victim, CLASS_MONK) &&

IS_SET(victim->newbits,NEW_JAWLOCK) && number_percent( ) > 30)
{
sprintf(buf,"Not with god holding you!\n\r");
send_to_char(buf,ch);
act("$n cant escape god's mighty hold!",ch,NULL,victim,TO_ROOM);
return;
}

   if (IS_CLASS(victim, CLASS_WEREWOLF) && 

IS_SET(victim->newbits,NEW_JAWLOCK) && number_percent( ) > 10)
{
sprintf(buf,"Not with %s's jaws clamped on your neck!",victim->name);
send_to_char(buf,ch);
act("$n cant escape $N's clamped jaws!",ch,NULL,victim,TO_ROOM);
return;
}
    if (IS_AFFECTED(ch,AFF_TENDRILS))
{
send_to_char("You are unable to move while tangled in tendrils.\n\r",ch);
return;
}

    if (!IS_NPC(ch) && ch->rage >= 0)
    {
        if (IS_CLASS(ch,CLASS_VAMPIRE) && number_percent() <= ch->rage)
        {
            send_to_char("Your inner beast refuses to let you run!\n\r",ch);
            WAIT_STATE(ch,12);
            return;
        }
        else if (IS_CLASS(ch, CLASS_WEREWOLF) && number_percent() <= ch->rage * 0.3)
        {
            send_to_char("Your rage is too great!\n\r",ch);
            WAIT_STATE(ch,12);
            return;
        }
    }
    was_in = ch->in_room;
    for ( attempt = 0; attempt < 6; attempt++ )
    {
        EXIT_DATA *pexit;
        int door;

        door = number_door( );
        if ( ( pexit = was_in->exit[door] ) == 0
        ||   pexit->to_room == NULL
        ||   IS_SET(pexit->exit_info, EX_CLOSED)
        || ( IS_NPC(ch)
        &&   IS_SET(pexit->to_room->room_flags, ROOM_NO_MOB) ) )
            continue;

        move_char( ch, door );
        if ( ( now_in = ch->in_room ) == was_in )
            continue;
        
        ch->in_room = was_in;
        act( "$n has fled!", ch, NULL, NULL, TO_ROOM );
        ch->in_room = now_in;

        if ( !IS_NPC(ch) )
            send_to_char( "You flee from combat!  Coward!\n\r", ch );

        stop_fighting( ch, TRUE );
        return;
    }

    send_to_char( "You were unable to escape!\n\r", ch );
    return;
}



void do_rescue( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    CHAR_DATA *fch;

    one_argument( argument, arg );
    if ( arg[0] == '\0' )
    {
        send_to_char( "Rescue whom?\n\r", ch );
        return;
    }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
        send_to_char( "They aren't here.\n\r", ch );
        return;
    }

    if ( victim == ch )
    {
        send_to_char( "What about fleeing instead?\n\r", ch );
        return;
    }

    if ( !IS_NPC(ch) && IS_NPC(victim) )
    {
        send_to_char( "Doesn't need your help!\n\r", ch );
        return;
    }

    if ( ch->fighting == victim )
    {
        send_to_char( "Too late.\n\r", ch );
        return;
    }

    if ( ( fch = victim->fighting ) == NULL )
    {
        send_to_char( "That person is not fighting right now.\n\r", ch );
        return;
    }

    if ( is_safe(ch, fch) || is_safe(ch, victim) ) return;

    WAIT_STATE( ch, skill_table[gsn_rescue].beats );
    if ( !IS_NPC(ch) && number_percent( ) > ch->pcdata->learned[gsn_rescue] )
    {
        send_to_char( "You fail the rescue.\n\r", ch );
        return;
    }

    act( "You rescue $N!",  ch, NULL, victim, TO_CHAR    );
    act( "$n rescues you!", ch, NULL, victim, TO_VICT    );
    act( "$n rescues $N!",  ch, NULL, victim, TO_NOTVICT );

    stop_fighting( fch, FALSE );
    stop_fighting( victim, FALSE );

    check_killer( ch, fch );
    set_fighting( ch, fch );
    set_fighting( fch, ch );

    do_humanity(ch,"");
    return;
}



void do_kick( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    OBJ_DATA *boots;
    int dam;
    int stance;
    int hitpoints;

    if ( !IS_NPC(ch)
    &&   ch->level < skill_table[gsn_kick].skill_level)
    {
        send_to_char(
            "First you should learn to kick.\n\r", ch );
        return;
    }

    if ( ( victim = ch->fighting ) == NULL )
    {
        send_to_char( "You aren't fighting anyone.\n\r", ch );
        return;
    }

    WAIT_STATE( ch, skill_table[gsn_kick].beats );
    if ( IS_NPC(ch) || number_percent( ) < ch->pcdata->learned[gsn_kick] )
        dam = number_range(1,4);
    else
    {
        dam = 0;
        damage( ch, victim, dam, gsn_kick );
        return;
    }

    dam += char_damroll(ch);
    if (dam == 0) dam = 1;
    if ( !IS_AWAKE(victim) )
        dam *= 2;


    if ( !IS_NPC(victim) && IS_CLASS(victim, CLASS_WEREWOLF) )
    {
        if (IS_SET(victim->special, SPC_WOLFMAN)) dam *= 0.8;
        if (victim->power[DISC_WERE_BOAR] > 2 ) dam *= 0.5;
        if ( ( boots = get_eq_char( ch, WEAR_FEET ) ) != NULL 
            && IS_SET(boots->spectype, SITEM_SILVER)) dam *= 2;
    }

       

    if ( !IS_NPC(ch) ) dam = dam + (dam * ((ch->wpn[0]+1) / 100));

    if ( !IS_NPC(ch) )
    {
        stance = ch->stance[0];
        if ( IS_STANCE(ch, STANCE_NORMAL) ) dam *= 1.25;
        else dam = dambonus(ch,victim,dam,stance);
    }

    if ( !IS_NPC(victim) && dam > 750 )
        dam = 750;
    if ( dam <= 0 )
        dam = 2;

    dam = cap_dam(ch, victim, dam);

    hitpoints = victim->hit;

        if ( !IS_NPC(victim) && IS_IMMUNE(victim, IMM_KICK) &&
!(IS_CLASS(ch, CLASS_DEMON) && IS_DEMAFF(ch, DEM_HOOVES)))
    {
        if (IS_CLASS(ch, CLASS_DEMON) && IS_DEMAFF(ch, DEM_HOOVES))
        dam = dam /2 ;
        victim->hit += dam;
        damage( ch, victim, dam, gsn_kick );
        victim->hit = hitpoints;
    }
    else if IS_IMMUNE(victim, IMM_KICK)
    {
    dam=dam/2;
    }
else damage( ch, victim, dam, gsn_kick );
    return;
}


int dambonus( CHAR_DATA *ch, CHAR_DATA *victim, int dam, int stance)
{
    if (dam < 1) return 0;
    if (stance < 1) return dam;
    if (!IS_NPC(ch) && !can_counter(victim))
    {
        if ( IS_STANCE(ch, STANCE_MONKEY) )
        {
            int mindam = dam * 0.25;
            dam *= (ch->stance[STANCE_MONKEY]+1) / 200;
            if (dam < mindam) dam = mindam;
        }
        else if ( IS_STANCE(ch, STANCE_BULL) && ch->stance[STANCE_BULL] > 100 )
            dam += dam * (ch->stance[STANCE_BULL] / 100);
        else if ( IS_STANCE(ch, STANCE_DRAGON) && ch->stance[STANCE_DRAGON] > 100 )
            dam += dam * (ch->stance[STANCE_DRAGON] / 100);
         else if ( IS_STANCE(ch, STANCE_WOLF) && ch->stance[STANCE_WOLF] > 100)
           dam += dam*(ch->stance[STANCE_DRAGON] /100);
        else if ( IS_STANCE(ch, STANCE_TIGER) && ch->stance[STANCE_TIGER] > 100 )
            dam += dam * (ch->stance[STANCE_TIGER] / 100);
        else if ( IS_STANCE(ch, STANCE_KOZUDO) && ch->stance[STANCE_KOZUDO] > 100 )
            dam += dam * (ch->stance[STANCE_KOZUDO] / 100);
        else if ( ch->stance[0] > 0 && ch->stance[stance] < 100 )
            dam *= 0.5;
    }
    if (!IS_NPC(victim) && !can_counter(ch))
    {
        if ( IS_STANCE(victim, STANCE_CRAB) && victim->stance[STANCE_CRAB] > 100 )
            dam /= victim->stance[STANCE_CRAB]/100;
        else if ( IS_STANCE(victim, STANCE_DRAGON) && victim->stance[STANCE_DRAGON] > 100)
            dam /= victim->stance[STANCE_DRAGON]/100;
        else if ( IS_STANCE(victim, STANCE_DRAGON) && victim->stance[STANCE_DRAGON] > 100 )
            dam /= victim->stance[STANCE_DRAGON]/100;
        else if ( IS_STANCE(victim, STANCE_SWALLOW) && victim->stance[STANCE_SWALLOW] > 100 )
            dam /= victim->stance[STANCE_SWALLOW]/100;
        else if ( IS_STANCE(victim, STANCE_KOZUDO) && victim->stance[STANCE_KOZUDO] > 100 )
            dam /= victim->stance[STANCE_KOZUDO]/100;
    }
    return dam;
}



void do_punch( CHAR_DATA *ch, char *argument )
{
    char arg [MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    int dam;
    int store;
    bool broke = FALSE;

    one_argument(argument,arg);

    if ( IS_NPC(ch) ) return;

    if ( ch->level < skill_table[gsn_punch].skill_level)
    {
        send_to_char( "First you should learn to punch.\n\r", ch );
        return;
    }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
        send_to_char( "You aren't fighting anyone.\n\r", ch );
        return;
    }

    if ( ch == victim )
    {
        send_to_char( "You cannot punch yourself!\n\r", ch );
        return;
    }

    if (is_safe(ch,victim)) return;

    if ( victim->hit < victim->max_hit )
    {
        send_to_char( "They are hurt and suspicious.\n\r", ch );
        return;
    }

    if ( victim->position < POS_FIGHTING )
    {
        send_to_char( "You can only punch someone who is standing.\n\r", ch );
        return;
    }

    act("You draw your fist back and aim a punch at $N.",ch,NULL,victim,TO_CHAR);
    act("$n draws $s fist back and aims a punch at you.",ch,NULL,victim,TO_VICT);
    act("$n draws $s fist back and aims a punch at $N.",ch,NULL,victim,TO_NOTVICT);
    WAIT_STATE( ch, skill_table[gsn_punch].beats );
    if ( IS_NPC(ch) || number_percent( ) < ch->pcdata->learned[gsn_punch] )
        dam = number_range(1,4);
    else
    {
        dam = 0;
        damage( ch, victim, dam, gsn_punch );
        return;
    }

    dam += char_damroll(ch);
    if (dam == 0) dam = 1;
    if ( !IS_AWAKE(victim) )
        dam *= 2;
    if ( !IS_NPC(ch) ) dam = dam + (dam * (ch->wpn[0] / 100));

    if ( dam <= 0 )
        dam = 1;

    if (!IS_NPC(victim) && IS_CLASS(victim, CLASS_WEREWOLF) && victim->power[DISC_WERE_BOAR] > 3)
    {
        store = victim->hit;
        victim->hit += dam;
        damage( ch, victim, dam, gsn_punch );
        victim->hit = store;
        if (number_percent() <= 25 && !IS_ARM_L(ch,LOST_ARM) && 
        !IS_ARM_L(ch,LOST_HAND))
        {
            if (!IS_ARM_L(ch, LOST_FINGER_I) && !IS_ARM_L(ch, BROKEN_FINGER_I))
                {SET_BIT(ch->loc_hp[LOC_ARM_L],BROKEN_FINGER_I);broke = TRUE;}
            if (!IS_ARM_L(ch, LOST_FINGER_M) && !IS_ARM_L(ch, BROKEN_FINGER_M))
                {SET_BIT(ch->loc_hp[LOC_ARM_L],BROKEN_FINGER_M);broke = TRUE;}
            if (!IS_ARM_L(ch, LOST_FINGER_R) && !IS_ARM_L(ch, BROKEN_FINGER_R))
                {SET_BIT(ch->loc_hp[LOC_ARM_L],BROKEN_FINGER_R);broke = TRUE;}
            if (!IS_ARM_L(ch, LOST_FINGER_L) && !IS_ARM_L(ch, BROKEN_FINGER_L))
                {SET_BIT(ch->loc_hp[LOC_ARM_L],BROKEN_FINGER_L);broke = TRUE;}
            if (broke)
            {
                act("The fingers on your left hand shatter under the impact of the blow!",ch,NULL,NULL,TO_CHAR);
                act("The fingers on $n's left hand shatter under the impact of the blow! ",ch,NULL,NULL,TO_ROOM);
            }
        }
        else if (number_percent() <= 25 && !IS_ARM_R(ch,LOST_ARM) && 
        !IS_ARM_R(ch,LOST_HAND))
        {
            if (!IS_ARM_R(ch, LOST_FINGER_I) && !IS_ARM_R(ch, BROKEN_FINGER_I))
                {SET_BIT(ch->loc_hp[LOC_ARM_R],BROKEN_FINGER_I);broke = TRUE;}
            if (!IS_ARM_R(ch, LOST_FINGER_M) && !IS_ARM_R(ch, BROKEN_FINGER_M))
                {SET_BIT(ch->loc_hp[LOC_ARM_R],BROKEN_FINGER_M);broke = TRUE;}
            if (!IS_ARM_R(ch, LOST_FINGER_R) && !IS_ARM_R(ch, BROKEN_FINGER_R))
                {SET_BIT(ch->loc_hp[LOC_ARM_R],BROKEN_FINGER_R);broke = TRUE;}
            if (!IS_ARM_R(ch, LOST_FINGER_L) && !IS_ARM_R(ch, BROKEN_FINGER_L))
                {SET_BIT(ch->loc_hp[LOC_ARM_R],BROKEN_FINGER_L);broke = TRUE;}
            if (broke)
            {
                act("The fingers on your right hand shatter under the impact of the blow!",ch,NULL,NULL,TO_CHAR);
                act("The fingers on $n's right hand shatter under the impact of the blow! ",ch,NULL,NULL,TO_ROOM);
            }
        }
        stop_fighting(victim,TRUE);
        return;
    }

    damage( ch, victim, dam, gsn_punch );
    if (victim == NULL || victim->position == POS_DEAD || dam < 1) return;
    if (victim->position == POS_FIGHTING) stop_fighting(victim,TRUE);
    if (number_percent() <= 25 && !IS_HEAD(victim,BROKEN_NOSE)
         && !IS_HEAD(victim,LOST_NOSE))
    {
        act("Your nose shatters under the impact of the blow!",victim,NULL,NULL,TO_CHAR);
        act("$n's nose shatters under the impact of the blow!",victim,NULL,NULL,TO_ROOM);
        SET_BIT(victim->loc_hp[LOC_HEAD],BROKEN_NOSE);
    }
    else if (number_percent() <= 25 && !IS_HEAD(victim,BROKEN_JAW))
    {
        act("Your jaw shatters under the impact of the blow!",victim,NULL,NULL,TO_CHAR);
        act("$n's jaw shatters under the impact of the blow!",victim,NULL,NULL,TO_ROOM);
        SET_BIT(victim->loc_hp[LOC_HEAD],BROKEN_JAW);
    }
    act("You fall to the ground stunned!",victim,NULL,NULL,TO_CHAR);
    act("$n falls to the ground stunned!",victim,NULL,NULL,TO_ROOM);
    victim->position = POS_STUNNED;
    return;
}


void do_berserk( CHAR_DATA *ch, char *argument )
{
    char       arg [MAX_INPUT_LENGTH];
    CHAR_DATA *vch;
    CHAR_DATA *vch_next;
    CHAR_DATA *mount;
    int number_hit = 0;

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if ( ch->level < skill_table[gsn_berserk].skill_level)
    {
        send_to_char( "You are not wild enough to go berserk.\n\r", ch );
        return;
    }

    WAIT_STATE( ch, skill_table[gsn_berserk].beats );
    if ( number_percent( ) > ch->pcdata->learned[gsn_berserk] )
    {
        act("You rant and rave, but nothing much happens.",ch,NULL,NULL,TO_CHAR);
        act("$n gets a wild look in $s eyes, but nothing much happens.",ch,NULL,NULL,TO_ROOM);
        return;
    }

    act("You go BERSERK!",ch,NULL,NULL,TO_CHAR);
    act("$n goes BERSERK!",ch,NULL,NULL,TO_ROOM);
        
        /* Autostancing - Loki *
    if (!IS_NPC(ch) && IS_SET(ch->extra, EXTRA_STANCE) )
    {
      if ( ch->stance[11] == STANCE_VIPER )
        do_stance(ch,"viper");
      else if ( ch->stance[11] == STANCE_CRANE )
        do_stance(ch,"crane");
      else if ( ch->stance[11] == STANCE_CRAB )
        do_stance(ch,"crab");
      else if ( ch->stance[11] == STANCE_MONGOOSE )
        do_stance(ch,"mongoose");
      else if ( ch->stance[11] == STANCE_BULL )
        do_stance(ch,"bull");
      else if ( ch->stance[11] == STANCE_MANTIS )
        do_stance(ch,"mantis");
      else if ( ch->stance[11] == STANCE_DRAGON )
        do_stance(ch,"dragon");
      else if ( ch->stance[11] == STANCE_TIGER )
        do_stance(ch,"tiger");
      else if ( ch->stance[11] == STANCE_MONKEY )
        do_stance(ch,"monkey");
      else if ( ch->stance[11] == STANCE_SWALLOW )
        do_stance(ch,"swallow");
      else if ( ch->stance[11] == STANCE_KOZUDO )
        do_stance(ch,"kozudo");
    }
*/



    for ( vch = char_list; vch != NULL; vch = vch_next )
    {
        vch_next        = vch->next;
        if (number_hit > 4) continue;
        if ( vch->in_room == NULL )
            continue;
        if ( !IS_NPC(vch) && vch->pcdata->chobj != NULL )
            continue;
        if ( ch == vch )
            continue;
        if ( vch->in_room == ch->in_room )
        {
            if ( ( mount = ch->mount ) != NULL ) {if ( mount == vch ) continue;}
            if (can_see(ch,vch))
            {
/*
    if (!IS_NPC(vch) && IS_SET(vch->extra, EXTRA_STANCE) )
    {
      if ( vch->stance[11] == STANCE_VIPER )
        do_stance(vch,"viper");
      else if ( vch->stance[11] == STANCE_CRANE )
        do_stance(vch,"crane");
      else if ( vch->stance[11] == STANCE_CRAB )
        do_stance(vch,"crab");
      else if ( vch->stance[11] == STANCE_MONGOOSE )
        do_stance(vch,"mongoose");
      else if ( vch->stance[11] == STANCE_BULL )
        do_stance(vch,"bull");
      else if ( vch->stance[11] == STANCE_MANTIS )
        do_stance(vch,"mantis");
      else if ( vch->stance[11] == STANCE_DRAGON )
        do_stance(vch,"dragon");
      else if ( vch->stance[11] == STANCE_TIGER )
        do_stance(vch,"tiger");
      else if ( vch->stance[11] == STANCE_MONKEY )
        do_stance(vch,"monkey");
      else if ( vch->stance[11] == STANCE_SWALLOW )
        do_stance(vch,"swallow");
      else if ( vch->stance[11] == STANCE_KOZUDO )
        do_stance(vch,"kozudo");
    }
*/
                multi_hit( ch, vch, TYPE_UNDEFINED );
                          number_hit++;
                
  if (IS_CLASS(ch,CLASS_WEREWOLF) && ch->power[DISC_WERE_RAPT] >0)
                {
                send_to_char("You go NUTS!\n\r",ch);
                multi_hit(ch,vch,TYPE_UNDEFINED);
                          number_hit++;
                }
            }
        }
    }
    do_beastlike(ch,"");
    return;
}
       


/* Hurl skill by KaVir */
void do_hurl( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA       *victim;
    CHAR_DATA       *mount;
    ROOM_INDEX_DATA *to_room;
    EXIT_DATA       *pexit;
    EXIT_DATA       *pexit_rev;
    char            buf       [MAX_INPUT_LENGTH];
    char            direction [MAX_INPUT_LENGTH];
    char            arg1      [MAX_INPUT_LENGTH];
    char            arg2      [MAX_INPUT_LENGTH];
    int             door;
    int             rev_dir;
    int             dam;

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if ( !IS_NPC(ch) && ch->pcdata->learned[gsn_hurl] < 1 )
    {
        send_to_char("Maybe you should learn the skill first?\n\r",ch);
        return;
    }

    if ( arg1[0] == '\0' )
    {
        send_to_char("Who do you wish to hurl?\n\r", ch);
        return;
    }

    if ( ( victim = get_char_room( ch, arg1 ) ) == NULL )
    {
        send_to_char("They are not here.\n\r", ch);
        return;
    }

    if ( victim == ch )
    {
        send_to_char( "How can you hurl yourself?\n\r", ch );
        return;
    }

    if ( is_safe( ch, victim ) )
      return;

    if ( (mount = victim->mount) != NULL && victim->mounted == IS_MOUNT)
    {
        send_to_char("But they have someone on their back!\n\r",ch);
        return;
    }
    else if ( (mount = victim->mount) != NULL && victim->mounted == IS_RIDING)
    {
        send_to_char("But they are riding!\n\r",ch);
        return;
    }

    if ( !IS_NPC(victim) && IS_IMMUNE(victim, IMM_HURL) )
    {
        send_to_char("You are unable to get their feet of the ground.\n\r",ch);
        return;
    }

    if ( IS_NPC(victim) && victim->level > 900 )
    {
        send_to_char("You are unable to get their feet of the ground.\n\r",ch);
        return;
    }

    if ( (victim->hit < victim->max_hit)
         || ( victim->position == POS_FIGHTING && victim->fighting != ch) )
    {
        act( "$N is hurt and suspicious, and you are unable to approach $M.",
            ch, NULL, victim, TO_CHAR );
        return;
    }

    WAIT_STATE( ch, skill_table[gsn_hurl].beats );
    if ( !IS_NPC(ch) && number_percent( ) > ch->pcdata->learned[gsn_hurl] )
    {
            send_to_char("You are unable to get their feet of the ground.\n\r",ch);
            multi_hit( victim, ch, TYPE_UNDEFINED );
            return;
    }

    rev_dir = 0;

    if ( arg2[0] == '\0' )
        door = number_range(0,3);
    else
    {
        if      ( !str_cmp( arg2, "n" ) || !str_cmp( arg2, "north" ) )
            door = 0;
        else if ( !str_cmp( arg2, "e" ) || !str_cmp( arg2, "east" ) )
            door = 1;
        else if ( !str_cmp( arg2, "s" ) || !str_cmp( arg2, "south" ) )
            door = 2;
        else if ( !str_cmp( arg2, "w" ) || !str_cmp( arg2, "west" ) )
            door = 3;
        else
        {
            send_to_char("You can only hurl people north, south, east or west.\n\r", ch);
            return;
        }
    }

    if (door == 0) {sprintf(direction,"north");rev_dir = 2;}
    if (door == 1) {sprintf(direction,"east");rev_dir = 3;}
    if (door == 2) {sprintf(direction,"south");rev_dir = 0;}
    if (door == 3) {sprintf(direction,"west");rev_dir = 1;}

    if (( pexit = ch->in_room->exit[door]) == NULL || (to_room = pexit->to_room) == NULL)
    {
        sprintf(buf,"$n hurls $N into the %s wall.", direction);
        act(buf,ch,NULL,victim,TO_NOTVICT);
        sprintf(buf,"You hurl $N into the %s wall.", direction);
        act(buf,ch,NULL,victim,TO_CHAR);
        sprintf(buf,"$n hurls you into the %s wall.", direction);
        act(buf,ch,NULL,victim,TO_VICT);
        dam = number_range(ch->level, (ch->level * 4));
        victim->hit = victim->hit - dam;
        update_pos(victim);
        if (IS_NPC(victim) && !IS_NPC(ch)) ch->mkill = ch->mkill + 1;
        if (!IS_NPC(victim) && IS_NPC(ch)) victim->mdeath = victim->mdeath + 1;
        if (victim->position == POS_DEAD) {raw_kill(victim);return;}
        return;
    }

    pexit = victim->in_room->exit[door];
    if (IS_SET(pexit->exit_info, EX_CLOSED) && 
        !IS_AFFECTED(victim,AFF_PASS_DOOR ) &&
        !IS_AFFECTED(victim,AFF_ETHEREAL  ) )
    {
        if (IS_SET(pexit->exit_info, EX_LOCKED))
            REMOVE_BIT(pexit->exit_info, EX_LOCKED);
        if (IS_SET(pexit->exit_info, EX_CLOSED))
            REMOVE_BIT(pexit->exit_info, EX_CLOSED);
        sprintf(buf,"$n hoists $N in the air and hurls $M %s.", direction);
        act(buf,ch,NULL,victim,TO_NOTVICT);
        sprintf(buf,"You hoist $N in the air and hurl $M %s.", direction);
        act(buf,ch,NULL,victim,TO_CHAR);
        sprintf(buf,"$n hurls you %s, smashing you through the %s.", direction,pexit->keyword);
        act(buf,ch,NULL,victim,TO_VICT);
        sprintf(buf,"There is a loud crash as $n smashes through the $d.");
        act(buf,victim,NULL,pexit->keyword,TO_ROOM);

        if ( ( to_room   = pexit->to_room               ) != NULL
        &&   ( pexit_rev = to_room->exit[rev_dir] ) != NULL
        &&   pexit_rev->to_room == ch->in_room
        &&   pexit_rev->keyword != NULL )
        {
            if (IS_SET(pexit_rev->exit_info, EX_LOCKED))
                REMOVE_BIT( pexit_rev->exit_info, EX_LOCKED );
            if (IS_SET(pexit_rev->exit_info, EX_CLOSED))
                REMOVE_BIT( pexit_rev->exit_info, EX_CLOSED );
            if (door == 0) sprintf(direction,"south");
            if (door == 1) sprintf(direction,"west");
            if (door == 2) sprintf(direction,"north");
            if (door == 3) sprintf(direction,"east");
            char_from_room(victim);
            char_to_room(victim,to_room);
            sprintf(buf,"$n comes smashing in through the %s $d.", direction);
            act(buf,victim,NULL,pexit->keyword,TO_ROOM);
            dam = number_range(ch->level, (ch->level * 6));
            victim->hit = victim->hit - dam;
            update_pos(victim);
            if (IS_NPC(victim) && !IS_NPC(ch)) ch->mkill = ch->mkill + 1;
            if (!IS_NPC(victim) && IS_NPC(ch)) victim->mdeath = victim->mdeath + 1;
            if (victim->position == POS_DEAD) {raw_kill(victim);return;}
        }
    }
    else
    {
        sprintf(buf,"$n hurls $N %s.", direction);
        act(buf,ch,NULL,victim,TO_NOTVICT);
        sprintf(buf,"You hurl $N %s.", direction);
        act(buf,ch,NULL,victim,TO_CHAR);
        sprintf(buf,"$n hurls you %s.", direction);
        act(buf,ch,NULL,victim,TO_VICT);
        if (door == 0) sprintf(direction,"south");
        if (door == 1) sprintf(direction,"west");
        if (door == 2) sprintf(direction,"north");
        if (door == 3) sprintf(direction,"east");
        char_from_room(victim);
        char_to_room(victim,to_room);
        sprintf(buf,"$n comes flying in from the %s.", direction);
        act(buf,victim,NULL,NULL,TO_ROOM);
        dam = number_range(ch->level, (ch->level * 2));
        victim->hit = victim->hit - dam;
        update_pos(victim);
        if (IS_NPC(victim) && !IS_NPC(ch)) ch->mkill = ch->mkill + 1;
        if (!IS_NPC(victim) && IS_NPC(ch)) victim->mdeath = victim->mdeath + 1;
        if (victim->position == POS_DEAD) {raw_kill(victim);return;}
    }
    return;
}



void do_disarm( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    OBJ_DATA *obj;
    int percent;

    if ( !IS_NPC(ch)
    &&   ch->level < skill_table[gsn_disarm].skill_level)
    {
        send_to_char( "You don't know how to disarm opponents.\n\r", ch );
        return;
    }

    if ( ( get_eq_char( ch, WEAR_WIELD ) == NULL )
    &&   ( get_eq_char( ch, WEAR_HOLD  ) == NULL ) )
    {
        send_to_char( "You must wield a weapon to disarm.\n\r", ch );
        return;
    }

    if ( ( victim = ch->fighting ) == NULL )
    {
        send_to_char( "You aren't fighting anyone.\n\r", ch );
        return;
    }

    if ( ( ( obj = get_eq_char( victim, WEAR_WIELD ) ) == NULL )
    &&   ( ( obj = get_eq_char( victim, WEAR_HOLD  ) ) == NULL ) )
    {
        send_to_char( "Your opponent is not wielding a weapon.\n\r", ch );
        return;
    }

    WAIT_STATE( ch, skill_table[gsn_disarm].beats );
    percent = number_percent( ) + victim->level - ch->level;
    if (!IS_NPC(victim) && IS_IMMUNE(victim, IMM_DISARM))
        send_to_char( "You failed.\n\r", ch );
    else if ( IS_NPC(ch) || percent < ch->pcdata->learned[gsn_disarm] * 2 / 3 )
        disarm( ch, victim );
    else
        send_to_char( "You failed.\n\r", ch );
    return;
}



void do_sla( CHAR_DATA *ch, char *argument )
{
    send_to_char( "If you want to SLAY, spell it out.\n\r", ch );
    return;
}



void do_slay( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char arg[MAX_INPUT_LENGTH];

    one_argument( argument, arg );
    if ( arg[0] == '\0' )
    {
        send_to_char( "Slay whom?\n\r", ch );
        return;
    }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
        send_to_char( "They aren't here.\n\r", ch );
        return;
    }

    if ( ch == victim )
    {
        send_to_char( "Suicide is a mortal sin.\n\r", ch );
        return;
    }

    if (IS_SET(victim->act, PLR_GODLESS))
    {
        send_to_char( "You failed.\n\r", ch );
        return;
    }

    if ( !IS_NPC(victim) && victim->level >= ch->level )
    {
        send_to_char( "You failed.\n\r", ch );
        return;
    }

    act( "You slay $M in cold blood!",  ch, NULL, victim, TO_CHAR    );
    act( "$n slays you in cold blood!", ch, NULL, victim, TO_VICT    );
    act( "$n slays $N in cold blood!",  ch, NULL, victim, TO_NOTVICT );
    raw_kill( victim );
    return;
}

/* Had problems with people not dying when POS_DEAD...KaVir */
void do_killperson( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char arg[MAX_INPUT_LENGTH];

    one_argument( argument, arg );
    if ( arg[0] == '\0' )
        return;
    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
        return;
    send_to_char( "You have been KILLED!!\n\r\n\r", victim );
    if (IS_NPC(victim) && !IS_NPC(ch)) ch->mkill = ch->mkill + 1;
    if (!IS_NPC(victim) && IS_NPC(ch)) victim->mdeath = victim->mdeath + 1;
    raw_kill( victim );
    return;
}

/* Demons Soul Stealing Shit. */
void do_stealsoul( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char arg[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];

    one_argument( argument, arg );

    if ( IS_NPC(ch) ) return;

    if (!IS_CLASS(ch, CLASS_DEMON))
    {
        stc("Huh?\n\r",ch);
      return;
    }

    if ( arg[0] == '\0' )
    {
        send_to_char( "Who's soul are you going to steal?\n\r", ch );
        return;
    }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
        send_to_char( "They aren't here.\n\r", ch );
        return;
    }

    if ( IS_CLASS(victim, CLASS_DEMON) )
    {
        stc("Demons don't have a soul!\n\r",ch);
        return;
    }


    if ( ch == victim )
    {
        send_to_char( "That might be a bit tricky...\n\r", ch );
        return;
    }

    if ( IS_NPC(victim) )
    {
        send_to_char( "You can only steal the soul of other players.\n\r", ch );
        return;
    }

    if ( !CAN_PK(ch) )
    {
        send_to_char( "You must be an avatar to steal someone's soul.\n\r", ch );
        return;
    }

    if ( !CAN_PK(victim) )
    {
        send_to_char( "You can only steal the soul of other Avatars.\n\r", ch );
        return;
    }

    if ( victim->position > 1 )
    {
        send_to_char( "You can only do this to mortally wounded players.\n\r", ch );
        return;
    }

    if (is_safe(ch,victim)) return;

    act( "You tear $N's soul out of their body!",  ch, NULL, victim, TO_CHAR    );
    send_to_char( "Your soul is torn from your body!\n\r", victim);
    act( "$n tears $N's soul out of $M lifeless body!",  ch, NULL, victim, TO_NOTVICT );
    act( "$n's soul is torn from $m body!", victim, NULL, NULL, TO_ROOM);
    
    if (( ch->race - victim->race > 10 && ch->race > 0)
        || (victim->race == 0 && ch->race > 0)  )
    {
        ch->paradox[0] += ch->race;
        ch->paradox[1] += ch->race;
        ch->paradox[2] += PARADOX_TICK;
        sprintf(buf,"%s's has been stolen by %s.",victim->pcdata->switchname,ch->pcdata->switchname);
        do_info(ch,buf);
        sprintf( log_buf, "%s soulstealed by %s at %d for no status.",
            victim->pcdata->switchname, ch->pcdata->switchname, victim->in_room->vnum );
        log_string( log_buf );
        do_paradox(ch,"self");
        if (IS_CLASS(victim, CLASS_VAMPIRE)) do_mortalvamp(victim,"");
        else if (IS_SET(victim->special, SPC_WOLFMAN)) do_unwerewolf(victim,"");
        if (IS_CLASS(victim, CLASS_MAGE) && IS_AFFECTED(victim, AFF_POLYMORPH)) 
            do_unpolymorph(victim,"");
        behead( victim );
        do_beastlike(ch,"");
        ch->pkill = ch->pkill + 1;
        victim->pdeath = victim->pdeath + 1;
        if (ch->pcdata->kingdom != 0)
        king_table[ch->pcdata->kingdom].pk += 1;
        if (victim->pcdata->kingdom != 0)
        king_table[victim->pcdata->kingdom].pd += 1;
        save_kingdoms();
        victim->level = 2;
        return;
    }
    
    if (ch->race == 0) ch->race++;
        ch->pcdata->souls++;
        if (ch->pcdata->souls >= souls_needed(ch))
            stc("You have achieved the required souls for a promotion!\n\r",ch);
    if (IS_CLASS(victim, CLASS_VAMPIRE))      do_mortalvamp(victim,"");
    else if (IS_SET(victim->special, SPC_WOLFMAN)) do_unwerewolf(victim,"");
    if (IS_CLASS(victim, CLASS_MAGE) && IS_AFFECTED(victim, AFF_POLYMORPH)) 
        do_unpolymorph(victim,"");
    behead( victim );
    do_beastlike(ch,"");
        if (ch->pcdata->kingdom != 0)
        king_table[ch->pcdata->kingdom].pk += 1;
        if (victim->pcdata->kingdom != 0)
        king_table[victim->pcdata->kingdom].pd += 1;
        save_kingdoms();

    ch->pkill = ch->pkill + 1;
    victim->pdeath = victim->pdeath + 1;
    victim->pcdata->stats[UNI_RAGE] = 0;
    victim->level = 2;
    sprintf(buf,"%s's soul has been stolen by %s.",victim->pcdata->switchname,ch->pcdata->switchname);
    do_info(ch,buf);
    sprintf( log_buf, "%s soulstolen by %s at %d.",
        victim->pcdata->switchname, ch->pcdata->switchname,
victim->in_room->vnum );
    log_string( log_buf );
    return;
}


/* For decapitating players - KaVir */
void do_decapitate( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    OBJ_DATA  *obj;
    OBJ_DATA  *obj2;
    char arg[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];

    one_argument( argument, arg );

    if ( IS_NPC(ch) ) return;

    obj2 = get_eq_char( ch, WEAR_HOLD );
    if ( ( obj = get_eq_char( ch, WEAR_WIELD ) ) == NULL )
    {
        if ( ( obj2 = get_eq_char( ch, WEAR_HOLD ) ) == NULL )
        {
            send_to_char( "First you better get a weapon out!\n\r", ch );
            return;
        }
    }

    if ( ( obj != NULL && obj->item_type != ITEM_WEAPON ) )
    {
        if ( ( obj2 != NULL && obj2->item_type != ITEM_WEAPON ) )
        {
            send_to_char( "But you are not wielding any weapons!\n\r", ch );
            return;
        }
    }

    if ( ( obj  != NULL && obj->value[3]  != 1 && obj->value[3]  != 3 )
    &&   ( obj2 != NULL && obj2->value[3] != 1 && obj2->value[3] != 3 ) )
    {
        if (IS_CLASS(ch, CLASS_DROW)) {
        if (( obj != NULL && obj->value[3] != 4) && (obj2 != NULL &&
        obj2->value[3] != 4)) {
        send_to_char("You need to wield a slashing, slicing, or whipping weapon to decapitate.\n\r", ch );
        return;}}
        else {
        send_to_char( "You need to wield a slashing or slicing weapon to decapitate.\n\r", ch );
        return;}
    }

    if ( arg[0] == '\0' )
    {
        send_to_char( "Decapitate whom?\n\r", ch );
        return;
    }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
        send_to_char( "They aren't here.\n\r", ch );
        return;
    }

    if ( ch == victim )
    {
        send_to_char( "That might be a bit tricky...\n\r", ch );
        return;
    }

    if ( IS_NPC(victim) )
    {
        send_to_char( "You can only decapitate other players.\n\r", ch );
        return;
    }


    if ( !CAN_PK(ch) )
    {
        send_to_char( "You must be an avatar to decapitate someone.\n\r", ch );
        return;
    }

    if ( !CAN_PK(victim) )
    {
        send_to_char( "You can only decapitate other avatars.\n\r", ch );
        return;
    }

    if ( victim->position > 1 )
    {
        send_to_char( "You can only do this to mortally wounded players.\n\r", ch );
        return;
    }

    if (is_safe(ch,victim)) return;

    if ( IS_CLASS(ch, CLASS_VAMPIRE) && IS_SET(ch->special, SPC_INCONNU) && 
        (IS_CLASS(victim, CLASS_VAMPIRE) || IS_VAMPAFF(victim, VAM_MORTAL)))
    {
        send_to_char( "You cannot decapitate another vampire.\n\r", ch );
        return;
    }

    if ( IS_CLASS(victim, CLASS_VAMPIRE) && IS_SET(victim->special, SPC_INCONNU) && 
        (IS_CLASS(ch, CLASS_VAMPIRE) || IS_VAMPAFF(ch, VAM_MORTAL)))
    {
        send_to_char( "You cannot decapitate an Inconnu vampire.\n\r", ch );
        return;
    }

    act( "You bring your weapon down upon $N's neck!",  ch, NULL, victim, TO_CHAR    );
    send_to_char( "Your head is sliced from your shoulders!\n\r", victim);
    act( "$n swings $s weapon down towards $N's neck!",  ch, NULL, victim, TO_NOTVICT );
    act( "$n's head is sliced from $s shoulders!", victim, NULL, NULL, TO_ROOM);

 
        if (IS_CLASS(ch, CLASS_DEMON) || IS_SET(ch->special, SPC_CHAMPION)) 

    if ((IS_CLASS(ch, CLASS_DEMON) || IS_SET(ch->special, SPC_CHAMPION)) && 
        !IS_CLASS(victim,CLASS_DEMON) &&
        !IS_SET(victim->special,SPC_CHAMPION) && !IS_CLASS(ch, CLASS_DROW))
    {
        if (ch->race == 0 && victim->race == 0)
        {
            ch->pcdata->stats[DEMON_CURRENT] += 1000;
            ch->pcdata->stats[DEMON_TOTAL] += 1000;
        }
        else
        {
            ch->pcdata->stats[DEMON_CURRENT] += victim->race * 1000;
            ch->pcdata->stats[DEMON_TOTAL] += victim->race * 1000;
        }
    }

   if (IS_CLASS(ch, CLASS_DROW) && !IS_CLASS(victim, CLASS_DEMON) && !IS_CLASS(victim, CLASS_DROW)) {
        if (victim->race == 0 && ch->race == 0 )
                ch->pcdata->stats[DROW_POWER] += 1000;
        else ch->pcdata->stats[DROW_POWER] += 1000* victim->race;
}
    if (( ch->race - victim->race > 10 && ch->race > 0)
        || (victim->race == 0 && ch->race > 0)  )
    {
        ch->paradox[0] += ch->race;
        ch->paradox[1] += ch->race;
        ch->paradox[2] += PARADOX_TICK;
/*
        if (!str_cmp(ch->name,"amoeba"))
        {
            ch->paradox[0] += (25 - ch->race);
            ch->paradox[1] += (25 - ch->race);
        }
*/


        sprintf(buf,"%s has been decapitated by %s for no status.",victim->pcdata->switchname,ch->pcdata->switchname);
        do_info(ch,buf);
        sprintf( log_buf, "%s decapitated by %s at %d for no status.",
            victim->pcdata->switchname, ch->pcdata->switchname, victim->in_room->vnum );
        log_string( log_buf );
                   do_paradox(ch,"self");
        if (IS_CLASS(victim, CLASS_VAMPIRE))      do_mortalvamp(victim,"");
        else if (IS_SET(victim->special, SPC_WOLFMAN)) do_unwerewolf(victim,"");
        if (IS_CLASS(victim, CLASS_MAGE) && IS_AFFECTED(victim, AFF_POLYMORPH)) 
            do_unpolymorph(victim,"");
        ch->fight_timer += 10;
        behead( victim );
        do_beastlike(ch,"");
        if (ch->pcdata->kingdom != 0)
        king_table[ch->pcdata->kingdom].pk += 1;
        if (victim->pcdata->kingdom != 0)
        king_table[victim->pcdata->kingdom].pd += 1;
        save_kingdoms();

        ch->pkill = ch->pkill + 1;
        victim->pdeath = victim->pdeath + 1;
        victim->level = 2;
        return;
    }
    ch->exp = ch->exp +1000;
    if (ch->race - ((ch->race/100)*100) == 0)
        ch->race = ch->race + 1;
    else if (ch->race - ((ch->race/100)*100) < 45)
        ch->race = ch->race + 1;
    if (ch->race - ((ch->race/100)*100) == 0)
        victim->race = victim->race;
    else if (victim->race - ((victim->race/100)*100) > 0)
        victim->race = victim->race - 1;
    act( "A misty white vapour pours from $N's corpse into your body.",  ch, NULL, victim, TO_CHAR    );
    act( "A misty white vapour pours from $N's corpse into $n's body.",  ch, NULL, victim, TO_NOTVICT );
    act( "You double over in agony as raw energy pulses through your veins.",  ch, NULL, NULL, TO_CHAR    );
    act( "$n doubles over in agony as sparks of energy crackle around $m.",  ch, NULL, NULL, TO_NOTVICT );
    if (IS_CLASS(victim, CLASS_VAMPIRE))      do_mortalvamp(victim,"");
    else if (IS_SET(victim->special, SPC_WOLFMAN)) do_unwerewolf(victim,"");
    if (IS_CLASS(victim, CLASS_MAGE) && IS_AFFECTED(victim, AFF_POLYMORPH)) 
        do_unpolymorph(victim,"");
    ch->fight_timer += 10;
    if (IS_CLASS(ch, CLASS_DEMON) && !IS_NPC(ch) && !IS_NPC(victim) && victim->race + 15 >= ch->race)
    {
      send_to_char("You rip away a part of their soul.\n\r", ch);
      send_to_char("You feel a part of your soul has been torn away.\n\r", victim);
      ch->pcdata->souls += 1;
      if (ch->pcdata->souls > souls_needed(ch))
          ch->pcdata->souls = souls_needed(ch);
    }
    behead( victim );
    do_beastlike(ch,"");
        if (ch->pcdata->kingdom != 0)
        king_table[ch->pcdata->kingdom].pk += 1;
        if (victim->pcdata->kingdom != 0)
        king_table[victim->pcdata->kingdom].pd += 1;
        save_kingdoms();

    ch->pkill = ch->pkill + 1;
    victim->pdeath = victim->pdeath + 1;
    victim->rage = 0;
    victim->level = 2;
    sprintf(buf,"%s got his head chopped off by %s.",victim->pcdata->switchname,ch->pcdata->switchname);
    ch->exp += 10000;
 
    do_info(ch,buf);
    sprintf( log_buf, "%s decapitated by %s at %d.",
        victim->pcdata->switchname, ch->pcdata->switchname, victim->in_room->vnum );
    log_string( log_buf );
    return;
}

void do_tear( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char arg[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];

    one_argument( argument, arg );

    if ( IS_NPC(ch) ) return;

    if ( !IS_CLASS(ch, CLASS_WEREWOLF))
    {
        send_to_char( "Huh?\n\r", ch );
        return;
    }

    if ( !IS_SET(ch->special, SPC_WOLFMAN))
    {
        send_to_char( "You can only tear heads off while in Crinos form.\n\r", ch );
        return;
    }

    if ( !IS_VAMPAFF(ch, VAM_CLAWS))
    {
        send_to_char( "You better get your claws out first.\n\r", ch );
        return;
    }

    if ( arg[0] == '\0' )
    {
        send_to_char( "Who's head do you wish to tear off?\n\r", ch );
        return;
    }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
        send_to_char( "They aren't here.\n\r", ch );
        return;
    }


    if ( ch == victim )
    {
        send_to_char( "That might be a bit tricky...\n\r", ch );
        return;
    }

    if ( IS_NPC(victim) )
    {
        send_to_char( "You can only tear the heads off other players.\n\r", ch );
        return;
    }
    if (!str_cmp(victim->pcdata->switchname,"SirMog")) return;

    if ( !CAN_PK(ch) )
    {
        send_to_char( "You must be an avatar to tear someone's head off.\n\r", ch );
        return;
    }

    if ( !CAN_PK(victim) )
    {
        send_to_char( "You can only tear the head off another avatar.\n\r", ch );
        return;
    }

    if ( victim->position > 1 )
    {
        send_to_char( "You can only do this to mortally wounded players.\n\r", ch );
        return;
    }

    if (is_safe(ch,victim)) return;

    act( "You tear $N's head from $S shoulders!",  ch, NULL, victim, TO_CHAR    );
    send_to_char( "Your head is torn from your shoulders!\n\r", victim);
    act( "$n tears $N's head from $S shoulders!",  ch, NULL, victim, TO_NOTVICT );
    if ((IS_CLASS(ch, CLASS_DEMON) || IS_SET(ch->special, SPC_CHAMPION))
        && !IS_CLASS(victim, CLASS_DEMON) && !IS_CLASS(victim, CLASS_DROW)
        && !IS_SET(victim->special, SPC_CHAMPION)) 
    {
        if (ch->race == 0 && victim->race == 0)
        {
            ch->pcdata->stats[DEMON_CURRENT] += 1000;
            ch->pcdata->stats[DEMON_TOTAL] += 1000;
        }
        else
        {
            ch->pcdata->stats[DEMON_CURRENT] += victim->race * 1000;
            ch->pcdata->stats[DEMON_TOTAL] += victim->race * 1000;
        }
    }
        if (IS_CLASS(ch, CLASS_DROW) && !IS_CLASS(victim, CLASS_DROW) &&
        !IS_CLASS(victim, CLASS_DEMON) && !IS_SET(victim->special, SPC_CHAMPION))
        {
                if (ch->race == 0 && victim->race == 0)
                ch->pcdata->stats[DROW_POWER] += 1000;
                else
                ch->pcdata->stats[DROW_POWER] += 1000 * victim->race;
        }
 
    if (( ch->race - victim->race > 10 && ch->race > 0)
        || (victim->race == 0 && ch->race > 0)  )
    {
        ch->paradox[0] += ch->race;
        ch->paradox[1] += ch->race;
        ch->paradox[2] += PARADOX_TICK;

        sprintf(buf,"%s has been decapitated by %s.",victim->pcdata->switchname,ch->pcdata->switchname);
        do_info(ch,buf);
        sprintf( log_buf, "%s decapitated by %s at %d for no status.",
            victim->pcdata->switchname, ch->pcdata->switchname, victim->in_room->vnum );
        log_string( log_buf );
        if (IS_CLASS(victim, CLASS_VAMPIRE))      do_mortalvamp(victim,"");
        else if (IS_SET(victim->special, SPC_WOLFMAN)) do_unwerewolf(victim,"");
        if (IS_CLASS(victim, CLASS_MAGE) && IS_AFFECTED(victim, AFF_POLYMORPH)) 
            do_unpolymorph(victim,"");
        ch->fight_timer += 10;
        behead( victim );
        do_beastlike(ch,"");
        if (ch->pcdata->kingdom != 0)
        king_table[ch->pcdata->kingdom].pk += 1;
        if (victim->pcdata->kingdom != 0)
        king_table[victim->pcdata->kingdom].pd += 1;
        save_kingdoms();

        ch->pkill = ch->pkill + 1;
        victim->pdeath = victim->pdeath + 1;
        return;
    }
    ch->exp = ch->exp +1000;
    if (ch->race - ((ch->race/100)*100) == 0)
        ch->race = ch->race + 1;
    else if (ch->race - ((ch->race/100)*100) < 45)
        ch->race = ch->race + 1;
    if (ch->race - ((ch->race/100)*100) == 0)
        victim->race = victim->race;
    else if (victim->race - ((victim->race/100)*100) > 0)
        victim->race = victim->race - 1;
    act( "A misty white vapour pours from $N's corpse into your body.",  ch, NULL, victim, TO_CHAR    );
    act( "A misty white vapour pours from $N's corpse into $n's body.",  ch, NULL, victim, TO_NOTVICT );
    act( "You double over in agony as raw energy pulses through your veins.",  ch, NULL, NULL, TO_CHAR    );
    act( "$n doubles over in agony as sparks of energy crackle around $m.",  ch, NULL, NULL, TO_NOTVICT );
    if (IS_CLASS(victim, CLASS_VAMPIRE))      do_mortalvamp(victim,"");
    else if (IS_SET(victim->special, SPC_WOLFMAN)) do_unwerewolf(victim,"");
    if (IS_CLASS(victim, CLASS_MAGE) && IS_AFFECTED(victim, AFF_POLYMORPH)) 
        do_unpolymorph(victim,"");
    ch->fight_timer += 10;
    behead( victim );
    do_beastlike(ch,"");
        if (ch->pcdata->kingdom != 0)
        king_table[ch->pcdata->kingdom].pk += 1;
        if (victim->pcdata->kingdom != 0)
        king_table[victim->pcdata->kingdom].pd += 1;
        save_kingdoms();

    ch->pkill = ch->pkill + 1;
    victim->pdeath = victim->pdeath + 1;
    victim->rage = 0;
    victim->level = 2;
    sprintf(buf,"%s has been decapitated by %s.",victim->pcdata->switchname,ch->pcdata->switchname);
    do_info(ch,buf);
    sprintf( log_buf, "%s decapitated by %s at %d.",
        victim->pcdata->switchname, ch->pcdata->switchname, victim->in_room->vnum );
    log_string( log_buf );
    return;
}

void do_crack( CHAR_DATA *ch, char *argument )
{
    OBJ_DATA  *obj;
    OBJ_DATA  *right;
    OBJ_DATA  *left;

    right = get_eq_char( ch, WEAR_WIELD );
    left = get_eq_char( ch, WEAR_HOLD );
    if (right != NULL && right->pIndexData->vnum == 12) obj = right;
    else if (left != NULL && left->pIndexData->vnum == 12) obj = left;
    else
    {
        send_to_char("You are not holding any heads.\n\r",ch);
        return;
    }
    act("You hurl $p at the floor.", ch, obj, NULL, TO_CHAR);
    act("$n hurls $p at the floor.", ch, obj, NULL, TO_ROOM);
    act("$p cracks open, leaking brains out across the floor.", ch, obj, NULL, TO_CHAR);
    if (obj->chobj != NULL)
        {act("$p cracks open, leaking brains out across the floor.", ch, obj, obj->chobj, TO_NOTVICT);
        act("$p crack open, leaking brains out across the floor.", ch, obj, obj->chobj, TO_VICT);}
    else
        {act("$p cracks open, leaking brains out across the floor.", ch, obj, NULL, TO_ROOM);}
    crack_head(ch,obj,obj->name);
    obj_from_char(obj);
    extract_obj(obj);
}

void crack_head( CHAR_DATA *ch, OBJ_DATA *obj, char *argument )
{
    CHAR_DATA *victim;
    MOB_INDEX_DATA *pMobIndex; 

    char      arg1 [MAX_INPUT_LENGTH];
    char      arg2 [MAX_INPUT_LENGTH];
    char       buf [MAX_INPUT_LENGTH];

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );
    if (str_cmp(arg2,"mob") && obj->chobj != NULL && !IS_NPC(obj->chobj) &&
        IS_AFFECTED(obj->chobj,AFF_POLYMORPH))
    {
        victim = obj->chobj;
        make_part(victim,"cracked_head");
        make_part(victim,"brain");
        sprintf(buf,"the quivering brain of %s",victim->name);
        free_string(victim->morph);
        victim->morph = str_dup(buf);
        return;
    }
    else if (!str_cmp(arg2,"mob"))
    {
        if ( ( pMobIndex = get_mob_index( obj->value[1] ) ) == NULL ) return;
        victim = create_mobile( pMobIndex );
        char_to_room(victim,ch->in_room);
        make_part(victim,"cracked_head");
        make_part(victim,"brain");
        extract_char(victim,TRUE);
        return;
    }
    else
    {
        if ( ( pMobIndex = get_mob_index( 30002 ) ) == NULL ) return;
        victim = create_mobile( pMobIndex );

        sprintf( buf, capitalize(arg2) );
        free_string( victim->short_descr );
        victim->short_descr = str_dup( buf );

        char_to_room(victim,ch->in_room);
        make_part(victim,"cracked_head");
        make_part(victim,"brain");
        extract_char(victim,TRUE);
        return;
    }
    return;
}

/* Voodoo skill by KaVir */

void do_voodoo( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    OBJ_DATA  *obj;
    char      arg1 [MAX_INPUT_LENGTH];
    char      arg2 [MAX_INPUT_LENGTH];
    char       buf [MAX_INPUT_LENGTH];
    char     part1 [MAX_INPUT_LENGTH];
    char     part2 [MAX_INPUT_LENGTH];

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if ( arg1[0] == '\0')
    {
        send_to_char( "Who do you wish to use voodoo magic on?\n\r", ch );
        return;
    }

    if ( ( obj = get_eq_char( ch, WEAR_HOLD ) ) == NULL )
    {
        send_to_char( "You are not holding a voodoo doll.\n\r", ch );
        return;
    }

    if ( ( victim = get_char_world( ch, arg1 ) ) == NULL )
    {
        send_to_char( "They are not here.\n\r", ch );
        return;
    }

    if ( IS_NPC(victim) )
    {
        send_to_char( "Not on NPC's.\n\r", ch );
        return;
    }

    sprintf(part2,obj->name);
    sprintf(part1,"%s voodoo doll",victim->name);

    if ( str_cmp(part1,part2) )
    {
        sprintf(buf,"But you are holding %s, not %s!\n\r",obj->short_descr,victim->name);
        send_to_char( buf, ch );
        return;
    }

    if ( arg2[0] == '\0')
    {
        send_to_char( "You can 'stab', 'burn' or 'throw' the doll.\n\r", ch );
    }
    else if ( !str_cmp(arg2, "stab") )
    {
        WAIT_STATE(ch,12);
        act("You stab a pin through $p.", ch, obj, NULL, TO_CHAR); 
        act("$n stabs a pin through $p.", ch, obj, NULL, TO_ROOM);
        if (!IS_NPC(victim) && IS_IMMUNE(victim, IMM_VOODOO)) return;
        act("You feel an agonising pain in your chest!", victim, NULL, NULL, TO_CHAR);
        act("$n clutches $s chest in agony!", victim, NULL, NULL, TO_ROOM);
    }
    else if ( !str_cmp(arg2, "burn") )
    {
        WAIT_STATE(ch,12);
        act("You set fire to $p.", ch, obj, NULL, TO_CHAR);
        act("$n sets fire to $p.", ch, obj, NULL, TO_ROOM);
        act("$p burns to ashes.", ch, obj, NULL, TO_CHAR);
        act("$p burns to ashes.", ch, obj, NULL, TO_ROOM);
        obj_from_char(obj);
        extract_obj(obj);
        if (!IS_NPC(victim) && IS_IMMUNE(victim, IMM_VOODOO)) return;
        if (IS_AFFECTED(victim,AFF_FLAMING) )
            return;
        SET_BIT(victim->affected_by, AFF_FLAMING);
        act("You suddenly burst into flames!", victim, NULL, NULL, TO_CHAR);
        act("$n suddenly bursts into flames!", victim, NULL, NULL, TO_ROOM);
    }
    else if ( !str_cmp(arg2, "throw") )
    {
        WAIT_STATE(ch,12);
        act("You throw $p to the ground.", ch, obj, NULL, TO_CHAR);
        act("$n throws $p to the ground.", ch, obj, NULL, TO_ROOM);
        obj_from_char(obj);
        obj_to_room(obj, ch->in_room);
        if (!IS_NPC(victim) && IS_IMMUNE(victim, IMM_VOODOO)) return;
        if (victim->position < POS_STANDING)
            return;
        if (victim->position == POS_FIGHTING)
            stop_fighting(victim, TRUE);
        act("A strange force picks you up and hurls you to the ground!", victim, NULL, NULL, TO_CHAR);
        act("$n is hurled to the ground by a strange force.", victim, NULL, NULL, TO_ROOM);
        victim->position = POS_RESTING;
        victim->hit = victim->hit - number_range(ch->level,(5*ch->level));
        update_pos(victim);
        if (victim->position == POS_DEAD && !IS_NPC(victim))
        {
            do_killperson(ch,victim->name);
            return;
        }
    }
    else
    {
        send_to_char( "You can 'stab', 'burn' or 'throw' the doll.\n\r", ch );
    }
    return;
}

void check_arena( CHAR_DATA *ch, CHAR_DATA *victim )
{
    DESCRIPTOR_DATA *d; /* needed for Arena bet checking */
    char buf[MAX_STRING_LENGTH];
    float odds;
    float lvl1, lvl2;
    int payoff;

    sprintf(buf,"[Arena] %s has defeated %s!\n\r", 
                 ch->name,victim->name);
    for ( d = descriptor_list; d; d = d->next )
    {
       if( d->connected == CON_PLAYING &&
         ( d->character != victim && d->character != ch ))
       {
          ADD_COLOUR(ch,buf,L_RED);
          send_to_char( buf, d->character );
       }
    }

    ch->pcdata->awins += 1;
    victim->pcdata->alosses += 1;
    lvl1 = ch->hit;
    lvl2 = victim->hit;
    odds = ( lvl2 / lvl1 );
    for( d = descriptor_list; d; d = d->next )
    {
       if (d->connected == CON_PLAYING )
       {
          if (d->character->gladiator == ch)
          {
             payoff = d->character->pcdata->plr_wager * ( odds + 1 );
             sprintf(buf, "You won! Your wager: %d, payoff: %d\n\r",
                           d->character->pcdata->plr_wager, payoff );
             send_to_char(buf,d->character);
             d->character->exp += payoff;
             /* reset the betting info */
             d->character->gladiator = NULL;
             d->character->pcdata->plr_wager = 0;
             payoff = 0;
          }
          if (d->character->gladiator != ch
           && d->character->pcdata->plr_wager >= 1)
          {
             int tmp = 0;
             sprintf(buf, "You lost! Your wager: %d\n\r",
                           d->character->pcdata->plr_wager);
             send_to_char(buf,d->character);
             if (d->character->pcdata->plr_wager >d->character->exp )
             {
                tmp = d->character->pcdata->plr_wager; 
                d->character->pcdata->plr_wager -= tmp;
             }
             if ( tmp > 0 )
                d->character->pcdata->quest -= tmp;
             d->character->exp -= d->character->pcdata->plr_wager;
             /* reset the betting info */
             d->character->gladiator = NULL;
             d->character->pcdata->plr_wager = 0;
          }
       }
    }

    /* now move both fighters out of arena and back
       to the regular "world" be sure to define 
       ROOM_VNUM_AWINNER and ROOM_VNUM_ALOSER */
    stop_fighting(victim,TRUE);
    char_from_room(victim);
    char_to_room(victim,get_room_index(ROOM_VNUM_ALOSER));
    victim->hit = victim->max_hit;
    victim->mana = victim->max_mana;
    update_pos( victim );
    do_look(victim, "auto");
    stop_fighting(ch,TRUE);
    char_from_room(ch);
    char_to_room(ch,get_room_index(ROOM_VNUM_AWINNER));
    ch->hit = ch->max_hit;
    ch->mana = ch->max_mana;
    update_pos( ch );
    do_look(ch, "auto");

    if (IS_SET(ch->act,PLR_CHALLENGER))
        REMOVE_BIT(ch->act,PLR_CHALLENGER);
    if (IS_SET(victim->act,PLR_CHALLENGER))
        REMOVE_BIT(victim->act,PLR_CHALLENGER);
    if (IS_SET(victim->act,PLR_CHALLENGED))
        REMOVE_BIT(victim->act,PLR_CHALLENGED);
    if (IS_SET(ch->act,PLR_CHALLENGED))
        REMOVE_BIT(ch->act,PLR_CHALLENGED);

    ch->challenger = NULL;
    ch->challenged = NULL;
    victim->challenger = NULL;
    victim->challenged = NULL;
    REMOVE_BIT(ch->act, PLR_SILENCE);
    REMOVE_BIT(ch->act,PLR_NO_TELL);
    REMOVE_BIT(victim->act,PLR_SILENCE);
    REMOVE_BIT(victim->act,PLR_NO_TELL);

    arena = FIGHT_OPEN; /* clear the arena */

return;
}

void check_wrestle( CHAR_DATA *ch, CHAR_DATA *victim )
{
    DESCRIPTOR_DATA *d; /* needed for Arena bet checking */
    char buf[MAX_STRING_LENGTH];

    sprintf(buf,"[Wrestling] %s has pinned %s!\n\r", 
                 ch->name,victim->name);
    for ( d = descriptor_list; d; d = d->next )
    {
       if( d->connected == CON_PLAYING &&
         ( d->character != victim && d->character != ch ))
       {
          ADD_COLOUR(ch,buf,L_RED);
          send_to_char( buf, d->character );
       }
    }

    do_info(ch,buf);

    ch->pcdata->wwins += 1;
    victim->pcdata->wlosses += 1;
    stop_fighting(victim,TRUE);
    char_from_room(victim);
    char_to_room(victim,get_room_index(ROOM_VNUM_ALOSER));
    victim->hit = victim->max_hit;
    victim->mana = victim->max_mana;
    update_pos( victim );
    do_look(victim, "auto");
    stop_fighting(ch,TRUE);
    char_from_room(ch);
    char_to_room(ch,get_room_index(ROOM_VNUM_AWINNER));
    ch->hit = ch->max_hit;
    ch->mana = ch->max_mana;
    update_pos( ch );
    do_look(ch, "auto");

    if (IS_SET(ch->act,PLR_CHALLENGER))
        REMOVE_BIT(ch->act,PLR_CHALLENGER);
    if (IS_SET(victim->act,PLR_CHALLENGER))
        REMOVE_BIT(victim->act,PLR_CHALLENGER);
    if (IS_SET(victim->act,PLR_CHALLENGED))
        REMOVE_BIT(victim->act,PLR_CHALLENGED);
    if (IS_SET(ch->act,PLR_CHALLENGED))
        REMOVE_BIT(ch->act,PLR_CHALLENGED);

    ch->challenger = NULL;
    ch->challenged = NULL;
    victim->challenger = NULL;
    victim->challenged = NULL;
    REMOVE_BIT(ch->act, PLR_SILENCE);
    REMOVE_BIT(ch->act,PLR_NO_TELL);
    REMOVE_BIT(victim->act,PLR_SILENCE);
    REMOVE_BIT(victim->act,PLR_NO_TELL);

    wrestle == WRESTLE_OPEN;

return;
}

void do_garotte(CHAR_DATA *ch, char *argument)
{
        char buf[MAX_STRING_LENGTH];
        char arg[MAX_INPUT_LENGTH];
        CHAR_DATA *victim;
        OBJ_DATA *obj;
        int chance;

        one_argument(argument, arg);
        chance = number_percent();

        if (IS_NPC(ch)) return;

        if (!IS_CLASS(ch, CLASS_DROW) || !IS_SET(ch->pcdata->powers[1], DPOWER_GAROTTE)) {
        send_to_char("Huh?\n\r", ch );
        return;}

        if ((victim = get_char_room(ch, arg)) == NULL) {
        send_to_char("Garotte whom?\n\r", ch );
        return;}

        if (victim == ch) {
        send_to_char("That would be a bad idea.\n\r", ch );
        return;}

        if (!IS_NPC(victim) && !str_cmp(victim->pcdata->switchname,"SirMog"))
        return;

        if (is_safe(ch, victim)) return;

    if ( ( ( obj = get_eq_char( ch, WEAR_WIELD ) ) == NULL
    ||   obj->value[3] != 4 )
    &&   ( ( obj = get_eq_char( ch, WEAR_HOLD ) ) == NULL
    ||   obj->value[3] != 4 ) )
    {
        send_to_char( "You need to wield a whip.\n\r", ch );
        return;
    }
     
    if ( victim->fighting != NULL )
    {
        send_to_char( "You can't garotte a fighting person.\n\r", ch );
        return;
    }

        if (victim->hit < victim->max_hit) {
        act("$N is too hurt for you to sneak up.", ch, NULL,victim,TO_CHAR);
        return;}

        check_killer(ch, victim);
        WAIT_STATE(ch, skill_table[gsn_garotte].beats);
        
        if (chance <= 5) {
        ch->fight_timer += 5;
        damage(ch, victim, 0, gsn_garotte);
        return;}

        if ( chance == 13 || chance == 31 ) { /* bad luck :) */
        act("$n wraps a whip around $N's neck! $N is choking to death!",ch,NULL,victim,TO_NOTVICT);
        act("You wrap your whip around $N's neck and refuse to let go!",ch,NULL,victim,TO_CHAR);
        act("$n wraps his whip around your neck, and you can't break free!",ch,NULL,victim,TO_VICT);
        
        if (!IS_NPC(victim)) {
        ch->fight_timer += 5;
        behead(victim);
        ch->pkill = ch->pkill + 1;
        victim->pdeath = victim->pdeath + 1;
        if (ch->pcdata->kingdom != 0)
        king_table[ch->pcdata->kingdom].pk += 1;
        if (victim->pcdata->kingdom != 0)
        king_table[victim->pcdata->kingdom].pd += 1;
        save_kingdoms();
        victim->level = 2;
        do_call(victim,"all");
        sprintf(buf, "%s has been assassinated by %s!",victim->name,ch->name);
        do_info(ch,buf);
        } else
        {
        victim->hit = 1;
        damage(ch, victim, 1000, gsn_garotte);
        }

        return;} else
        {
        multi_hit(ch, victim, gsn_garotte);
        return;
        }
        return;
}

void do_dark_garotte(CHAR_DATA *ch, char *argument)
{
        char buf[MAX_STRING_LENGTH];
        char arg[MAX_INPUT_LENGTH];
        CHAR_DATA *victim;
        OBJ_DATA *obj;
        int chance;
        int i;

        one_argument(argument, arg);
        chance = number_percent();

        if (IS_NPC(ch)) return;

        if (!IS_CLASS(ch, CLASS_DROW) || !IS_SET(ch->pcdata->powers[1], DPOWER_GAROTTE)
        || !IS_SET(ch->pcdata->powers[1], DPOWER_DGAROTTE)) {
        send_to_char("Huh?\n\r", ch );
        return;}

        if (!IS_SET(ch->newbits, NEW_DARKNESS)) {
        send_to_char("You have to be surrounded in darkness.\n\r", ch );
        return;}

        if ((victim = get_char_room(ch, arg)) == NULL) {
        send_to_char("Dark Garotte whom?\n\r", ch );
        return;}

        if (victim == ch) {
        send_to_char("That would be a bad idea.\n\r", ch );
        return;}

        if (!IS_NPC(victim) && !str_cmp(victim->pcdata->switchname,"SirMog"))
        return;

        if (is_safe(ch, victim)) return;

    if ( ( ( obj = get_eq_char( ch, WEAR_WIELD ) ) == NULL
    ||   obj->value[3] != 4 )
    &&   ( ( obj = get_eq_char( ch, WEAR_HOLD ) ) == NULL
    ||   obj->value[3] != 4 ) )
    {
        send_to_char( "You need to wield a whip.\n\r", ch );
        return;
    }
     
    if ( victim->fighting != NULL )
    {
        send_to_char( "You can't garotte a fighting person.\n\r", ch );
        return;
    }

        if (victim->hit < victim->max_hit) {
        act("$N is too hurt for you to sneak up.", ch, NULL,victim,TO_CHAR);
        return;}

        check_killer(ch, victim);
        WAIT_STATE(ch, skill_table[gsn_garotte].beats);
        REMOVE_BIT(ch->newbits, NEW_DARKNESS);  
        REMOVE_BIT(ch->in_room->room_flags, ROOM_TOTAL_DARKNESS);

        if ( chance > 95 ) { /* bad luck :) */
        act("$n wraps a whip around $N's neck! $N is choking to death!",ch,NULL,victim,TO_NOTVICT);
        act("You wrap your whip around $N's neck and refuse to let go!",ch,NULL,victim,TO_CHAR);
        act("$n wraps his whip around your neck, and you can't break free!",ch,NULL,victim,TO_VICT);
        
        if (!IS_NPC(victim)) {
        ch->fight_timer += 5;
        behead(victim);
        ch->pkill = ch->pkill + 1;
        victim->pdeath = victim->pdeath + 1;
        if (ch->pcdata->kingdom != 0)
        king_table[ch->pcdata->kingdom].pk += 1;
        if (victim->pcdata->kingdom != 0)
        king_table[victim->pcdata->kingdom].pd += 1;
        save_kingdoms();
        victim->level = 2;
        do_call(victim,"all");
        sprintf(buf, "%s has been assassinated by %s!",victim->name,ch->name);
        do_info(ch,buf);
        } else
        {
        victim->hit = 1;
        damage(ch, victim, 1000, gsn_garotte);
        }

        return;} else
        if (chance <= 5) {
        ch->fight_timer += 5;
        damage(ch, victim, 0, gsn_garotte);
        return;}
        else 
        {
        for (i = 1; i < 4; i++)
        multi_hit(ch, victim, gsn_garotte);
        return;
        }
        return;
}


bool has_timer(CHAR_DATA *ch) 
{
        if (ch->fight_timer > 0 && !IS_NPC(ch)) {
        send_to_char("Not until your fight timer runs out!\n\r", ch );
        return TRUE;}

        return FALSE;
}



void do_circle( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    OBJ_DATA *obj;

    one_argument( argument, arg );

        if (IS_NPC(ch)) return;

        if (!IS_CLASS(ch, CLASS_NINJA) || ch->pcdata->powers[NPOWER_NINGENNO] < 6) {
        send_to_char("Huh?\n\r", ch );
        return;}

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
        if (ch->fighting == NULL) {
        send_to_char( "They aren't here.\n\r", ch );
        return;}
        else victim = ch->fighting;
    }

    if ( victim == ch )
    {
        send_to_char( "How can you circle yourself?\n\r", ch );
        return;
    }

    if ( is_safe( ch, victim ) )
      return;

    if ( ( ( obj = get_eq_char( ch, WEAR_WIELD ) ) == NULL
    ||   obj->value[3] != 11 )
    &&   ( ( obj = get_eq_char( ch, WEAR_HOLD ) ) == NULL
    ||   obj->value[3] != 11 ) )
    {
        send_to_char( "You need to wield a piercing weapon.\n\r", ch );
        return;
    }

    check_killer( ch, victim );
        if (number_percent() > 10)
        multi_hit( ch, victim, gsn_circle );
    else
        damage( ch, victim, 0, gsn_circle );

    WAIT_STATE( ch, 8 );
    return;
}


void do_autostance(CHAR_DATA *ch, char *argument ) {

        char    arg     [MAX_INPUT_LENGTH];

        argument = one_argument(argument,arg);

        if (IS_NPC(ch)) return;

        if (!str_cmp(arg,"none")) {
        send_to_char("You no longer autostance.\n\r", ch );
        ch->stance[MONK_AUTODROP] = STANCE_NONE;}
        else if (!str_cmp(arg, "crane")) {
        send_to_char("You now autostance into the crane stance.\n\r",ch );
        ch->stance[MONK_AUTODROP] = STANCE_CRANE;}
        else if (!str_cmp(arg, "crab")) {
        send_to_char("You now autostance into the crab stance.\n\r", ch );
        ch->stance[MONK_AUTODROP] = STANCE_CRAB;}
        else if (!str_cmp(arg, "bull")) {
        send_to_char("You now autostance into the bull stance.\n\r", ch );
        ch->stance[MONK_AUTODROP] = STANCE_BULL;}
        else if (!str_cmp(arg, "viper")) {
        send_to_char("You now autostance into the viper stance.\n\r", ch );
        ch->stance[MONK_AUTODROP] = STANCE_VIPER;}
        else if (!str_cmp(arg, "mongoose")) {
        send_to_char("You now autostance into the mongoose stance.\n\r", ch);
        ch->stance[MONK_AUTODROP] = STANCE_MONGOOSE;}
        else if (!str_cmp(arg, "mantis")
        && ch->stance[STANCE_CRANE] >= 200
        && ch->stance[STANCE_VIPER] >= 200) {
        send_to_char("You now autostance into the mantis stance.\n\r", ch);
        ch->stance[MONK_AUTODROP] = STANCE_MANTIS;}
        else if (!str_cmp(arg, "monkey")
        && ch->stance[STANCE_CRANE] >= 200
        && ch->stance[STANCE_MONGOOSE] >= 200) {
        send_to_char("You now autostance into the monkey stance.\n\r", ch);
        ch->stance[MONK_AUTODROP] = STANCE_MONKEY;}
        else if (!str_cmp(arg, "swallow")  
        && ch->stance[STANCE_CRAB] >= 200
        && ch->stance[STANCE_MONGOOSE] >= 200) {
        send_to_char("You now autostance into the swallow stance.\n\r", ch);
        ch->stance[MONK_AUTODROP] = STANCE_SWALLOW;}
        else if (!str_cmp(arg, "tiger")  
        && ch->stance[STANCE_BULL] >= 200
        && ch->stance[STANCE_VIPER] >= 200) {
        send_to_char("You now autostance into the tiger stance.\n\r", ch);
        ch->stance[MONK_AUTODROP] = STANCE_TIGER;}
        else if (!str_cmp(arg, "dragon")  
        && ch->stance[STANCE_CRAB] >= 200
        && ch->stance[STANCE_BULL] >= 200) {
        send_to_char("You now autostance into the dragon stance.\n\r", ch);
        ch->stance[MONK_AUTODROP] = STANCE_DRAGON;}
        else send_to_char("You can't set your autostance to that!\n\r",ch);
        /*else if (!str_cmp(arg, "kozudo")
        && ch->stance[STANCE_TIGER] >= 200
        && ch->stance[STANCE_SWALLOW] >= 200) {
        send_to_char("You now autostance into the kozudo stance.\n\r", ch);
        ch->stance[MONK_AUTODROP] = STANCE_KOZUDO;}
        else send_to_char("You can't set your autostance to that!\n\r",ch);*/
}

void autodrop(CHAR_DATA *ch) {
        
        int st;
        char buf [MAX_INPUT_LENGTH];
        char buf2 [MAX_INPUT_LENGTH];
        char stancename [10];

        if (IS_NPC(ch)) return;

        st = ch->stance[11];
        if (st == STANCE_VIPER) sprintf(stancename,"viper");
        else if (st == STANCE_CRANE) sprintf(stancename,"crane");
        else if (st == STANCE_CRAB) sprintf(stancename,"crab");
        else if (st == STANCE_MONGOOSE) sprintf(stancename,"mongoose");
        else if (st == STANCE_BULL) sprintf(stancename,"bull");
        else if (st == STANCE_MANTIS) sprintf(stancename,"mantis");
        else if (st == STANCE_DRAGON) sprintf(stancename,"dragon");
        else if (st == STANCE_TIGER) sprintf(stancename,"tiger");
        else if (st == STANCE_MONKEY) sprintf(stancename,"monkey");
        else if (st == STANCE_SWALLOW) sprintf(stancename,"swallow");
        else if (st == STANCE_KOZUDO) sprintf(stancename,"kozudo");
        else return;
     
        if (ch->stance[0] < 1) {
        ch->stance[0] = st;
    
        sprintf(buf, "#7You autodrop into the #3%s#7 stance.",
stancename);
        act(buf, ch, NULL, NULL, TO_CHAR);
        sprintf(buf2, "#7$n autodrops into the #3%s#7 stance.",
stancename);
        act(buf2, ch, NULL, NULL, TO_ROOM);
}       
}



#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"
#include "garou.h"

void do_gifts( CHAR_DATA *ch, char *argument )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    char buf [MAX_STRING_LENGTH];
    char lin [MAX_STRING_LENGTH];

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch, CLASS_WEREWOLF))
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }

    if (arg1[0] == '\0' && arg2[0] == '\0')
    { 
 	sprintf(lin,"============================================================================");
	stc(lin, ch);
	stc("                                     Breed\n\r",ch);
	stc(lin, ch);
	sprintf(buf,"        Homid     [ %d ]         Metis    [ %d ]         Lupus       [ %d ]\n\r",
			ch->gifts[HOMID], ch->gifts[METIS], ch->gifts[LUPUS] );
	stc(buf, ch);
        stc(lin, ch);
	stc("                                    Auspice\n\r",ch);
	stc(lin, ch);
	sprintf(buf,"       Ragabash   [ %d ]        Theurge   [ %d ]        Philodox     [ %d ]\n\r",
		      ch->gifts[RAGABASH], ch->gifts[THEURGE], ch->gifts[PHILODOX] );
	stc(buf, ch);
	sprintf(buf,"          Galliard   [ %d ]        Ahroun      [ %d ]\n\r",
			ch->gifts[GALLIARD], ch->gifts[AHROUN] );
	stc(buf, ch);
	stc(lin, ch);
	 /* stc("                                     Tribe\n\r",ch);
	stc(lin, ch);
	sprintf(buf,"     Black Furies [ %d ]     Bone Gnawers [ %d ]    Children of Gaia [ %d ]\n\r",
			ch->gifts[BLACKFURIES], ch->gifts[BONEGNAWERS], ch->gifts[CHILDREN] );
	stc(buf, ch);
	sprintf(buf,"        Fianna    [ %d ]    Get of Fenris [ %d ]      Glass Walkers  [ %d ]\n\r",
			ch->gifts[FIANNA], ch->gifts[GETOFFENRIS], ch->gifts[GLASSWALKERS] );
	stc(buf, ch);
	sprintf(buf,"      Red Talons  [ %d ]     Shadow Lords [ %d ]     Silent Striders [ %d ]\n\r",
			ch->gifts[REDTALONS], ch->gifts[SHADOWLORDS], ch->gifts[SILENTSTRIDERS] );
	stc(buf, ch);
	sprintf(buf,"     Silver Fangs [ %d ]      StarGazers  [ %d ]          Uktena     [ %d ]\n\r",
			ch->gifts[SILVERFANGS], ch->gifts[STARGAZERS], ch->gifts[UKTENA] );
	stc(buf, ch);
	sprintf(buf,"                              Wendigo    [ %d ]\n\r",
			ch->gifts[WENDIGO] );
	stc(buf, ch);
	stc(lin, ch);*/
	return;
    }
    if (arg2[0] == '\0')
    {
      /* Temporary, until gifts are in */
      do_gifts(ch, "");
      return;
    }

    if (!str_cmp(arg2,"learn"))
    {
	int improve;
	int cost;
	int max = 5;

	     if (!str_cmp(arg1,"homid"            )) improve = HOMID;
	else if (!str_cmp(arg1,"metis"            )) improve = METIS;
	else if (!str_cmp(arg1,"lupus"            )) improve = LUPUS;
	else if (!str_cmp(arg1,"ragabash"         )) improve = RAGABASH;
	else if (!str_cmp(arg1,"theurge"          )) improve = THEURGE;
	else if (!str_cmp(arg1,"philodox"         )) improve = PHILODOX;
	else if (!str_cmp(arg1,"galliard"         )) improve = GALLIARD;
	else if (!str_cmp(arg1,"ahroun"           )) improve = AHROUN;
	else if (!str_cmp(arg1,"black furies"     )) improve = BLACKFURIES;
        else if (!str_cmp(arg1,"children of gaia" )) improve = CHILDREN;
        else if (!str_cmp(arg1,"bone gnawers"     )) improve = BONEGNAWERS;
        else if (!str_cmp(arg1,"fianna"           )) improve = FIANNA;
	else if (!str_cmp(arg1,"get of fenris"    )) improve = GETOFFENRIS;
	else if (!str_cmp(arg1,"glass walkers"    )) improve = GLASSWALKERS;
        else if (!str_cmp(arg1,"red talons"       )) improve = REDTALONS;
	else if (!str_cmp(arg1,"shadow lords"     )) improve = SHADOWLORDS;
	else if (!str_cmp(arg1,"silent striders"  )) improve = SILENTSTRIDERS;
	else if (!str_cmp(arg1,"silver fangs"     )) improve = SILVERFANGS;
	else if (!str_cmp(arg1,"stargazers"       )) improve = STARGAZERS;
	else if (!str_cmp(arg1,"uktena"           )) improve = UKTENA;
	else if (!str_cmp(arg1,"wendigo"          )) improve = WENDIGO;
        else
	{
	    do_gifts(ch,"");
	    return;
	}

	cost = (ch->gifts[improve]+1) * 10;
	arg1[0] = UPPER(arg1[0]);
	if ( ch->gifts[improve] >= max )
	{
	    sprintf(buf,"You have already gained all of the %s gifts.\n\r", arg1);
	    send_to_char(buf,ch);
	    return;
	}

	if ( cost > ch->practice )
	{
	    sprintf(buf,"It costs you %d primal to learn a new %s gift.\n\r", cost, arg1);
	    send_to_char(buf,ch);
	    return;
	}

	ch->gifts[improve] += 1;
	ch->practice -= cost;
	sprintf(buf,"You have learned a new %s gift.\n\r", arg1);
	send_to_char(buf,ch);
	return;
    }

    else send_to_char("To learn a new gift, type: gifts '<name>' learn.\n\r",ch);
    return;
}


/*
 * Homid Gifts
 * Level One  - Persuasion    - Like Awe for Vampires.  Automatic
 * Level Two  - Staredown     - Mobs flee
 * Level Three- Disquiet      - Spell effect, -hit\dam in combat for opponent.
 * Level Four - Reshape Object- Rename objects
 * Level Five - Cocoon        - Damage Reduction
 */

/*
 * Homid - 2 - Staredown 
 */

void do_staredown( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char arg[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];

    argument = one_argument( argument, arg );

    if ( IS_NPC(ch) ) return;

    if ( !IS_CLASS(ch, CLASS_WEREWOLF) )
    {
	stc("Huh?\n\r",ch);
	return;
    }

    if ( ch->gifts[HOMID] < 2 )
    {
      stc("You have not learned the Homid gift of Staredown.\n\r",ch);
      return;
    }

    if ( ( victim = get_char_room( ch, arg) ) == NULL )
    {
      stc("They aren't here.\n\r",ch);
      return;
    }

    arg[0] = UPPER(arg[0]);    

    if ( ch->fighting == NULL )
    {
      stc("You must be fighting to use the gift of Staredown.\n\r",ch);
      return;
    }

    if ( victim->fighting == NULL )
    {
      sprintf(buf, "%s is not fighting anyone.", arg);
      stc(buf, ch);
      return;
    }  

    WAIT_STATE( ch, 16 );

    if ( IS_NPC(victim) )
    {
      if ( ch->gifts[HOMID] < 4 )
      {
	  if ( number_range( 1, 3 ) != 1 )
        {
          act("You stare deeply into $N's eyes, but nothing happens.",ch,NULL,victim,TO_CHAR);
          act("$n stares deeply into your eyes.",ch,NULL,victim,TO_VICT);
          act("$n stares deeply into $N's eyes, but nothing happens.",ch,NULL,victim,TO_NOTVICT);
	    return;
        }
      }

      act("You stare into $N's eyes, and $E flees in terror.",ch,NULL,victim,TO_CHAR);
      act("$n stares deeply into your eyes, and you are filled with terror.",ch,NULL,victim,TO_VICT);
      act("$n stares deeply into $N's eyes, and $E flees in terror.",ch,NULL,victim,TO_NOTVICT);
      do_flee( victim, "" );
      return;
    }

    else
    {
      if ( ch->gifts[HOMID] < 5 )
      {
        if ( number_range( 1, 4 ) != 2 )
        {
          act("You stare deeply into $N's eyes, but nothing happens.",ch,NULL,victim,TO_CHAR);
          act("$n stares deeply into your eyes.",ch,NULL,victim,TO_VICT);
          act("$n stares deeply into $N's eyes, but nothing happens.",ch,NULL,victim,TO_NOTVICT);
	    return;
        }
      }

      act("You stare into $N's eyes, and $E flees in terror.",ch,NULL,victim,TO_CHAR);
      act("$n stares deeply into your eyes, and you are filled with terror.",ch,NULL,victim,TO_VICT);
      act("$n stares deeply into $N's eyes, and $E flees in terror.",ch,NULL,victim,TO_NOTVICT);
      do_flee( victim, "" );
      return;
    }

  return;

}

void do_disquiet( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    AFFECT_DATA af;
    char arg [MAX_INPUT_LENGTH];

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch, CLASS_WEREWOLF))
    {
      send_to_char("Huh?\n\r", ch);
      return;
    }

    if ( ch->gifts[HOMID] < 3 )
    {
      send_to_char("You have not learned the Homid gift of Disquiet.\n\r", ch);
      return;
    }

    if ( ( victim = get_char_room(ch, arg) ) == NULL ) 
    {
      stc("They are not here.\n\r",ch);
      return;
    }

    if ( is_safe( ch, victim) ) return;

    if ( ch->gnosis[GCURRENT] < 1 )
    {
      stc("You need one point of gnosis power to use the gift of Disquiet.\n\r",ch);
      return;
    }

    af.duration  = ch->gifts[HOMID];
    af.location  = APPLY_DAMROLL;
    af.modifier  = -( ch->gifts[HOMID] * 5 );
    af.bitvector = 0;
    affect_to_char( victim, &af );

    af.duration  = ch->gifts[HOMID];
    af.location  = APPLY_HITROLL;
    af.modifier  = -( ch->gifts[HOMID] * 5 );
    af.bitvector = 0;
    affect_to_char( victim, &af );

    ch->gnosis[CURRENT]--;
    act("Your eyes glow a sinister red as you glare at $N.",ch,NULL,victim,TO_CHAR);
    act("$n's eyes glow a sinister red as $e glares at you.\n\rYou feel odd.",ch,NULL,victim,TO_VICT);
    act("$n's eyes glow a sinister red as $e glares at $N.",ch,NULL,victim,TO_NOTVICT);
    
    return;

}

void do_reshape(CHAR_DATA *ch, char *argument)
{
    char arg1[MAX_STRING_LENGTH];
    char arg2[MAX_STRING_LENGTH];
    OBJ_DATA *obj; 
 
    argument=one_argument(argument,arg1);
    strcpy(arg2,argument);

    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch,CLASS_WEREWOLF))
    {
      send_to_char("Huh?\n\r",ch);
      return;
    }

    if (ch->gifts[HOMID] < 4)
    {
      send_to_char("You have not achieved the Homid gift of Reshape Object.\n\r",ch);
      return;
    }

    if (arg1 == NULL || arg2 == NULL)
    {
       send_to_char("Syntax: Reshape (Item) (Description).\n\r",ch);
       return;
    }

    if ( ( obj = get_obj_carry( ch,arg1 ) ) == NULL )
    {
      send_to_char("You dont have that item.\n\r",ch);
      return;
    }

    if (strlen(arg2) > 40 || strlen(arg2) < 3)
    {
      send_to_char("The name should be between 3 and 40 characters.\n\r",ch);
      return;
    }

    free_string(obj->name);
    obj->name = str_dup(arg2);
    free_string(obj->short_descr);
    obj->short_descr=str_dup(arg2);
    send_to_char("Ok.\n\r",ch);
    return;
}

void do_cocoon( CHAR_DATA *ch, char *argument )
{
    if ( IS_NPC(ch) ) return;

    if ( !IS_CLASS(ch, CLASS_WEREWOLF) )
    {
	stc("Huh?\n\r",ch);
	return;
    }

    if ( ch->gifts[HOMID] < 5 )
    {
      stc("You haven't learned the Homid gift of Cocoon.\n\r",ch);
      return;
    }


    if ( IS_GAR1(ch, WOLF_COCOON) )
    {
      stc("Your cocoon breaks and falls to the ground.\n\r",ch);
      act("$n's cocoon breaks and falls to the ground.",ch,NULL,NULL,TO_ROOM);
      REMOVE_BIT(ch->garou1, WOLF_COCOON);
      return;
    } 

    if ( ch->gnosis[GCURRENT] < 2 )
    {
      stc("You do not have enough gnosis to use Cocoon.\n\r",ch);
      return;
    }

    else
    {
      stc("Your body is surrounded by a thick, opaque epidermis.\n\r",ch);
      act("$n's body is surrounded by a thick, opaque epidermis.",ch,NULL,NULL,TO_ROOM);
      SET_BIT(ch->garou1, WOLF_COCOON);
      ch->gnosis[GCURRENT]--;
      return;
    }
  return;
}

/*
 * Metis Gifts
 * Level One  - Gift of the Porcupine - Quills
 * Level Two  - Burrow          - Like Demon Travel
 * Level Three- Eyes of the Cat - Nightsight
 * Level Four - Wither Limb	- Withers a limb, easier on NPCs
 * Level Five - Totem Gift	- Random, Special Power. Ooo.
 */

void do_quills( CHAR_DATA *ch, char *argument )
{
    if ( IS_NPC(ch) ) return;

    if ( !IS_CLASS(ch, CLASS_WEREWOLF) )
    {
   	stc("Huh?\n\r",ch);
	return;
    }

    if ( ch->gifts[METIS] < 1 )
    {
        stc("You haven't learned the Gift of the Porcupine.\n\r",ch);
	return;
    }

    if ( IS_SET(ch->newbits, NEW_QUILLS) )
    {
        stc("Your quills soften and twist into fur.\n\r",ch);
	act("$n's quills soften and revert back to fur.",ch,NULL,NULL,TO_ROOM);
        REMOVE_BIT(ch->newbits, NEW_QUILLS);
	return;
    }

    if ( !IS_SET(ch->newbits, NEW_QUILLS) )
    {
        stc("Your fur becomes bristly and sharp.\n\r",ch);
	act("$n's fur becomes bristly and sharp.",ch,NULL,NULL,TO_ROOM);
	SET_BIT(ch->newbits, NEW_QUILLS);
	return;
    }
  return;
}

void do_burrow( CHAR_DATA *ch, char *argument )
{
    char      arg [MAX_INPUT_LENGTH];
    CHAR_DATA *victim;

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if ( !IS_CLASS(ch, CLASS_WEREWOLF) )
    {
        send_to_char("Huh?\n\r",ch);
        return;
    }

    if ( ch->gifts[METIS] < 2 )
    {
        send_to_char("You haven't learned the Metis gift of Burrow.\n\r", ch);
        return;
    }

    if ( arg[0] == '\0' )
    {
        send_to_char("Burrow to who?\n\r", ch);
        return;
    }

    if ( ( victim = get_char_world( ch, arg ) ) == NULL )
    {
        send_to_char( "They are not here.\n\r", ch );
        return;
    }

    if ( IS_NPC(victim) )
    {
        send_to_char( "Not on NPC's.\n\r", ch );
        return;
    }

    if (IS_IMMUNE(victim, IMM_TRAVEL))
    {
        send_to_char("I don't think they want you to do that.\n\r",ch);
        return;
    }        

    if ( victim == ch )
    {
        send_to_char( "You cannot burrow to yourself.\n\r", ch);
        return;
    }

    if ( victim->level != LEVEL_AVATAR || !IS_CLASS(victim, CLASS_WEREWOLF))
    {
        send_to_char( "Nothing happens.\n\r", ch );
        return;
    }

    if (victim->in_room == NULL)
    {
        send_to_char( "Nothing happens.\n\r", ch );
        return;
    }

    send_to_char("You burrow into the ground.\n\r",ch);
    act("$n burrows into the ground.",ch,NULL,NULL,TO_ROOM);
    char_from_room(ch);
    char_to_room(ch,victim->in_room);
    do_look(ch,"");
    send_to_char("You burrow out of the ground.\n\r",ch);
    act("$n burrows out of the ground.",ch,NULL,NULL,TO_ROOM);
    return;
}
  
// Eyes of the Cat - Nightsight.  clan.c

void do_wither( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    OBJ_DATA *obj;
    char arg[MAX_INPUT_LENGTH];
    bool blah = FALSE;
    int chance = 0;

    argument = one_argument( argument, arg );

    if ( IS_NPC(ch) ) return;

    if ( !IS_CLASS(ch, CLASS_WEREWOLF) )
    {
	stc("Huh?\n\r",ch);
	return;
    }

    if ( ch->gifts[METIS] < 4 )
    {
	stc("You haven't learned the Metis gift of Wither Limb.\n\r",ch);
	return;
    }

    if ( ch->gnosis[GCURRENT] < 3 )
    {
	stc("You do not have enough gnosis power stored to use the gift of Wither Limb.\n\r",ch);
	return;
    }

    if ( arg[0] == '\0' )
    {
	stc("Who's limb do you wish to wither?\n\r",ch);
	return;
    }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	stc("They aren't here.\n\r",ch);
	return;
    }

    if ( IS_ARM_R(victim, LOST_ARM) && IS_ARM_L(victim, LOST_ARM) )
    {
	stc("They have already lost both their arms.\n\r",ch);
	return;
    }
 
    WAIT_STATE(ch, 32);
    ch->gnosis[CURRENT] -= 3;
    if ( IS_NPC( victim ) )
    {
      chance = number_range( 45, 55 );

      if ( number_percent( ) > chance )
      {
	stc("Nothing happened.\n\r",ch);
	return;
      }

       if ( !IS_ARM_R(victim, LOST_ARM) )
         blah = FALSE;
       else blah = TRUE;

	 if ( !blah )
         {
 	  if (!IS_ARM_R(victim,LOST_ARM))
	      SET_BIT(victim->loc_hp[3],LOST_ARM);
	  if (!IS_BLEEDING(victim,BLEEDING_ARM_R))
	      SET_BIT(victim->loc_hp[6],BLEEDING_ARM_R);
	  if (IS_BLEEDING(victim,BLEEDING_HAND_R))
	      REMOVE_BIT(victim->loc_hp[6],BLEEDING_HAND_R);
	  act("You concentrate deeply and $N's arm starts to wither!",ch,NULL,victim,TO_CHAR);
	  act("$n's eyes glow dark red as $e gazes at you, and your arm begins withering!",ch,NULL,victim,TO_NOTVICT);
	  act("$n gazes evilly at $N, and $S arm begins withering!",ch,NULL,victim,TO_VICT);
	  make_part(victim,"arm");
	  if (IS_ARM_L(victim,LOST_ARM) && IS_ARM_R(victim,LOST_ARM))
	  {
	      if ((obj = get_eq_char( victim, WEAR_ARMS )) != NULL)
		  take_item(victim,obj);
	  }
	  if ((obj = get_eq_char( victim, WEAR_WIELD )) != NULL)
	      take_item(victim,obj);
	  if ((obj = get_eq_char( victim, WEAR_HANDS )) != NULL)
	      take_item(victim,obj);
	  if ((obj = get_eq_char( victim, WEAR_WRIST_R )) != NULL)
	      take_item(victim,obj);
	  if ((obj = get_eq_char( victim, WEAR_FINGER_R )) != NULL)
	      take_item(victim,obj);
	  return;
         }
       
	 else if ( blah )
	 {
 	  if (!IS_ARM_L(victim,LOST_ARM))
	      SET_BIT(victim->loc_hp[2],LOST_ARM);
	  else blah = TRUE;
	  if (!IS_BLEEDING(victim,BLEEDING_ARM_L))
	      SET_BIT(victim->loc_hp[6],BLEEDING_ARM_L);
	  if (IS_BLEEDING(victim,BLEEDING_HAND_L))
	      REMOVE_BIT(victim->loc_hp[6],BLEEDING_HAND_L);
	  act("You concentrate deeply and $N's arm starts to wither!",ch,NULL,victim,TO_CHAR);
	  act("$n's eyes glow dark red as $e gazes at you, and your arm begins withering!",ch,NULL,victim,TO_NOTVICT);
	  act("$n gazes evilly at $N, and $S arm begins withering!",ch,NULL,victim,TO_VICT);
	  make_part(victim,"arm");
	  if (IS_ARM_L(victim,LOST_ARM) && IS_ARM_R(victim,LOST_ARM))
	  {
	      if ((obj = get_eq_char( victim, WEAR_ARMS )) != NULL)
		  take_item(victim,obj);
	  }
	  if ((obj = get_eq_char( victim, WEAR_WIELD )) != NULL)
	      take_item(victim,obj);
	  if ((obj = get_eq_char( victim, WEAR_HANDS )) != NULL)
	      take_item(victim,obj);
	  if ((obj = get_eq_char( victim, WEAR_WRIST_L )) != NULL)
	      take_item(victim,obj);
	  if ((obj = get_eq_char( victim, WEAR_FINGER_L )) != NULL)
	      take_item(victim,obj);
	  return;
        }
    }

    else if ( !IS_NPC(victim) )
    {
	chance = 15;
      if ( number_percent( ) > chance )
      {
	act("You gaze intently at $N.\n\rNothing happens.",ch,NULL,victim,TO_CHAR);
	act("$n gazes eerily at you.\n\rNothing happens.",ch,NULL,victim,TO_VICT);
	act("$n gazes eerily at $N.",ch,NULL,victim,TO_NOTVICT);
	return;
      }


       if ( !IS_ARM_R(victim, LOST_ARM) )
         blah = FALSE;
       else blah = TRUE;

	 if ( !blah )
         {
 	  if (!IS_ARM_R(victim,LOST_ARM))
	      SET_BIT(victim->loc_hp[3],LOST_ARM);
	  if (!IS_BLEEDING(victim,BLEEDING_ARM_R))
	      SET_BIT(victim->loc_hp[6],BLEEDING_ARM_R);
	  if (IS_BLEEDING(victim,BLEEDING_HAND_R))
	      REMOVE_BIT(victim->loc_hp[6],BLEEDING_HAND_R);
	  act("You concentrate deeply and $N's arm starts to wither!",ch,NULL,victim,TO_CHAR);
	  act("$n's eyes glow dark red as $e gazes at you, and your arm begins withering!",ch,NULL,victim,TO_NOTVICT);
	  act("$n gazes evilly at $N, and $S arm begins withering!",ch,NULL,victim,TO_VICT);
	  make_part(victim,"arm");
	  if (IS_ARM_L(victim,LOST_ARM) && IS_ARM_R(victim,LOST_ARM))
	  {
	      if ((obj = get_eq_char( victim, WEAR_ARMS )) != NULL)
		  take_item(victim,obj);
	  }
	  if ((obj = get_eq_char( victim, WEAR_WIELD )) != NULL)
	      take_item(victim,obj);
	  if ((obj = get_eq_char( victim, WEAR_HANDS )) != NULL)
	      take_item(victim,obj);
	  if ((obj = get_eq_char( victim, WEAR_WRIST_R )) != NULL)
	      take_item(victim,obj);
	  if ((obj = get_eq_char( victim, WEAR_FINGER_R )) != NULL)
	      take_item(victim,obj);
	  return;
	 }

	 else if ( blah )
	 {
 	  if (!IS_ARM_L(victim,LOST_ARM))
	      SET_BIT(victim->loc_hp[2],LOST_ARM);
	  else blah = TRUE;
	  if (!IS_BLEEDING(victim,BLEEDING_ARM_L))
	      SET_BIT(victim->loc_hp[6],BLEEDING_ARM_L);
	  if (IS_BLEEDING(victim,BLEEDING_HAND_L))
	      REMOVE_BIT(victim->loc_hp[6],BLEEDING_HAND_L);
	  act("You concentrate deeply and $N's arm starts to wither!",ch,NULL,victim,TO_CHAR);
	  act("$n's eyes glow dark red as $e gazes at you, and your arm begins withering!",ch,NULL,victim,TO_NOTVICT);
	  act("$n gazes evilly at $N, and $S arm begins withering!",ch,NULL,victim,TO_VICT);
	  make_part(victim,"arm");
	  if (IS_ARM_L(victim,LOST_ARM) && IS_ARM_R(victim,LOST_ARM))
	  {
	      if ((obj = get_eq_char( victim, WEAR_ARMS )) != NULL)
		  take_item(victim,obj);
	  }
	  if ((obj = get_eq_char( victim, WEAR_WIELD )) != NULL)
	      take_item(victim,obj);
	  if ((obj = get_eq_char( victim, WEAR_HANDS )) != NULL)
	      take_item(victim,obj);
	  if ((obj = get_eq_char( victim, WEAR_WRIST_L )) != NULL)
	      take_item(victim,obj);
	  if ((obj = get_eq_char( victim, WEAR_FINGER_L )) != NULL)
	      take_item(victim,obj);
	  return;
        }
      }
  return;
}

/*
 * Ahroun Gifts
 */

void do_razorclaws(CHAR_DATA *ch, char *argument)
{

   if (IS_CLASS(ch, CLASS_WEREWOLF))
   {
	if ( ch->gifts[AHROUN] <= 1 )
        {
	    stc("Huh?\n\r",ch);
	    return;
	}
   }

   if ( !IS_VAMPAFF(ch, VAM_CLAWS) )
   {
	stc("Your talons aren't even extended!\n\r",ch);
	return;
   }

   if ( IS_GAR1(ch, WOLF_RAZORCLAWS ) )
   {
      stc("Your claws lose their razor-sharp edge.\n\r",ch);
      act("$n's claws lose their razor-sharp edge.",ch,NULL,NULL,TO_ROOM);
      REMOVE_BIT(ch->garou1, WOLF_RAZORCLAWS);
   }
   else
   {
	send_to_char("You hone your claws to a razor sharpness.\n\r",ch);
	act("$n hones $s claws to a razor sharpness.",ch, NULL, NULL, TO_ROOM);
	SET_BIT( ch->garou1, WOLF_RAZORCLAWS );
   }

  return;

}



3
*********************************
 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
 *                                                                         *
 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
 *  Chastain, Michael Quan, and Mitchell Tse.                              *
 *                                                                         *
 *  In order to use any part of this Merc Diku Mud, you must comply with   *
 *  both the original Diku license in 'license.doc' as well the Merc       *
 *  license in 'license.txt'.  In particular, you may not remove either of *
 *  these copyright notices.                                               *
 *                                                                         *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 ***************************************************************************/

#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "merc.h"



AFFECT_DATA *		affect_free;



/*
 * Local functions.
 */



/*
 * Retrieve a character's trusted level for permission checking.
 */
int get_trust( CHAR_DATA *ch )
{
    if ( ch->desc != NULL && ch->desc->original != NULL )
	ch = ch->desc->original;

    if ( ch->trust != 0 )
	return ch->trust;

    if ( IS_NPC(ch) && ch->level >= LEVEL_HERO )
	return LEVEL_HERO - 1;
    else
	return ch->level;
}



/*
 * Retrieve a character's age.
 */
int get_age( CHAR_DATA *ch )
{
    return 17 + ( ch->played + (int) (current_time - ch->logon) ) / 7200;
}



/*
 * Retrieve character's current strength.
 */
int get_curr_str( CHAR_DATA *ch )
{
    int max;

    if ( IS_NPC(ch) )
	return 13;

    max = 25;

    return URANGE( 3, ch->pcdata->perm_str + ch->pcdata->mod_str, max );
}



/*
 * Retrieve character's current intelligence.
 */
int get_curr_int( CHAR_DATA *ch )
{
    int max;

    if ( IS_NPC(ch) )
	return 13;

    max = 25;

    return URANGE( 3, ch->pcdata->perm_int + ch->pcdata->mod_int, max );
}



/*
 * Retrieve character's current wisdom.
 */
int get_curr_wis( CHAR_DATA *ch )
{
    int max;

    if ( IS_NPC(ch) )
	return 13;

    max = 25;

    return URANGE( 3, ch->pcdata->perm_wis + ch->pcdata->mod_wis, max );
}



/*
 * Retrieve character's current dexterity.
 */
int get_curr_dex( CHAR_DATA *ch )
{
    int max;

    if ( IS_NPC(ch) )
	return 13;

    max = 25;

    return URANGE( 3, ch->pcdata->perm_dex + ch->pcdata->mod_dex, max );
}



/*
 * Retrieve character's current constitution.
 */
int get_curr_con( CHAR_DATA *ch )
{
    int max;

    if ( IS_NPC(ch) )
	return 13;

    max = 25;

    return URANGE( 3, ch->pcdata->perm_con + ch->pcdata->mod_con, max );
}



/*
 * Retrieve a character's carry capacity.
 */
int can_carry_n( CHAR_DATA *ch )
{
    if ( !IS_NPC(ch) && ch->level >= LEVEL_IMMORTAL )
	return 1000;

    if ( IS_NPC(ch) && IS_SET(ch->act, ACT_PET) )
	return 0;

    return MAX_WEAR + 2 * get_curr_dex( ch ) / 3;
}



/*
 * Retrieve a character's carry capacity.
 */
int can_carry_w( CHAR_DATA *ch )
{
    if ( !IS_NPC(ch) && ch->level >= LEVEL_IMMORTAL )
	return 1000000;

    if ( IS_NPC(ch) && IS_SET(ch->act, ACT_PET) )
	return 0;

    return str_app[get_curr_str(ch)].carry;
}




/*
 * See if a string is one of the names of an object.
 */

bool is_name ( char *str, char *namelist )
{
    char name[MAX_INPUT_LENGTH], part[MAX_INPUT_LENGTH];
    char *list, *string;

    /* fix crash on NULL namelist */
    if (namelist == NULL || namelist[0] == '\0')
        return FALSE;

    /* fixed to prevent is_name on "" returning TRUE */
    if (str[0] == '\0')
        return FALSE;

    string = str;
    /* we need ALL parts of string to match part of namelist */
    for ( ; ; )  /* start parsing string */
    {
        str = one_argument(str,part);

        if (part[0] == '\0' )
            return TRUE;

        /* check to see if this is part of namelist */
        list = namelist;
        for ( ; ; )  /* start parsing namelist */
        {
            list = one_argument(list,name);
            if (name[0] == '\0')  /* this name was not found */
                return FALSE;

            if (!str_prefix(string,name))
                return TRUE; /* full pattern match */

            if (!str_prefix(part,name))
                break;
        }
    }
}


bool is_full_name( const char *str, char *namelist )
{
    char name[MAX_INPUT_LENGTH];

    for ( ; ; )
    {
	namelist = one_argument( namelist, name );
	if ( name[0] == '\0' )
	    return FALSE;
	if ( !str_cmp( str, name ) )
	    return TRUE;
    }
}



/*
 * Apply or remove an affect to a character.
 */
void affect_modify( CHAR_DATA *ch, AFFECT_DATA *paf, bool fAdd )
{
    OBJ_DATA *wield;
    int mod;

    mod = paf->modifier;

    if ( fAdd )
    {
	SET_BIT( ch->affected_by, paf->bitvector );
    }
    else
    {
	REMOVE_BIT( ch->affected_by, paf->bitvector );
	mod = 0 - mod;
    }

    if ( IS_NPC(ch) )
    {
    	switch ( paf->location )
    	{
	    default: break;
	    case APPLY_NONE:						break;
	    case APPLY_MANA:          ch->max_mana		+= mod;	break;
	    case APPLY_HIT:           ch->max_hit		+= mod;	break;
	    case APPLY_MOVE:          ch->max_move		+= mod;	break;
	    case APPLY_AC:            ch->armor			+= mod;	break;
	    case APPLY_HITROLL:       ch->hitroll		+= mod;	break;
	    case APPLY_DAMROLL:       ch->damroll		+= mod;	break;
	    case APPLY_SAVING_PARA:   ch->saving_throw		+= mod;	break;
	    case APPLY_SAVING_ROD:    ch->saving_throw		+= mod;	break;
	    case APPLY_SAVING_PETRI:  ch->saving_throw		+= mod;	break;
	    case APPLY_SAVING_BREATH: ch->saving_throw		+= mod;	break;
	    case APPLY_SAVING_SPELL:  ch->saving_throw		+= mod;	break;
	    case APPLY_POLY:	      ch->polyaff		+= mod;	break;
	}
	return;
    }

    if ( IS_CLASS(ch, CLASS_HIGHLANDER) )
    {
    	switch ( paf->location )
    	{
	    default: break;
	    case APPLY_NONE:						break;
	}
	return;
    }

    switch ( paf->location )
    {
    default:
	bug( "Affect_modify: unknown location %d.", paf->location );
	return;

    case APPLY_NONE:						break;
    case APPLY_STR:           ch->pcdata->mod_str	+= mod;	break;
    case APPLY_DEX:           ch->pcdata->mod_dex	+= mod;	break;
    case APPLY_INT:           ch->pcdata->mod_int	+= mod;	break;
    case APPLY_WIS:           ch->pcdata->mod_wis	+= mod;	break;
    case APPLY_CON:           ch->pcdata->mod_con	+= mod;	break;
/*
    case APPLY_SEX:           ch->sex			+= mod;	break;
*/
    case APPLY_SEX:						break;
    case APPLY_CLASS:						break;
    case APPLY_LEVEL:						break;
    case APPLY_AGE:						break;
    case APPLY_HEIGHT:						break;
    case APPLY_WEIGHT:						break;
    case APPLY_MANA:          ch->max_mana		+= mod;	break;
    case APPLY_HIT:           ch->max_hit		+= mod;	break;
    case APPLY_MOVE:          ch->max_move		+= mod;	break;
    case APPLY_GOLD:						break;
    case APPLY_EXP:						break;
    case APPLY_AC:            ch->armor			+= mod;	break;
    case APPLY_HITROLL:       ch->hitroll		+= mod;	break;
    case APPLY_DAMROLL:       ch->damroll		+= mod;	break;
    case APPLY_SAVING_PARA:   ch->saving_throw		+= mod;	break;
    case APPLY_SAVING_ROD:    ch->saving_throw		+= mod;	break;
    case APPLY_SAVING_PETRI:  ch->saving_throw		+= mod;	break;
    case APPLY_SAVING_BREATH: ch->saving_throw		+= mod;	break;
    case APPLY_SAVING_SPELL:  ch->saving_throw		+= mod;	break;
    case APPLY_POLY:	      ch->polyaff		+= mod;	break;
    }


    /*
     * Check for weapon wielding.
     * Guard against recursion (for weapons with affects).
     */
    if ( ( wield = get_eq_char( ch, WEAR_WIELD ) ) != NULL
    &&   wield->item_type == ITEM_WEAPON
    &&   get_obj_weight(wield) > str_app[get_curr_str(ch)].wield )
    {
	static int depth;

	if ( depth == 0 )
	{
	    depth++;
	    act( "You drop $p.", ch, wield, NULL, TO_CHAR );
	    act( "$n drops $p.", ch, wield, NULL, TO_ROOM );
	    obj_from_char( wield );
	    obj_to_room( wield, ch->in_room );
	    depth--;
	}
    }

    return;
}

/*
 * Remove an exit from a room					-Thoric
 */
void extract_exit( ROOM_INDEX_DATA *room, EXIT_DATA *pexit )
{
    UNLINK( pexit, room->first_exit, room->last_exit, next, prev );
    if ( pexit->rexit )
      pexit->rexit->rexit = NULL;
    STRFREE( pexit->keyword );
    STRFREE( pexit->description );
    DISPOSE( pexit );
}


void set_learnable_disciplines (CHAR_DATA *ch)
{
    int i;
    
    /* this bit clears all the disciplines, just in case */

    for (i = 0 ; i < MAX_DISCIPLINES ; i++)
	ch->power[i] = -1;


    /* Put the extra disciplines in here, by race */
    if (IS_CLASS(ch, CLASS_VAMPIRE))
    {
        ch->power[DISC_VAMP_FORT] = 0;
        ch->power[DISC_VAMP_CELE] = 0;
        ch->power[DISC_VAMP_OBTE] = 0;
        ch->power[DISC_VAMP_PRES] = 0;
        ch->power[DISC_VAMP_QUIE] = 0;
        ch->power[DISC_VAMP_THAU] = 0;
        ch->power[DISC_VAMP_AUSP] = 0;
        ch->power[DISC_VAMP_DOMI] = 0;
        ch->power[DISC_VAMP_OBFU] = 0;
        ch->power[DISC_VAMP_POTE] = 0;
        ch->power[DISC_VAMP_PROT] = 0;
        ch->power[DISC_VAMP_SERP] = 0;
        ch->power[DISC_VAMP_VICI] = 0;
        ch->power[DISC_VAMP_DAIM] = 0;
        ch->power[DISC_VAMP_ANIM] = 0;
	ch->power[DISC_VAMP_CHIM] = 0;
	ch->power[DISC_VAMP_MELP] = 0;
	ch->power[DISC_VAMP_NECR] = 0;
	ch->power[DISC_VAMP_THAN] = 0;
	ch->power[DISC_VAMP_OBEA] = 0;
    }
    if (IS_CLASS(ch, CLASS_WEREWOLF))
    {
        ch->power[DISC_WERE_BEAR] = 0;
        ch->power[DISC_WERE_LYNX] = 0;
        ch->power[DISC_WERE_BOAR] = 0;
        ch->power[DISC_WERE_OWL]  = 0;
        ch->power[DISC_WERE_SPID] = 0;
        ch->power[DISC_WERE_WOLF] = 0;
        ch->power[DISC_WERE_HAWK] = 0;
        ch->power[DISC_WERE_MANT] = 0;
        ch->power[DISC_WERE_RAPT] = 0;
        ch->power[DISC_WERE_LUNA] = 0;
        ch->power[DISC_WERE_PAIN] = 0;
        ch->power[DISC_WERE_CONG] = 0;
    }
  
/*
    if (IS_CLASS(ch, CLASS_VAMPIRE))
    {
	ch->power[DISC_VAMP_CELE] = ch->pcdata->powers[VPOWER_CELERITY];
        ch->power[DISC_VAMP_FORT] = ch->pcdata->powers[VPOWER_FORTITUDE];
        ch->power[DISC_VAMP_OBTE] = ch->pcdata->powers[VPOWER_OBTENEBRATION];
        ch->power[DISC_VAMP_PRES] = ch->pcdata->powers[VPOWER_PRESENCE];
        ch->power[DISC_VAMP_QUIE] = ch->pcdata->powers[VPOWER_QUIETUS];
        ch->power[DISC_VAMP_THAU] = ch->pcdata->powers[VPOWER_THAU];
        ch->power[DISC_VAMP_AUSP] = ch->pcdata->powers[VPOWER_AUSPEX];
        ch->power[DISC_VAMP_DOMI] = ch->pcdata->powers[VPOWER_DOMINATE];
        ch->power[DISC_VAMP_OBFU] = ch->pcdata->powers[VPOWER_OBFUSCATE];
        ch->power[DISC_VAMP_POTE] = ch->pcdata->powers[VPOWER_POTENCE];
        ch->power[DISC_VAMP_PROT] = ch->pcdata->powers[VPOWER_PROTEAN];
        ch->power[DISC_VAMP_SERP] = ch->pcdata->powers[VPOWER_SERPENTIS];
        ch->power[DISC_VAMP_VICI] = ch->pcdata->powers[VPOWER_VICISSITUDE];
        ch->power[DISC_VAMP_DAIM] = ch->pcdata->powers[VPOWER_DAIM];
        ch->power[DISC_VAMP_ANIM] = ch->pcdata->powers[VPOWER_ANIMAL];
    }
    if (IS_CLASS(ch, CLASS_WEREWOLF))
    {
	  ch->power[DISC_WERE_BEAR] = ch->pcdata->powers[WPOWER_BEAR];
	  ch->power[DISC_WERE_LYNX] = ch->pcdata->powers[WPOWER_LYNX];
	  ch->power[DISC_WERE_BOAR] = ch->pcdata->powers[WPOWER_BOAR];
	  ch->power[DISC_WERE_OWL]  = ch->pcdata->powers[WPOWER_OWL];
	  ch->power[DISC_WERE_SPID] = ch->pcdata->powers[WPOWER_SPIDER];
	  ch->power[DISC_WERE_WOLF] = ch->pcdata->powers[WPOWER_WOLF];
	  ch->power[DISC_WERE_HAWK] = ch->pcdata->powers[WPOWER_HAWK];
	  ch->power[DISC_WERE_MANT] = ch->pcdata->powers[WPOWER_MANTIS];
	  ch->power[DISC_WERE_RAPT] = ch->pcdata->powers[WPOWER_RAPTOR];
	  ch->power[DISC_WERE_LUNA] = ch->pcdata->powers[WPOWER_LUNA];
	  ch->power[DISC_WERE_PAIN] = ch->pcdata->powers[WPOWER_PAIN];
	  ch->power[DISC_WERE_CONG] = ch->pcdata->powers[WPOWER_CONGREGATION];
    }
  }
*/

    if (IS_CLASS(ch, CLASS_DEMON))
    {
	ch->power[DISC_DAEM_ATTA] = 0;
	ch->power[DISC_DAEM_IMMU] = 0;
	ch->power[DISC_DAEM_TEMP] = 0;
	ch->power[DISC_DAEM_CORR] = 0;
	ch->power[DISC_DAEM_HELL] = 0;
	ch->power[DISC_DAEM_GELU] = 0;
	ch->power[DISC_DAEM_MORP] = 0;
	ch->power[DISC_DAEM_NETH] = 0;
	ch->power[DISC_DAEM_DISC] = 0;
    }

    save_char_obj(ch);
}



/*
 * Give an affect to a char.
 */
void affect_to_char( CHAR_DATA *ch, AFFECT_DATA *paf )
{
    AFFECT_DATA *paf_new;

    if ( affect_free == NULL )
    {
	paf_new		= alloc_perm( sizeof(*paf_new) );
    }
    else
    {
	paf_new		= affect_free;
	affect_free	= affect_free->next;
    }

    *paf_new		= *paf;
    paf_new->next	= ch->affected;
    ch->affected	= paf_new;

    affect_modify( ch, paf_new, TRUE );
    return;
}



/*
 * Remove an affect from a char.
 */
void affect_remove( CHAR_DATA *ch, AFFECT_DATA *paf )
{
    if ( ch->affected == NULL )
    {
	bug( "Affect_remove: no affect.", 0 );
	return;
    }

    affect_modify( ch, paf, FALSE );

    if ( paf == ch->affected )
    {
	ch->affected	= paf->next;
    }
    else
    {
	AFFECT_DATA *prev;

	for ( prev = ch->affected; prev != NULL; prev = prev->next )
	{
	    if ( prev->next == paf )
	    {
		prev->next = paf->next;
		break;
	    }
	}

	if ( prev == NULL )
	{
	    bug( "Affect_remove: cannot find paf.", 0 );
	    return;
	}
    }

    paf->next	= affect_free;
    affect_free	= paf->next;
    return;
}



/*
 * Strip all affects of a given sn.
 */
void affect_strip( CHAR_DATA *ch, int sn )
{
    AFFECT_DATA *paf;
    AFFECT_DATA *paf_next;

    for ( paf = ch->affected; paf != NULL; paf = paf_next )
    {
	paf_next = paf->next;
	if ( paf->type == sn )
	    affect_remove( ch, paf );
    }

    return;
}



/*
 * Return true if a char is affected by a spell.
 */
bool is_affected( CHAR_DATA *ch, int sn )
{
    AFFECT_DATA *paf;

    for ( paf = ch->affected; paf != NULL; paf = paf->next )
    {
	if ( paf->type == sn )
	    return TRUE;
    }

    return FALSE;
}



/*
 * Add or enhance an affect.
 */
void affect_join( CHAR_DATA *ch, AFFECT_DATA *paf )
{
    AFFECT_DATA *paf_old;
    bool found;

    found = FALSE;
    for ( paf_old = ch->affected; paf_old != NULL; paf_old = paf_old->next )
    {
	if ( paf_old->type == paf->type )
	{
	    paf->duration += paf_old->duration;
	    paf->modifier += paf_old->modifier;
	    affect_remove( ch, paf_old );
	    break;
	}
    }

    affect_to_char( ch, paf );
    return;
}



/*
 * Move a char out of a room.
 */
void char_from_room( CHAR_DATA *ch )
{
    OBJ_DATA *obj;

    if ( ch->in_room == NULL )
    {
	bug( "Char_from_room: NULL.", 0 );
	return;
    }

 //   if ( !IS_NPC(ch) )
//	--ch->in_room->area->nplayer;

    if ( ( obj = get_eq_char( ch, WEAR_WIELD ) ) != NULL
    &&   obj->item_type == ITEM_LIGHT
    &&   obj->value[2] != 0
    &&   ch->in_room->light > 0 )
	--ch->in_room->light;
    else if ( ( obj = get_eq_char( ch, WEAR_HOLD ) ) != NULL
    &&   obj->item_type == ITEM_LIGHT
    &&   obj->value[2] != 0
    &&   ch->in_room->light > 0 )
	--ch->in_room->light;

    if ( !IS_NPC(ch)  &&  IS_SET(ch->newbits, NEW_DARKNESS))
    {
	if (ch->in_room != NULL)
	    REMOVE_BIT(ch->in_room->room_flags, ROOM_TOTAL_DARKNESS); 
    }

    if ( ch == ch->in_room->people )
    {
	ch->in_room->people = ch->next_in_room;
    }
    else
    {
	CHAR_DATA *prev;

	for ( prev = ch->in_room->people; prev; prev = prev->next_in_room )
	{
	    if ( prev->next_in_room == ch )
	    {
		prev->next_in_room = ch->next_in_room;
		break;
	    }
	}

	if ( prev == NULL )
	    bug( "Char_from_room: ch not found.", 0 );
    }

    ch->in_room      = NULL;
    ch->next_in_room = NULL;
    return;
}



/*
 * Move a char into a room.
 */
void char_to_room( CHAR_DATA *ch, ROOM_INDEX_DATA *pRoomIndex )
{
    OBJ_DATA *obj;

    if ( !pRoomIndex )
    {
	char buf[MAX_STRING_LENGTH];

	sprintf( buf, "Char_to_room: %s -> NULL room!  Putting char in limbo (%d)", ch->name, ROOM_VNUM_LIMBO );
	bug( buf, 0 );
        /* This used to just return, but there was a problem with crashing
           and I saw no reason not to just put the char in limbo. -Narn */
        pRoomIndex = get_room_index( ROOM_VNUM_LIMBO );
    }

    ch->in_room		= pRoomIndex;
    ch->next_in_room	= pRoomIndex->people;
    pRoomIndex->people	= ch;

//    if ( !IS_NPC(ch) )
//	++ch->in_room->area->nplayer;


    if ( ( obj = get_eq_char( ch, WEAR_WIELD ) ) != NULL
    &&   obj->item_type == ITEM_LIGHT
    &&   obj->value[2] != 0 )
	++ch->in_room->light;
    else if ( ( obj = get_eq_char( ch, WEAR_HOLD ) ) != NULL
    &&   obj->item_type == ITEM_LIGHT
    &&   obj->value[2] != 0 )
	++ch->in_room->light;

    if (ch->loc_hp[6] > 0 && ch->in_room->blood < 1000) ch->in_room->blood += 1;

    if ( !IS_NPC(ch)  &&  IS_SET(ch->newbits, NEW_DARKNESS))
        SET_BIT(ch->in_room->room_flags, ROOM_TOTAL_DARKNESS);  

    return;
}



/*
 * Give an obj to a char.
 */
void obj_to_char( OBJ_DATA *obj, CHAR_DATA *ch )
{
    if (obj == NULL) return;
    obj->next_content	 = ch->carrying;
    ch->carrying	 = obj;
    obj->carried_by	 = ch;
    obj->in_room	 = NULL;
    obj->in_obj		 = NULL;
    ch->carry_number	+= 1;
    ch->carry_weight	+= get_obj_weight( obj );
}



/*
 * Take an obj from its character.
 */
void obj_from_char( OBJ_DATA *obj )
{
    CHAR_DATA *ch;

    if (obj == NULL) return;
    if ( ( ch = obj->carried_by ) == NULL )
    {
	( "Obj_from_char: null ch.", 0 );
	return;
    }

    if ( obj->wear_loc != WEAR_NONE )
	unequip_char( ch, obj );

    if ( ch->carrying == obj )
    {
	ch->carrying = obj->next_content;
    }
    else
    {
	OBJ_DATA *prev;

	for ( prev = ch->carrying; prev != NULL; prev = prev->next_content )
	{
	    if ( prev->next_content == obj )
	    {
		prev->next_content = obj->next_content;
		break;
	    }
	}

	if ( prev == NULL )
	  
  ( "Obj_from_char: obj not in list.", 0 );
    }

    obj->carried_by	 = NULL;
    obj->next_content	 = NULL;
    ch->carry_number	-= 1;
    ch->carry_weight	-= get_obj_weight( obj );
    return;
}



/*
 * Find the ac value of an obj, including position effect.
 */
int apply_ac( OBJ_DATA *obj, int iWear )
{
    if ( obj->item_type != ITEM_ARMOR )
	return 0;

    switch ( iWear )
    {
    case WEAR_BODY:	return 3 * obj->value[0];
    case WEAR_HEAD:	return 2 * obj->value[0];
    case WEAR_LEGS:	return 2 * obj->value[0];
    case WEAR_FEET:	return     obj->value[0];
    case WEAR_HANDS:	return     obj->value[0];
    case WEAR_ARMS:	return     obj->value[0];
    case WEAR_SHIELD:	return     obj->value[0];
    case WEAR_FINGER_L:	return     obj->value[0];
    case WEAR_FINGER_R: return     obj->value[0];
    case WEAR_NECK_1:	return     obj->value[0];
    case WEAR_NECK_2:	return     obj->value[0];
    case WEAR_ABOUT:	return 2 * obj->value[0];
    case WEAR_WAIST:	return     obj->value[0];
    case WEAR_WRIST_L:	return     obj->value[0];
    case WEAR_WRIST_R:	return     obj->value[0];
    case WEAR_HOLD:	return     obj->value[0];
    case WEAR_FACE:	return     obj->value[0];
    case WEAR_SCABBARD_L:return 0;
    case WEAR_SCABBARD_R:return 0;
    }

    return 0;
}



/*
 * Find a piece of eq on a character.
 */
OBJ_DATA *get_eq_char( CHAR_DATA *ch, int iWear )
{
    OBJ_DATA *obj;

    for ( obj = ch->carrying; obj != NULL; obj = obj->next_content )
    {
	if ( obj->wear_loc == iWear )
	    return obj;
    }

    return NULL;
}



/*
 * Equip a char with an obj.
 */
void equip_char( CHAR_DATA *ch, OBJ_DATA *obj, int iWear )
{
    CHAR_DATA   *chch;
    AFFECT_DATA *paf;
    int sn;
/*
    if ( get_eq_char( ch, iWear ) != NULL )
    {
	bug( "Equip_char: already equipped (%d).", iWear );
	return;
    }
work on this */
    if ( ( IS_OBJ_STAT(obj, ITEM_ANTI_EVIL)    && IS_EVIL(ch)    )
    ||   ( IS_OBJ_STAT(obj, ITEM_ANTI_GOOD)    && IS_GOOD(ch)    )
    ||   ( IS_OBJ_STAT(obj, ITEM_ANTI_NEUTRAL) && IS_NEUTRAL(ch) ) )
    {
	/*
	 * Thanks to Morgenes for the bug fix here!
	 */
	act( "You are zapped by $p and drop it.", ch, obj, NULL, TO_CHAR );
	act( "$n is zapped by $p and drops it.",  ch, obj, NULL, TO_ROOM );
	obj_from_char( obj );
	obj_to_room( obj, ch->in_room );
	do_autosave( ch, "" );
	return;
    }

	if (IS_SET(obj->spectype, SITEM_DROW) || obj->pIndexData->vnum ==
	29600 || obj->pIndexData->vnum == 29601)
	if (IS_NPC(ch) || !IS_CLASS(ch, CLASS_DROW)) {
	act( "You are zapped by $p and drop it.", ch, obj, NULL, TO_CHAR );
	act( "$n is zapped by $p and drops it.",  ch, obj, NULL, TO_ROOM );
	obj_from_char( obj );
	obj_to_room( obj, ch->in_room );
	do_autosave( ch, "" );
	return;
	} 

	if (obj->pIndexData->vnum == 29700 && (IS_NPC(ch) ||
!IS_CLASS(ch,CLASS_NINJA))) {
	act( "You are zapped by $p and drop it.", ch, obj, NULL, TO_CHAR);
	act( "$n is zapped by $p and drops it.", ch, obj, NULL, TO_ROOM);
	obj_from_char(obj);
	obj_to_room(obj, ch->in_room);
	do_autosave(ch, "");
	return;
	}

    if ((IS_NPC(ch) || !IS_CLASS(ch,
     CLASS_DEMON)) && IS_SET(obj->spectype, SITEM_DEMONIC))
    {
	act( "You are zapped by $p and drop it.", ch, obj, NULL, TO_CHAR );
	act( "$n is zapped by $p and drops it.",  ch, obj, NULL, TO_ROOM );
	obj_from_char( obj );
	obj_to_room( obj, ch->in_room );
	do_autosave( ch, "" );
	return;
    }

    if ((IS_NPC(ch) || !IS_IMMORTAL(ch)) && IS_SET(obj->quest,QUEST_RELIC)
	&&  !IS_SET(obj->spectype,SITEM_DEMONIC)
	&&  !IS_SET(obj->spectype,SITEM_HIGHLANDER) && !IS_CLASS(ch,
CLASS_WEREWOLF) && !IS_CLASS(ch, CLASS_NINJA) &&  obj->chobj == NULL &&
!IS_CLASS(ch, CLASS_DROW))
    {
	act( "You are zapped by $p and drop it.", ch, obj, NULL, TO_CHAR );
	act( "$n is zapped by $p and drops it.",  ch, obj, NULL, TO_ROOM );
	obj_from_char( obj );
	obj_to_room( obj, ch->in_room );
	do_autosave( ch, "" );
	return;
    }
/*
 * Mercpoint - commented out to enable wearing more than one artifact.
 * Damcap is not modified by more than 500 on wearing more than one
 * artifact due to the fact that the damcap modifier is based on whether
 * a player is affected by ITEMA_ARTIFACT and as this can only be either
 * on or off it only affects damcap once :)
 * Therefore this enables a player to wear all the artifacts they have
 * aquired (call it a reward for having got them) as because we have
 * changed the code such that artifacts can no longer be put in bags,
 * it now follows that a player with more than one artifact who is decapped
 * will have his corpse looted for all of those artifacts.
 * Hence he might as well can the benefit for having them.
 *
 * It miht be an idea to add a check such that if the player is still
 * wearing an artifact when they remove one that the ITEMA_ARTIFACT bit
 * isn't removed. - Merc (4/10/96)
 *
    if (IS_SET(obj->quest, QUEST_ARTIFACT) && IS_ITEMAFF(ch, ITEMA_ARTIFACT))
    {
	act( "You are zapped by $p and drop it.", ch, obj, NULL, TO_CHAR );
	act( "$n is zapped by $p and drops it.",  ch, obj, NULL, TO_ROOM );
	obj_from_char( obj );
	obj_to_room( obj, ch->in_room );
	do_autosave( ch, "" );
	return;
    }
 */

    if ((IS_NPC(ch) || !IS_CLASS(ch, CLASS_HIGHLANDER)) 
	&& IS_SET(obj->spectype, SITEM_HIGHLANDER))
    {
	act( "You are zapped by $p and drop it.", ch, obj, NULL, TO_CHAR );
	act( "$n is zapped by $p and drops it.",  ch, obj, NULL, TO_ROOM );
	obj_from_char( obj );
	obj_to_room( obj, ch->in_room );
	do_autosave( ch, "" );
	return;
    }


    if ( iWear == WEAR_SCABBARD_L ||
    	iWear == WEAR_SCABBARD_R ) 
    {
	obj->wear_loc = iWear;
	return;
    }

    if ( IS_NPC(ch) || !IS_CLASS(ch, CLASS_HIGHLANDER) ) 
	ch->armor -= apply_ac( obj, iWear );
    obj->wear_loc = iWear;

    for ( paf = obj->pIndexData->affected; paf != NULL; paf = paf->next )
	affect_modify( ch, paf, TRUE );
    for ( paf = obj->affected; paf != NULL; paf = paf->next )
	affect_modify( ch, paf, TRUE );

    if ( obj->item_type == ITEM_LIGHT
    &&   obj->value[2] != 0
    &&   ch->in_room != NULL )
	++ch->in_room->light;

    if (!IS_NPC(ch) && !IS_CLASS(ch, CLASS_DEMON))
    {
    	if ( (chch = get_char_world(ch,ch->name)) == NULL ) return;
    	if ( chch->desc != ch->desc) return;
    }

    if (obj->chpoweron != NULL && obj->chpoweron != '\0'
	&& str_cmp(obj->chpoweron,"(null)")
	&& !IS_SET(obj->spectype, SITEM_TELEPORTER)
	&& !IS_SET(obj->spectype, SITEM_TRANSPORTER) )
	{
	    kavitem(str_dup(obj->chpoweron),ch,obj,NULL,TO_CHAR);
	    if (IS_SET(obj->spectype, SITEM_ACTION))
		kavitem(str_dup(obj->chpoweron),ch,obj,NULL,TO_ROOM);
	}
    if (obj->victpoweron != NULL && obj->victpoweron != '\0'
	&& str_cmp(obj->victpoweron,"(null)")
	&& !IS_SET(obj->spectype, SITEM_ACTION)
	&& !IS_SET(obj->spectype, SITEM_TELEPORTER)
	&& !IS_SET(obj->spectype, SITEM_TRANSPORTER) )
	kavitem(str_dup(obj->victpoweron),ch,obj,NULL,TO_ROOM);

    if ( obj->wear_loc == WEAR_NONE )
	return;
    if (   ((obj->item_type == ITEM_ARMOR ) && (obj->value[3] >= 1   ))
	|| ((obj->item_type == ITEM_WEAPON) && (obj->value[0] >= 1000))
	|| IS_SET(obj->spectype, SITEM_SILVER)
	|| IS_SET(obj->spectype, SITEM_DEMONIC)
	|| IS_SET(obj->quest, QUEST_ARTIFACT) )
    {
	/* It would be so much easier if weapons had 5 values *sigh*.  
	 * Oh well, I'll just have to use v0 for two.  KaVir.
	 */
	if (obj->item_type == ITEM_ARMOR)
	    sn = obj->value[3];
	else
	    sn = obj->value[0] / 1000;

	if      ((sn ==  4) && (IS_AFFECTED(ch, AFF_BLIND)))        return;
	else if ((sn == 27) && (IS_AFFECTED(ch, AFF_DETECT_INVIS))) return;
	else if ((sn == 39) && (IS_AFFECTED(ch, AFF_FLYING)))       return;
	else if ((sn == 45) && (IS_AFFECTED(ch, AFF_INFRARED)))     return;
	else if ((sn == 46) && (IS_AFFECTED(ch, AFF_INVISIBLE)))    return;
	else if ((sn == 52) && (IS_AFFECTED(ch, AFF_PASS_DOOR)))    return;
	else if ((sn == 54) && (IS_AFFECTED(ch, AFF_PROTECT)))      return;
	else if ((sn == 57) && (IS_AFFECTED(ch, AFF_SANCTUARY)))    return;
	else if ((sn == 2 ) && (IS_AFFECTED(ch, AFF_DETECT_INVIS))) return;
	else if ((sn == 3 ) && (IS_AFFECTED(ch, AFF_FLYING)))       return;
	else if ((sn == 1 ) && (IS_AFFECTED(ch, AFF_INFRARED)))     return;
	else if ((sn == 5 ) && (IS_AFFECTED(ch, AFF_INVISIBLE)))    return;
	else if ((sn == 6 ) && (IS_AFFECTED(ch, AFF_PASS_DOOR)))    return;
	else if ((sn == 7 ) && (IS_AFFECTED(ch, AFF_PROTECT)))      return;
	else if ((sn == 8 ) && (IS_AFFECTED(ch, AFF_SANCTUARY)))    return;
	else if ((sn == 9 ) && (IS_AFFECTED(ch, AFF_SNEAK)))        return;
	else if ((sn == 10) && (IS_ITEMAFF(ch, ITEMA_SHOCKSHIELD))) return;
	else if ((sn == 11) && (IS_ITEMAFF(ch, ITEMA_FIRESHIELD)))  return;
	else if ((sn == 12) && (IS_ITEMAFF(ch, ITEMA_ICESHIELD)))   return;
	else if ((sn == 13) && (IS_ITEMAFF(ch, ITEMA_ACIDSHIELD)))  return;
	else if ((sn == 14) && (IS_ITEMAFF(ch, ITEMA_DBPASS)))      return;
	else if ((sn == 15) && (IS_ITEMAFF(ch, ITEMA_CHAOSSHIELD))) return;
	else if ((sn == 16) && (IS_ITEMAFF(ch, ITEMA_REGENERATE)))  return;
	else if ((sn == 17) && (IS_ITEMAFF(ch, ITEMA_SPEED)))       return;
	else if ((sn == 18) && (IS_ITEMAFF(ch, ITEMA_VORPAL)))      return;
	else if ((sn == 19) && (IS_ITEMAFF(ch, ITEMA_PEACE)))       return;
	else if ((sn == 20) && (IS_ITEMAFF(ch, ITEMA_REFLECT)))     return;
	else if ((sn == 21) && (IS_ITEMAFF(ch, ITEMA_RESISTANCE)))  return;
	else if ((sn == 22) && (IS_ITEMAFF(ch, ITEMA_VISION)))      return;
	else if ((sn == 23) && (IS_ITEMAFF(ch, ITEMA_STALKER)))     return;
	else if ((sn == 24) && (IS_ITEMAFF(ch, ITEMA_VANISH)))      return;
	else if ((sn == 25) && (IS_ITEMAFF(ch, ITEMA_RAGER)))       return;
	else if ((sn == 60) && (IS_AFFECTED(ch, AFF_DETECT_HIDDEN)))return;

	if (sn == 4)
	{
	    SET_BIT(ch->affected_by, AFF_BLIND);
	    send_to_char( "You cannot see a thing!\n\r", ch );
	    act("$n seems to be blinded!",ch,NULL,NULL,TO_ROOM);
	}
	else if (sn == 27 || sn == 2)
	{
	    SET_BIT(ch->affected_by, AFF_DETECT_INVIS);
	    send_to_char( "Your eyes tingle.\n\r", ch );
	    act("$n's eyes flicker with light.",ch,NULL,NULL,TO_ROOM);
	}
	else if (sn == 39 || sn == 3)
	{
	    SET_BIT(ch->affected_by, AFF_FLYING);
	    send_to_char( "Your feet rise off the ground.\n\r", ch );
	    act("$n's feet rise off the ground.",ch,NULL,NULL,TO_ROOM);
	}
	else if (sn == 45 || sn == 1)
	{
	    SET_BIT(ch->affected_by, AFF_INFRARED);
	    send_to_char( "Your eyes glow red.\n\r", ch );
	    act("$n's eyes glow red.",ch,NULL,NULL,TO_ROOM);
	}
	else if (sn == 46 || sn == 5)
	{
	    SET_BIT(ch->affected_by, AFF_INVISIBLE);
	    send_to_char( "You fade out of existance.\n\r", ch );
	    act("$n fades out of existance.",ch,NULL,NULL,TO_ROOM);
	}
	else if (sn == 52 || sn == 6)
	{
	    SET_BIT(ch->affected_by, AFF_PASS_DOOR);
	    send_to_char( "You turn translucent.\n\r", ch );
	    act("$n turns translucent.",ch,NULL,NULL,TO_ROOM);
	}
	else if (sn == 60)
	{
	    SET_BIT(ch->affected_by, AFF_DETECT_HIDDEN);
	    send_to_char( "You awarenes improves.\n\r", ch );
	    act("$n eyes tingle.",ch,NULL,NULL,TO_ROOM);
	}
	else if (sn == 54 || sn == 7)
	{
	    SET_BIT(ch->affected_by, AFF_PROTECT);
	    send_to_char( "You are surrounded by a divine aura.\n\r", ch );
	    act("$n is surrounded by a divine aura.",ch,NULL,NULL,TO_ROOM);
	}
	else if (sn == 57 || sn == 8)
	{
	    SET_BIT(ch->affected_by, AFF_SANCTUARY);
	    send_to_char( "You are surrounded by a white aura.\n\r", ch );
	    act("$n is surrounded by a white aura.",ch,NULL,NULL,TO_ROOM);
	}
	else if (sn == 9)
	{
	    SET_BIT(ch->affected_by, AFF_SNEAK);
	    send_to_char( "Your footsteps stop making any sound.\n\r", ch );
	    act("$n's footsteps stop making any sound.",ch,NULL,NULL,TO_ROOM);
	}
	else if (sn == 10)
	{
	    SET_BIT(ch->itemaffect, ITEMA_SHOCKSHIELD);
	    send_to_char( "You are surrounded by a crackling shield of lightning.\n\r", ch );
	    act("$n is surrounded by a crackling shield of lightning.",ch,NULL,NULL,TO_ROOM);
	}
	else if (sn == 11)
	{
	    SET_BIT(ch->itemaffect, ITEMA_FIRESHIELD);
	    send_to_char( "You are surrounded by a burning shield of flames.\n\r", ch );
	    act("$n is surrounded by a burning shield of flames.",ch,NULL,NULL,TO_ROOM);
	}
	else if (sn == 12)
	{
	    SET_BIT(ch->itemaffect, ITEMA_ICESHIELD);
	    send_to_char( "You are surrounded by a shimmering shield of ice.\n\r", ch );
	    act("$n is surrounded by a shimmering shield of ice.",ch,NULL,NULL,TO_ROOM);
	}
	else if (sn == 13)
	{
	    SET_BIT(ch->itemaffect, ITEMA_ACIDSHIELD);
	    send_to_char( "You are surrounded by a bubbling shield of acid.\n\r", ch );
	    act("$n is surrounded by a bubbling shield of acid.",ch,NULL,NULL,TO_ROOM);
	}
	else if (sn == 14)
	{
	    SET_BIT(ch->itemaffect, ITEMA_DBPASS);
	    send_to_char( "You are now safe from the DarkBlade clan guardians.\n\r", ch );
	}
	else if (sn == 15)
	{
	    SET_BIT(ch->itemaffect, ITEMA_CHAOSSHIELD);
	    send_to_char( "You are surrounded by a swirling shield of chaos.\n\r", ch );
	    act("$n is surrounded by a swirling shield of chaos.",ch,NULL,NULL,TO_ROOM);
	}
	else if (sn == 16)
	    SET_BIT(ch->itemaffect, ITEMA_REGENERATE);
	else if (sn == 17)
	{
	    SET_BIT(ch->itemaffect, ITEMA_SPEED);
	    send_to_char( "You start moving faster than the eye can follow.\n\r", ch );
	    act("$n starts moving faster than the eye can follow.",ch,NULL,NULL,TO_ROOM);
	}
	else if (sn == 18)
	    SET_BIT(ch->itemaffect, ITEMA_VORPAL);
	else if (sn == 19)
	    SET_BIT(ch->itemaffect, ITEMA_PEACE);
	else if (sn == 20)
	{
	    SET_BIT(ch->itemaffect, ITEMA_REFLECT);
	    send_to_char( "You are surrounded by flickering shield of darkness.\n\r", ch );
	    act("$n is surrounded by a flickering shield of darkness.",ch,NULL,NULL,TO_ROOM);
	}
	else if (sn == 21)
	    SET_BIT(ch->itemaffect, ITEMA_RESISTANCE);
	else if (sn == 22)
	{
	    SET_BIT(ch->itemaffect, ITEMA_VISION);
	    send_to_char( "Your eyes begin to glow bright white.\n\r", ch );
	    act("$n's eyes begin to glow bright white.",ch,NULL,NULL,TO_ROOM);
	}
	else if (sn == 23)
	    SET_BIT(ch->itemaffect, ITEMA_STALKER);
	else if (sn == 24)
	{
	    SET_BIT(ch->itemaffect, ITEMA_VANISH);
	    send_to_char( "You blend into the shadows.\n\r", ch );
	    act("$n gradually fades into the shadows.",ch,NULL,NULL,TO_ROOM);
	}
	else if (sn == 25 && !IS_NPC(ch))
	{
	    SET_BIT(ch->itemaffect, ITEMA_RAGER);
	    if (IS_CLASS(ch, CLASS_WEREWOLF) && ch->rage < 100)
	    {
		ch->rage = 300;
		do_werewolf(ch,"");
	    }
	    else if (IS_CLASS(ch, CLASS_WEREWOLF))
		ch->rage = 300;
	    else if (IS_CLASS(ch, CLASS_VAMPIRE))
		ch->rage = 25;
	    else if (IS_CLASS(ch, CLASS_DEMON))
		ch->rage = 125;
	}

	if (IS_SET(obj->spectype, SITEM_DEMONIC) && !IS_NPC(ch))
	if (ch->pcdata->stats[DEMON_POWER] < 15) ch
->pcdata->stats[DEMON_POWER] += 1;
	if (IS_SET(obj->spectype, SITEM_HIGHLANDER) && !IS_NPC(ch) && obj->item_type == ITEM_WEAPON)
	{
	    if (obj->value[3] == ch->pcdata->powers[HPOWER_WPNSKILL])
		SET_BIT(ch->itemaffect, ITEMA_HIGHLANDER);
	}
	if (IS_SET(obj->quest, QUEST_ARTIFACT))
	    SET_BIT(ch->itemaffect, ITEMA_ARTIFACT);
	if (IS_SET(obj->spectype, SITEM_SILVER) && obj->wear_loc == WEAR_WIELD)
	    SET_BIT(ch->itemaffect, ITEMA_RIGHT_SILVER);
	if (IS_SET(obj->spectype, SITEM_SILVER) && obj->wear_loc == WEAR_HOLD)
	    SET_BIT(ch->itemaffect, ITEMA_LEFT_SILVER);
    }
    return;
}

/*
 * Unequip a char with an obj.
 */
void unequip_char( CHAR_DATA *ch, OBJ_DATA *obj )
{
    CHAR_DATA   *chch;
    AFFECT_DATA *paf;
    int sn;
    int oldpos = obj->wear_loc;

    if ( obj->wear_loc == WEAR_NONE )
    {
	bug( "Unequip_char: already unequipped.", 0 );
	return;
    }

    if ( obj->wear_loc == WEAR_SCABBARD_L ||
    	obj->wear_loc == WEAR_SCABBARD_R ) {obj->wear_loc = -1;return;}

    if ( IS_NPC(ch) || !IS_CLASS(ch, CLASS_HIGHLANDER) ) 
	ch->armor += apply_ac(obj, obj->wear_loc);
    obj->wear_loc	 = -1;

    for ( paf = obj->pIndexData->affected; paf != NULL; paf = paf->next )
	affect_modify( ch, paf, FALSE );
    for ( paf = obj->affected; paf != NULL; paf = paf->next )
	affect_modify( ch, paf, FALSE );

    if ( obj->item_type == ITEM_LIGHT
    &&   obj->value[2] != 0
    &&   ch->in_room != NULL
    &&   ch->in_room->light > 0 )
	--ch->in_room->light;

    if ( (chch = get_char_world(ch,ch->name)) == NULL ) return;
    if ( chch->desc != ch->desc) return;

    if (!IS_NPC(ch) && (ch->desc != NULL && ch->desc->connected != CON_PLAYING)) return;

    if (obj->chpoweroff != NULL && obj->chpoweroff != '\0'
	&& str_cmp(obj->chpoweroff,"(null)")
	&& !IS_SET(obj->spectype, SITEM_TELEPORTER)
	&& !IS_SET(obj->spectype, SITEM_TRANSPORTER) )
	{
	    kavitem(str_dup(obj->chpoweroff),ch,obj,NULL,TO_CHAR);
	    if (IS_SET(obj->spectype, SITEM_ACTION))
		kavitem(str_dup(obj->chpoweroff),ch,obj,NULL,TO_ROOM);
	}
    if (obj->victpoweroff != NULL && obj->victpoweroff != '\0'
	&& str_cmp(obj->victpoweroff,"(null)")
	&& !IS_SET(obj->spectype, SITEM_ACTION)
	&& !IS_SET(obj->spectype, SITEM_TELEPORTER)
	&& !IS_SET(obj->spectype, SITEM_TRANSPORTER) )
	kavitem(str_dup(obj->victpoweroff),ch,obj,NULL,TO_ROOM);

    if ( ((obj->item_type == ITEM_ARMOR ) && (obj->value[3] >= 1   ))
        || ((obj->item_type == ITEM_WEAPON) && (obj->value[0] >= 1000))
	|| IS_SET(obj->spectype, SITEM_SILVER)
	|| IS_SET(obj->spectype, SITEM_DEMONIC)
	|| IS_SET(obj->quest, QUEST_ARTIFACT) )
    {
	if (obj->item_type == ITEM_ARMOR)
	    sn = obj->value[3];
	else
	    sn = obj->value[0] / 1000;
	if (IS_AFFECTED(ch, AFF_BLIND) && (sn == 4)
		&& !is_affected(ch, 4))
	{
	    REMOVE_BIT(ch->affected_by, AFF_BLIND);
	    send_to_char( "You can see again.\n\r", ch );
	    act("$n seems to be able to see again.",ch,NULL,NULL,TO_ROOM);
	}
	else if (IS_AFFECTED(ch, AFF_DETECT_INVIS) && (sn == 27 || sn == 2)
		&& !is_affected(ch, 27))
	{
	    REMOVE_BIT(ch->affected_by, AFF_DETECT_INVIS);
	    send_to_char( "Your eyes stop tingling.\n\r", ch );
	    act("$n's eyes stop flickering with light.",ch,NULL,NULL,TO_ROOM);
	}
	else if (IS_AFFECTED(ch, AFF_FLYING) && (sn == 39 || sn == 3)
		&& !is_affected(ch, 39))
	{
	    REMOVE_BIT(ch->affected_by, AFF_FLYING);
	    send_to_char( "You slowly float to the ground.\n\r", ch );
	    act("$n slowly floats to the ground.",ch,NULL,NULL,TO_ROOM);
	}
	else if (IS_AFFECTED(ch, AFF_INFRARED) && (sn == 45 || sn == 1)
		&& !is_affected(ch, 45))
	{
	    REMOVE_BIT(ch->affected_by, AFF_INFRARED);
	    send_to_char( "Your eyes stop glowing red.\n\r", ch );
	    act("$n's eyes stop glowing red.",ch,NULL,NULL,TO_ROOM);
	}
	else if (IS_AFFECTED(ch, AFF_INVISIBLE) && (sn == 46 || sn == 5)
		&& !is_affected(ch, 46))
	{
	    REMOVE_BIT(ch->affected_by, AFF_INVISIBLE);
	    send_to_char( "You fade into existance.\n\r", ch );
	    act("$n fades into existance.",ch,NULL,NULL,TO_ROOM);
	}
	else if (IS_AFFECTED(ch, AFF_PASS_DOOR) && (sn == 52 || sn == 6)
		&& !is_affected(ch, 52))
	{
	    REMOVE_BIT(ch->affected_by, AFF_PASS_DOOR);
	    send_to_char( "You feel solid again.\n\r", ch );
	    act("$n is no longer translucent.",ch,NULL,NULL,TO_ROOM);
	}
	else if (IS_AFFECTED(ch, AFF_PROTECT) && (sn == 54 || sn == 7)
		&& !is_affected(ch, 54))
	{
	    REMOVE_BIT(ch->affected_by, AFF_PROTECT);
	    send_to_char( "The divine aura around you fades.\n\r", ch );
	    act("The divine aura around $n fades.",ch,NULL,NULL,TO_ROOM);
	}
	else if (IS_AFFECTED(ch, AFF_SANCTUARY) && (sn == 57 || sn == 8)
		&& !is_affected(ch, 57))
	{
	    REMOVE_BIT(ch->affected_by, AFF_SANCTUARY);
	    send_to_char( "The white aura around your body fades.\n\r", ch );
	    act("The white aura about $n's body fades.",ch,NULL,NULL,TO_ROOM);
	}
	else if (IS_AFFECTED(ch, AFF_SNEAK) && (sn == 9)
		&& !is_affected(ch, 80))
	{
	    REMOVE_BIT(ch->affected_by, AFF_SNEAK);
	    send_to_char( "You are no longer moving so quietly.\n\r", ch );
	    act("$n is no longer moving so quietly.",ch,NULL,NULL,TO_ROOM);
	}
	else if (IS_AFFECTED(ch, AFF_DETECT_HIDDEN) && (sn == 60))
	{
	    REMOVE_BIT(ch->affected_by, AFF_DETECT_HIDDEN);
	    send_to_char( "You feel less aware of your surrondings.\n\r",ch );
	    act("$n eyes tingle.",ch,NULL,NULL,TO_ROOM);
	}
	else if (IS_ITEMAFF(ch, ITEMA_SHOCKSHIELD) && (sn == 10))
	{
	    REMOVE_BIT(ch->itemaffect, ITEMA_SHOCKSHIELD);
	    send_to_char( "The crackling shield of lightning around you fades.\n\r", ch );
	    act("The crackling shield of lightning around $n fades.",ch,NULL,NULL,TO_ROOM);
	}
	else if (IS_ITEMAFF(ch, ITEMA_FIRESHIELD) && (sn == 11))
	{
	    REMOVE_BIT(ch->itemaffect, ITEMA_FIRESHIELD);
	    send_to_char( "The burning shield of fire around you fades.\n\r", ch );
	    act("The burning shield of fire around $n fades.",ch,NULL,NULL,TO_ROOM);
	}
	else if (IS_ITEMAFF(ch, ITEMA_ICESHIELD) && (sn == 12))
	{
	    REMOVE_BIT(ch->itemaffect, ITEMA_ICESHIELD);
	    send_to_char( "The shimmering shield of ice around you fades.\n\r", ch );
	    act("The shimmering shield of ice around $n fades.",ch,NULL,NULL,TO_ROOM);
	}
	else if (IS_ITEMAFF(ch, ITEMA_ACIDSHIELD) && (sn == 13))
	{
	    REMOVE_BIT(ch->itemaffect, ITEMA_ACIDSHIELD);
	    send_to_char( "The bubbling shield of acid around you fades.\n\r", ch );
	    act("The bubbling shield of acid around $n fades.",ch,NULL,NULL,TO_ROOM);
	}
	else if (IS_ITEMAFF(ch, ITEMA_DBPASS) && (sn == 14))
	{
	    REMOVE_BIT(ch->itemaffect, ITEMA_DBPASS);
	    send_to_char( "You are no longer safe from the DarkBlade clan guardians.\n\r", ch );
	}
	else if (IS_ITEMAFF(ch, ITEMA_CHAOSSHIELD) && (sn == 15))
	{
	    REMOVE_BIT(ch->itemaffect, ITEMA_CHAOSSHIELD);
	    send_to_char( "The swirling shield of chaos around you fades.\n\r", ch );
	    act("The swirling shield of chaos around $n fades.",ch,NULL,NULL,TO_ROOM);
	}
	else if (sn == 16)
	    REMOVE_BIT(ch->itemaffect, ITEMA_REGENERATE);
	else if (IS_ITEMAFF(ch, ITEMA_SPEED) && (sn == 17))
	{
	    REMOVE_BIT(ch->itemaffect, ITEMA_SPEED);
	    send_to_char( "Your actions slow down to normal speed.\n\r", ch );
	    act("$n stops moving at supernatural speed.",ch,NULL,NULL,TO_ROOM);
	}
	else if (sn == 18)
	    REMOVE_BIT(ch->itemaffect, ITEMA_VORPAL);
	else if (sn == 19)
	    REMOVE_BIT(ch->itemaffect, ITEMA_PEACE);
	else if (IS_ITEMAFF(ch, ITEMA_REFLECT) && sn == 20)
	{
	    REMOVE_BIT(ch->itemaffect, ITEMA_REFLECT);
	    send_to_char( "The flickering shield of darkness around you fades.\n\r", ch );
	    act("The flickering shield of darkness around $n fades.",ch,NULL,NULL,TO_ROOM);
	}
	else if (sn == 21)
	    REMOVE_BIT(ch->itemaffect, ITEMA_RESISTANCE);
	else if (IS_ITEMAFF(ch, ITEMA_VISION) && sn == 22)
	{
	    REMOVE_BIT(ch->itemaffect, ITEMA_VISION);
	    send_to_char( "Your eyes stop glowing bright white.\n\r", ch );
	    act("$n's eyes stop glowing bright white.",ch,NULL,NULL,TO_ROOM);
	}
	else if (sn == 23)
	    REMOVE_BIT(ch->itemaffect, ITEMA_STALKER);
	else if (IS_ITEMAFF(ch, ITEMA_VANISH) && sn == 24)
	{
	    REMOVE_BIT(ch->itemaffect, ITEMA_VANISH);
	    send_to_char( "You emerge from the shadows.\n\r", ch );
	    act("$n gradually fades out of the shadows.",ch,NULL,NULL,TO_ROOM);
	}
	else if (sn == 25 && !IS_NPC(ch) && IS_ITEMAFF(ch, ITEMA_RAGER))
	{
	    REMOVE_BIT(ch->itemaffect, ITEMA_RAGER);
	    if (IS_CLASS(ch, CLASS_WEREWOLF) && ch->rage >= 100)
	    {
		ch->rage = 0;
		do_unwerewolf(ch,"");
	    }
	    ch->rage = 0;
	}
	if (IS_SET(obj->spectype, SITEM_DEMONIC) && !IS_NPC(ch)
	    && ch->pcdata->stats[DEMON_POWER] > 0)
	    ch->pcdata->stats[DEMON_POWER] -= 1;
	if (IS_SET(obj->spectype, SITEM_PDEMONIC) && !IS_NPC(ch)
	    && ch->pcdata->stats[DEMON_PPOWER] > 0)
	    ch->pcdata->stats[DEMON_PPOWER] -= 1;

	if (IS_SET(obj->spectype, SITEM_HIGHLANDER) && !IS_NPC(ch) && obj->item_type == ITEM_WEAPON)
	{
	    if (obj->value[3] == ch->pcdata->powers[HPOWER_WPNSKILL])
		REMOVE_BIT(ch->itemaffect, ITEMA_HIGHLANDER);
	}
	if (IS_SET(obj->quest, QUEST_ARTIFACT)) 
	    REMOVE_BIT(ch->itemaffect, ITEMA_ARTIFACT);
	if (IS_SET(obj->spectype, SITEM_SILVER) && oldpos == WEAR_WIELD)
	    REMOVE_BIT(ch->itemaffect, ITEMA_RIGHT_SILVER);
	if (IS_SET(obj->spectype, SITEM_SILVER) && oldpos == WEAR_HOLD)
	    REMOVE_BIT(ch->itemaffect, ITEMA_LEFT_SILVER);
    }
    return;
}



/*
 * Count occurrences of an obj in a list.
 */
int count_obj_list( OBJ_INDEX_DATA *pObjIndex, OBJ_DATA *list )
{
    OBJ_DATA *obj;
    int nMatch;

    nMatch = 0;
    for ( obj = list; obj != NULL; obj = obj->next_content )
    {
	if ( obj->pIndexData == pObjIndex )
	    nMatch++;
    }

    return nMatch;
}



/*
 * Move an obj out of a room.
 */
void obj_from_room( OBJ_DATA *obj )
{
    ROOM_INDEX_DATA *in_room;

    if (obj == NULL) return;
    if ( ( in_room = obj->in_room ) == NULL )
    {
	bug( "obj_from_room: NULL.", 0 );
	return;
    }

    if ( obj == in_room->contents )
    {
	in_room->contents = obj->next_content;
    }
    else
    {
	OBJ_DATA *prev;

	for ( prev = in_room->contents; prev; prev = prev->next_content )
	{
	    if ( prev->next_content == obj )
	    {
		prev->next_content = obj->next_content;
		break;
	    }
	}

	if ( prev == NULL )
	{
	    bug( "Obj_from_room: obj not found.", 0 );
	    return;
	}
    }

    obj->in_room      = NULL;
    obj->next_content = NULL;
    return;
}



/*
 * Move an obj into a room.
 */
void obj_to_room( OBJ_DATA *obj, ROOM_INDEX_DATA *pRoomIndex )
{
    if (obj == NULL) return;
    obj->next_content		= pRoomIndex->contents;
    pRoomIndex->contents	= obj;
    obj->in_room		= pRoomIndex;
    obj->carried_by		= NULL;
    obj->in_obj			= NULL;
    return;
}



/*
 * Move an object into an object.
 */
void obj_to_obj( OBJ_DATA *obj, OBJ_DATA *obj_to )
{
    if (obj == NULL) return;
    obj->next_content		= obj_to->contains;
    obj_to->contains		= obj;
    obj->in_obj			= obj_to;
    obj->in_room		= NULL;
    obj->carried_by		= NULL;

    for ( ; obj_to != NULL; obj_to = obj_to->in_obj )
    {
	if ( obj_to->carried_by != NULL && !IS_SET(obj_to->spectype,SITEM_MORPH))
	    obj_to->carried_by->carry_weight += get_obj_weight( obj );
    }

    return;
}



/*
 * Move an object out of an object.
 */
void obj_from_obj( OBJ_DATA *obj )
{
    OBJ_DATA *obj_from;

    if (obj == NULL) return;
    if ( ( obj_from = obj->in_obj ) == NULL )
    {
	bug( "Obj_from_obj: null obj_from.", 0 );
	return;
    }

    if ( obj == obj_from->contains )
    {
	obj_from->contains = obj->next_content;
    }
    else
    {
	OBJ_DATA *prev;

	for ( prev = obj_from->contains; prev; prev = prev->next_content )
	{
	    if ( prev->next_content == obj )
	    {
		prev->next_content = obj->next_content;
		break;
	    }
	}

	if ( prev == NULL )
	{
	    bug( "Obj_from_obj: obj not found.", 0 );
	    return;
	}
    }

    obj->next_content = NULL;
    obj->in_obj       = NULL;

    for ( ; obj_from != NULL; obj_from = obj_from->in_obj )
    {
	if ( obj_from->carried_by != NULL && !IS_SET(obj_from->spectype,SITEM_MORPH))
	    obj_from->carried_by->carry_weight -= get_obj_weight( obj );
    }

    return;
}



/*
 * Extract an obj from the world.
 */
void extract_obj( OBJ_DATA *obj )
{
    CHAR_DATA *ch;
    OBJ_DATA *obj_content;
    OBJ_DATA *obj_next;

    if ( obj == NULL ) return;
    if ( obj->in_room != NULL )
	obj_from_room( obj );
    else if ( obj->carried_by != NULL )
	obj_from_char( obj );
    else if ( obj->in_obj != NULL )
	obj_from_obj( obj );

    if ( ( ch = obj->chobj ) != NULL
    &&   !IS_NPC(ch)
    &&   ch->pcdata->chobj == obj
    &&   IS_HEAD(ch,LOST_HEAD))
    {
	REMOVE_BIT(ch->loc_hp[0],LOST_HEAD);
	REMOVE_BIT(ch->affected_by,AFF_POLYMORPH);
	free_string(ch->morph);
	ch->morph = str_dup("");
	ch->hit = 1;
	char_from_room(ch);
	char_to_room(ch,get_room_index(ROOM_VNUM_ALTAR));
	ch->pcdata->chobj = NULL;
	obj->chobj = NULL;
	send_to_char("You have been KILLED!!\n\r",ch);
	do_look(ch,"auto");
	ch->position = POS_RESTING;
    }
    else if ( ( ch = obj->chobj ) != NULL
    &&   !IS_NPC(ch)
    &&   ch->pcdata->chobj == obj
    &&   (IS_EXTRA(ch,EXTRA_OSWITCH) || ch->pcdata->obj_vnum != 0))
    {
	if (ch->pcdata->obj_vnum != 0)
	{
	    send_to_char("You have been destroyed!\n\r",ch);
	    ch->pcdata->chobj = NULL;
	    obj->chobj = NULL;
	}
	else
	{
	    REMOVE_BIT(ch->extra,EXTRA_OSWITCH);
	    REMOVE_BIT(ch->affected_by,AFF_POLYMORPH);
	    free_string(ch->morph);
	    ch->morph = str_dup("");
	    char_from_room(ch);
	    char_to_room(ch,get_room_index(ROOM_VNUM_ALTAR));
	    ch->pcdata->chobj = NULL;
	    obj->chobj = NULL;
	    send_to_char("You return to your body.\n\r",ch);
	}
    }
    else if ( obj->chobj != NULL )
    {
	if (!IS_NPC(obj->chobj)) obj->chobj->pcdata->chobj = NULL;
	obj->chobj = NULL;
	bug( "Extract_obj: obj %d chobj invalid.", obj->pIndexData->vnum );
    }

    for ( obj_content = obj->contains; obj_content; obj_content = obj_next )
    {
	obj_next = obj_content->next_content;
	if (obj->contains != NULL) extract_obj( obj->contains );
    }

    if ( object_list == obj )
    {
	object_list = obj->next;
    }
    else
    {
	OBJ_DATA *prev;

	for ( prev = object_list; prev != NULL; prev = prev->next )
	{
	    if ( prev->next == obj )
	    {
		prev->next = obj->next;
		break;
	    }
	}

	if ( prev == NULL )
	{
	    bug( "Extract_obj: obj %d not found.", obj->pIndexData->vnum );
	    return;
	}
    }

    {
	AFFECT_DATA *paf;
	AFFECT_DATA *paf_next;

	for ( paf = obj->affected; paf != NULL; paf = paf_next )
	{
	    paf_next    = paf->next;
	    paf->next   = affect_free;
	    affect_free = paf;
	}
    }

    {
	EXTRA_DESCR_DATA *ed;
	EXTRA_DESCR_DATA *ed_next;

	for ( ed = obj->extra_descr; ed != NULL; ed = ed_next )
	{
	    ed_next		= ed->next;
	    free_string( ed->description );
	    free_string( ed->keyword     );
	    extra_descr_free	= ed;
	}
    }

    free_string( obj->name        );
    free_string( obj->description );
    free_string( obj->short_descr );
    if (obj->chpoweron    != NULL) free_string( obj->chpoweron   );
    if (obj->chpoweroff   != NULL) free_string( obj->chpoweroff  );
    if (obj->chpoweruse   != NULL) free_string( obj->chpoweruse  );
    if (obj->victpoweron  != NULL) free_string( obj->victpoweron );
    if (obj->victpoweroff != NULL) free_string( obj->victpoweroff);
    if (obj->victpoweruse != NULL) free_string( obj->victpoweruse);
    if (obj->questmaker   != NULL) free_string( obj->questmaker  );
    if (obj->questowner   != NULL) free_string( obj->questowner  );
    --obj->pIndexData->count;
    obj->next	= obj_free;
    obj_free	= obj;
    return;
}



/*
 * Extract a char from the world.
 */
void extract_char( CHAR_DATA *ch, bool fPull )
{
    CHAR_DATA *wch;
    CHAR_DATA *familiar;
    CHAR_DATA *wizard;
    OBJ_DATA *obj;
    OBJ_DATA *obj_next;

    if ( ch == NULL ) return;

    if ( ch->in_room == NULL )
    {
	bug( "Extract_char: NULL.", 0 );
	return;
    }

    if ( fPull )
	die_follower( ch );

    stop_fighting( ch, TRUE );

    for ( obj = ch->carrying; obj != NULL; obj = obj_next )
    {
	obj_next = obj->next_content;
	extract_obj( obj );
    }
    
    char_from_room( ch );

    if ( IS_NPC(ch) )
	--ch->pIndexData->count;
    else if ( ch->pcdata->chobj != NULL )
    {
	ch->pcdata->chobj->chobj = NULL;
	ch->pcdata->chobj = NULL;
    }

    if ( !fPull )
    {
	char_to_room( ch, get_room_index( ROOM_VNUM_ALTAR ) );
	return;
    }

    if ( ch->desc != NULL && ch->desc->original != NULL )
	do_return( ch, "" );

    for ( wch = char_list; wch != NULL; wch = wch->next )
    {
	if ( wch->reply == ch )
	    wch->reply = NULL;
    }

    if ( ch == char_list )
    {
       char_list = ch->next;
    }
    else
    {
	CHAR_DATA *prev;

	for ( prev = char_list; prev != NULL; prev = prev->next )
	{
	    if ( prev->next == ch )
	    {
		prev->next = ch->next;
		break;
	    }
	}

	if ( prev == NULL )
	{
	    bug( "Extract_char: char not found.", 0 );
	    return;
	}
    }

    if ( ch->desc )
	ch->desc->character = NULL;

    if ( (wizard = ch->wizard) != NULL)
    {
	if (!IS_NPC(wizard)) wizard->pcdata->familiar = NULL;
	ch->wizard = NULL;
    }
    if ( !IS_NPC(ch) )
    {
	if ((familiar = ch->pcdata->familiar) != NULL)
	{
	    familiar->wizard = NULL;
	    ch->pcdata->familiar = NULL;
	    if (IS_NPC(familiar))
	    {
		act("$n slowly fades away to nothing.",familiar,NULL,NULL,TO_ROOM);
		extract_char(familiar,TRUE);
	    }
	}
	if ((familiar = ch->pcdata->partner) != NULL)
	    ch->pcdata->partner = NULL;
	if ((familiar = ch->pcdata->propose) != NULL)
	    ch->pcdata->propose = NULL;
	for ( familiar = char_list; familiar != NULL; familiar = familiar->next)
	{
	    if ( !IS_NPC(familiar) && familiar->pcdata->propose != NULL && 
		familiar->pcdata->propose == ch )
		familiar->pcdata->propose = NULL;
	    if ( !IS_NPC(familiar) && familiar->pcdata->partner != NULL && 
		familiar->pcdata->partner == ch )
		familiar->pcdata->partner = NULL;
	}
    }
    else if (IS_NPC(ch) && strlen(ch->lord) > 1)
    {
	for ( wch = char_list; wch != NULL ; wch = wch->next )
	{
	    if (IS_NPC(wch)) continue;
	    if (str_cmp(wch->name, ch->lord)) continue;
	    if (wch->pcdata->followers > 0) wch->pcdata->followers--;
	}
    }

    free_char( ch );
    return;
}



/*
 * Find a char in the room.
 */
CHAR_DATA *get_char_room( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *rch;
    int number;
    int count;

    number = number_argument( argument, arg );
    count  = 0;
    if ( !str_cmp( arg, "self" ) && (IS_NPC(ch) || ch->pcdata->chobj == NULL))
	return ch;
    for ( rch = ch->in_room->people; rch != NULL; rch = rch->next_in_room )
    {
	if ( !IS_NPC(rch) && IS_HEAD(rch, LOST_HEAD) ) continue;
	else if ( !IS_NPC(rch) && IS_EXTRA(rch, EXTRA_OSWITCH) ) continue;
	else if ( !can_see( ch, rch ) || ( !is_name( arg, rch->name ) &&
	 (IS_NPC(rch) || !is_name(arg, rch->pcdata->switchname)) &&
	    ( IS_NPC(rch) || !is_name( arg, rch->morph ))))
	    continue;
	if ( ++count == number )
	    return rch;
    }

    return NULL;
}




/*
 * Find a char in the world.
 */
CHAR_DATA *get_char_world( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *wch;
    int number;
    int count;

    if ( ( wch = get_char_room( ch, argument ) ) != NULL )
	return wch;

    number = number_argument( argument, arg );
    count  = 0;
    for ( wch = char_list; wch != NULL ; wch = wch->next )
    {
	if ( !IS_NPC(wch) && IS_HEAD(wch, LOST_HEAD) ) continue;
	else if ( !IS_NPC(wch) && IS_EXTRA(wch, EXTRA_OSWITCH) ) continue;
	else if ( !can_see( ch, wch ) || ( !is_name( arg, wch->name ) &&
	 (IS_NPC(wch) || !is_name(arg, wch->pcdata->switchname)) &&

	    ( IS_NPC(wch) || !is_name( arg, wch->morph ))))
	    continue;
	if ( ++count == number )
	    return wch;
    }

    return NULL;
}



/*
 * Find some object with a given index data.
 * Used by area-reset 'P' command.
 */
OBJ_DATA *get_obj_type( OBJ_INDEX_DATA *pObjIndex )
{
    OBJ_DATA *obj;

    for ( obj = object_list; obj != NULL; obj = obj->next )
    {
	if ( obj->pIndexData == pObjIndex )
	    return obj;
    }

    return NULL;
}


/*
 * Find an obj in a list.
 */
OBJ_DATA *get_obj_list( CHAR_DATA *ch, char *argument, OBJ_DATA *list )
{
    char arg[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;
    int number;
    int count;

    number = number_argument( argument, arg );
    count  = 0;
    for ( obj = list; obj != NULL; obj = obj->next_content )
    {
	if ( can_see_obj( ch, obj ) && is_name( arg, obj->name ) )
	{
	    if ( ++count == number )
		return obj;
	}
    }

    return NULL;
}



/*
 * Find an object within the object you are in.
 */
OBJ_DATA *get_obj_in_obj( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;
    OBJ_DATA *obj2;
    int number;
    int count;

    number = number_argument( argument, arg );
    count  = 0;
    if (IS_NPC(ch) || ch->pcdata->chobj == NULL || ch->pcdata->chobj->in_obj == NULL)
	return NULL;
    obj = ch->pcdata->chobj;
    if (obj->in_obj->item_type != ITEM_CONTAINER && obj->in_obj->item_type != ITEM_CORPSE_NPC &&
    	obj->in_obj->item_type != ITEM_CORPSE_PC ) return NULL;

    for ( obj2 = obj->in_obj->contains; obj2 != NULL; obj2 = obj2->next_content )
    {
	if (obj != obj2
	&&  is_name( arg, obj2->name ) )
	{
	    if ( ++count == number )
		return obj2;
	}
    }

    return NULL;
}



/*
 * Find an obj in player's inventory.
 */
OBJ_DATA *get_obj_carry( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;
    int number;
    int count;

    number = number_argument( argument, arg );
    count  = 0;
    for ( obj = ch->carrying; obj != NULL; obj = obj->next_content )
    {
	if ( obj->wear_loc == WEAR_NONE
	&&   can_see_obj( ch, obj )
	&&   is_name( arg, obj->name ) )
	{
	    if ( ++count == number )
		return obj;
	}
    }

    return NULL;
}



/*
 * Find an obj in player's equipment.
 */
OBJ_DATA *get_obj_wear( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;
    int number;
    int count;

    number = number_argument( argument, arg );
    count  = 0;
    for ( obj = ch->carrying; obj != NULL; obj = obj->next_content )
    {
	if ( obj->wear_loc != WEAR_NONE
	&&   can_see_obj( ch, obj )
	&&   is_name( arg, obj->name ) )
	{
	    if ( ++count == number )
		return obj;
	}
    }

    return NULL;
}



/*
 * Find an obj in the room or in inventory.
 */
OBJ_DATA *get_obj_here( CHAR_DATA *ch, char *argument )
{
    OBJ_DATA *obj;

    obj = get_obj_list( ch, argument, ch->in_room->contents );
    if ( obj != NULL )
	return obj;

    if ( ( obj = get_obj_carry( ch, argument ) ) != NULL )
	return obj;

    if ( ( obj = get_obj_wear( ch, argument ) ) != NULL )
	return obj;

    if ( ( obj = get_obj_in_obj( ch, argument ) ) != NULL )
	return obj;

    return NULL;
}



/*
 * Find an obj in the room or in inventory.
 */
OBJ_DATA *get_obj_room( CHAR_DATA *ch, char *argument )
{
    OBJ_DATA *obj;

    obj = get_obj_list( ch, argument, ch->in_room->contents );
    if ( obj != NULL )
	return obj;

    return NULL;
}



/*
 * Find an obj in the world.
 */
OBJ_DATA *get_obj_world( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;
    int number;
    int count;

    if ( ( obj = get_obj_here( ch, argument ) ) != NULL )
	return obj;

    number = number_argument( argument, arg );
    count  = 0;
    for ( obj = object_list; obj != NULL; obj = obj->next )
    {
	if ( can_see_obj( ch, obj ) && is_name( arg, obj->name ) )
	{
	    if ( ++count == number )
		return obj;
	}
    }

    return NULL;
}



/*
 * Create a 'money' obj.
 */
OBJ_DATA *create_money( int amount )
{
    char buf[MAX_STRING_LENGTH];
    OBJ_DATA *obj;

    if ( amount <= 0 )
    {
	bug( "Create_money: zero or negative money %d.", amount );
	amount = 1;
    }

    if ( amount == 1 )
    {
	obj = create_object( get_obj_index( OBJ_VNUM_MONEY_ONE ), 0 );
    }
    else
    {
	obj = create_object( get_obj_index( OBJ_VNUM_MONEY_SOME ), 0 );
	sprintf( buf, obj->short_descr, amount );
	free_string( obj->short_descr );
	obj->short_descr	= str_dup( buf );
	obj->value[0]		= amount;
    }

    return obj;
}



/*
 * Return weight of an object, including weight of contents.
 */
int get_obj_weight( OBJ_DATA *obj )
{
    int weight;

    weight = obj->weight;
    for ( obj = obj->contains; obj != NULL; obj = obj->next_content )
	weight += get_obj_weight( obj );

    return weight;
}



/*
 * True if room is dark.
 */
bool room_is_dark( ROOM_INDEX_DATA *pRoomIndex )
{
    if ( pRoomIndex->light > 0 )
	return FALSE;

    if ( IS_SET(pRoomIndex->room_flags, ROOM_DARK) )
	return TRUE;

    if ( pRoomIndex->sector_type == SECT_INSIDE
    ||   pRoomIndex->sector_type == SECT_CITY )
	return FALSE;

    if ( weather_info.sunlight == SUN_SET
    ||   weather_info.sunlight == SUN_DARK )
	return TRUE;

    return FALSE;
}



/*
 * True if room is private.
 */
bool room_is_private( ROOM_INDEX_DATA *pRoomIndex )
{
    CHAR_DATA *rch;
    int count;

    count = 0;
    for ( rch = pRoomIndex->people; rch != NULL; rch = rch->next_in_room )
	count++;

    if ( IS_SET(pRoomIndex->room_flags, ROOM_PRIVATE)  && count >= 2 )
	return TRUE;

    if ( IS_SET(pRoomIndex->room_flags, ROOM_SOLITARY) && count >= 1 )
	return TRUE;

    return FALSE;
}



/*
 * True if char can see victim.
 */
bool can_see( CHAR_DATA *ch, CHAR_DATA *victim )
{
    if ( ch == victim )
	return TRUE;

    if ( victim->blinkykill != NULL )
	return FALSE;

    if ( !IS_NPC(victim)
    &&   IS_SET(victim->act, PLR_WIZINVIS)
    &&   get_trust( ch ) < get_trust( victim ) )
	return FALSE;

    if ( !IS_NPC(victim) && IS_SET(victim->act, PLR_INCOG)
    &&   get_trust( ch ) < get_trust( victim ) 
    &&   ch->in_room != victim->in_room )
	return FALSE;


    if ( IS_SET ( ch->in_room->room_flags, ROOM_TOTAL_DARKNESS))
    {
        if (!IS_IMMORTAL( ch ) && !IS_CLASS(ch, CLASS_DROW) )
	    return FALSE;
        else
	    return TRUE;
    }

	if (!IS_NPC(victim) && IS_CLASS(victim, CLASS_NINJA) &&
IS_AFFECTED(victim, AFF_HIDE)) {
	if (!IS_IMMORTAL(ch) && !IS_CLASS(ch, CLASS_NINJA))
	return FALSE;
	else return TRUE;
	}

	if (!IS_NPC(victim) && IS_CLASS(victim, CLASS_MONK) &&
	IS_AFFECTED(victim, AFF_HIDE)) {
	if (!IS_IMMORTAL(ch) && !IS_CLASS(ch, CLASS_MONK))
	return FALSE;
	else return TRUE;
	}

    if ( IS_EXTRA(ch, BLINDFOLDED))
	return FALSE;

    if ( !IS_NPC(ch) && IS_SET(ch->act, PLR_HOLYLIGHT) )
	return TRUE;

    if ( IS_ITEMAFF(ch, ITEMA_VISION) )
	return TRUE;

    if (IS_AFFECTED(ch,AFF_SHADOWPLANE) && !IS_AFFECTED(victim,AFF_SHADOWPLANE)
	&& !IS_AFFECTED(ch,AFF_SHADOWSIGHT))
	return FALSE;

    if (!IS_AFFECTED(ch,AFF_SHADOWPLANE) && IS_AFFECTED(victim,AFF_SHADOWPLANE)
	&& !IS_AFFECTED(ch,AFF_SHADOWSIGHT))
	return FALSE;

    if ( !IS_NPC(ch) && IS_VAMPAFF(ch, VAM_SONIC) )
	return TRUE;

    if ( IS_HEAD(ch, LOST_EYE_L) && IS_HEAD(ch, LOST_EYE_R) )
	return FALSE;

    if ( IS_AFFECTED(ch, AFF_BLIND) && !IS_AFFECTED(ch, AFF_SHADOWSIGHT))
	return FALSE;

    if ( room_is_dark( ch->in_room ) && !IS_AFFECTED(ch, AFF_INFRARED) 
	&& (!IS_NPC( ch) && !IS_VAMPAFF(ch, VAM_NIGHTSIGHT)))
	return FALSE;

    if ( IS_AFFECTED(victim, AFF_INVISIBLE)
    &&   !IS_AFFECTED(ch, AFF_DETECT_INVIS) )
	return FALSE;

    if ( IS_AFFECTED(victim, AFF_HIDE)
    &&   !IS_AFFECTED(ch, AFF_DETECT_HIDDEN) )
	return FALSE;

    if ( !IS_NPC(ch) && IS_HEAD(ch, LOST_HEAD) )
	return TRUE;

    if ( !IS_NPC(ch) && IS_EXTRA(ch, EXTRA_OSWITCH) )
	return TRUE;

    if ( !IS_NPC(ch) && IS_HEAD(ch, LOST_HEAD) &&
	ch->in_room != NULL && ch->in_room->vnum == ROOM_VNUM_IN_OBJECT)
	return TRUE;

    if ( !IS_NPC(ch) && IS_EXTRA(ch, EXTRA_OSWITCH) &&
	ch->in_room != NULL && ch->in_room->vnum == ROOM_VNUM_IN_OBJECT)
	return TRUE;

    return TRUE;
}



/*
 * True if char can see obj.
 */
bool can_see_obj( CHAR_DATA *ch, OBJ_DATA *obj )
{
    if ( !IS_NPC(ch) && IS_SET(ch->act, PLR_HOLYLIGHT) )
	return TRUE;

    if ( IS_ITEMAFF(ch, ITEMA_VISION) )
	return TRUE;

    if (( IS_SET(obj->extra_flags, ITEM_SHADOWPLANE)
    &&   obj->carried_by == NULL)
    &&   !IS_AFFECTED(ch, AFF_SHADOWSIGHT)
    &&   !IS_AFFECTED(ch, AFF_SHADOWPLANE))
	return FALSE;

    if (( !IS_SET(obj->extra_flags, ITEM_SHADOWPLANE)
    &&   obj->carried_by == NULL)
    &&   !IS_AFFECTED(ch, AFF_SHADOWSIGHT)
    &&   IS_AFFECTED(ch, AFF_SHADOWPLANE))
	return FALSE;

    if ( !IS_NPC(ch) && IS_VAMPAFF(ch, VAM_SONIC) )
	return TRUE;

    if ( obj->item_type == ITEM_POTION )
	return TRUE;

    if ( IS_HEAD(ch, LOST_EYE_L) && IS_HEAD(ch, LOST_EYE_R) )
	return FALSE;

    if ( IS_EXTRA(ch, BLINDFOLDED) )
	return FALSE;

    if ( IS_AFFECTED( ch, AFF_BLIND ) && !IS_AFFECTED(ch, AFF_SHADOWSIGHT) )
	return FALSE;

    if ( obj->item_type == ITEM_LIGHT && obj->value[2] != 0 )
	return TRUE;

    if ( room_is_dark( ch->in_room ) && !IS_AFFECTED(ch, AFF_INFRARED) 
	&& (!IS_NPC( ch ) && !IS_VAMPAFF(ch, VAM_NIGHTSIGHT)))
	return FALSE;

    if ( IS_SET(obj->extra_flags, ITEM_INVIS)
    &&   !IS_AFFECTED(ch, AFF_DETECT_INVIS) )
	return FALSE;

    if ( !IS_NPC(ch) && IS_HEAD(ch, LOST_HEAD) &&
	ch->in_room != NULL && ch->in_room->vnum == ROOM_VNUM_IN_OBJECT)
	return TRUE;

    if ( !IS_NPC(ch) && IS_EXTRA(ch, EXTRA_OSWITCH) &&
	ch->in_room != NULL && ch->in_room->vnum == ROOM_VNUM_IN_OBJECT)
	return TRUE;

    return TRUE;
}



/*
 * True if char can drop obj.
 */
bool can_drop_obj( CHAR_DATA *ch, OBJ_DATA *obj )
{
    if ( !IS_SET(obj->extra_flags, ITEM_NODROP) )
	return TRUE;

    if ( !IS_NPC(ch) && ch->level >= LEVEL_IMMORTAL )
	return TRUE;

    return FALSE;
}



/*
 * Return ascii name of an item type.
 */
char *item_type_name( OBJ_DATA *obj )
{
    switch ( obj->item_type )
    {
    case ITEM_LIGHT:		return "light";
    case ITEM_SCROLL:		return "scroll";
    case ITEM_WAND:		return "wand";
    case ITEM_STAFF:		return "staff";
    case ITEM_WEAPON:		return "weapon";
    case ITEM_TREASURE:		return "treasure";
    case ITEM_ARMOR:		return "armor";
    case ITEM_POTION:		return "potion";
    case ITEM_FURNITURE:	return "furniture";
    case ITEM_TRASH:		return "trash";
    case ITEM_CONTAINER:	return "container";
    case ITEM_DRINK_CON:	return "drink container";
    case ITEM_KEY:		return "key";
    case ITEM_FOOD:		return "food";
    case ITEM_MONEY:		return "money";
    case ITEM_BOAT:		return "boat";
    case ITEM_CORPSE_NPC:	return "npc corpse";
    case ITEM_CORPSE_PC:	return "pc corpse";
    case ITEM_FOUNTAIN:		return "fountain";
    case ITEM_PILL:		return "pill";
    case ITEM_PORTAL:		return "portal";
    case ITEM_EGG:		return "egg";
    case ITEM_VOODOO:		return "voodoo doll";
    case ITEM_STAKE:		return "stake";
    case ITEM_MISSILE:		return "missile";
    case ITEM_AMMO:		return "ammo";
    case ITEM_QUEST:		return "quest token";
    case ITEM_QUESTCARD:	return "quest card";
    case ITEM_QUESTMACHINE:	return "quest generator";
    case ITEM_SYMBOL:		return "magical symbol";
    case ITEM_BOOK:		return "book";
    case ITEM_PAGE:		return "page";
    case ITEM_TOOL:		return "tool";
    case ITEM_COPPER:           return "copper";    
    case ITEM_IRON:             return "iron";
    case ITEM_STEEL:            return "steel";
    case ITEM_ADAMANTITE:       return "adamantite";
    case ITEM_GEMSTONE:         return "gemstone";
    case ITEM_HILT:             return "hilt";
}

    bug( "Item_type_name: unknown type %d.", obj->item_type );
    return "(unknown)";
}



/*
 * Return ascii name of an affect location.
 */
char *affect_loc_name( int location )
{
    switch ( location )
    {
    case APPLY_NONE:		return "none";
    case APPLY_STR:		return "strength";
    case APPLY_DEX:		return "dexterity";
    case APPLY_INT:		return "intelligence";
    case APPLY_WIS:		return "wisdom";
    case APPLY_CON:		return "constitution";
    case APPLY_SEX:		return "sex";
    case APPLY_CLASS:		return "class";
    case APPLY_LEVEL:		return "level";
    case APPLY_AGE:		return "age";
    case APPLY_MANA:		return "mana";
    case APPLY_HIT:		return "hp";
    case APPLY_MOVE:		return "moves";
    case APPLY_GOLD:		return "gold";
    case APPLY_EXP:		return "experience";
    case APPLY_AC:		return "armor class";
    case APPLY_HITROLL:		return "hit roll";
    case APPLY_DAMROLL:		return "damage roll";
    case APPLY_SAVING_PARA:	return "save vs paralysis";
    case APPLY_SAVING_ROD:	return "save vs rod";
    case APPLY_SAVING_PETRI:	return "save vs petrification";
    case APPLY_SAVING_BREATH:	return "save vs breath";
    case APPLY_SAVING_SPELL:	return "save vs spell";
    case APPLY_POLY:		return "polymorph form";
    }

    bug( "Affect_location_name: unknown location %d.", location );
    return "(unknown)";
}



/*
 * Return ascii name of an affect bit vector.
 */
char *affect_bit_name( int vector )
{
    static char buf[512];

    buf[0] = '\0';
    if ( vector & AFF_BLIND         ) strcat( buf, " blind"         );
    if ( vector & AFF_INVISIBLE     ) strcat( buf, " invisible"     );
    if ( vector & AFF_DETECT_EVIL   ) strcat( buf, " detect_evil"   );
    if ( vector & AFF_DETECT_INVIS  ) strcat( buf, " detect_invis"  );
    if ( vector & AFF_DETECT_MAGIC  ) strcat( buf, " detect_magic"  );
    if ( vector & AFF_DETECT_HIDDEN ) strcat( buf, " detect_hidden" );
    if ( vector & AFF_SHADOWPLANE   ) strcat( buf, " shadowplane"   );
    if ( vector & AFF_SANCTUARY     ) strcat( buf, " sanctuary"     );
    if ( vector & AFF_FAERIE_FIRE   ) strcat( buf, " faerie_fire"   );
    if ( vector & AFF_INFRARED      ) strcat( buf, " infrared"      );
    if ( vector & AFF_CURSE         ) strcat( buf, " curse"         );
    if ( vector & AFF_FLAMING       ) strcat( buf, " flaming"       );
    if ( vector & AFF_POISON        ) strcat( buf, " poison"        );
    if ( vector & AFF_PROTECT       ) strcat( buf, " protect"       );
    if ( vector & AFF_ETHEREAL      ) strcat( buf, " ethereal"      );
    if ( vector & AFF_SLEEP         ) strcat( buf, " sleep"         );
    if ( vector & AFF_SNEAK         ) strcat( buf, " sneak"         );
    if ( vector & AFF_HIDE          ) strcat( buf, " hide"          );
    if ( vector & AFF_CHARM         ) strcat( buf, " charm"         );
    if ( vector & AFF_FLYING        ) strcat( buf, " flying"        );
    if ( vector & AFF_PASS_DOOR     ) strcat( buf, " pass_door"     );
    if ( vector & AFF_POLYMORPH     ) strcat( buf, " polymorph"     );
    if ( vector & AFF_SHADOWSIGHT   ) strcat( buf, " shadowsight"   );
    if ( vector & AFF_WEBBED        ) strcat( buf, " web"           );
  /*  if ( vector & AFF_DARKNESS      ) strcat( buf, " darkness" );*/
    if ( vector & AFF_TENDRILS )     strcat(buf, " tendrils" );
    if ( vector & AFF_INFIRMITY     ) strcat( buf, " infirmity" );
    return ( buf[0] != '\0' ) ? buf+1 : "none";
}



/*
 * Return ascii name of extra flags vector.
 */
char *extra_bit_name( int extra_flags )
{
    static char buf[512];

    buf[0] = '\0';
    if ( extra_flags & ITEM_GLOW         ) strcat( buf, " glow"         );
    if ( extra_flags & ITEM_HUM          ) strcat( buf, " hum"          );
    if ( extra_flags & ITEM_INVIS        ) strcat( buf, " invis"        );
    if ( extra_flags & ITEM_MAGIC        ) strcat( buf, " magic"        );
    if ( extra_flags & ITEM_NODROP       ) strcat( buf, " nodrop"       );
    if ( extra_flags & ITEM_ANTI_GOOD    ) strcat( buf, " anti-good"    );
    if ( extra_flags & ITEM_ANTI_EVIL    ) strcat( buf, " anti-evil"    );
    if ( extra_flags & ITEM_ANTI_NEUTRAL ) strcat( buf, " anti-neutral" );
    if ( extra_flags & ITEM_BLESS        ) strcat( buf, " bless"        );
    if ( extra_flags & ITEM_NOREMOVE     ) strcat( buf, " noremove"     );
    if ( extra_flags & ITEM_INVENTORY    ) strcat( buf, " inventory"    );
    if ( extra_flags & ITEM_LOYAL        ) strcat( buf, " loyal"        );
    if ( extra_flags & ITEM_SHADOWPLANE  ) strcat( buf, " shadowplane"  );
    if ( extra_flags & ITEM_THROWN       ) strcat( buf, " thrown"       );
    if ( extra_flags & ITEM_KEEP         ) strcat( buf, " keep"         );
    if ( extra_flags & ITEM_VANISH       ) strcat( buf, " vanish"       );
    return ( buf[0] != '\0' ) ? buf+1 : "none";
}

CHAR_DATA *get_char_world2( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *wch;

    if (argument[0] == '\0') return NULL;

    for ( wch = char_list; wch != NULL ; wch = wch->next )
    {
	if ( IS_NPC(wch) && !str_cmp( argument, wch->short_descr ) ) return wch;
    }

    return NULL;
}

OBJ_DATA *get_obj_world2( CHAR_DATA *ch, char *argument )
{
    OBJ_DATA *obj;
    int vnum = 0;

    if (argument[0] == '\0') return NULL;

    for ( obj = object_list; obj != NULL; obj = obj->next )
    {
	if ( !str_cmp( argument, obj->short_descr ) )
	{
	    if ((vnum = obj->pIndexData->vnum) == 30037 || vnum == 30041)
		continue;
	    return obj;
	}
    }

    return NULL;
}





 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
 *                                                                         *
 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
 *  Chastain, Michael Quan, and Mitchell Tse.                              *
 *                                                                         *
 *  In order to use any part of this Merc Diku Mud, you must comply with   *
 *  both the original Diku license in 'license.doc' as well the Merc       *
 *  license in 'license.txt'.  In particular, you may not remove either of *
 *  these copyright notices.                                               *
 *                                                                         *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 ***************************************************************************/

#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h> /* unlink() */
#include "merc.h"
#include "garou.h"


bool	check_social	args( ( CHAR_DATA *ch, char *command,
			    char *argument ) );
bool	check_xsocial	args( ( CHAR_DATA *ch, char *command,
			    char *argument ) );
void	make_preg	args( ( CHAR_DATA *mother, CHAR_DATA *father ) );


int can_interpret args( (CHAR_DATA *ch, int cmd) );

int can_interpret (CHAR_DATA *ch, int cmd)
{
    bool cando = FALSE;

    if (ch->level == 12)
	cando = TRUE;

    if (cmd_table[cmd].level > get_trust(ch)) return 0;

    if (cmd_table[cmd].race == 0
        && cmd_table[cmd].discipline == 0)
	cando = TRUE;

    if (cmd_table[cmd].race > 0
         && cmd_table[cmd].discipline == 0
         && ch->class == cmd_table[cmd].race)
	cando = TRUE;

    if (cmd_table[cmd].discipline > 0
         && ch->power [ cmd_table[cmd].discipline ] >= cmd_table[cmd].disclevel)
 	cando = TRUE;

    if (!cando) return 0;


    if ( ch->position < cmd_table[cmd].position )
	return -1; 

    return 1;
}

void do_racecommands( CHAR_DATA *ch, char *argument )
{
    int i, cmd, foundpower = 0;
    char buf[MAX_STRING_LENGTH];
    bool displayed;

    if ( (ch->class == 0 && !IS_IMMORTAL(ch)) || IS_NPC(ch) )
    {
	send_to_char("You don't have any special powers.\n\r", ch);
	return;
    }

    banner_to_char("Powers", ch);

    if ( IS_CLASS(ch, CLASS_WEREWOLF) )
    {
      for ( i = 1; i < MAX_GIFTS; i++ )
      {
	displayed = FALSE;
	if ((ch->gifts[i] > 0 && strlen(wwgift[i]) > 0 )
	        || argument[0] == '\0'
	        || !str_prefix(argument, wwgift[i]))
        {
	    foundpower = 1;
		
		for ( cmd = 0; cmd_table[cmd].name[0] != '\0'; cmd++ )
		{
		    if (cmd_table[cmd].discipline == i
		        && ch->gifts[i] >= cmd_table[cmd].disclevel 
			&& cmd_table[cmd].race == CLASS_WEREWOLF)
		    {
		        if (!displayed)
                        {
			    displayed = TRUE;
   			    sprintf(buf, " %15s : ", wwgift[i]);
			    stc(buf,ch);
                        }
                        send_to_char(cmd_table[cmd].name, ch);
                        send_to_char(" ", ch);
                    }
                }
                if (displayed) send_to_char("\n\r", ch);
        }
    }
  }

  if ( !IS_CLASS(ch, CLASS_WEREWOLF) )
  {
    for (i = 1 ; i < MAX_DISCIPLINES ; i++)
    {
	displayed = FALSE;
	if (ch->power[i] > 0 && strlen(discipline[i]) > 0
		&& (ch->level < 7 || argument[0] == '\0' 
		|| !str_prefix(argument, discipline[i])))
	{
	    foundpower = 1;

		for ( cmd = 0; cmd_table[cmd].name[0] != '\0'; cmd++ )
		{
		    if (cmd_table[cmd].discipline == i
			&& ch->power[i] >= cmd_table[cmd].disclevel
			&& cmd_table[cmd].race == ch->class)
		    {
			if (!displayed)
			{
			    displayed = TRUE;
	    		    sprintf(buf, " %15s : ", discipline[i]);
			    send_to_char(buf, ch);
			}			    
			send_to_char(cmd_table[cmd].name, ch);
			send_to_char(" ", ch);
		    }
	        }
		if (displayed) send_to_char("\n\r", ch);
	}
    }
   }

    i = 0;
    displayed = FALSE;
    for (cmd = 0; cmd_table[cmd].name[0] != '\0'; cmd++)
    {
	if (cmd_table[cmd].race == ch->class
	    && cmd_table[cmd].discipline == 0)
	{
	    strcpy(buf, "");
	    if (i == 0)
	    {
		switch (ch->class)
		{
		    case 1 : sprintf(buf, " %15s : ", "Demon Kind");break;
                    case 2 : sprintf(buf, " %15s : ", "Magi");break;
                    case 4 : sprintf(buf, " %15s : ", "Innate"); break;
                    case 8 : sprintf(buf, " %15s : ", "Innate");break;
                    case 16: sprintf(buf, " %15s : ", "Weaponsmaster");break;
                    case 32: sprintf(buf, " %15s : ", "Drow Abilities");break;
                    case 64: sprintf(buf, " %15s : ", "Monk Abilities");break;
                    case 128:sprintf(buf, " %15s : ", "Ninja Abilities");break;
		}
	    }
	    else if (i % 4 == 0)
	    {
		sprintf(buf, "\n\r                   ");
	    }
	    i++;

	    send_to_char(buf, ch);
	    send_to_char(cmd_table[cmd].name,ch);
	    send_to_char(" ",ch);
	    displayed = TRUE;
	    foundpower++;
	}
    }

    if (displayed) send_to_char("\n\r",ch);
  
    if (foundpower == 0)
    {
        send_to_char("\n\r You do not yet possess any powers.\n\r", ch);
	divide4_to_char(ch);
    }
    else divide4_to_char(ch);

}
	
void do_klaive( CHAR_DATA *ch, char *argument )
 
{
OBJ_DATA *obj;
 
if (IS_NPC(ch)) return;
 
if (!IS_CLASS(ch, CLASS_WEREWOLF))
{
send_to_char("Huh?\n\r",ch);
return;
}
 
if ( 60 > ch->practice)
{
send_to_char("It costs 60 points of primal to create a Lesser Klaive.\n\r",ch);
return;
}
ch->practice   -= 60;
obj = create_object(get_obj_index(OBJ_VNUM_LKLAIVE)  ,0 );
if (IS_SET(obj->quest, QUEST_ARTIFACT))
REMOVE_BIT(obj->quest, QUEST_ARTIFACT);
obj_to_char(obj, ch);
act("A Lesser Klaive appears in your hands in a flash of light.",ch,NULL,NULL,TO_CHAR);
act("A Lesser Klaive appears in $n's hands in a flash of light.",ch,NULL,NULL,TO_ROOM);
return;
}
void do_katana( CHAR_DATA *ch, char *argument )
 
{
OBJ_DATA *obj;
 
if (IS_NPC(ch)) return;
 
if (!IS_CLASS(ch, CLASS_HIGHLANDER))
{
send_to_char("Huh?\n\r",ch);
return;
}
 
if ( 60 > ch->practice)
{
send_to_char("It costs 60 points of primal to create a katana.\n\r",ch);
return;
}
ch->practice   -= 60;
obj = create_object(get_obj_index(29695)  ,0 );
if (IS_SET(obj->quest, QUEST_ARTIFACT))
REMOVE_BIT(obj->quest, QUEST_ARTIFACT);
obj_to_char(obj, ch);
act("A katana appears in your hands in a flash of light.",ch,NULL,NULL,TO_CHAR);
act("A katana appears in $n's hands in a flash of light.",ch,NULL,NULL,TO_ROOM);
return;
}


/*
 * Command logging types.
 */
#define LOG_NORMAL	0
#define LOG_ALWAYS	1
#define LOG_NEVER	2



/*
 * Log-all switch.
 */
bool				fLogAll		= FALSE;

bool  check_disabled (const struct cmd_type *command);
BAN_DATA *ban_first;
DISABLED_DATA *disabled_first;
#define END_MARKER    "END" /* for load_disabled() and save_disabled()*/


/*
 * Command table.
 */
const	struct	cmd_type	cmd_table	[] =
{
    /*
     * Common movement commands.
     */

    /* Name             Function    Min Position     Level  Log      Class,DiscLevel,DiscName*/

    { "north",		do_north,	POS_STANDING,	 0,  LOG_NORMAL, 0,0,0 },
    { "east",		do_east,	POS_STANDING,	 0,  LOG_NORMAL, 0,0,0 },
    { "south",		do_south,	POS_STANDING,	 0,  LOG_NORMAL, 0,0,0 },
    { "west",		do_west,	POS_STANDING,	 0,  LOG_NORMAL, 0,0,0 },
    { "up",		      do_up,	POS_STANDING,	 0,  LOG_NORMAL, 0,0,0 },
    { "down",		do_down,	POS_STANDING,	 0,  LOG_NORMAL, 0,0,0 },

    /*
     * Common other commands.
     * Placed here so one and two letter abbreviations work.
     */
    { "buy",		do_buy,	POS_SITTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "cast",		do_cast,	POS_FIGHTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "chant",		do_chant,	POS_MEDITATING,	 4,  LOG_NORMAL, 0,0,0
},
    { "mesmerise",	do_command,	POS_SITTING,	 3,  LOG_NORMAL, 8, DISC_VAMP_DOMI, 2 },
    { "command",	do_command,	POS_SITTING,	 3, LOG_NORMAL, 8,DISC_VAMP_DOMI,1	},
    { "crack",		do_crack,	POS_STANDING,	 0,  LOG_NORMAL, 0,0,0	},
    { "diagnose",	do_diagnose,POS_FIGHTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "dismount",	do_dismount,POS_STANDING,	 0,  LOG_NORMAL, 0,0,0	},
    { "enter",		do_enter,	POS_STANDING,	 0,  LOG_NORMAL, 0,0,0	},
    { "exits",		do_exits,	POS_SITTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "get",		do_get,	POS_SITTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "medit",          do_medit,       POS_DEAD,   7,  LOG_NORMAL, 0, 0,
0
},

    { "inventory",	do_inventory,POS_DEAD,	 	 0,  LOG_NORMAL, 0,0,0	},
    { "kill",		do_kill,	POS_FIGHTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "look",		do_look,	POS_MEDITATING,	 0,  LOG_NORMAL, 0,0,0	},
    { "ls",			do_look,	POS_MEDITATING,	 0,  LOG_NORMAL, 0,0,0	},
    { "meditate",		do_meditate,POS_MEDITATING,	 0,  LOG_NORMAL, 0,0,0	},
    { "mount",		do_mount,	POS_STANDING,	 0,  LOG_NORMAL, 0,0,0	},
    { "order",		do_order,	POS_SITTING,	 0,  LOG_ALWAYS, 0,0,0	},
    { "rest",		do_rest,	POS_MEDITATING,	 0,  LOG_NORMAL, 0,0,0	},
    { "sit",		do_sit,	POS_SITTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "stand",		do_stand,	POS_SLEEPING,	 0,  LOG_NORMAL, 0,0,0	},
    { "tell",		do_tell,	POS_MEDITATING,	 0,  LOG_NORMAL, 0,0,0	},
    { "whisper",		do_whisper,	POS_SITTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "wield",		do_wear,	POS_SITTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "wizhelp",		do_wizhelp,	POS_DEAD,	 	 4,  LOG_NORMAL, 0,0,0	},
    { "version",		do_version,	POS_DEAD,	 	 0,  LOG_NORMAL, 0,0,0	},
    { "donate",	      do_donate,	POS_SITTING,	 0,  LOG_NORMAL, 0,0,0	},


    { "for",		do_for,	POS_DEAD,		 10, LOG_NORMAL, 0,0,0 },

    /*
     * Informational commands.
     */
    { "areas",		do_areas,	POS_DEAD,	 	 0,  LOG_NORMAL, 0,0,0},
    { "bug",		do_bug,	POS_DEAD,	 	 0,  LOG_NORMAL, 0,0,0},
    { "commands",		do_commands,POS_DEAD,	 	 0,  LOG_NORMAL, 0,0,0},
    { "compare",		do_compare,	POS_SITTING,	 0,  LOG_NORMAL, 0,0,0},
    { "consider",		do_consider,POS_SITTING,	 0,  LOG_NORMAL, 0,0,0},
    { "credits",		do_credits,	POS_DEAD,	 	 0,  LOG_NORMAL, 0,0,0},
    { "equipment",	do_equipment,POS_DEAD,	 	 0,  LOG_NORMAL, 0,0,0},
    { "examine",		do_examine,	POS_SITTING,	 0,  LOG_NORMAL, 0,0,0},
    { "help",		do_help,	POS_DEAD,	 	 0,  LOG_NORMAL, 0,0,0},
    { "idea",		do_idea,	POS_DEAD,	  	 0,  LOG_NORMAL, 0,0,0},
    { "report",		do_report,	POS_DEAD,	 	 0,  LOG_NORMAL, 0,0,0},
    { "autostance",	do_autostance,	POS_STANDING,	0, LOG_NORMAL,
0,0,0,},
    { "exp",            do_level,  POS_FIGHTING,      0,  LOG_NORMAL,
0,0,0},
    { "level",            do_level,  POS_FIGHTING,      0, LOG_NORMAL,
0,0,0},

    { "score",		do_score,	POS_DEAD,	 	 0,
LOG_NORMAL, 0,0,0},
    { "spit",           do_spit,    POS_SITTING,       3,  LOG_NORMAL, 8,DISC_VAMP_QUIE,1},
    { "tongue",         do_tongue,  POS_FIGHTING,      3,  LOG_NORMAL, 8,DISC_VAMP_SERP,4},
    { "mindblast",      do_mindblast,POS_STANDING,     3,  LOG_NORMAL, 8,DISC_VAMP_PRES,2},
    { "stat",           do_stat,    POS_DEAD,          3,  LOG_NORMAL, 0,0,0},
    { "skill",		do_skill,	POS_MEDITATING,	 0,  LOG_NORMAL, 0,0,0 },
    { "spells",		do_spell,	POS_MEDITATING,	 0,  LOG_NORMAL, 0,0,0 },
    { "socials",		do_socials,	POS_DEAD,	 	 0,  LOG_NORMAL, 0,0,0 },
    { "time",		do_time,	POS_DEAD,	 	 0,  LOG_NORMAL, 0,0,0 },
    { "typo",		do_typo,	POS_DEAD,	 	 0,  LOG_NORMAL, 0,0,0 },
    { "weather",		do_weather,	POS_SITTING,	 0,  LOG_NORMAL, 0,0,0 },
    { "who",		do_who,	POS_DEAD,	 	 0,  LOG_NORMAL, 0,0,0 },
    { "wizlist",		do_wizlist,	POS_DEAD,	 	 0,  LOG_NORMAL, 0,0,0 },

    { "xemot",		do_huh,	POS_DEAD,	 	 1,  LOG_NORMAL, 0,0,0 },
    { "xemote",		do_xemote,	POS_SITTING,	 1,  LOG_NORMAL, 0,0,0 },

    { "xsocial",		do_huh,	POS_DEAD,	 	 1,  LOG_NORMAL, 0,0,0 },
    { "xsocials",		do_xsocials,POS_DEAD,	 	 1,  LOG_NORMAL, 0,0,0 },

    /*
     * Configuration commands.
     */
    { "alignment",	do_alignment,POS_DEAD,	 	 0,  LOG_NORMAL, 0,0,0	},
    { "channels",		do_channels,POS_DEAD,	 	 0,  LOG_NORMAL, 0,0,0	},
    { "config",		do_config,	POS_DEAD,	 	 0,  LOG_NORMAL, 0,0,0	},
    { "description",	do_description,POS_DEAD,	 0,  LOG_NORMAL, 0,0,0	},
    { "password",		do_password,POS_DEAD,	 	 0,  LOG_NEVER, 0,0,0	},
    { "title",		do_title,	POS_DEAD,	 	 0,  LOG_NORMAL, 0,0,0	},
    { "wimpy",		do_wimpy,	POS_DEAD,	 	 0,  LOG_NORMAL, 0,0,0	},

   
    { "ansi",		do_ansi,	POS_DEAD,	 	 0,  LOG_NORMAL, 0,0,0	},
    { "autoexit",		do_autoexit,POS_DEAD,	 	 0,  LOG_NORMAL, 0,0,0	},
    { "autoloot",		do_autoloot,POS_DEAD,	 	 0,  LOG_NORMAL, 0,0,0	},
    { "autosac",		do_autosac,	POS_DEAD,	 	 0,  LOG_NORMAL, 0,0,0	},
    { "blank",		do_blank,	POS_DEAD,	 	 0,  LOG_NORMAL, 0,0,0	},
    { "brief",		do_brief,	POS_DEAD,	 	 0,  LOG_NORMAL, 0,0,0	},
    { "cprompt",		do_cprompt,	POS_DEAD,	 	 0,  LOG_NORMAL, 0,0,0	},
    { "prompt",		do_prompt,	POS_DEAD,	 	 0,  LOG_NORMAL, 0,0,0	},

    /*
     * Communication commands.
     */
    { "answer",		do_answer,	POS_SLEEPING,	 2,  LOG_NORMAL, 0,0,0
},
    { "chat",		do_chat,	POS_DEAD,	 	 0,  LOG_NORMAL,
0,0,0	},
    { ".",			do_chat,	POS_DEAD,	 	 2,
LOG_NORMAL, 0,0,0	},
    { "wyrm",		do_wyrm,	POS_STANDING,	 0,	LOG_NORMAL, 0,0,0,},
    { "clan",		do_clandisc,	POS_DEAD,	 0,	LOG_NORMAL, 0,0,0,},
    { "clandisc",		do_clandisc,POS_SITTING,       3,  LOG_NORMAL, 0,0,0 },
    { "intro",		do_introduce,	POS_DEAD,	 3,
LOG_NORMAL, 8,0,0, },
    
 { "intro",          do_introduce,   POS_DEAD,        3,
LOG_NORMAL, 4,0,0, },
    { "emote",		do_xemote,	POS_SITTING,	 0,  LOG_NORMAL,
0,0,0 },
    { ",",			do_xemote,	POS_SITTING,	 0,  LOG_NORMAL, 0,0,0},
    { "email",		do_email,	POS_DEAD,	 	 0,  LOG_NORMAL, 0,0,0	},
    { "gtell",		do_gtell,	POS_DEAD,	 	 0,  LOG_NORMAL, 0,0,0	},
    { ";",			do_gtell,	POS_DEAD,	 	 0,  LOG_NORMAL, 0,0,0	},
    { "howl",		do_howl,	POS_DEAD,	 	 1,  LOG_NORMAL, 0,0,0	},
    { "music",		do_music,	POS_SLEEPING,	 2,  LOG_NORMAL, 0,0,0
},
    { "note",		do_note,	POS_DEAD,	 	 0,  LOG_NORMAL, 0,0,0	},
    { "board",		do_board,	POS_DEAD,	0,	LOG_NORMAL,0,0,0},
    { "pose",		do_emote,	POS_SITTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "quest",		do_quest,	POS_SITTING,	 0,  LOG_ALWAYS,
0,0,0	},
    { "question",	do_question,	POS_SLEEPING,	 2,  LOG_NORMAL, 0,0,0
},
    { "reply",		do_reply,	POS_MEDITATING,	 0,  LOG_NORMAL, 0,0,0 },
    { "say",		do_say,		POS_MEDITATING,	 0,  LOG_NORMAL, 0,0,0	},
    { "speak",		do_speak,	POS_MEDITATING,	 0,  LOG_NORMAL, 0,0,0	},
    { "'",		do_say,		POS_MEDITATING,	 0,  LOG_NORMAL, 0,0,0	},
    { "shout",		do_shout,	POS_SITTING,	 2,  LOG_NORMAL, 0,0,0
},
    { "yell",		do_yell,	POS_SITTING,	 2,  LOG_NORMAL, 0,0,0
},

    { "ignore",		do_ignore,	POS_SITTING,	 0,  LOG_NORMAL, 0,0,0 },
    { "unignore",	do_unignore,	POS_SITTING,	 0,  LOG_NORMAL, 0,0,0 },


    /*
     * Object manipulation commands.
     */
    { "activate",		do_activate,POS_STANDING,	 0,  LOG_NORMAL, 0,0,0	},
    { "brandish",		do_brandish,POS_SITTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "close",		do_close,	POS_SITTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "draw",		do_draw,	POS_FIGHTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "drink",		do_drink,	POS_SITTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "drop",		do_drop,	POS_SITTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "eat",		do_eat,	POS_SITTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "empty",		do_empty,	POS_SITTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "fill",		do_fill,	POS_SITTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "give",		do_give,	POS_SITTING,	 0,  LOG_ALWAYS, 0,0,0	},
    { "hold",		do_wear,	POS_SITTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "list",		do_list,	POS_SITTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "lock",		do_lock,	POS_SITTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "morph",		do_morph,	POS_STANDING,	 0,  LOG_NORMAL, 0,0,0	},
    { "open",		do_open,	POS_SITTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "pick",		do_pick,	POS_SITTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "press",		do_press,	POS_STANDING,	 0,  LOG_NORMAL, 0,0,0	},
    { "pull",		do_pull,	POS_STANDING,	 0,  LOG_NORMAL, 0,0,0	},
    { "put",		do_put,	POS_SITTING,	 0,  LOG_NORMAL, 0,0,0 },
    { "quaff",		do_quaff,	POS_SITTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "recite",		do_recite,	POS_SITTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "remove",		do_remove,	POS_SITTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "sell",		do_sell,	POS_SITTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "sheath",		do_sheath,	POS_STANDING,	 0,  LOG_NORMAL, 0,0,0	},
    { "take",		do_get,	POS_SITTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "reload",		do_reload,	POS_STANDING,	 0,  LOG_NORMAL, 0,0,0	},
    { "unload",		do_unload,	POS_STANDING,	 0,  LOG_NORMAL, 0,0,0	},
    { "read",		do_read,	POS_MEDITATING,	 0,  LOG_NORMAL, 0,0,0	},
    { "shoot",		do_shoot,	POS_STANDING,	 0,  LOG_NORMAL, 0,0,0	},
    { "throw",		do_throw,	POS_STANDING,	 0,  LOG_NORMAL, 0,0,0	},
    { "turn",		do_turn,	POS_MEDITATING,	 0,  LOG_NORMAL, 0,0,0	},
    { "twist",		do_twist,	POS_STANDING,	 0,  LOG_NORMAL, 0,0,0	},
    { "sacrifice",	do_sacrifice,	POS_SITTING,	 3,  LOG_NORMAL, 0,0,0	},
    { "unlock",		do_unlock,	POS_SITTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "value",		do_value,	POS_SITTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "wear",		do_wear,	POS_SITTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "write",		do_write,	POS_MEDITATING,	 0,  LOG_NORMAL, 0,0,0	},
    { "voodoo",		do_voodoo,	POS_SITTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "zap",		do_zap,	POS_SITTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "junk",           do_sacrifice,POS_STANDING,     3,  LOG_NORMAL, 0,0,0 },
    /*
     * Combat commands.
     */
    { "generation",     do_generation,POS_STANDING,   10,  LOG_ALWAYS, 0,0,0 },
    { "class",          do_class,   POS_STANDING,     10,  LOG_ALWAYS, 0,0,0 },
    { "backstab",		do_backstab,POS_STANDING,	 0,  LOG_NORMAL, 0,0,0	},
    { "berserk",		do_berserk,	POS_FIGHTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "bs",			do_backstab,POS_STANDING,	 0,  LOG_NORMAL, 0,0,0	},
    { "disarm",		do_disarm,	POS_FIGHTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "flee",		do_flee,	POS_FIGHTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "fightstyle",	do_fightstyle,POS_FIGHTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "hurl",		do_hurl,	POS_STANDING,	 0,  LOG_NORMAL, 0,0,0	},
    { "kick",		do_kick,	POS_FIGHTING,	 0,  LOG_NORMAL, 0,0,0	},
    /*{ "reseteq",        do_reseteq,     POS_DEAD,        0,  LOG_NORMAL, 0,0,0  },
*/    

    /*{ "showquest",	do_showquest, POS_DEAD, 12, LOG_NORMAL, 0,0,0 },
*/
    { "servant",        do_servant, POS_STANDING,      3,  LOG_NORMAL, 8,DISC_VAMP_DAIM,8 },
    { "punch",		do_punch,	POS_STANDING,	 0,  LOG_NORMAL, 0,0,0	},
    { "rescue",		do_rescue,	POS_FIGHTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "stance",		do_stance,	POS_FIGHTING,	 0,  LOG_NORMAL, 0,0,0	},

//                      ****|  V-A-M-P-I-R-E-S  |****
    { "sgt",		do_setgentick,POS_DEAD,     12,  LOG_NORMAL, 0,0,0 },

// Melpominee
    { "scream",		do_scream,    POS_STANDING,  3,  LOG_NORMAL, 8, DISC_VAMP_MELP, 1 },

// Daimoinon
    { "guardian",	do_guardian,  POS_STANDING,  3,  LOG_NORMAL, 8, DISC_VAMP_DAIM, 1 },
    { "fear",		do_fear,      POS_FIGHTING,  3,  LOG_NORMAL, 8, DISC_VAMP_DAIM, 2 },
    { "portal",		do_gate,      POS_STANDING,  3,  LOG_NORMAL, 8, DISC_VAMP_DAIM, 3 },
// Lvl 4 - curse ---
    { "vtwist",		do_twist,     POS_STANDING,  3,  LOG_NORMAL, 8, DISC_VAMP_DAIM, 5 },

// Thanatosis
    { "hagswrinkles",	do_hagswrinkles,POS_STANDING, 3, LOG_NORMAL, 8, DISC_VAMP_THAN, 1 },
    { "putrefaction",   do_rot,	      POS_STANDING,  3,  LOG_NORMAL, 8, DISC_VAMP_THAN, 2 },
    { "ashes",		do_ashes,     POS_STANDING,  3,  LOG_NORMAL, 8, DISC_VAMP_THAN, 3 },
    { "withering",	do_withering, POS_STANDING,  3,  LOG_NORMAL, 8, DISC_VAMP_THAN, 4 },
    { "drainlife",	do_drain,     POS_FIGHTING,  3,  LOG_NORMAL, 8, DISC_VAMP_THAN, 5 },

// Necromancy
   
    { "preserve",	do_preserve,  POS_STANDING,  3,  LOG_NORMAL, 8, DISC_VAMP_NECR, 2 },
    { "spiritgate",	do_spiritgate,POS_STANDING,  3,  LOG_NORMAL, 8, DISC_VAMP_NECR, 3 },
    { "spiritguard",	do_spiritguard,POS_STANDING, 3,  LOG_NORMAL, 8,
DISC_VAMP_NECR, 4 },


// Auspex
    { "truesight",	do_truesight, POS_FIGHTING,  3,  LOG_NORMAL, 8, DISC_VAMP_AUSP, 1 },
    { "readaura",	do_readaura,  POS_FIGHTING,  3,  LOG_NORMAL, 8, DISC_VAMP_AUSP, 2 },
    { "scry",		do_scry,      POS_FIGHTING,  3,  LOG_NORMAL, 8, DISC_VAMP_AUSP, 3 },
    { "astralwalk",	do_astralwalk,POS_STANDING,  3,  LOG_NORMAL, 8, DISC_VAMP_AUSP, 4 },
    { "unveil",		do_unveil,    POS_STANDING,  3,  LOG_NORMAL, 8, DISC_VAMP_AUSP, 5 },

// Obfuscate
    { "vanish",		do_vanish,    POS_STANDING,  3,  LOG_NORMAL, 8, DISC_VAMP_OBFU, 1 },
    { "mask",		do_mask,      POS_STANDING,  3,  LOG_NORMAL, 8, DISC_VAMP_OBFU, 2 },
    { "shield",		do_shield,    POS_STANDING,  3,  LOG_NORMAL, 8, DISC_VAMP_OBFU, 3 },
    { "mortal",		do_mortal,    POS_STANDING,  3,  LOG_NORMAL, 8, DISC_VAMP_OBFU, 4 },

// Chimerstry
    { "mirror",		do_mirror,    POS_STANDING,  3, LOG_NORMAL, 8, DISC_VAMP_CHIM, 1 },
    { "formillusion",	do_formillusion,POS_STANDING, 3, LOG_NORMAL,8, DISC_VAMP_CHIM, 2 },
    { "clone",		do_clone,     POS_STANDING,  3, LOG_NORMAL, 8, DISC_VAMP_CHIM, 3 },
    { "control",	do_control,   POS_STANDING,  3, LOG_NORMAL, 8, DISC_VAMP_CHIM, 4 },
    { "objectmask",     do_objmask,   POS_STANDING,  3, LOG_NORMAL, 8, DISC_VAMP_CHIM, 5 },

    /*
     * Miscellaneous commands.
     */
    { "accep",		do_huh,	POS_STANDING,	 2,  LOG_NORMAL, 0,0,0	},
    { "accept",		do_accept,	POS_STANDING,	 2,  LOG_NORMAL, 0,0,0	},
    { "agree",		do_agree,	POS_STANDING,	 2,  LOG_NORMAL, 0,0,0 },
    { "bet",		do_bet,	POS_STANDING,	 2,  LOG_NORMAL, 0,0,0 },
    { "challenge",	do_challenge,POS_STANDING,     2,  LOG_NORMAL, 0,0,0 },
    { "decline",		do_decline,	POS_STANDING,      2,  LOG_NORMAL, 0,0,0 },
    { "artifact",		do_artifact,POS_STANDING,	 0,  LOG_NORMAL, 0,0,0	},
    { "birth",		do_birth,	POS_STANDING,	 1,  LOG_NORMAL, 0,0,0	},
    { "blindfold",	do_blindfold,POS_STANDING,	 3,  LOG_NORMAL, 0,0,0	},
    { "breaku",		do_huh,	POS_STANDING,	 2,  LOG_NORMAL, 0,0,0	},
    { "breakup",		do_breakup,	POS_STANDING,	 2,  LOG_NORMAL, 0,0,0	},
    { "call",		do_call,	POS_RESTING,	 0,  LOG_NORMAL, 0,0,0 },
    { "claim",		do_claim,	POS_STANDING,	 0,  LOG_NORMAL, 0,0,0	},
    { "complete",		do_complete,POS_STANDING,	 0,
LOG_NORMAL, 0,0,0	},
    { "consen",		do_huh,	POS_STANDING,	 1,  LOG_NORMAL, 0,0,0	},
    { "consent",		do_consent,	POS_STANDING,	 1, LOG_NORMAL, 0,0,0	},
    { "finger",		do_finger,	POS_SITTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "follow",		do_follow,	POS_SITTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "gag",		do_gag,	POS_STANDING,	 3,  LOG_NORMAL, 0,0,0	},
    { "gift",		do_gift,	POS_STANDING,	 0,  LOG_NORMAL, 0,0,0	},
    { "godless",		do_godless,	POS_DEAD,	 	 3,  LOG_ALWAYS, 0,0,0	},
/*
    { "godsfavor",      do_godsfavor,POS_DEAD,         3,  LOG_NORMAL, 64,0,0 },
*/
    { "group",		do_group,	POS_DEAD,	 	 0,  LOG_NORMAL, 0,0,0	},
    { "hide",		do_hide,	POS_STANDING,	 0,  LOG_NORMAL, 0,0,0	},
    { "home",		do_home,	POS_STANDING,	 0,  LOG_NORMAL, 0,0,0	},
    { "hunt",		do_hunt,	POS_STANDING,	 0,  LOG_NORMAL, 0,0,0	},
    { "locate",		do_locate,	POS_STANDING,	 0,  LOG_NORMAL, 0,0,0	},
    { "practice",		do_practice,POS_SLEEPING,	 0,  LOG_NORMAL, 0,0,0	},
    { "propos",		do_huh,	POS_STANDING,	 2,  LOG_NORMAL, 0,0,0	},
    { "propose",		do_propose,	POS_STANDING,	 2,  LOG_NORMAL, 0,0,0	},
    { "qui",		do_qui,	POS_DEAD,		 0,  LOG_NORMAL, 0,0,0	},
    { "quit",		do_quit,	POS_SLEEPING,	 0,  LOG_NORMAL, 0,0,0	},
    { "recall",		do_recall,	POS_FIGHTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "escape",		do_escape,	POS_DEAD,	 	 3,  LOG_NORMAL, 0,0,0	},
    { "/",			do_recall,	POS_FIGHTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "recharge",		do_recharge,POS_STANDING,	 0,
LOG_NORMAL, 0,0,0	},
    { "rent",		do_rent,	POS_DEAD,	 	 0,  LOG_NORMAL, 0,0,0	},
    { "safe",		do_safe,	POS_STANDING,	 0,  LOG_NORMAL, 0,0,0	},
    { "save",		do_save,	POS_DEAD,	 	 0,  LOG_NORMAL, 0,0,0	},
    { "sleep",		do_sleep,	POS_SLEEPING,	 0,  LOG_NORMAL, 0,0,0	},
    { "smother",		do_smother,	POS_STANDING,	 0,  LOG_NORMAL, 0,0,0	},
    { "sneak",		do_sneak,	POS_STANDING,	 0,  LOG_NORMAL, 0,0,0	},
    { "split",		do_split,	POS_SITTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "scan",		do_scan,	POS_SITTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "spy",		do_spy,	POS_SITTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "steal",		do_steal,	POS_STANDING,	 0,  LOG_NORMAL, 0,0,0	},
    { "notravel",		do_notravel,POS_DEAD,	 	 0,
LOG_NORMAL, 0,0,0 },
    { "nosummon",		do_nosummon,POS_DEAD,	 	 0,  LOG_NORMAL, 0,0,0	},
    { "embrace",        do_embrace, POS_STANDING,      3,  LOG_NORMAL, 8,0,0 },
    { "diablerise",	do_diablerise, POS_STANDING, 3, LOG_NORMAL, 8,0,0 },
    { "assassinate",    do_assassinate,POS_STANDING,   3,  LOG_NORMAL, 8,DISC_VAMP_QUIE,4 },
    { "tendrils",           do_tendrils,POS_FIGHTING,      3,  LOG_NORMAL, 8,DISC_VAMP_SERP,4 },
    { "lamprey",        do_lamprey, POS_FIGHTING,      3,  LOG_NORMAL, 8,DISC_VAMP_OBTE,5 },
    { "entrance",       do_entrance,POS_STANDING,      3,  LOG_NORMAL, 8,DISC_VAMP_PRES,3 },
    { "fleshcraft",     do_fleshcraft,POS_STANDING,    3,  LOG_NORMAL, 8,DISC_VAMP_VICI,2 },
    { "zombie",         do_zombie,  POS_STANDING,      3,  LOG_NORMAL, 8,DISC_VAMP_NECR,5 },
    
/*
   { "wall",           do_wall,    POS_STANDING,      3,  LOG_NORMAL,
8,DISC_VAMP_DAIM,7 },
    { "facade",         do_facade,  POS_STANDING,      3,  LOG_NORMAL,
8,DISC_VAMP_PRES,6 },
*/    
{ "baal",           do_baal,    POS_STANDING,      3,  LOG_NORMAL, 8,DISC_VAMP_DOMI,5 },
{ "dragonform",     do_dragonform,POS_STANDING,    3,  LOG_NORMAL, 8,DISC_VAMP_VICI,4 },
    { "spew",           do_spew,    POS_FIGHTING,      3,  LOG_NORMAL, 8,DISC_VAMP_THAU,6 },
    { "bloodwater",     do_bloodwater,POS_FIGHTING,    3,  LOG_NORMAL,
8,DISC_VAMP_NECR,5 },
    { "gourge",         do_gourge,  POS_STANDING,      3,  LOG_NORMAL,
8,DISC_VAMP_THAU,8 },
  /*  { "shroud",	do_shroud, POS_STANDING,      3,  LOG_NORMAL,
8,DISC_VAMP_OBFU,5 },
    { "dub",            do_dub,     POS_STANDING,      3,  LOG_NORMAL,
8,DISC_VAMP_OBFU,4 },
*/    
{ "congregate",	do_congregation,POS_FIGHTING,  3,  LOG_NORMAL, 4,DISC_WERE_CONG,1 },
    { "quills",		do_quills,  POS_STANDING,      3,  LOG_NORMAL, 4,DISC_WERE_BEAR,5 },
    { "roar",		do_roar,    POS_FIGHTING,      3,  LOG_NORMAL, 4,DISC_WERE_BEAR,6 },
    { "jawlock",	do_jawlock, POS_STANDING,      3,  LOG_NORMAL, 4,DISC_WERE_RAPT,8 },
    { "perception",	do_perception,POS_STANDING,    3,  LOG_NORMAL, 4,DISC_WERE_RAPT,3 },
    { "skin",		do_skin,    POS_STANDING,      3,  LOG_NORMAL, 4,DISC_WERE_BEAR,7 },
    { "rend",		do_rend,    POS_STANDING,      3,  LOG_NORMAL, 4,DISC_WERE_BOAR,7 },
    { "slam",		do_slam,    POS_STANDING,      3,  LOG_NORMAL, 4,DISC_WERE_BEAR,8 },
    { "shred",		do_shred,   POS_STANDING,      3,  LOG_NORMAL, 4,DISC_WERE_RAPT,7 },
    { "diablerize",	do_diablerise, POS_STANDING,   3,  LOG_NORMAL, 8,0,0},
    { "testarm",	do_testarm,	POS_STANDING, 12,  LOG_NORMAL, 0,0,0 },  
    { "noarm",		do_noarm,   POS_DEAD,         0,  LOG_NORMAL, 0,0,0 }, 
    { "powers",	do_racecommands, POS_FIGHTING, 3, LOG_NORMAL,0,0,0 },

    { "taste",          do_taste,   POS_STANDING,      3,  LOG_NORMAL, 8,DISC_VAMP_THAU,1 },
    { "pigeon",         do_pigeon,  POS_STANDING,      3,  LOG_NORMAL, 8,DISC_VAMP_ANIM,3 },
    { "bloodagony",     do_bloodagony,POS_STANDING,    3,  LOG_NORMAL, 8,DISC_VAMP_QUIE,3 },
   /* { "decay",          do_decay,   POS_STANDING,      3,  LOG_NORMAL,
8,DISC_VAMP_DAIM,5 },
*/    
{ "tie",		do_tie,	POS_STANDING,	 3,  LOG_NORMAL, 0,0,0	},
    { "token",		do_token,	POS_STANDING,	 2,  LOG_NORMAL, 0,0,0	},
    { "track",		do_track,	POS_STANDING,	 0,  LOG_NORMAL, 0,0,0	},
    { "train",		do_train,   POS_SITTING,	 0,  LOG_NORMAL, 0,0,0	},
    { "unpolymorph",	do_unpolymorph,POS_STANDING,	 4,  LOG_NORMAL, 0,0,0 },
    { "untie",		do_untie,	POS_STANDING,	 3,  LOG_NORMAL, 0,0,0	},
    { "visible",		do_visible,	POS_SLEEPING,	 0,  LOG_NORMAL, 0,0,0 },
    { "wake",		do_wake,	POS_SLEEPING,	 0,  LOG_NORMAL, 0,0,0	},
    { "where",		do_where,	POS_SITTING,	 0,  LOG_NORMAL, 0,0,0	},
/* need it before forge */

 /*
  * Monk
  */
    { "ghold",		do_ghold,	POS_STANDING,    3,  LOG_NORMAL, 64,0,0 },
    { "godsheal",	do_godsheal,	POS_FIGHTING,	 3,  LOG_NORMAL, 64,0,0 },
    { "mantra",		do_mantra,	POS_STANDING,	 3,
LOG_NORMAL, 64,0,0 },
    { "guide",		do_guide,	POS_STANDING,	 3,  LOG_NORMAL, 64,0,0 },
    { "cloak",		do_cloak,	POS_STANDING,      3,  LOG_NORMAL, 64,0,0 },
 
    { "pray",		do_pray,	POS_MEDITATING,	 1,  LOG_NORMAL, 64,0,0 },
 
    { "prayofages",	do_prayofages,POS_STANDING,    3,  LOG_NORMAL, 64,0,0 },
    { "sacredinvis",	do_sacredinvis, POS_STANDING,	 3,  LOG_NORMAL, 64,0,0 },
    { "flaminghands",   do_flaminghands,POS_STANDING,  3,  LOG_NORMAL, 64,0,0 },

    { "adamantium",	do_adamantium,POS_STANDING,    3,  LOG_NORMAL, 64,0,0 },

    { "godseye",		do_godseye,	POS_STANDING,	 3,  LOG_NORMAL, 64,0,0 },

    { "celestial",	do_celestial,POS_STANDING,	 3,  LOG_NORMAL, 64,0,0 },

    { "steelskin",	do_steelskin,POS_STANDING,	 3,  LOG_NORMAL, 64,0,0 },
    { "godsbless",	do_godsbless,POS_FIGHTING,	 3,  LOG_NORMAL, 64,0,0 },


    { "thrustkick",	do_thrustkick,POS_FIGHTING,	3, LOG_NORMAL, 64,0,0 },
    { "spinkick",	do_spinkick,POS_FIGHTING,3,LOG_NORMAL,64,0,0 },
    { "backfist",	do_backfist,POS_FIGHTING,3,LOG_NORMAL,64,0,0 },
    { "elbow",		do_elbow,POS_FIGHTING,3,LOG_NORMAL,64,0,0 },
    { "sweep",		do_sweep,POS_FIGHTING,3,LOG_NORMAL,64,0,0 },
    { "reverse",	do_reverse,POS_FIGHTING,3,LOG_NORMAL,64,0,0 },
    { "knee",		do_knee,POS_FIGHTING,3,LOG_NORMAL,64,0,0 },
    { "shinkick",	do_shinkick,POS_FIGHTING,3,LOG_NORMAL,64,0,0 },
    { "palmstrike",	do_palmstrike,POS_STANDING,3,LOG_NORMAL,64,0,0 },
    { "chi",		do_chi,POS_FIGHTING,3, LOG_NORMAL,64,0,0 },
    { "spiritpower",	do_spiritpower,POS_FIGHTING,3,LOG_NORMAL,64,0,0},
    { "deathtouch",	do_deathtouch,POS_STANDING,3,LOG_NORMAL,64,0,0 },
    { "healingtouch",   do_healingtouch,POS_STANDING,3,LOG_NORMAL,64,0,0},
    { "relax",		do_relax,POS_FIGHTING,3,LOG_NORMAL,64,0,0},
    { "monktalk",	do_monktalk,POS_DEAD,3,LOG_NORMAL,64,0,0 },
    { "blinding",	do_blinding, POS_STANDING, 3, LOG_NORMAL, 64,0,0 },


    /*{ "disciplines",    do_disciplines,POS_STANDING,   3,  LOG_NORMAL,
0,0,0 },
    { "research",		do_research,POS_STANDING,      3,  LOG_NORMAL, 0,0,0 },
*/

/*
 * Garou
 */
// Ahroun
    { "razorclaws",	do_razorclaws, POS_FIGHTING, 3, LOG_NORMAL, 4,AHROUN,1 },

// Homid
//  Persuasion, automatic
    { "staredown",	do_staredown, POS_FIGHTING, 3, LOG_NORMAL, 4,HOMID,2 },
    { "disquiet",	do_disquiet, POS_FIGHTING, 3 , LOG_NORMAL, 4,HOMID,3 }, 
    { "reshape",	do_reshape,  POS_STANDING,  3,  LOG_NORMAL, 4,HOMID,4 },
    { "cocoon",		do_cocoon,   POS_FIGHTING,  3,  LOG_NORMAL, 4,HOMID, 5 },

// Metis
    { "quills",	do_quills, POS_FIGHTING, 3, LOG_NORMAL, 4,METIS,1 },
    { "burrow", do_burrow, POS_FIGHTING, 3, LOG_NORMAL, 4,METIS,2 },
    { "nightsight",do_nightsight,POS_FIGHTING,3,LOG_NORMAL,4,METIS,3 },
    { "wither", 
do_wither, POS_FIGHTING, 3, LOG_NORMAL, 4,METIS,4 },



    { "learn",		do_learn, POS_FIGHTING, 3, LOG_NORMAL, 64,0,0 },
    { "dtoken",		do_dtoken, POS_STANDING, 3, LOG_NORMAL, 0,0,0 },

    /*
     * Vampire and werewolf commands.
     */
    { "bloodwall",	do_bloodwall,POS_STANDING,	 3,  LOG_NORMAL, 8,DISC_VAMP_DAIM,2 },
    { "conceal",     do_conceal,  POS_STANDING,  3,  LOG_NORMAL,
8,DISC_VAMP_OBFU,5 },

{ "sharpen",	do_sharpen,  POS_STANDING,     3,  LOG_NORMAL,
8,DISC_VAMP_QUIE,7 },

     /* Protean */
/* healing has to go after drow heal */
    /* Obtene */
    { "grab",		do_grab,	POS_STANDING,    	 3,  LOG_NORMAL, 8,DISC_VAMP_OBTE,8 },
    { "shadowgaze",	do_shadowgaze,POS_STANDING,    3,  LOG_NORMAL, 8,DISC_VAMP_OBTE,10 },

   /* Luna Powers */
    { "flameclaws",	do_flameclaws,  POS_STANDING,  3,  LOG_NORMAL,
8,DISC_WERE_LUNA,1 },
    { "motherstouch",	do_motherstouch,POS_FIGHTING,  3,  LOG_NORMAL, 4,DISC_WERE_LUNA,3 },
    { "gmotherstouch",  do_gmotherstouch,POS_FIGHTING, 3,  LOG_NORMAL, 4,DISC_WERE_LUNA,4 },
    { "sclaws",		do_sclaws,	POS_STANDING,      3,  LOG_NORMAL, 4,DISC_WERE_LUNA,5 },
    { "moonbeam",	do_moonbeam,POS_FIGHTING,      3,  LOG_NORMAL, 4,DISC_WERE_LUNA,8 },
    { "moonarmour",	do_moonarmour,POS_STANDING,    3,  LOG_NORMAL, 4,DISC_WERE_LUNA,2 },
    { "moongate",	do_moongate,POS_STANDING,      3,  LOG_NORMAL, 4,DISC_WERE_LUNA,6 },
   /* No more luna Powers */

    { "claw",		do_claw,       POS_STANDING,   3, LOG_NORMAL, 4,0,0 },


    { "testform",	do_testform,   POS_DEAD,       12,LOG_NORMAL,0,0,0 },
    { "setdisc", 	do_setdisciplines,POS_DEAD,    10,LOG_ALWAYS, 0,0,0 },
    { "promote",	do_promote,    POS_STANDING,   3, LOG_NORMAL, 1,0,0 },
    { "demongate",	do_dgate,      POS_FIGHTING,   3, LOG_NORMAL, 1,0,0 },
    { "devour",		do_devour,     POS_STANDING,   3, LOG_NORMAL, 4,DISC_WERE_RAPT,5 },
    { "devoursoul",     do_devoursoul, POS_STANDING,   3, LOG_NORMAL, 1,0,0 },
    { "frostbreath",    do_frostbreath,POS_FIGHTING,   3, LOG_NORMAL, 1,DISC_DAEM_GELU,2 },
    { "tick",		do_tick,       POS_DEAD,      12, LOG_ALWAYS, 0,0,0},
    { "form",		do_form,       POS_DEAD,      10, LOG_ALWAYS, 0,0,0},
    { "resetarea",	do_resetarea,  POS_DEAD,      10, LOG_ALWAYS, 0,0,0},
    { "shadowdemon",    do_shadowdemon,POS_STANDING,   3, LOG_NORMAL, 1,DISC_DAEM_TEMP,6 },
    { "graft",		do_graft,      POS_STANDING,   3, LOG_NORMAL, 1,DISC_DAEM_ATTA,5 },
    { "rage",		do_rage,       POS_FIGHTING,   3, LOG_NORMAL, 1,DISC_DAEM_ATTA,3 },
    { "calm",		do_calm,       POS_FIGHTING,   3, LOG_NORMAL, 1,DISC_DAEM_ATTA,4 },
    { "vamptalk",       do_vamptalk,   POS_DEAD,       1, LOG_NORMAL, 8,0,0 },      
    { "vampallow",      do_vampallow,   POS_FIGHTING,    0,  LOG_ALWAYS,0,0,0 },
    { "soulsell",       do_demonallow,  POS_FIGHTING,    0,  LOG_ALWAYS,0,0,0 },
    { "dedicate",       do_warlockallow,POS_FIGHTING,    0,  LOG_ALWAYS,0,0,0 },
    { "submit",         do_wereallow,   POS_FIGHTING,    0,  LOG_ALWAYS,0,0,0 },
    { "stats",		do_racestats,  POS_STANDING,   3,  LOG_NORMAL, 0,0,0 },
    { "claws",		do_claws,	POS_FIGHTING,  3,  LOG_NORMAL, 1,DISC_DAEM_ATTA,1 },
    { "fangs",		do_fangs,	POS_FIGHTING,  3,  LOG_NORMAL, 1,DISC_DAEM_ATTA,2 },
    { "horns",		do_horns,	POS_FIGHTING,  3, LOG_NORMAL,
1,DISC_DAEM_ATTA,4 },
    { "blink",		do_blink,	POS_FIGHTING,  3,  LOG_NORMAL, 1,DISC_DAEM_ATTA,7 },
    { "inferno",	do_dinferno,	POS_DEAD,      3,  LOG_NORMAL, 1,DISC_DAEM_HELL, 3 },
    { "tail",		do_tail,	POS_FIGHTING,  3,  LOG_NORMAL,
1,0,0 },

/* Vamp */
    { "binferno",	do_inferno,	POS_STANDING,  3,  LOG_NORMAL, 1,DISC_VAMP_DAIM, 6 },
/* Vamp ^^^^ */

    { "destroy",	do_destroy,	POS_DEAD,      3,  LOG_ALWAYS, 1,DISC_DAEM_HELL,10 },
    { "immolate",	do_immolate,    POS_STANDING,  3,  LOG_NORMAL, 1,DISC_DAEM_HELL, 2 },
    { "daemonseed",	do_seed,	POS_STANDING,  3,  LOG_NORMAL, 1,DISC_DAEM_HELL, 7 },
    { "hellfire",	do_hellfire,	POS_STANDING,  3,  LOG_NORMAL, 1,DISC_DAEM_HELL, 8 },
    { "polymorph",	do_polymorph,   POS_STANDING,  3,  LOG_NORMAL, 1,DISC_DAEM_MORP,2 },
    { "ban",		do_ban,	POS_DEAD,		 11,  LOG_ALWAYS, 0,0,0	},

    { "transfer",       do_transfer,    POS_DEAD,      7,  LOG_NORMAL,0,0,0 },
    { "newbiepack",     do_newbiepack,  POS_DEAD,    0,  LOG_NORMAL,0,0,0 },
    { "afk",     	do_afk,         POS_DEAD,    0,  LOG_NORMAL,0,0,0 },
    /*{ "hedit",		do_hedit,	POS_STANDING, 10,
LOG_NORMAL,0,0,0
},*/
    { "freeze",		do_freeze,      POS_DEAD,     10, LOG_ALWAYS,0,0,0
},  
    { "transform",	do_transform,	POS_STANDING,  3,  LOG_NORMAL, 1,DISC_DAEM_MORP, 2 },
    { "unnerve",	do_unnerve,     POS_FIGHTING,  3,  LOG_NORMAL, 1,DISC_DAEM_DISC,1 },
    { "freezeweapon",	do_wfreeze,     POS_STANDING,  3, LOG_NORMAL, 1,DISC_DAEM_GELU, 1 },
    { "bane",		do_bane,	POS_FIGHTING,  3,  LOG_NORMAL, 1,DISC_DAEM_CORR, 3 },
    { "chaosportal",	do_chaosport,   POS_FIGHTING,  3,  LOG_NORMAL, 1,DISC_DAEM_DISC, 4 },
    { "caust",		do_caust,       POS_STANDING,  3,  LOG_NORMAL, 1,DISC_DAEM_CORR, 4 },
    { "gust",		do_gust,	POS_STANDING,  3,  LOG_NORMAL, 1,DISC_DAEM_GELU, 7 },
    { "entomb",		do_entomb,      POS_STANDING,  3,  LOG_NORMAL, 1,DISC_DAEM_GELU, 6 },
    { "evileye",	do_evileye,     POS_STANDING,  3,  LOG_NORMAL, 1,DISC_DAEM_DISC, 2 },
    { "leech",		do_leech,	POS_FIGHTING,  3,  LOG_NORMAL, 1,DISC_DAEM_NETH,4 },
   /* { "configure",	do_configure,   POS_DEAD,      12, LOG_ALWAYS,0,0,0 },*/
    { "stealsoul",	do_stealsoul,   POS_STANDING,  3,  LOG_NORMAL, 1,0,0 },
    { "deathsense",	do_deathsense,  POS_FIGHTING,  3,  LOG_NORMAL, 1,DISC_DAEM_NETH, 2 },
    { "prefix",		do_prefix,	POS_DEAD,      7,  LOG_NORMAL, 0,0,0 },

    /* bugaboo lala Dunkirk Shit Lala mmm POOP Daemon Stuff */


    /* Start of OLC Shit. Hmm */
    { "hset",		do_hset,        POS_DEAD,      12, LOG_ALWAYS, 0,0,0 },
    { "hlist",		do_hlist,	POS_DEAD,      12, LOG_ALWAYS, 0,0,0 },

    { "talons",         do_talons,   POS_FIGHTING,     3,  LOG_NORMAL, 4,DISC_WERE_RAPT,10 },
    { "run",            do_run,     POS_STANDING,      3,  LOG_NORMAL, 4,DISC_WERE_RAPT,2 },
    { "bonemod",		do_bonemod,	POS_STANDING,      3,  LOG_NORMAL, 8,DISC_VAMP_VICI,3 },
    { "vset",		do_vset,	POS_DEAD,		 11,  LOG_ALWAYS, 0,0,0 },
    { "cauldron",		do_cauldron,POS_FIGHTING,      3, LOG_NORMAL, 8,DISC_VAMP_THAU,2 },
    { "flamehands",	do_flamehands,POS_FIGHTING,	 3,  LOG_NORMAL, 8,DISC_VAMP_PROT,5 },
   
    { "summon",		do_summon,	POS_STANDING,      3,  LOG_NORMAL,
8,DISC_VAMP_PRES,4 },
    { "shroud",		do_shroud,	POS_STANDING,      3,  LOG_NORMAL,
8,DISC_VAMP_OBTE,1 },
    { "share",		do_share,	POS_STANDING,      3,  LOG_NORMAL, 8,DISC_VAMP_ANIM,4 },
    { "frenzy",		do_frenzy,	POS_FIGHTING,	 3,  LOG_NORMAL, 8,DISC_VAMP_ANIM,5 },
    { "far",		do_far,	POS_STANDING,	 3,  LOG_NORMAL, 8,DISC_VAMP_PRES,9 },
    { "awe",            do_awe,     POS_STANDING,      3,  LOG_NORMAL, 8,DISC_VAMP_PRES,1 },

/*
    { "forge",		do_forge,	POS_STANDING,  3,  LOG_ALWAYS,
0,0,0 },
*/
    { "forget",         do_forget,  POS_STANDING,      3,  LOG_NORMAL, 8,DISC_VAMP_DOMI,8 },
    { "return",         do_retrn,   POS_STANDING,      3,  LOG_NORMAL, 8,DISC_VAMP_OBFU,8 },
    { "acid",           do_acid,    POS_STANDING,      3,  LOG_NORMAL, 8,DISC_VAMP_DOMI,4 },
    { "vsilence",       do_death,   POS_STANDING,      3,  LOG_NORMAL, 8,DISC_VAMP_QUIE,5 },
    { "flash",          do_flash,   POS_STANDING,      3,  LOG_NORMAL, 8,DISC_VAMP_QUIE,9 },
    { "tide",   	do_tide,    POS_STANDING,      3,  LOG_NORMAL, 8,DISC_VAMP_THAU,5 },
    { "coil",           do_coil,    POS_STANDING,      3,  LOG_NORMAL, 8,DISC_VAMP_SERP,8 },
    { "infirmity",	do_infirmity,POS_FIGHTING,	 3,  LOG_NORMAL, 8,DISC_VAMP_QUIE,2 },
    { "potency",        do_potency, POS_STANDING,      3,  LOG_NORMAL, 8,DISC_VAMP_THAU,3 },
    { "klaive",         do_klaive,  POS_STANDING,      3,  LOG_NORMAL, 4,0,0 },
    { "bite",		do_bite,	POS_STANDING,	 3,  LOG_NORMAL, 8,0,0	},
    { "calm",		do_calm,	POS_STANDING,	 3,  LOG_NORMAL, 4,0,0	},
    { "change",		do_change,	POS_STANDING,	 3,  LOG_NORMAL, 8,DISC_VAMP_PROT,3	},
/*
    { "tot",		do_totalscore,POS_DEAD,	 	 3,  LOG_NORMAL, 0,0,0 },
*/
    { "katana",	do_katana,	POS_RESTING, 3, LOG_NORMAL, 0, 0, 0 },
    { "earthshatter",	do_earthshatter,POS_FIGHTING,   3, LOG_NORMAL, 0, 0, 0 },
    { "dagger",	do_dagger, POS_STANDING, 3, LOG_NORMAL, 0, 0, 0},
    { "sword", do_sword, POS_STANDING, 3, LOG_NORMAL, 0, 0, 0 },
    { "shadowstep",	do_shadowstep,POS_STANDING,    3,  LOG_NORMAL, 8,DISC_VAMP_OBTE,4 },
    { "claws",		do_claws,	POS_SITTING,	 3,  LOG_NORMAL, 8,DISC_VAMP_PROT,2	},
    { "darkheart",	do_darkheart,POS_STANDING,	 3,  LOG_NORMAL, 8,DISC_VAMP_SERP,1	},
    { "earthmeld",      do_earthmeld,POS_STANDING,     3,  LOG_NORMAL, 8,DISC_VAMP_PROT,4 },
    { "burrow",         do_burrow,  POS_STANDING,      3,  LOG_NORMAL, 4,DISC_WERE_BOAR,5 },
    { "fangs",		do_fangs,	POS_SITTING,	 3,  LOG_NORMAL, 8,0,0	},
    { "feed",		do_feed,	POS_SITTING,	 3,  LOG_NORMAL, 8,0,0	},
    { "flex",		do_flex,	POS_SITTING,	 3,  LOG_NORMAL, 0,0,0	},
    { "gcommand",		do_fcommand,POS_STANDING,	 3,  LOG_NORMAL, 0,0,0	},
    { "possession",     do_possession,POS_STANDING,    3,  LOG_NORMAL, 8,DISC_VAMP_DOMI,3 },
    { "hum",		do_monktalk,	POS_DEAD,		3, LOG_NORMAL, 0, 0, 0},

    { "humanform",	do_humanform,POS_SITTING,	 2,  LOG_NORMAL, 0,0,0 },
    { "theft",          do_theft,   POS_FIGHTING,      3,  LOG_NORMAL,
8,DISC_VAMP_THAU,4 },   
    { "plasma",         do_plasma,  POS_STANDING,      3,  LOG_NORMAL, 8,DISC_VAMP_VICI,5 },
    { "zuloform",       do_zuloform,POS_FIGHTING,      3,  LOG_NORMAL, 8,DISC_VAMP_VICI,2},
    { "beckon",         do_beckon,  POS_STANDING,      3,  LOG_NORMAL, 8,DISC_VAMP_ANIM,1},
    { "miktalk", do_miktalk, 	POS_SLEEPING, 2, LOG_NORMAL, 0, 0, 0},
    { "principles", do_principles, POS_MEDITATING, 3, LOG_NORMAL, 0, 0, 0 },
    { "michi", do_michi, POS_FIGHTING, 3, LOG_NORMAL, 0, 0, 0 },
    { "harakiri", do_hara_kiri, POS_MEDITATING,3, LOG_NORMAL, 0, 0, 0 },
    { "circle",	do_circle, POS_FIGHTING, 3, LOG_NORMAL, 0, 0, 0},
    { "discipline", do_discipline, POS_STANDING, 3, LOG_NORMAL, 0, 0, 0 },
    { "kakusu", do_kakusu, POS_MEDITATING, 3, LOG_NORMAL, 0, 0, 0 },
    { "kanzuite", do_kanzuite, POS_MEDITATING, 3, LOG_NORMAL, 0, 0, 0 },
    { "mienaku", do_mienaku, POS_FIGHTING, 3, LOG_NORMAL, 0, 0, 0 },
    { "bomuzite", do_bomuzite, POS_MEDITATING, 3, LOG_NORMAL, 0, 0, 0  },
    { "tsume", do_tsume, POS_FIGHTING, 3, LOG_NORMAL, 0, 0, 0 },
    { "mitsukeru", do_mitsukeru, POS_MEDITATING, 3, LOG_NORMAL, 0, 0, 0 },
    { "koryou", do_koryou, POS_MEDITATING, 3, LOG_NORMAL, 0,0,0},

/*start drow section */
    { "sign",		do_sign,	POS_FIGHTING,	 2,  LOG_NORMAL, 0,0,0 },
    { "relevel",		do_relevel,	POS_DEAD,   	 0,  LOG_ALWAYS, 0,0,0 },


    { "favor",		do_favor,	POS_STANDING,      3,  LOG_NORMAL, 0,0,0 },
    { "grant",		do_grant,	POS_STANDING,	 3,  LOG_NORMAL, 0,0,0 },
    { "drowsight",	do_drowsight,POS_STANDING,     3,  LOG_NORMAL, 0,0,0 },
    { "drowshield",	do_drowshield,POS_STANDING,    3,  LOG_NORMAL, 0,0,0 },
    { "drowfire",		do_drowfire,POS_FIGHTING,      3,  LOG_NORMAL, 0,0,0 },
    { "drowhate",	do_drowhate,	POS_STANDING,    3,  LOG_NORMAL, 0,0,0 },
    { "drowpowers",	do_drowpowers,	POS_STANDING,    3,  LOG_NORMAL, 0,0,0 },
    { "darkness",       do_darkness,	POS_STANDING,    3,  LOG_NORMAL, 0,0,0 },
    { "darkside",                do_darkside,     POS_STANDING,    0,  LOG_NORMAL, 0,0,0  },

    { "shadowwalk",	do_shadowwalk,	POS_STANDING,    3,  LOG_NORMAL, 0,0,0 },
    { "drowcreate",    	do_drowcreate,	POS_STANDING,    3,  LOG_NORMAL, 0,0,0 },
    { "heal",		do_heal,	POS_FIGHTING,    3,  LOG_NORMAL, 0,0,0 },
    { "garotte",	do_garotte,	POS_STANDING,    3,  LOG_NORMAL, 0,0,0 },
    { "spiderform",	do_spiderform,	POS_STANDING,    3,  LOG_NORMAL, 0,0,0 },
    {"chaosblast",	do_chaosblast,	POS_FIGHTING,    3,  LOG_NORMAL, 0,0,0 },
    {"dgarotte",	do_dark_garotte,POS_STANDING,   3, LOG_NORMAL, 0, 0, 0 },
    { "glamour",	do_glamour	,POS_RESTING,	3, LOG_NORMAL, 0, 0, 0 },
    { "confuse",	do_confuse	,POS_FIGHTING,  3, LOG_NORMAL, 0, 0, 0 },

/* end drow */



/*demon section*/

    { "champions",	do_champions,	POS_STANDING,	 3,  LOG_NORMAL, 1,0,0 },
    { "demonarmour",	do_demonarmour,	POS_STANDING,	 3,  LOG_NORMAL, 1,0,0 },
    { "hooves",		do_hooves,	POS_STANDING,	 3,  LOG_NORMAL, 1,0,0 },
    { "humanform",	do_humanform,	POS_SITTING,	 2,  LOG_NORMAL, 1,0,0 },
    { "inpart",		do_inpart,	POS_STANDING,	 3,  LOG_NORMAL, 1,0,0 },
    { "offersoul",	do_offersoul,	POS_STANDING,	 3,  LOG_NORMAL, 1,0,0 },
    { "pact",		do_pact,	POS_STANDING,	 3,  LOG_NORMAL, 1,0,0 },
    { "travel",		do_travel,	POS_STANDING,	 3,  LOG_NORMAL, 1,0,0 },
    { "weaponform",	do_weaponform,	POS_STANDING,	 2,  LOG_NORMAL, 1,0,0 },
    { "leap",		do_leap,	POS_STANDING,	 3,  LOG_NORMAL, 1,0,0 },
    { "wings",		do_wings,	POS_STANDING,	 3,  LOG_NORMAL, 1,0,0 },
    { "demonform",	do_demonform,	POS_STANDING,    3,  LOG_NORMAL, 1,0,0, },

/*end demon section*/



/* vamp protean healing*/
    { "healing",		do_healing, POS_FIGHTING,      3,   LOG_NORMAL, 8,DISC_VAMP_PROT,8},

    { "inconnu",		do_inconnu,	POS_STANDING,	 3,  LOG_NORMAL, 8,0,0	},
    { "majesty",		do_majesty,	POS_STANDING,	 3,  LOG_NORMAL, 8,DISC_VAMP_PRES,5	},
    { "nightsight",	do_nightsight,POS_SITTING,	 3,  LOG_NORMAL, 8,DISC_VAMP_PROT,1	},
    
    { "poison",		do_poison,	POS_STANDING,	 3,  LOG_NORMAL, 8,DISC_VAMP_SERP,3	},
    { "rage",		do_rage,	POS_FIGHTING,	 3,  LOG_NORMAL, 4,DISC_WERE_BEAR,3	},
    { "regenerate",	do_regenerate,POS_SLEEPING,	 3,  LOG_NORMAL, 8,0,0	},
    { "roll",		do_roll,	POS_RESTING,	 2,  LOG_NORMAL, 1,0,0	},
    { "stake",		do_stake,	POS_STANDING,	 3,  LOG_NORMAL, 0,0,0 },
    { "serpent",		do_serpent,	POS_STANDING,	 3,  LOG_NORMAL, 8,DISC_VAMP_SERP,2	},
    { "shadowplane",	do_shadowplane,POS_STANDING,	 3,  LOG_NORMAL, 8,DISC_VAMP_OBTE,3	},

    { "shadowsight",	do_shadowsight,POS_SITTING,	 3,  LOG_NORMAL, 8,DISC_VAMP_OBTE,2	},
    { "serenity",       do_serenity,POS_SITTING,       3,  LOG_NORMAL, 8,DISC_VAMP_ANIM,2 },
    { "weaponteach",    do_weaponteach, POS_STANDING,	 3,  LOG_NORMAL, 16,0,0, },
    { "teach",		do_teach,	POS_STANDING,	 3,  LOG_NORMAL, 0,0,0
},
    { "gifts",		do_gifts,	POS_SITTING,	 3,  LOG_NORMAL,
4,0,0	},
    { "totems",		do_totems,	POS_SITTING,	 3,  LOG_NORMAL, 4,0,0  },
    { "upkeep",		do_upkeep,	POS_DEAD,	       3,
LOG_NORMAL, 0,0,0	},
    { "vanish",		do_vanish,	POS_STANDING,	 3,  LOG_NORMAL, 4,DISC_WERE_OWL,1	},
    { "web",		do_web,	POS_FIGHTING,	 3,  LOG_NORMAL, 4,DISC_WERE_SPID,3	},
    { "mlearn",	do_mlearn, POS_RESTING, 3, LOG_NORMAL, 0, 0, 0 },

/* Tag commands */
    { "tag", do_tag, POS_STANDING, 0, LOG_NORMAL, 0, 0, 0 },
    { "notag", do_notag, POS_STANDING, 7, LOG_NORMAL, 0, 0, 0 },
   /* { "bounty", do_bounty, POS_STANDING, 0, LOG_NORMAL, 0, 0, 0 },*/

    /*
     * Immortal commands.
     */
    { "trust",		do_trust,	POS_DEAD,		 11,  LOG_ALWAYS, 0,0,0 },
    { "allow",		do_allow,	POS_DEAD,		 11,  LOG_ALWAYS, 0,0,0	},
    { "secset",		do_secset,	POS_DEAD,		 11,  LOG_NORMAL, 0,0,0	},
    { "addlag",		do_addlag,	POS_DEAD,		 11,  LOG_ALWAYS, 0,0,0	},
    { "bind",		do_bind,	POS_DEAD,		 10,  LOG_ALWAYS, 0,0,0	},
    { "clearstats",	do_clearstats,POS_STANDING,	 0,  LOG_NORMAL, 0,0,0	},
    { "clearvam",		do_clearvam,POS_STANDING,	 1,  LOG_NORMAL, 0,0,0	},
    { "clearvamp",	do_clearvamp,POS_STANDING,	 11,  LOG_ALWAYS, 0,0,0	},
    { "create",		do_create,	POS_STANDING,	 8,  LOG_NORMAL, 0,0,0	},
    { "deny",		do_deny,	POS_DEAD,		 10,  LOG_ALWAYS, 0,0,0	},
    { "disable",		do_disable,	POS_DEAD,		 11,  LOG_ALWAYS, 0,0,0 },
    { "disconnect",	do_disconnect,POS_DEAD,		 10,  LOG_ALWAYS, 0,0,0	},
    { "divorce",		do_divorce,	POS_DEAD,	 	 9,  LOG_ALWAYS, 0,0,0	},
    { "familiar",		do_familiar,POS_STANDING,	12,  LOG_NORMAL, 0,0,0	},
    { "fcommand",		do_fcommand,POS_STANDING,	 4,  LOG_NORMAL, 0,0,0	},
   /* { "fileupdate",	do_fileupdate,POS_DEAD,		 12,  LOG_ALWAYS	},*/
    { "freeze",		do_freeze,	POS_DEAD,		 9,  LOG_ALWAYS, 0,0,0	},
    { "marry",		do_marry,	POS_DEAD,	 	 9,  LOG_ALWAYS, 0,0,0	},
    { "paradox",		do_paradox,	POS_DEAD,		 12, LOG_ALWAYS, 0,0,0 },
    { "playerlist",     do_playerlist,  POS_DEAD,		 8,   LOG_NORMAL, 0,0,0  },
    { "qset",		do_qset,	POS_DEAD,	 	 8,  LOG_ALWAYS, 0,0,0	},
    { "qstat",		do_qstat,	POS_DEAD,	 	 8,  LOG_ALWAYS, 0,0,0	},
    { "qtrust",		do_qtrust,	POS_DEAD,		 10,  LOG_ALWAYS, 0,0,0	},
/*
    { "ntrust",		do_ntrust,	POS_DEAD,		 10,  LOG_ALWAYS, 0,0,0	},
*/
    { "reboo",		do_reboo,	POS_DEAD,		 10,  LOG_NORMAL, 0,0,0	},
    { "reboot",		do_reboot,	POS_DEAD,		 10,  LOG_ALWAYS, 0,0,0	},
    { "shutdow",		do_shutdow,	POS_DEAD,		 10,  LOG_NORMAL, 0,0,0	},
    { "shutdown",		do_shutdown,POS_DEAD,		 10,  LOG_ALWAYS, 0,0,0	},
    { "users",		do_users,	POS_DEAD,	 	 8,  LOG_NORMAL, 0,0,0	},
    { "omni",		do_omni,	POS_DEAD,		 10, LOG_NORMAL, 0,0,0 },
    { "wizlock",		do_wizlock,	POS_DEAD,		 11,  LOG_ALWAYS, 0,0,0	},
    { "closemud",	do_closemud,	POS_DEAD,	11,     LOG_ALWAYS, 0,0,0, },
    { "watche",		do_huh,	POS_DEAD,	 	 2,  LOG_NEVER,
0,0,0	},
    { "watcher",		do_watcher,	POS_DEAD,	 	 11,  LOG_NEVER, 0,0,0	},
    { "force",		do_force,	POS_DEAD,	 	 9,  LOG_ALWAYS, 0,0,0	},
    { "exlist",		do_exlist,	POS_DEAD,		 7, LOG_NORMAL, 0,0,0 },
    { "vlist",		do_vlist,	POS_DEAD,		 7, LOG_NORMAL, 0,0,0 },
    { "mclear",		do_mclear,	POS_DEAD,		 9,  LOG_ALWAYS, 0,0,0	},
    { "mload",		do_mload,	POS_DEAD,	 	 7,  LOG_ALWAYS, 0,0,0	},
    { "undeny",         do_undeny,  POS_DEAD,          12,  LOG_ALWAYS, 0,0,0 },
    { "mset",		do_mset,	POS_DEAD,	 	 7,
LOG_ALWAYS, 0,0,0	},
    { "noemote",		do_noemote,	POS_DEAD,	 	 9,  LOG_NORMAL, 0,0,0	},
    { "notell",		do_notell,	POS_DEAD,	 	 9,  LOG_NORMAL, 0,0,0	},
    { "oclone",		do_oclone,	POS_DEAD,	 	 8,  LOG_ALWAYS, 0,0,0	},
    { "oload",		do_oload,	POS_DEAD,	 	 7,  LOG_ALWAYS, 0,0,0	},
    { "oset",		do_oset,	POS_DEAD,	 	 7,
LOG_ALWAYS, 0,0,0	},
    { "otransfer",	do_otransfer,POS_DEAD,	 	 8,  LOG_ALWAYS, 0,0,0	},
    { "pload",		do_pload,	POS_DEAD,		 12,  LOG_ALWAYS, 0,0,0	},
    { "preturn",		do_preturn,	POS_DEAD,	 	 2,  LOG_NORMAL, 0,0,0	},
    { "pset",		do_pset,	POS_DEAD,		 10,  LOG_ALWAYS, 0,0,0	},
    { "purge",		do_purge,	POS_DEAD,	 	 7,  LOG_NORMAL, 0,0,0	},
    { "qmake",		do_qmake,	POS_DEAD,	 	 8,  LOG_ALWAYS, 0,0,0	},
    { "release",		do_release,	POS_DEAD,	 	 9,  LOG_ALWAYS, 0,0,0	},
    { "restore",		do_restore,	POS_DEAD,	 	 8,  LOG_ALWAYS, 0,0,0	},
    { "rset",		do_rset,	POS_DEAD,		 7,  LOG_ALWAYS, 0,0,0	},
    { "silence",		do_silence,	POS_DEAD,	 	 9,  LOG_NORMAL, 0,0,0 },
    { "sla",		do_sla,	POS_DEAD,		 10,  LOG_NORMAL, 0,0,0	},
    { "slay",		do_slay,	POS_DEAD,		 10,  LOG_ALWAYS, 0,0,0	},
    { "special",		do_special,	POS_DEAD,		 10,  LOG_ALWAYS, 0,0,0	},
    { "decapitate",	do_decapitate,POS_STANDING,	 3,  LOG_ALWAYS, 0,0,0	},
    { "sset",		do_sset,	POS_DEAD,		 10,  LOG_ALWAYS, 0,0,0 },
    { "tear",		do_tear,	POS_STANDING,	 3,  LOG_ALWAYS, 0,0,0	},
    { "transfer",		do_transfer,POS_DEAD,	 	 7,  LOG_ALWAYS, 0,0,0	},

    { "transport",	do_transport,POS_DEAD,	 	 0,  LOG_NORMAL, 0,0,0	},
    { "astat",		do_astat,	POS_DEAD,	 	 10,
LOG_NORMAL, 0,0,0 },
    { "alock",		do_alock,	POS_DEAD,	 	 10, LOG_NORMAL, 0,0,0 },
    { "aclear",		do_aclear,	POS_DEAD,	 	 10, LOG_NORMAL, 0,0,0 },
    { "abusy",		do_abusy,	POS_DEAD,	 	 10, LOG_NORMAL, 0,0,0 },
    { "at",			do_at,	POS_DEAD,	 	 8,  LOG_NORMAL, 0,0,0	},
    { "bamfin",		do_bamfin,	POS_DEAD,	 	 7,  LOG_NORMAL, 0,0,0	},
    { "bamfout",		do_bamfout,	POS_DEAD,	 	 7,  LOG_NORMAL, 0,0,0	},
    { "echo",		do_echo,	POS_DEAD,	 	 8,  LOG_ALWAYS, 0,0,0	},
    { "goto",		do_goto,	POS_DEAD,	 	 7,  LOG_NORMAL, 0,0,0	},
    { "holylight",	do_holylight,POS_DEAD,	 	 7,  LOG_NORMAL, 0,0,0	},
    { "incog",          do_incog,   POS_DEAD,          7,  LOG_NORMAL, 0,0,0 },
    { "invis",		do_invis,	POS_DEAD,	 	 7,  LOG_NORMAL, 0,0,0	},
    { "log",		do_log,	POS_DEAD,	 	 9,  LOG_ALWAYS, 0,0,0	},
    { "memory",		do_memory,	POS_DEAD,	 	 7,  LOG_NORMAL, 0,0,0	},
    { "mfind",		do_mfind,	POS_DEAD,	 	 7,  LOG_NORMAL, 0,0,0 },
    { "mstat",		do_mstat,	POS_DEAD,	 	 7,  LOG_NORMAL, 0,0,0	},
    { "mwhere",		do_mwhere,	POS_DEAD,	 	 8,  LOG_NORMAL, 0,0,0 },
    { "ofind",		do_ofind,	POS_DEAD,	 	 7,  LOG_NORMAL, 0,0,0 },
    { "ostat",		do_ostat,	POS_DEAD,	 	 7,  LOG_NORMAL, 0,0,0	},
    { "oswitch",		do_oswitch,	POS_DEAD,	 	 8,  LOG_NORMAL, 0,0,0	},
    { "oreturn",		do_oreturn,	POS_DEAD,	 	 8,  LOG_NORMAL, 0,0,0	},
    { "peace",		do_peace,	POS_DEAD,		 8,  LOG_NORMAL, 0,0,0	},
    { "recho",		do_recho,	POS_DEAD,	 	 8,  LOG_ALWAYS, 0,0,0	},
    { "immreturn",	do_return,	POS_DEAD,	 	 8, LOG_NORMAL, 0,0,0	},
    { "rstat",		do_rstat,	POS_DEAD,	 	 7,  LOG_NORMAL, 0,0,0	},
    { "slookup",		do_slookup,	POS_DEAD,	 	 7,  LOG_NORMAL, 0,0,0 },
    { "snoop",		do_snoop,	POS_DEAD,	 	 8,  LOG_NORMAL, 0,0,0	},
    { "switch",		do_switch,	POS_DEAD,	 	 8,  LOG_ALWAYS, 0,0,0	},
    { "hightalk",		do_hightalk,POS_DEAD,	 	 1,  LOG_NORMAL, 0,0,0 },
    { "magetalk",		do_magetalk,POS_DEAD,	 	 2,  LOG_NORMAL, 0,0,0	},
    { "vtalk",		do_vamptalk,POS_DEAD,	 	 1,  LOG_NORMAL, 0,0,0	},
    { ">",			do_vamptalk,POS_DEAD,	 	 1,  LOG_NORMAL, 0,0,0	},
    { "vampire",		do_vampire,	POS_STANDING,	 0,  LOG_NORMAL, 0,0,0	},
    { "immune",		do_immune,	POS_DEAD,	 	 0,  LOG_NORMAL, 0,0,0	},
    { "[",			do_fcommand,POS_SITTING,	 3,  LOG_NORMAL, 0,0,0	},
    { "immtalk",		do_immtalk,	POS_DEAD,	 	 7,  LOG_NORMAL, 0,0,0	},
    { ":",			do_immtalk,	POS_DEAD,	 	 7,  LOG_NORMAL, 0,0,0	},
    { "clannum", 	do_clannum,	POS_DEAD,	10, LOG_NORMAL, 0, 0, 0
},
    { "clanset",	do_clanset,	POS_DEAD,	11, LOG_NORMAL, 0, 0,
0},
    { "clanlist",	do_clanlist,	POS_RESTING,	2, LOG_NORMAL, 0, 0,0},
    { "clannable",	do_clannable,	POS_RESTING,	2, LOG_NORMAL, 0,
0, 0 },
    { "outcast",	do_outcast,	POS_RESTING,	2, LOG_NORMAL, 0,
0, 0 },
    { "induct",	do_induct,	POS_RESTING,	2,	LOG_NORMAL,
0,0,0},
    { "prince",	do_prince,	POS_RESTING, 2, LOG_NORMAL, 0,0,0},
    { "kingdom", do_kingdom,	POS_RESTING, 2, LOG_NORMAL, 0,0,0},
    { "ktalk", do_ktalk,	POS_RESTING, 2, LOG_NORMAL, 0,0 ,0},
    { "krecall", do_krecall,   POS_FIGHTING, 2, LOG_NORMAL, 0,0,0},

    /*
     * OLC 1.1b
     */
    { "aedit",          do_aedit,       POS_DEAD,    7,  LOG_NORMAL, 0, 0,
0 },
    { "redit",          do_redit,       POS_DEAD,    7,  LOG_NORMAL, 0, 0,
0 },
    { "oedit",          do_oedit,       POS_DEAD,    7,  LOG_NORMAL, 0, 0,
0
},
    { "asave",          do_asave,       POS_DEAD,    7,  LOG_NORMAL, 0, 0,
0 },
    { "alist",          do_alist,       POS_DEAD,    7,  LOG_NORMAL, 0, 0,
0 },
    { "resets",         do_resets,      POS_DEAD,    7,  LOG_NORMAL, 0, 0,
0 },

    { "wrestle",	do_wrestle,	POS_STANDING, 0, LOG_NORMAL, 0, 0, 0},
    { "wagree",		do_wagree,	POS_STANDING, 0, LOG_NORMAL, 0, 0, 0},
    { "wdecline",	do_wdecline,	POS_STANDING, 0, LOG_NORMAL, 0, 0, 0},

    /* Cyborgs- Zaphonite */
    { "implant",	do_implant,	POS_STANDING, 0, LOG_NORMAL, 0, 0, 0},
    { "assimilate",	do_assimilate,	POS_STANDING, 0, LOG_NORMAL, 0, 0, 0},
    { "collective",	do_collective,	POS_STANDING, 0, LOG_NORMAL, 0, 0, 0},
    { "stuntubes",	do_stuntubes,	POS_FIGHTING, 0, LOG_NORMAL, 0, 0, 0},
    { "cybercloak",	do_cybercloak,	POS_STANDING, 0, LOG_NORMAL, 0, 0, 0},
    { "infravision",	do_infravision,	POS_STANDING, 0, LOG_NORMAL, 0, 0, 0},
    { "linkregenerate",	do_linkregenerate, POS_SITTING,  0, LOG_NORMAL, 0, 0, 0},


    /*
     * End of list.
     */
    { "",		0,		POS_DEAD,	 0,  LOG_NORMAL, 0,0,0	}
};



/*
 * The social table.
 * Add new socials here.
 * Alphabetical order is not required.
 */
const	struct	social_type	social_table [] =
{
    {
	"accuse",
	"Accuse whom?",
	"$n is in an accusing mood.",
	"You look accusingly at $M.",
	"$n looks accusingly at $N.",
	"$n looks accusingly at you.",
	"You accuse yourself.",
	"$n seems to have a bad conscience."
    },

    {
	"ack",
	"You gasp and say 'ACK!' at your mistake.",
	"$n ACKS at $s big mistake.",
	"You ACK $M.",
	"$n ACKS $N.",
	"$n ACKS you.",
	"You ACK yourself.",
	"$n ACKS $mself.  Must be a bad day."
    },
	
    {
	"addict",
	"You stand and admit to all in the room, 'Hi, I'm $n, and I'm a mud addict.'",
	"$n stands and says, 'Hi, I'm $n, and I'm a mud addict.'",
	"You tell $M that you are addicted to $S love.",
	"$n tells $N that $e is addicted to $S love.",
	"$n tells you that $e is addicted to your love.",
	"You stand and admit to all in the room, 'Hi, I'm $n, and I'm a mud addict.'",
	"$n stands and says, 'Hi, I'm $n, and I'm a mud addict.'",
    },

    {
	"afk",
	"You announce that you are going away from keyboard.",
	"$n announces that $e is going away from keyboard.",
	"You announce that you are going away from keyboard.",
	"$n informs $N that $e is going away from keyboard.",
	"$n informs you that $e is going away from keyboard.",
	"You announce that you are going away from keyboard.",
	"$n announces that $e is going away from keyboard.",
    },

    {
	"imawhore",
	"You seem to be in an agreeable mood.",
	"$n seems to agree.",
	"You agree with $M.",
	"$n agrees with $N.",
	"$n agrees with you.",
	"Well I hope you would agree with yourself!",
	"$n agrees with $mself, of course."
    },

    {
	"airguitar",
	"You sizzle the air with your BITCHIN' guitar playing!",
	"$n air-guitars like Jimi Hendrix!",
	"You sizzle the air with your BITCHIN' guitar playing!",
	"$n air-guitars like Jimi Hendrix!",
	"$n air-guitars like Jimi Hendrix, just for you!",
	"You forget all else as you sizzle the air with your BITCHIN' guitar playing!",
	"$n forgets all else as $e air-guitars like Jimi Hendrix."
    },
    
    {
	"apologize",
	"You apologize for your behavior.",
	"$n apologizes for $s rude behavior.",
	"You apologize to $M.",
	"$n apologizes to $N.",
	"$n apologizes to you.",
	"You apologize to yourself.",
	"$n apologizes to $mself.  Hmmmm."
    },

    {
	"applaud",
	"Clap, clap, clap.",
	"$n gives a round of applause.",
	"You clap at $S actions.",
	"$n claps at $N's actions.",
	"$n gives you a round of applause.  You MUST'VE done something good!",
	"You applaud at yourself.  Boy, are we conceited!",
	"$n applauds at $mself.  Boy, are we conceited!"
    },

    {
	"banzai",
	"You scream 'BANZAI!!!!' and charge into the fray.",
	"$n screams 'BANZAI!!!!' and charges into the fray.",
	"You scream 'BANZAI!!!!' and drag $M into the fray with you.",
	"$n screams 'BANZAI!!!!' and drags $N into the fray with $m!",
	"$n screams 'BANZAI!!!!' and drags you into the fray with $m!",
	"You scream 'BANZAI!!!!' and brandish your weapon for battle.",
	"$n screams 'BANZAI!!!!' and brandishes $s weapon for battle.",
    },


    {
	"bark",
	"Woof!  Woof!",
	"$n barks like a dog.",
	"You bark at $M.",
	"$n barks at $N.",
	"$n barks at you.",
	"You bark at yourself.  Woof!  Woof!",
	"$n barks at $mself.  Woof!  Woof!"
    },

    {
	"bbl",
	"You announce that you will be back later.",
	"$n announces that $e'll be back later.",
	"You inform $M that you will be back later.",
	"$n informs $N that $e will be back later",
	"$n informs you that $e will be back later",
	"You mumble to yourself that you'll be back later.",
	"$n mumbles to $mself that $e'll be back later."
    },

    {
	"bearhug",
	"You hug a grizzly bear.",
	"$n hugs a flea-infested grizzly bear.",
	"You bearhug $M.",
	"$n bearhugs $N.  Some ribs break.",
	"$n bearhugs you.  Wonder what's coming next?",
	"You bearhug yourself.",
	"$n bearhugs $mself."
    },

    {
        "beef",
        "You loudly exclaim 'WHERE'S THE BEEF??????'",
        "$n loudly exclaims 'WHERE'S THE BEEF??????'",
        "You poke $N and exclaim, 'WHERE'S THE BEEF?????'",
        "$n pokes $N, and exclaims, 'WHERE'S THE BEEF????'",
        "$n pokes you and exclaims, 'WHERE'S THE BEEF????'",
        "You poke your fat rolls and exclaim, 'Oh, THERE'S THE BEEF!'",
        "$n pokes $s fat rolls, and exclaims, 'Oh, THERE'S THE BEEF!'"
    },
   
    {
	"beer",
	"You down a cold, frosty beer.",
	"$n downs a cold, frosty beer.",
	"You draw a cold, frosty beer for $N.",
	"$n draws a cold, frosty beer for $N.",
	"$n draws a cold, frosty beer for you.",
	"You draw yourself a beer.",
	"$n draws $mself a beer."
    },

    {
	"beg",
	"You beg the for mercy.",
	"$n falls to the ground and begs for mercy.",
	"You desperately beg $M for mercy.",
	"$n begs you for mercy.",
	"$n begs $N for mercy!",
	"Begging yourself for mercy doesn't help.",
	"$n begs $mself for mercy."
    },

    {
	"whimper",
	"You whimper softly.",
	"$n whimpers pathetically.",
	"You look at $N and whimper sadly.",
	"$n looks at $N and whimpers sadly.",
	"$n looks at you and whimpers sadly.",
	"You whimper to yourself.",
	"$n whimpers to $mself."
    },

    {
	"behead",
	"You look around for some heads to cut off.",
	"$n looks around for some heads to cut off.",
	"You grin evilly at $N and brandish your weapon.",
	"$n grins evilly at $N, while branding $s weapon!",
	"$n grins evilly at you, brandishing $s weapon.",
	"I really don't think you want to do that...",
	"$n is so desperate for exp that $e tries to decapitate $mself!"
    },

    {
	"bkiss",
	"Blow a kiss to whom?",
	"$n blows at $s hand.",
	"You blow a kiss to $M.",
	"$n blows a kiss to $N.  Touching, ain't it?",
	"$n blows a kiss to you.  Not as good as a real one, huh?",
	"You blow a kiss to yourself.",
	"$n blows a kiss to $mself.  Wierd."
    },
  
    {
	"bleed",
	"You bleed all over the room!",
	"$n bleeds all over the room!  Get out of $s way!",
	"You bleed all over $M!",
	"$n bleeds all over $N.  Better leave, you may be next!",
	"$n bleeds all over you!  YUCK!",
	"You bleed all over yourself!",
	"$n bleeds all over $mself."
    },

    {
	"blink",
	"You blink in utter disbelief.",
	"$n blinks in utter disbelief.",
	"You blink at $M in confusion.",
	"$n blinks at $N in confusion.",
	"$n blinks at you in confusion.",
	"You are sooooooooooooo confused",
	"$n blinks at $mself in complete confusion."
    },

	/* This social is for Stephen of ACK mud :) */
    {
	"blownose",
	"You blow your nose loudly.",
	"$n blows $s nose loudly.",
	"You blow your nose on $S shirt.",
	"$n blows $s nose on $N's shirt.",
	"$n blows $s nose on your shirt.",
	"You blow your nose on your shirt.",
	"$n blows $s nose on $s shirt."
    },

    {
	"blush",
	"Your cheeks are burning.",
	"$n blushes.",
	"You get all flustered up seeing $M.",
	"$n blushes as $e sees $N here.",
	"$n blushes as $e sees you here.  Such an effect on people!",
	"You blush at your own folly.",
	"$n blushes as $e notices $s boo-boo."
    },

    {
	"boggle",
	"You boggle at all the loonies around you.",
	"$n boggles at all the loonies around $m.",
	"You boggle at $S ludicrous idea.",
	"$n boggles at $N's ludicrous idea.",
	"$n boggles at your ludicrous idea.",
	"BOGGLE.",
	"$n wonders what BOGGLE means."
    },

    {
	"bonk",
	"BONK.",
	"$n spells 'potato' like Dan Quayle: 'B-O-N-K'.",
	"You bonk $M for being a numbskull.",
	"$n bonks $N.  What a numbskull.",
	"$n bonks you.  BONK BONK BONK!",
	"You bonk yourself.",
	"$n bonks $mself."
    },

    {
	"boogie",
	"You boogie down!",
	"$n gets down and boogies!!",
	"You grab $M and boogie down!",
	"$n grabs $N and they boogie down!",
	"$n grabs you and boogies with you!",
	"You boogie with yourself.  What a great dancer you are!",
	"$n boogies with $mself.  Guess no one will dance with $m."
    },
    
    {
	"bottle",
	"You open up a cold bottle of brew.",
	"$n opens a cold bottle of brew.",
	"You open up a cold bottle of brew for $M.",
	"$n opens a cold bottle of brew for $N.",
	"$n opens a cold bottle of brew for you.",
	"You open a cold bottle of brew for yourself.",
	"$n opens a cold bottle of brew for $mself." 
    },
 
    {
	"bounce",
	"BOIINNNNNNGG!",
	"$n bounces around.",
	"You bounce onto $S lap.",
	"$n bounces onto $N's lap.",
	"$n bounces onto your lap.",
	"You bounce your head like a basketball.",
	"$n plays basketball with $s head."
    },

    {
	"bow",
	"You bow deeply.",
	"$n bows deeply.",
	"You bow before $M.",
	"$n bows before $N.",
	"$n bows before you.",
	"You kiss your toes.",
	"$n folds up like a jack knife and kisses $s own toes."
    },

    {
	"brb",
	"You announce that you will be right back.",
	"$n says in a stern voice, 'I'll be back!'",
	"You announce to $M that you will be right back.",
	"$n says to $N in a stern voice, 'I'll be back!'",
	"$n says to you in a stern voice, 'I'll be right back!'",
	"You mumble to yourself, 'I'll be right back'",
	"$n mumbles to $mself, 'I'll be right back, won't I?'"
    },

    {
	"brush",
	"Brush what? Who? Where?",
	NULL,
	"You brush out $S hair for $M.  Very thoughtful.",
	"$n brushes $N's hair for $M.  Looks better now.",
	"$n brushes out your hair.  How nice of $m.",
	"You brush out your hair.  There - much better.",
	"$n brushes out $s hair.  Looks much better now."
    },

    {
	"bully",
	"You growl and demand everyone's lunch money NOW!",
	"$n growls and demands everyone's lunch money.",  
	"You growl and demand $S lunch money NOW!",
	"$n growls and demands $N's lunch money.",
	"$n growls and demands your lunch money.",
	"You bully yourself, and take your own lunch money.",
	"$n bullies $mself, and takes $s lunch money away from $mself???"
    },
 
    {  
	"bungy",
	"You tie a bungy cord to the mud and jump into internet.",
	"$n ties a bungy cord to the mud and jumps into internet.",
	"You tie a bungy cord to $N and throw $M off the mud.",
	"$n ties a bungy cord to $N and throws $M off the mud.",
	"$n ties a bungy cord to you and throws you off the mud.",
	"You tie a bungy cord to yourself and jump off the mud.",
	"$n ties a bungy cord to $mself and jumps off the mud."
    },

    {
	"burp",
	"You burp loudly.",
	"$n burps loudly.",
	"You burp loudly to $M in response.",
	"$n burps loudly in response to $N's remark.",
	"$n burps loudly in response to your remark.",
	"You burp at yourself.",
	"$n burps at $mself.  What a sick sight."
    },

    {
	"bye",
	"You say goodbye to all in the room.",
	"$n says goodbye to everyone in the room.",
	"You say goodbye to $N.",
	"$n says goodbye to $N.",
	"$n says goodbye to you.",
	"You say goodbye to yourself.  Contemplating suicide?",
	"$n says goodbye to $mself.  Is $e contemplating suicide?"
    },

    {
	"byron",
	"You recite romantic poems to yourself.",
	"$n mutters romantic poems to himself, must be practicing for someone.",
	"You recite a romantic poem to $N.",
	"$n recites a beautiful romantic poem for $N.",
	"$n recites a heartstoppingly beautiful romantic poem for you.",
	"You read yourself romantic poems.  Falling in love with yourself?",
	"$n reads $mself a romantic poem.  Perhaps he loves $mself?",
    },

    {
	"cackle",
	"You throw back your head and cackle with insane glee!",
	"$n throws back $s head and cackles with insane glee!",
	"You cackle gleefully at $N",
	"$n cackles gleefully at $N.",
	"$n cackles gleefully at you.  Better keep your distance from $m.",
	"You cackle at yourself.  Now, THAT'S strange!",
	"$n is really crazy now!  $e cackles at $mself."
    },

    {
	"cannonball",
	"You cannonball into the pool.   *SPLOOSH*",
	"$n cannonballs into the pool.   *SPLOOSH*",
	"You cannonball into the pool and splash water over $N.",
	"$n cannonballs into the pool and splashes $N.",
	"$n cannonballs into the pool and sends water over you.  You are WET!",
	"You bounce cannonballs off your head to show your strength.",
	"$n bounces cannonballs off $s head.  Can you say 'nutcase'?"
    },

    {
	"catnap",
	"You curl into a tiny ball and go to sleep.",
	"$n curls $mself into a tiny ball and goes to sleep.",
	"You curl up in $S lap and go to sleep.",
	"$n curls up in $N's lap and goes to sleep.",
	"$n curls up in your lap and goes to sleep.",
	"You curl into a tiny ball and go to sleep.",
	"$n curls $mself into a tiny ball and goes to sleep."
    },

    {
	"cheer",
	"ZIS BOOM BAH!  BUGS BUNNY BUGS BUNNY RAH RAH RAH!",
	"$n cheers 'BUGS BUNNY BUGS BUNNY RAH RAH RAH!'",
	"You cheer loudly: 'Go $N Go!'",
	"$n cheers loudly: 'Go $N Go!'",
	"$n cheers you on!",
	"You cheer yourself up.",
	"$n cheers $mself on."
    },

    {
	"chekov",
	"You speak your best Russian in hopes of finding a nuclear wessel.",
	"$n asks sheepishly, 'Ver are the nuclear wessels?'",
	"You ask $M about the nuclear wessels.",
	"$n asks $N sheepishly, 'Ver are the nuclear wessels?'",
	"$n asks you sheepishly, 'Ver are the nuclear wessels?'",
	"You look around, muttering, 'Ver are the nuclear wessels?'",
	"$n looks around, muttering, 'Ver are the nuclear wessels?'"
    },
    
    {
	"chortle",
	"You chortle with glee.",
	"$n chortles with glee.",
	"You chortle loudly at $M.",
	"$n chortles loudly at $N.",
	"$n chortles loudly at you.",
	"You chortle loudly to yourself.",
	"$n chortles loudly to $mself."
    },

    {
	"chuckle",
	"You chuckle politely.",
	"$n chuckles politely.",
	"You chuckle at $S joke.",
	"$n chuckles at $N's joke.",
	"$n chuckles at your joke.",
	"You chuckle at your own joke, since no one else would.",
	"$n chuckles at $s own joke, since none of you would."
    },

    {
	"clap",
	"You clap your hands together.",
	"$n shows $s approval by clapping $s hands together.",
	"You clap at $S performance.",
	"$n claps at $N's performance.",
	"$n claps at your performance.",
	"You clap at your own performance.",
	"$n claps at $s own performance."
    },

    { 
        "clue",
        "You mumble 'DUM-DUM-DUM-DUM ... ah, a clue!'",
        "$n mumbles 'DUM-DUM-DUM-DUM ... ah, a clue!'",
        "You mumble 'DUM-DUM-DUM-DUM ... ah, a clue!'",
        "$n mumbles 'DUM-DUM-DUM-DUM ... ah, a clue!'",
        "$n mumbles 'DUM-DUM-DUM-DUM ... $N, aha, a clue!'",
        "You mumble to yourself, 'DUM-DUM-DUM-DUM ... ah, a clue!'",
        "$n mumbles to $mself, 'DUM-DUM-DUM-DUM ... ah, a clue!'"
    },
   
    {
	"clueless",
	"You chastise everyone in the room for being clueless.",
	"$n chastises everyone for being clueless.",
	"You chastise $M for being clueless.",
	"$n chastises $N for being clueless.",
	"$n chastises you for being clueless.",
	"You chastise yourself for being clueless.  What a dweeb you are!",
	"$n chastises $mself for being clueless.  What a dweeb!"
    },

    {
	"comb",
	"You comb your hair - perfect.",
	"$n combs $s hair, how dashing!",
	"You patiently untangle $N's hair - what a mess!",
	"$n tries patiently to untangle $N's hair.",
	"$n pulls your hair in an attempt to comb it.",
	"You pull your hair, but it will not be combed.",
	"$n tries to comb $s tangled hair."
    },

    {
	"comfort",
	"Do you feel uncomfortable?",
	NULL,
	"You comfort $M.",
	"$n comforts $N.",
	"$n comforts you.",
	"You make a vain attempt to comfort yourself.",
	"$n has no one to comfort $m but $mself."
    },

    {
	"cough",
	"You cough to clear your throat and eyes and nose and....",
	"$n coughs loudly.",
	"You cough loudly.  It must be $S fault, $E gave you this cold.",
	"$n coughs loudly, and glares at $N, like it is $S fault.",
	"$n coughs loudly, and glares at you.  Did you give $m that cold?",
	"You cough loudly.  Why don't you take better care of yourself?",
	"$n coughs loudly.  $n should take better care of $mself." 
    },

    { 
	"cower",
	"What are you afraid of?",
	"$n cowers in the corner from claustrophobia.",
	"You cower in the corner at the sight of $M.",
	"$n cowers in the corner at the sight of $N.",
	"$n cowers in the corner at the sight of you.",
	"You cower in the corner at the thought of yourself.  You scaredy cat!",
	"$n cowers in the corner.  What is wrong with $m now?"  
    },
    
    {
	"cringe",
	"You cringe in terror.",
	"$n cringes in terror!",
	"You cringe away from $M.",
	"$n cringes away from $N in mortal terror.",
	"$n cringes away from you.",
	"I beg your pardon?",
	NULL
    },

    {
	"crush",
	"You squint and hold two fingers up, saying 'I'm crushing your heads!'",
	"$n squints and holds two fingers up, saying 'I'm crushing your heads!'",
	"You hold two fingers up at $M and say, 'I'm crushing your head!'",
	"$n holds two fingers up at $N and says, 'I'm crushing your head!'",
	"$n holds two fingers up at you and says, 'I'm crushing your head!'",
	"You crush yourself.  YEEEEOOOUUUUCH!",
	"$n crushes $mself into the ground.  OUCH!"
    },

    {
	"cry",
	"Waaaaah ...",
	"$n bursts into tears.",
	"You cry on $S shoulder.",
	"$n cries on $N's shoulder.",
	"$n cries on your shoulder.",
	"You cry to yourself.",
	"$n sobs quietly to $mself."
    },

    {
	"cuddle",
	"Whom do you feel like cuddling today?",
	NULL,
	"You cuddle $M.",
	"$n cuddles $N.",
	"$n cuddles you.",
	"You must feel very cuddly indeed ... :)",
	"$n cuddles up to $s shadow.  What a sorry sight."
    },

    {
	"curse",
	"You swear loudly for a long time.",
	"$n swears: @*&^%@*&!",
	"You swear at $M.",
	"$n swears at $N.",
	"$n swears at you!  Where are $s manners?",
	"You swear at your own mistakes.",
	"$n starts swearing at $mself.  Why don't you help?"
    },

    {
	"curtsey",
	"You curtsey to your audience.",
	"$n curtseys gracefully.",
	"You curtsey to $M.",
	"$n curtseys gracefully to $N.",
	"$n curtseys gracefully for you.",
	"You curtsey to your audience (yourself).",
	"$n curtseys to $mself, since no one is paying attention to $m."
    },

    {
	"dance",
	"Feels silly, doesn't it?",
	"$n tries to break dance, but nearly breaks $s neck!",
	"You sweep $M into a romantic waltz.",
	"$n sweeps $N into a romantic waltz.",
	"$n sweeps you into a romantic waltz.",
	"You skip and dance around by yourself.",
	"$n dances a pas-de-une."
    },

    {
	"dive",
	"You dive into the ocean.",
	"$n dives into the ocean.",
	"You dive behind $M and hide.",
	"$n dives behind $N and hides.",
	"$n dives behind you and hides.",
	"You take a dive.",
	"$n takes a dive."
    },
    
    {
        "dizzy",
        "You are so dizzy from all this chatter.",
        "$n spins twice and hits the ground, dizzy from all this chatter.",
        "You are dizzy from all of $N's chatter.",
        "$n spins twice and hits the ground, dizzy from all $N's chatter.",
        "$n spins twice and hits the ground, dizzy from all your chatter.",
        "You are dizzy from lack of air.  Don't talk so much!",
        "$n spins twice and falls to the ground from lack of air."
    },

    {
	"doc",
	"You nibble on a carrot and say 'Eh, what's up Doc?'",
	"$n nibbles on a carrot and says 'Eh, what's up Doc?'",
	"You nibble on a carrot and say to $M, 'Eh, what's up Doc?'",
	"$n nibbles on a carrot and says to $N, 'Eh, what's up Doc?'",
	"$n nibbles on a carrot and says to you, 'Eh, what's up Doc?'",
	"You nibble on a carrot and say to yourself, 'Eh, what's up $n?'",
	"$n nibbles on a carrot and says 'Eh, what's up Doc?'" 
    },
    
    {
	"doh",
	"You say, 'Doh!!' and hit your forehead.  What an idiot you are!",
	"$n hits $mself in the forehead and says, 'Doh!!!'",
	"You say, 'Doh!!' and hit your forehead.  What an idiot you are!",
	"$n hits $mself in the forehead and says, 'Doh!!!'",
	"$n hits $mself in the forehead and says, 'Doh!!!'",
	"You hit yourself in the forehead and say, 'Doh!!!'",
	"$n hits $mself in the forehead and says, 'Doh!!!'"    
    },
    
    /*
     * This one's for Baka, Penn, and Onethumb!
     */
    {
	"drool",
	"You drool on yourself.",
	"$n drools on $mself.",
	"You drool all over $N.",
	"$n drools all over $N.",
	"$n drools all over you.",
	"You drool on yourself.",
	"$n drools on $mself."
    },

    {
	"duck",
	"Whew!  That was close!",
	"$n is narrowly missed by a low-flying dragon.",
	"You duck behind $M.  Whew!  That was close!",
	"$n ducks behind $N to avoid the fray.",
	"$n ducks behind you to avoid the fray.",
	"You duck behind yourself.  Oww that hurts!",
	"$n tries to duck behind $mself.  $n needs help getting untied now."
    },

    {   
	"sembrace",
	"Who do you want to hold?",
	"$n looks around for someone to hold close to $m.",
	"You hold $M in a warm and loving embrace.",
	"$n holds $N in a warm and loving embrace.",
	"$n holds you in a warm and loving embrace.",
	"You hold yourself in a warm and loving embrace.  Feels silly doesn't it?",
	"$n holds $mself in a warm and loving embrace.  $e looks pretty silly."
    },

    {
	"eskimo",
	"Who do you want to eskimo kiss with?",
	"$n is looking for someone to rub noses with.  Any volunteers?",
	"You rub noses with $M.",
	"$n rubs noses with $N.  You didn't know they were eskimos!",
	"$n rubs noses with you.",
	"You ponder the difficulties involved in rubbing noses with yourself.",
	"$n ponders the difficulties involved in rubbing noses with $mself."
    },
    
    {
	"evilgrin",
	"You grin so evilly that everyones alignment drops to -1000.",
	"$n grins evilly that everyones alignment drops to -1000.",
	"You grin so evilly at $M that $S alignment drops to -1000.",
	"$n grins so evilly at $N that $S alignment drops to -1000.",
	"$n grins so evilly at you that your alignment drops to -1000.",
	"You grin so evilly at yourself that your alignment drops to -1000.",
	"$n grins so evilly that $s alignment drops to -1000."
    },

    {
	"eyebrow",
	"You raise an eyebrow.",
	"$n raises an eyebrow.",
	"You raise an eyebrow at $M.",
	"$n raises an eyebrow at $N.",
	"$n raises an eyebrow at you.",
	"You raise an eyebrow at yourself.  That hurt!",
	"$n raises an eyebrow at $mself.  That must have hurt!"
    },

    {
	"faint",
	"You feel dizzy and hit the ground like a board.",
	"$n's eyes roll back in $s head and $e crumples to the ground.",
	"You faint into $S arms.",
	"$n faints into $N's arms.",
	"$n faints into your arms.  How romantic.",
	"You look down at your condition and faint.",
	"$n looks down at $s condition and faints dead away."
    },
   
    {  
	"fakerep",
	"You report: 12874/13103 hp 9238/10230 mana 2483/3451 mv 2.31E13 xp.",
	"$n reports: 12874/13103 hp 9238/10230 mana 2483/3451 mv 2.31E13 xp.",
	"You report: 12874/13103 hp 9238/10230 mana 2483/3451 mv 2.31E13 xp.",
	"$n reports: 12874/13103 hp 9238/10230 mana 2483/3451 mv 2.31E13 xp.",
	"$n reports: 12874/13103 hp 9238/10230 mana 2483/3451 mv 2.31E13 xp.",
	"You report: 12874/13103 hp 9238/10230 mana 2483/3451 mv 2.31E13 xp.",
	"$n reports: 12874/13103 hp 9238/10230 mana 2483/3451 mv 2.31E13 xp."
    },

    {
	"fart",
	"Where are your manners?",
	"$n lets off a real rip-roarer ... a greenish cloud envelops $n!",
	"You fart at $M.  Boy, you are sick.",
	"$n farts in $N's direction.  Better flee before $e turns to you!",
	"$n farts in your direction.  You gasp for air.",
	"You fart at yourself.  You deserve it.",
	"$n farts at $mself.  Better $m than you."
    },

    {
	"flash",
	"You flash your naked body at the gawking crowd.",
	"$n flashes $s naked body at everyone.  Gasp!",
	"You flash your naked body at $M.",
	"$n flashes $s naked body at $N.  Aren't you jealous?",
	"$n flashes $s naked body at you.  Everyone else is jealous.",
	"You flash your naked body at yourself.  How strange.",
	"$n is looking down $s shirt and grinning.  Very wierd!"
    },

    {
	"flip",
	"You flip head over heels.",
	"$n flips head over heels.",
	"You flip $M over your shoulder.",
	"$n flips $N over $s shoulder.",
	"$n flips you over $s shoulder.  Hmmmm.",
	"You tumble all over the room.",
	"$n does some nice tumbling and gymnastics."
    },

    {
	"flirt",
	"Wink wink!",
	"$n flirts -- probably needs a date, huh?",
	"You flirt with $M.",
	"$n flirts with $N.",
	"$n wants you to show some interest and is flirting with you.",
	"You flirt with yourself.",
	"$n flirts with $mself.  Hoo boy."
    },
    
    {
	"flutter",
	"You flutter your eyelashes.",
	"$n flutters $s eyelashes.",
	"You flutter your eyelashes at $M.",
	"$n flutters $s eyelashes in $N's direction.",
	"$n looks at you and flutters $s eyelashes.",
	"You flutter your eyelashes at the thought of yourself.",
	"$n flutters $s eyelashes at no one in particular." 
    },

    {
	"fondle",
	"Who needs to be fondled?",
	NULL,
	"You fondly fondle $M.",
	"$n fondly fondles $N.",
	"$n fondly fondles you.",
	"You fondly fondle yourself, feels funny doesn't it?",
	"$n fondly fondles $mself - this is going too far!!"
    },

    {
	"french",
	"Kiss whom?",
	NULL,
	"You give $N a long and passionate kiss.",
	"$n kisses $N passionately.",
	"$n gives you a long and passionate kiss.",
	"You gather yourself in your arms and try to kiss yourself.",
	"$n makes an attempt at kissing $mself."
    },

    {
	"frown",
	"What's bothering you ?",
	"$n frowns.",
	"You frown at what $E did.",
	"$n frowns at what $E did.",
	"$n frowns at what you did.",
	"You frown at yourself.  Poor baby.",
	"$n frowns at $mself.  Poor baby."
    },

    {
	"fume",
	"You grit your teeth and fume with rage.",
	"$n grits $s teeth and fumes with rage.",
	"You stare at $M, fuming.",
	"$n stares at $N, fuming with rage.",
	"$n stares at you, fuming with rage!",
	"That's right - hate yourself!",
	"$n clenches $s fists and stomps his feet, fuming with anger."
    },

    {
        "garth",
        "You will give your weapons away....NOT.",
	"$n yells 'WAYNE'S WORLD WAYNE'S WORLD -- PARTY TIME!  EXCELLENT!'",
	"You yell 'WAYNE'S WORLD WAYNE'S WORLD -- PARTY TIME!  EXCELLENT!'",
	"$n yells 'WAYNE'S WORLD WAYNE'S WORLD -- PARTY TIME!  EXCELLENT!'",
	"$n yells 'WAYNE'S WORLD WAYNE'S WORLD -- PARTY TIME!  EXCELLENT!'",
	"You yell 'WAYNE'S WORLD WAYNE'S WORLD -- PARTY TIME!  EXCELLENT!'",
	"$n yells 'WAYNE'S WORLD WAYNE'S WORLD -- PARTY TIME!  EXCELLENT!'"
    },
    
    {
	"gasp",
	"You gasp in astonishment.",
	"$n gasps in astonishment.",
	"You gasp as you realize what $E did.",
	"$n gasps as $e realizes what $N did.",
	"$n gasps as $e realizes what you did.",
	"You look at yourself and gasp!",
	"$n takes one look at $mself and gasps in astonisment!"
    },

    {
	"gawk",
	"You gawk at evryone around you.",
	"$n gawks at everyone in the room.",
	"You gawk at $M.",
	"$n gawks at $N.",
	"$n gawks at you.",
	"You gawk as you think what you must look like to others.",
	"$n is gawking again.  What is on $s mind?" 
    },
 
    {
	"german",
	"You speak your best German in hopes of getting a beer.",
	"$n says 'Du bist das hundchen!'  What the hell?",
	"You speak your best German to $M in hopes of getting a beer.",
	"$n says to $N, 'Du bist das hundchen!'  What the hell?",
	"$n says to you, 'Du bist das hundchen!'  What the hell?",
	"You speak your best German in hopes of getting a beer.",
	"$n says 'Du bist das hundchen!'  What the hell?"
    },
    
    {
	"ghug",
	"GROUP HUG!  GROUP HUG!",
	"$n hugs you all in a big group hug.  How sweet!",
	"GROUP HUG!  GROUP HUG!",
	"$n hugs you all in a big group hug.  How sweet!",
	"$n hugs you all in a big group hug.  How sweet!",
	"GROUP HUG!  GROUP HUG!",
	"$n hugs you all in a big group hug.  How sweet!"
    },
    
    {
	"giggle",
	"You giggle.",
	"$n giggles.",
	"You giggle in $S's presence.",
	"$n giggles at $N's actions.",
	"$n giggles at you.  Hope it's not contagious!",
	"You giggle at yourself.  You must be nervous or something.",
	"$n giggles at $mself.  $e must be nervous or something."
    },

    {
	"glare",
	"You glare at nothing in particular.",
	"$n glares around $m.",
	"You glare icily at $M.",
	"$n glares at $N.",
	"$n glares icily at you, you feel cold to your bones.",
	"You glare icily at your feet, they are suddenly very cold.",
	"$n glares at $s feet, what is bothering $m?"
    },

    {
	"goose",
	"You honk like a goose.",
	"$n honks like a goose.",
	"You goose $S luscious bottom.",
	"$n gooses $N's soft behind.",
	"$n squeezes your tush.  Oh my!",
	"You goose yourself.",
	"$n gooses $mself.  Yuck."
    },

    {
	"grimace",
	"You contort your face in disgust.",
	"$n grimaces is disgust.",
	"You grimace in disgust at $M.",
	"$n grimaces in disgust at $N.",
	"$n grimaces in disgust at you.",
	"You grimace at yourself in disgust.",
	"$n grimaces at $mself in disgust."
    },

    {
	"grin",
	"You grin evilly.",
	"$n grins evilly.",
	"You grin evilly at $M.",
	"$n grins evilly at $N.",
	"$n grins evilly at you.  Hmmm.  Better keep your distance.",
	"You grin at yourself.  You must be getting very bad thoughts.",
	"$n grins at $mself.  You must wonder what's in $s mind."
    },

    {
	"groan",
	"You groan loudly.",
	"$n groans loudly.",
	"You groan at the sight of $M.",
	"$n groans at the sight of $N.",
	"$n groans at the sight of you.",
	"You groan as you realize what you have done.",
	"$n groans as $e realizes what $e has done."
    },

    {
	"grope",
	"Whom do you wish to grope?",
	NULL,
	"Well, what sort of noise do you expect here?",
	"$n gropes $N.",
	"$n gropes you.",
	"You grope yourself - YUCK.",
	"$n gropes $mself - YUCK."
    },

    {
	"grovel",
	"You grovel in the dirt.",
	"$n grovels in the dirt.",
	"You grovel before $M.",
	"$n grovels in the dirt before $N.",
	"$n grovels in the dirt before you.",
	"That seems a little silly to me.",
	NULL
    },

    {
	"growl",
	"Grrrrrrrrrr ...",
	"$n growls.",
	"Grrrrrrrrrr ... take that, $N!",
	"$n growls at $N.  Better leave the room before the fighting starts.",
	"$n growls at you.  Hey, two can play it that way!",
	"You growl at yourself.  Boy, do you feel bitter!",
	"$n growls at $mself.  This could get interesting..."
    },

    {
	"grumble",
	"You grumble.",
	"$n grumbles.",
	"You grumble to $M.",
	"$n grumbles to $N.",
	"$n grumbles to you.",
	"You grumble under your breath.",
	"$n grumbles under $s breath."
    },

    {
	"grunt",
	"GRNNNHTTTT.",
	"$n grunts like a pig.",
	"GRNNNHTTTT.",
	"$n grunts to $N.  What a pig!",
	"$n grunts to you.  What a pig!",
	"GRNNNHTTTT.",
	"$n grunts to nobody in particular.  What a pig!"
    },

    {
	"hand",
	"Kiss whose hand?",
	NULL,
	"You kiss $S hand.",
	"$n kisses $N's hand.  How continental!",
	"$n kisses your hand.  How continental!",
	"You kiss your own hand.",
	"$n kisses $s own hand."
    },

    {
	"hangover",
	"You pop a few aspirin and put on your sunglasses.  Ow, your head hurts!",
	"$n holds $s head and says 'Quit breathing so loud!'",
	"Won't $N be quiet?  Your head is gonna split in two if $E keeps talking!",
	"$n complains to $N 'Be quiet!  I have a hangover!",
	"$n complains to you 'Be quiet!  I have a hangover!",
	"You shoosh yourself.  Be quiet!  You have a hangover!",
	"$n shooshes $mself.  Wow, what a hangover that must be!"
    },

    {
	"happy",
	"You smile wide like Cindy Brady.",
	"$n is as happy as a maggot on a piece of rotten meat.",
	"You smile wide at $M like Cindy Brady.",
	"$n is as happy as a maggot on a piece of rotten meat.",
	"$n is as happy as a maggot on a piece of rotten meat.",
	"You smile wide like Cindy Brady.",
	"$n is as happy as a maggot on a piece of rotten meat."
    },

    {
	"heal",
	"You start yelling for a heal!",
	"$n yells 'Hey, how about a heal? I'm DYING here!'",
	"You start yelling at $N for a heal!",
	"$n yells 'Hey $N, how about a heal? I'm DYING here!'",
	"$n yells 'Hey $N, how about a heal? I'm DYING here!'",
	"You start yelling for a heal!",
	"$n yells 'Hey, how about a heal? I'm DYING here!'"
    },

    {   
	"hello",
	"You say hello to everyone in the room.",
	"$n says hello to everyone in the room.",
	"You tell $M how truly glad you are to see $M.",
	"$n tells $N 'Hi!'",
	"$n tells you how truly glad $e is that you are here.",
	"You greet yourself enthusiastically.",
	"$n greets $mself enthusiastically.  How odd."
    },

    {
	"highfive",
	"You jump in the air...oops, better get someone else to join you.",
	"$n jumps in the air by $mself.  Is $e a cheerleader, or just daft?",
	"You jump in the air and give $M a big highfive!",
	"$n jumps in the air and gives $N a big highfive!",
	"$n jumps in the air and gives you a big highfive!",
	"You jump in the air and congratulate yourself!",
	"$n jumps in the air and gives $mself a big highfive!  Wonder what $e did?"
    },

    {
	"hmm",
	"You Hmmmm out loud.",
	"$n thinks, 'Hmmmm.'",
	"You gaze thoughtfully at $M and say 'Hmmm.'",
	"$n gazes thoughtfully at $N and says 'Hmmm.'",
	"$n gazes thoughtfully at you and says 'Hmmm.'",
	"You Hmmmm out loud.",
	"$n thinks, 'Hmmmm.'"
    },

    {
        "hologram",
        "You snap your fingers and create an illusion.",
        "$n leaves south.",
        "You snap your fingers and create an illusion.",
        "$n leaves south.",
        "$n waves at you and leaves south.",
        "You snap your fingers and create an illusion of yourself.",
        "Suddenly, there are 2 $n's standing here!"
    },
    
    {
	"hop",
	"You hop around like a little kid.",
	"$n hops around like a little kid.",
        "You hop into $N's lap.",
        "$n hops into $N's lap.",
        "$n hops into your lap.",
	NULL,
	NULL
    },

    {
	"hug",
	"Hug whom?",
	NULL,
	"You hug $M.",
	"$n hugs $N.",
	"$n hugs you.",
	"You hug yourself.",
	"$n hugs $mself in a vain attempt to get friendship."
    },

    {
	"hum",
	"Hmm Hmm Hmm Hmmmmmmm.",
	"$n hums like a bee with a chest cold.",
	"You hum a little ditty for $M.  Hmm Hmm Hmm Hmmmmmm.",
	"$n hums a little ditty for $N.  Hmm Hmm Hmm Hmmmmmm.",
	"$n hums a little ditty for you.  Hmm Hmm Hmm Hmmmmmm.",
	"Hmm Hmm Hmmmmmmm.",
	"$n hums like a bee with a chest cold."
    }, 

    {
	"invite",
	"You speak your best French in hopes of getting lucky.",
	"$n tells you, 'Voulez-vous couche avec moi ce soir?'",  
	"You speak your best French to $M in hopes of getting lucky.",
	"$n tells $N, 'Voulez-vous couche avec moi ce soir?'",
	"$n tells you, 'Voulez-vous couche avec moi ce soir?'",
	"You speak your best French in hopes of getting lucky, with yourself???",
	"$n says to $mself, 'Voulez-vous couche avec moi ce soir?'"
    },
  
    {
        "jsave",
        "You profess 'Jesus saves!  But Gretsky recovers...he scores!'",
        "$n announces 'Jesus saves!  But Gretsky recovers...he scores!'",
        "You profess 'Jesus saves!  But Gretsky recovers...he scores!'",
        "$n announces 'Jesus saves!  But Gretsky recovers...he scores!'",
        "$n announces to you 'Jesus saves!  But Gretsky recovers...he scores!'",
        "You profess 'Jesus saves!  But Gretsky recovers...he scores!'",
        "$n announces 'Jesus saves!  But Gretsky recovers...he scores!'"
    },

    {
	"kiss",
	"Isn't there someone you want to kiss?",
	NULL,
	"You kiss $M.",
	"$n kisses $N.",
	"$n kisses you.",
	"All the lonely people :(",
	NULL
    },

    {
	"laugh",
	"You laugh.",
	"$n laughs.",
	"You laugh at $N mercilessly.",
	"$n laughs at $N mercilessly.",
	"$n laughs at you mercilessly.  Hmmmmph.",
	"You laugh at yourself.  I would, too.",
	"$n laughs at $mself.  Let's all join in!!!"
    },

    {
	"lag",
	"You complain about the terrible lag.",
	"$n starts complaining about the terrible lag.",
	"You complain to $N about the terrible lag.",
	"$n complains to $N about the terrible lag.",
	"$n complains to you about the terrible lag.",
	"You start muttering about the awful lag.",
	"$n starts muttering about the awful lag."
    },

    {
	"lick",
	"You lick your lips and smile.",
	"$n licks $s lips and smiles.",
	"You lick $M.",
	"$n licks $N.",
	"$n licks you.",
	"You lick yourself.",
	"$n licks $mself - YUCK."
    },

    {
	"love",
	"You love the whole world.",
	"$n loves everybody in the world.",
	"You tell your true feelings to $N.",
	"$n whispers softly to $N.",
	"$n whispers to you sweet words of love.",
	"Well, we already know you love yourself (lucky someone does!)",
	"$n loves $mself, can you believe it ?"
    },

    {
	"lust",
	"You are getting lusty feelings!",
	"$n looks around lustily.",
	"You stare lustily at $N.",
	"$n stares lustily at $N.",
	"$n stares lustily at you.",
	"You stare lustily at...youself?",
	"$n looks $mself up and down lustily."
    },

    {
	"maim",
	"Who do you want to maim?",
	"$n is looking for someone to maim.",
	"You maim $M with your dull fingernails.",
	"$n raises $s hand and tries to maim $N to pieces.",
	"$n raises $s hand and paws at you.  You've been maimed!",
	"You maim yourself with your dull fingernails.",
	"$n raises $s hand and maims $mself to pieces."
    },

    {
	"marvelous",
	"You say 'Ah dahling, you look MAHVELLOUS!'",
	"$n says 'Ah dahling, you look MAHVELLOUS!'",
	"You say to $M, 'Ah dahling, you look MAHVELLOUS!'",
	"$n says to $N, 'Ah dahling, you look MAHVELLOUS!'",
	"$n says to you, 'Ah dahling, you look MAHVELLOUS!'",
	"You say 'Ah dahling, I look MAHVELLOUS!'",
	"$n says 'Ah dahling, I look MAHVELLOUS!'"
    },
    
    {
	"massage",
	"Massage what?  Thin air?",
	NULL,
	"You gently massage $N's shoulders.",
	"$n massages $N's shoulders.",
	"$n gently massages your shoulders.  Ahhhhhhhhhh ...",
	"You practice yoga as you try to massage yourself.",
	"$n gives a show on yoga positions, trying to massage $mself."
    },

    {
	"meow",
	"MEOW.",
	"$n meows.  What's $e going to do next, wash $mself with $s tongue?",
	"You meow at $M, hoping $E will give you some milk.",
	"$n meows at $N, hoping $E will give $m some milk. ",
	"$n meows at you.  Maybe $e wants some milk.",
	"You meow like a kitty cat.",
	"$n meows like a kitty cat."
    },

    {
	"mmm",
	"You go mmMMmmMMmmMMmm.",
	"$n says 'mmMMmmMMmmMMmm.'",
	"You go mmMMmmMMmmMMmm.",
	"$n says 'mmMMmmMMmmMMmm.'",
	"$n thinks of you and says, 'mmMMmmMMmmMMmm.'",
	"You think of yourself and go mmMMmmMMmmMMmm.",
	"$n thinks of $mself and says 'mmMMmmMMmmMMmm.'",
    },
    
    {
	"moan",
	"You start to moan.",
	"$n starts moaning.",
	"You moan for the loss of $m.",
	"$n moans for the loss of $N.",
	"$n moans at the sight of you.  Hmmmm.",
	"You moan at yourself.",
	"$n makes $mself moan."
    },

    {
        "mooch",
        "You beg for money, weapons, coins.",
        "$n says 'Spare change?'",
        "You beg $N for money, weapons, coins.",
        "$n begs you for favors of the insidious type...",
        "$n begs you for favors of the insidious type...",
        "You beg for money, weapons, coins.",
        "$n says 'Spare change?'"
    },
    
    {
	"moocow",
	"You make cow noises.  Mooooooooooooooooooo!",
	"$n Mooooooooooooooooooooooooos like a cow.",
	"You make cow noises at $M.  Mooooooooooooooooooo!",
	"$n Mooooooooooooooooooooooooos like a cow at $N.",
	"$n looks at you and Mooooooooooooooooooooooooos like a cow.",
	"You make cow noises.  Mooooooooooooooooooo!",
	"$n Mooooooooooooooooooooooooos like a cow."
    },
    
    {
	"smoon",
	"Gee your butt is big.",
	"$n moons the entire room.",
	"You show your big butt to $M.",
	"$n shows $s big butt to $N.  Find a paddle, quick!",
	"$n shows $s big ugly butt to you.  How do you like it?",
	"You moon yourself.",
	"$n moons $mself.  Ugliest butt you ever saw."
    },
    
    {
	"mosh",
	"You MOSH insanely about the room.",
	"$n MOSHES insanely about the room.",
	"You MOSH $M into a pile of Jello pudding.  Ewww!",
	"$n MOSHES $N into Jello pudding.  Ah, the blood!",
	"$n MOSHES you into the ground.",
	"You MOSH yourself.  Ah the blood!",
	"$n MOSHES and MOSHES and MOSHES and MOSHES..."
    },
    
    {
	"muhaha",
	"You laugh diabolically.  MUHAHAHAHAHAHA!.",
	"$n laughs diabolically.  MUHAHAHAHAHAHA!..",
	"You laugh at $M diabolically.  MUHAHAHAHAHAHA!..",
	"$n laughs at $N diabolically.  MUHAHAHAHAHAHA!..",
	"$n laughs at you diabolically.  MUHAHAHAHAHAHA!..",
	"Muhaha at yourself??  Wierd.",
	NULL
    },

    {
	"mwalk",
	"You grab your hat and moonwalk across the room.",
	"$n grabs $s black hat and sparkly glove and moonwalks across the room.",      
	"You grab your hat and moonwalk across the room.",
	"$n grabs $s black hat and sparkly glove and moonwalks across the room.", 
	"$n grabs $s black hat and sparkly glove and moonwalks across the room.", 
	"You grab your hat and moonwalk across the room.",
	"$n grabs $s black hat and sparkly glove and moonwalks across the room."
    },

    {
        "nail",
        "You nibble nervously on your nails.",
        "$n nibbles nervously on $s fingernails.",
        "You nibble nervously on your nails.",
        "$n nibbles nervously on $s fingernails.",
        "$n nibbles nervously on your fingernails.  Yuck!",
        "You nibble nervously on your nails.",
        "$n nibbles nervously on $s fingernails."
    },
    
    {
	"nasty",
	"You do the best imitation of the nasty you can.",
	"$n does the nasty solo? -- wow.",
	"You do the nasty with $M.",
	"$n does the nasty with $N.  Find a firehose quick!",
	"$n does the nasty with you.  How do you like it?",
	"You do the nasty with yourself.",
	"$n does the nasty with $mself.  Hoo boy."
    },
    
    {
	"newbie",
	"You inform everyone that you're a newbie.",
	"$n says 'Hi, I'm a newbie, please help!'",
	"You ask $N to help you because you're a newbie.",
	"$n asks $N to help $m, because $e's a newbie.",
	"$n asks you to help $m, because $e's a newbie.",
	NULL,
	NULL
    },

    {
	"nibble",
	"Nibble on whom?",
	NULL,
	"You nibble on $N's ear.",
	"$n nibbles on $N's ear.",
	"$n nibbles on your ear.",
	"You nibble on your OWN ear.",
	"$n nibbles on $s OWN ear."
    },

    {
	"nod",
	"You nod affirmative.",
	"$n nods affirmative.",
	"You nod in recognition to $M.",
	"$n nods in recognition to $N.",
	"$n nods in recognition to you.  You DO know $m, right?",
	"You nod at yourself.  Are you getting senile?",
	"$n nods at $mself.  $e must be getting senile."
    },

    {
	"nose",
	"You wiggle your nose.",
	"$n wiggles $s nose.",
	"You tweek $S nose.",
	"$n tweeks $N's nose.",
	"$n tweeks your nose.",
	"You tweek your own nose!",
	"$n tweeks $s own nose!"
    },

    {
	"nudge",
	"Nudge whom?",
	NULL,
	"You nudge $M.",
	"$n nudges $N.",
	"$n nudges you.",
	"You nudge yourself, for some strange reason.",
	"$n nudges $mself, to keep $mself awake."
    },

    {
	"nuke",
	"Who do you want to nuke?",
	"$n tries to put something in the microwave.",
	"You envelop $M in a mushroom cloud.",
	"$n detonates a nuclear warhead at $N.  Uh oh!",
	"$n envelops you in a mushroom cloud.",
	"You nuke yourself.",
	"$n puts $mself in the microwave."
    },

    {
	"nuzzle",
	"Nuzzle whom?",
	NULL,
	"You nuzzle $S neck softly.",
	"$n softly nuzzles $N's neck.",
	"$n softly nuzzles your neck.",
	"I'm sorry, friend, but that's impossible.",
	NULL
    },

    {
	"ogle",
	"Whom do you want to ogle?",
	NULL,
	"You ogle $M like $E was a piece of meat.",
	"$n ogles $N.  Maybe you should leave them alone for awhile?",
	"$n ogles you.  Guess what $e is thinking about?",
	"You ogle yourself.  You may just be too wierd for this mud.",
	"$n ogles $mself.  Better hope that $e stops there."
    },

    {
	"ohno",
	"Oh no!  You did it again!",
	"Oh no!  $n did it again!",
	"You exclaim to $M, 'Oh no!  I did it again!'",
	"$n exclaims to $N, 'Oh no!  I did it again!'",
	"$n exclaims to you, 'Oh no!  I did it again!'",
	"You exclaim to yourself, 'Oh no!  I did it again!'",
	"$n exclaims to $mself, 'Oh no!  I did it again!'"
    },
    
    {
	"oink",
	"You make pig noises.  OINK!",
	"$n oinks 'OINK OINK OINK!'",
	"You make pig noises at $M.  OINK!",
	"$n oinks at $N: 'OINK OINK OINK!'",
	"$n oinks at you: 'OINK OINK OINK!'",
	"You make pig noises.  OINK!",
	"$n oinks 'OINK OINK OINK!'"
    },
 
    {
        "ooo",
        "You go ooOOooOOooOOoo.",
        "$n says, 'ooOOooOOooOOoo.'",
        "You go ooOOooOOooOOoo.",
        "$n says, 'ooOOooOOooOOoo.'",
        "$n thinks of you and says, 'ooOOooOOooOOoo.'",
        "You go ooOOooOOooOOoo.",
        "$n says, 'ooOOooOOooOOoo.'"
    },

    {
	"pat",
	"Pat whom?",
	NULL,
	"You pat $N on $S head.",
	"$n pats $N on $S head.",
	"$n pats you on your head.",
	"You pat yourself on your head.",
	"$n pats $mself on the head."
    },

    {
	"peck",
	"You peck for seeds on the ground.",
	"$n pecks for seeds on the ground.",
	"You give $M a little peck on the cheek.",
	"$n gives $N a small peck on the cheek.",
	"$n gives you a sweet peck on the cheek.",
	"You kiss your own pectoral muscles.",
	"$n pecks $mself on $s pectoral muscles."
    },

    {
	"peer",
	"You peer intently about your surroundings.",
	"$n peers intently about the area, looking for thieves no doubt.",
	"You peer at $M quizzically.",
	"$n peers at $N quizzically.",
	"$n peers at you quizzically.",
	"You peer intently about your surroundings.",
	"$n peers intently about the area, looking for thieves no doubt."
    },

    {
	"pinch",
	"You toss a pinch of salt over your shoulder.",
	"$n tosses a pinch of salt over $s shoulder.",
	"You pinch $S rosy cheeks.",
	"$n pinches $N's rosy cheeks.",
	"$n pinches your chubby cheeks.",
	"You need a pinch of salt.",
	"$n needs a pinch of salt."
    },

    {
        "ping",
        "Ping who?",
        NULL,
        "You ping $N.  $N is unreachable.",
        "$n pings $N.  $N is unreachable.",
        "$n pings you.  Is your server dead or alive?",
        "You ping yourself. Ooof!",
        "$n pings $mself. Ooof!"
    },

    {
	"point",
	"Point at whom?",
	NULL,
	"You point at $M accusingly.",
	"$n points at $N accusingly.",
	"$n points at you accusingly.",
	"You point proudly at yourself.",
	"$n points proudly at $mself."
    },

    {
	"poke",
	"Poke whom?",
	NULL,
	"You poke $M in the ribs.",
	"$n pokes $N in the ribs.",
	"$n pokes you in the ribs.",
	"You poke yourself in the ribs, feeling very silly.",
	"$n pokes $mself in the ribs, looking very sheepish."
    },

    {
	"ponder",
	"You ponder the question.",
	"$n sits down and thinks deeply.",
	NULL,
	NULL,
	NULL,
	NULL,
	NULL
    },

    {
	"possum",
	"You do your best imitation of a corpse.",
	"$n hits the ground... DEAD.",
	"You do your best imitation of a corpse.",
	"$n hits the ground... DEAD.",
	"$n hits the ground... DEAD.",
	"You do your best imitation of a corpse.",
	"$n hits the ground... DEAD."
    },

    {
	"poupon",
	"You say 'Pardon me, do you have any Grey Poupon?'.",
	"$n says 'Pardon me, do you have any Grey Poupon?'",
	"You say to $M, 'Pardon me, do you have any Grey Poupon?'.",
	"$n says to $N, 'Pardon me, do you have any Grey Poupon?'",
	"$n says to you, 'Pardon me, do you have any Grey Poupon?'",
	"You say 'Pardon me, do you have any Grey Poupon?'.",
	"$n says 'Pardon me, do you have any Grey Poupon?'"
    },

    {
	"pout",
	"Ah, don't take it so hard.",
	"$n pouts.",
	"You pout at $M.",
	"$n pouts at $N.",
	"$n pouts at you.",
	"Ah, don't take it so hard.",
	"$n pouts."
    },

    {   
	"pretend",
	"You pretend you are a GOD, and slay everyone in sight!",
	"$n is pretending $e is an implementor again.  *sigh*",
	"You pretend you are a GOD, and demote $M to level 1.",
	"$n pretends $e is a GOD, and says, '$N, you're demoted to level 1!'",
	"$n pretends $e is a GOD, and says, 'You are demoted to level 1!'",
	"You pretend you are an implementor, and you demote yourself to level 1.",
	"$n pretends $e is a GOD, and demotes $mself to level 1."
    },

    {
	"puke",
	"You puke ... chunks everywhere!",
	"$n pukes.",
	"You puke on $M.",
	"$n pukes on $N.",
	"$n spews vomit and pukes all over your clothing!",
	"You puke on yourself.",
	"$n pukes on $s clothes."
    },

    {
	"purr",
	"MMMMEEEEEEEEOOOOOOOOOWWWWWWWWWWWW.",
	"$n purrs contentedly.",
	"You purr contentedly in $M lap.",
	"$n purrs contentedly in $N's lap.",
	"$n purrs contentedly in your lap.",
	"You purr at yourself.",
	"$n purrs at $mself.  Must be a cat thing."
    },

    {
	"raise",
	"You raise your hand in response.",
	"$n raises $s hand in response.",
	"You raise your hand in response.",
	"$n raises $s hand in response.",
	"$n raises $s hand in response to you.",
	"You raise your hand in response.",
	"$n raises $s hand in response."
    },
   
    {   
	"renandstimpy",
	"You say, 'Oh Happy Happy, Joy Joy!'",
	"$n exclaims, 'Oh Happy Happy, Joy Joy!'",
	"You exclaim, 'Oh Happy Happy, Joy Joy!' at the mere thought of $M.",
	"$n exclaims, 'Oh Happy Happy, Joy Joy!' as $e sees $N enter the room.",
	"$n exclaims, 'Oh Happy Happy, Joy Joy!' when $e sees you approach.",
	"You exclaim, 'Oh Happy Happy, Joy Joy!' at the thought of yourself.",
	"$n exclaims, 'Oh Happy Happy, Joy Joy!' at the thought of $mself."
    },  

    {
	"rofl",
	"You roll on the floor laughing hysterically.",
	"$n rolls on the floor laughing hysterically.",
	"You laugh your head off at $S remark.",
	"$n rolls on the floor laughing at $N's remark.",
	"$n can't stop laughing at your remark.",
	"You roll on the floor and laugh at yourself.",
	"$n laughs at $mself.  Join in the fun."
    },
    
    {
	"rolleyes",
	"You roll your eyes.",
	"$n rolls $s eyes.",
	"You roll your eyes at $M.",
	"$n rolls $s eyes at $N.",
	"$n rolls $s eyes at you.",
	"You roll your eyes at yourself.",
	"$n rolls $s eyes at $mself."
    },

    {
	"roll2",
	"You roll your eyes and make a repetative motion near your crotch.",
	"$n rolls $s eyes and makes a repetative motion near $s crotch.",
	"You roll your eyes at $M and make a repetative motion near your crotch.",
	"$n rolls $s eyes at $N and makes a repetative motion near $s crotch.",
	"$n rolls $s eyes at you and makes a repetative motion near $s crotch.",
	"You make a repetative motion near your crotch...you find you quite like it!",
	"$n starts making a repetative motion near $s crotch...how strange..."
    },

    {
	"rub",
	"You rub your eyes.  How long have you been at this?",
	"$n rubs $s eyes.  $n must have been playing all day.",
	"You rub your eyes.  Has $N been playing as long as you have?",
	"$n rubs $s eyes.  $n must have been playing all day.",
	"$n rubs $s eyes.  Have you been playing as long as $m?",
	"You rub your eyes.  How long have you been at this?",
	"$n rubs $s eyes.  $n must have been playing all day."
    },

    {
	"ruffle",
	"You've got to ruffle SOMEONE.",
	NULL,
	"You ruffle $N's hair playfully.",
	"$n ruffles $N's hair playfully.",
	"$n ruffles your hair playfully.",
	"You ruffle your hair.",
	"$n ruffles $s hair."
    },

    {
	"runaway",
	"You scream 'RUN AWAY! RUN AWAY!'.",
	"$n screams 'RUN AWAY! RUN AWAY!'.",
	"You scream '$N, QUICK! RUN AWAY!'.",
	"$n screams '$N, QUICK! RUN AWAY!'.",
	"$n screams '$N, QUICK! RUN AWAY!'.",
	"You desperately look for somewhere to run to!",
	"$n looks like $e's about to run away.",
    },

    {
	"russian",
	"You speak Russian.  Yeah, right.  Dream on.",
	"$n says 'Ya horosho stari malenky koshka.'  Huh?",
	"You speak Russian to $M.  Yeah, right.  Dream on.",
	"$n says to $N 'Ya horosho stari malenky koshka.'  Huh?",
	"$n says to you 'Ya horosho stari malenky koshka.'  Huh?",
	"You speak Russian.  Yeah, right.  Dream on.",
	"$n says 'Ya horosho stari malenky koshka.'  Huh?"
    },

    {
	"sad",
	"You put on a glum expression.",
	"$n looks particularly glum today.  *sniff*",
	"You give $M your best glum expression.",
	"$n looks at $N glumly.  *sniff*  Poor $n.",
	"$n looks at you glumly.  *sniff*   Poor $n.",
	"You bow your head and twist your toe in the dirt glumly.",
	"$n bows $s head and twists $s toe in the dirt glumly."
    },

    {
	"salute",
	"You salute smartly.",
	"$n salutes smartly.",
	"You salute $M.",
	"$n salutes $N.",
	"$n salutes you.",
	"Huh?",
	NULL
    },

    {
	"scowl",
	"You scowl angrilly.",
	"$n scowls angrilly.",
	"You scowl angrilly at $M.",
	"$n scowls angrilly at $N.",
	"$n scowls angrilly at you.",
	"You scowl angrilly at yourself.",
	"$n scowls angrilly at $mself."
    },

    {
	"scream",
	"ARRRRRRRRRRGH!!!!!",
	"$n screams loudly!",
	"ARRRRRRRRRRGH!!!!!  Yes, it MUST have been $S fault!!!",
	"$n screams loudly at $N.  Better leave before $n blames you, too!!!",
	"$n screams at you!  That's not nice!  *sniff*",
	"You scream at yourself.  Yes, that's ONE way of relieving tension!",
	"$n screams loudly at $mself!  Is there a full moon up?"
    },

    {
	"shake",
	"You shake your head.",
	"$n shakes $s head.",
	"You shake $S hand.",
	"$n shakes $N's hand.",
	"$n shakes your hand.",
	"You are shaken by yourself.",
	"$n shakes and quivers like a bowl full of jelly."
    },

    {
	"shiver",
	"Brrrrrrrrr.",
	"$n shivers uncomfortably.",
	"You shiver at the thought of fighting $M.",
	"$n shivers at the thought of fighting $N.",
	"$n shivers at the suicidal thought of fighting you.",
	"You shiver to yourself?",
	"$n scares $mself to shivers."
    },

    {
	"shrug",
	"You shrug.",
	"$n shrugs helplessly.",
	"You shrug in response to $s question.",
	"$n shrugs in response to $N's question.",
	"$n shrugs in respopnse to your question.",
	"You shrug to yourself.",
	"$n shrugs to $mself.  What a strange person."
    },

    {
	"sigh",
	"You sigh.",
	"$n sighs loudly.",
	"You sigh as you think of $M.",
	"$n sighs at the sight of $N.",
	"$n sighs as $e thinks of you.  Touching, huh?",
	"You sigh at yourself.  You MUST be lonely.",
	"$n sighs at $mself.  What a sorry sight."
    },

    {
	"sing",
	"You raise your clear voice towards the sky.",
	"$n has begun to sing.",
	"You sing a ballad to $m.",
	"$n sings a ballad to $N.",
	"$n sings a ballad to you!  How sweet!",
	"You sing a little ditty to yourself.",
	"$n sings a little ditty to $mself."
    },

    {
	"slap",
	"Slap whom?",
	NULL,
	"You slap $M across the face.",
	"$n slaps $N across the face for $s stupidity.",
	"$n slaps you across the face. Don't take it from $m.",
	"You slap yourself.  You deserve it.",
	"$n slaps $mself.  Why don't you join in?"
    },

    {
	"slobber",
	"You slobber all over the floor.",
	"$n slobbers all over the floor.",
	"You slobber all over $M.",
	"$n slobbers all over $N.",
	"$n slobbers all over you.",
	"You slobber all down your front.",
	"$n slobbers all over $mself."
    },

    {
	"slut",
	"You act like a total slut.",
	"$n lounges about looking like a total slut.",
	"You come on to $N, breathing sensuality.",
	"$n comes on to $N, perhaps he's trying to take Rosario's reputation?",
	"$n comes on to you, $n is like a living embodiment of sensuality.",
	"You sigh, and say 40 partners is average for a 18 yr old, right?",
	"$n sighs, and says 40 partners is about right for an 18 yr old right?"
    },

    {
	"smile",
	"You smile happily.",
	"$n smiles happily.",
	"You smile at $M.",
	"$n beams a smile at $N.",
	"$n smiles at you.",
	"You smile at yourself.",
	"$n smiles at $mself."
    },

    {
	"smirk",
	"You smirk.",
	"$n smirks.",
	"You smirk at $S saying.",
	"$n smirks at $N's saying.",
	"$n smirks at your saying.",
	"You smirk at yourself.  Okay ...",
	"$n smirks at $s own 'wisdom'."
    },

    {
	"smoke",
	"You calmly light a cigarette and take a puff.",
	"$n calmly lights a cigarette and take a puff.",
	"You blow smoke into $S eyes.",
	"$n blows smoke into $N's eyes.",
	"$n blows smoke rings into your eyes.",
	"You call down lightning and SMOKE yourself.",
	"$n calls down lightning and SMOKES $mself."
    },

    {
	"smooch",
	"You are searching for someone to smooch.",
	"$n is looking for someone to smooch.",
	"You give $M a nice, wet smooch.",
	"$n and $N are smooching in the corner.",
	"$n smooches you passionately on the lips.",
	"You smooch yourself.",
	"$n smooches $mself.  Yuck."
    },

    {
	"snap",
	"PRONTO ! You snap your fingers.",
	"$n snaps $s fingers.",
	"You snap back at $M.",
	"$n snaps back at $N.",
	"$n snaps back at you!",
	"You snap yourself to attention.",
	"$n snaps $mself to attention."
    },

    {
	"snarl",
	"You grizzle your teeth and look mean.",
	"$n snarls angrily.",
	"You snarl at $M.",
	"$n snarls at $N.",
	"$n snarls at you, for some reason.",
	"You snarl at yourself.",
	"$n snarls at $mself."
    },

    {
	"sneer",
	"You sneer in contempt.",
	"$n sneers in contempt.",
	"You sneer at $M in contempt.",
	"$n sneers at $N in contempt.",
	"$n sneers at you in contempt.",
	"You sneer at yourself in contempt.",
	"$n sneers at $mself in contempt."
    },

    {
	"sneeze",
	"Gesundheit!",
	"$n sneezes.",
	"You sneeze all over $M.",
	"$n sneezes all over $N.",
	"$n sneezes all over you.",
	NULL,
	NULL
    },

    {
	"snicker",
	"You snicker softly.",
	"$n snickers softly.",
	"You snicker with $M about your shared secret.",
	"$n snickers with $N about their shared secret.",
	"$n snickers with you about your shared secret.",
	"You snicker at your own evil thoughts.",
	"$n snickers at $s own evil thoughts."
    },

    {
	"sniff",
	"You sniff sadly. *SNIFF*",
	"$n sniffs sadly.",
	"You sniff sadly at the way $E is treating you.",
	"$n sniffs sadly at the way $N is treating $m.",
	"$n sniffs sadly at the way you are treating $m.",
	"You sniff sadly at your lost opportunities.",
	"$n sniffs sadly at $mself.  Something MUST be bothering $m."
    },

    {
	"snore",
	"Zzzzzzzzzzzzzzzzz.",
	"$n snores loudly.",
	NULL,
	NULL,
	NULL,
	NULL,
	NULL
    },

    {
	"snort",
	"You snort in disgust.",
	"$n snorts in disgust.",
	"You snort at $M in disgust.",
	"$n snorts at $N in disgust.",
	"$n snorts at you in disgust.",
	"You snort at yourself in disgust.",
	"$n snorts at $mself in disgust."
    },

    {
	"snowball",
	"Whom do you want to throw a snowball at?",
	NULL,
	"You throw a snowball in $N's face.",
	"$n throws a snowball at $N.",
	"$n throws a snowball at you.",
	"You throw a snowball at yourself.",
	"$n throws a snowball at $mself."
    },

    {
	"snuggle",
	"Who?",
	NULL,
	"You snuggle up contentedly in $M lap.",
	"$n snuggles up contentedly in $N's lap.",
	"$n snuggles up contentedly in your lap.",
	"You snuggle up, getting ready to sleep.",
	"$n snuggles up, getting ready to sleep."
    },

    {
	"spam",
	"You mutter 'SPAM' quietly to yourself.",
	"$n sings 'SPAM SPAM SPAM SPAM SPAM SPAM....'",
	"You hurl a can of SPAM at $M.",
	"$n hurls a can of SPAM at $N.",
	"$n SPAMS you viciously.",
	"You mutter 'SPAM' in the corner quietly.",
	"$n mutters 'SPAM SPAM SPAM SPAM'.  Join in!"
    },
    
    {
	"spanish",
	"You speak Spanish or at least you think you do.",
	"$n says 'Naces pendejo, mueres pendejo.'  Uh oh.",
	"You speak Spanish or at least you think you do.",
	"$n says 'Naces pendejo, mueres pendejo.'  Uh oh.",
	"$n says 'Naces pendejo, mueres pendejo.'  Uh oh.",
	"You speak Spanish or at least you think you do.",
	"$n says to $mself 'Naces pendejo, mueres pendejo.'  Uh oh."
    },

    {
	"spank",
	"Spank whom?",
	NULL,
	"You spank $M playfully.",
	"$n spanks $N playfully.",
	"$n spanks you playfully.  OUCH!",
	"You spank yourself.  Kinky!",
	"$n spanks $mself.  Kinky!"
    },

    {
	"spin",
	"You twirl in a graceful pirouette.",
	"$n twirls in a graceful pirouette.",
	"You spin $M on one finger.",
	"$n spins $N on $s finger.",
	"$n spins you around on $s finger.",
	"You spin yourself around and around and around....",
	"$n spins $mself around and around and around..."
    },
    
    {
	"squeeze",
	"Where, what, how, whom?",
	NULL,
	"You squeeze $M fondly.",
	"$n squeezes $N fondly.",
	"$n squeezes you fondly.",
	"You squeeze yourself - try to relax a little!",
	"$n squeezes $mself."
    },

    {
	"squeak",
	"You squeak like a mouse.",
	"$n squeaks like a mouse.",
	"You squeak at $M.",
	"$n squeaks at $N.  Is $e a man or a mouse?",
	"$n squeaks at you.  Is $e a man or a mouse?",
	"You squeak at yourself like a mouse.",
	"$n squeaks at $mself like a mouse."
    },

    {
	"squeal",
	"You squeal with delight.",
	"$n squeals with delight.",
	"You squeal at $M.",
	"$n squeals at $N.  Wonder why?",
	"$n squeals at you.  You must be doing something good.",
	"You squeal at yourself.",
	"$n squeals at $mself."
    },

    {
	"squirm",
	"You squirm guiltily.",
	"$n squirms guiltily.  Looks like $e did it.",
	"You squirm in front of $M.",
	"$n squirms in front of $N.",
	"$n squirms in front of you.  You make $m nervous.",
	"You squirm and squirm and squirm....",
	"$n squirms and squirms and squirm....."
    },
    
    {
	"squish",
	"You squish your toes into the sand.",
	"$n squishes $s toes into the sand.",
	"You squish $M between your legs.",
	"$n squishes $N between $s legs.",
	"$n squishes you between $s legs.",
	"You squish yourself.",
	"$n squishes $mself.  OUCH."
    },

    {
	"stare",
	"You stare at the sky.",
	"$n stares at the sky.",
	"You stare dreamily at $N, completely lost in $S eyes..",
	"$n stares dreamily at $N.",
	"$n stares dreamily at you, completely lost in your eyes.",
	"You stare dreamily at yourself - enough narcissism for now.",
	"$n stares dreamily at $mself - NARCISSIST!"
    },

    {
	"stickup",
	"You don a mask and ask for everyone's gold.",
	"$n says 'This is a stickup.  Gimme yer gold, NOW!'",
	"You don a mask and ask for $S gold.",
	"$n says to $N, 'This is a stickup.  Gimme yer gold, NOW!'",
	"$n says to you, 'This is a stickup.  Gimme yer gold, NOW!'",
	"You extort money from yourself.",
	"$n holds $s weapon to $s throat and says 'Ok, me, give me all my money!'"
    },
   
    {
	"stretch",
	"You stretch and relax your sore muscles.",
	"$n stretches luxuriously.  Make you want to, doesn't it.",
	"You stretch and relax your sore muscles.",
	"$n stretches luxuriously.  Make you want to, doesn't it.",
	"$n stretches luxuriously.  Make you want to, doesn't it.",
	"You stretch and relax your sore muscles.",
	"$n stretches luxuriously.  Make you want to, doesn't it."
    },
    
    {
	"strip",
	"You show some of your shoulder as you begin your performance.",
	"$n shows $s bare shoulder and glances seductively around the room.",
	"You show some of your shoulder as you begin your performance.",
	"$n shows $s bare shoulder and glances seductively at $N.",
	"$n shows $s bare shoulder and glances seductively at you.",
	"You show some of your shoulder as you begin your performance.",
	"$n shows $s bare shoulder and glances seductively around the room."
    },

    {
	"strut",
	"Strut your stuff.",
	"$n struts proudly.",
	"You strut to get $S attention.",
	"$n struts, hoping to get $N's attention.",
	"$n struts, hoping to get your attention.",
	"You strut to yourself, lost in your own world.",
	"$n struts to $mself, lost in $s own world."
    },

    {
	"suffer",
	"No xp again?  You suffer at the hands of fate.",
	"$n is suffering.  Looks like $e can't seem to level.",
	"You tell $M how you suffer whenever you're away from $M.",
	"$n tells $N that $e suffers whenever they're apart.",
	"$n tells you that $e suffers whenever you're apart.",
	"No xp again?  You suffer at the hands of fate.",
	"$n is suffering.  Looks like $e can't seem to level."
    },  
    
    {
	"sulk",
	"You sulk.",
	"$n sulks in the corner.",
	NULL,
	NULL,
	NULL,
	NULL,
	NULL
    },

    {
	"surf",
	"You stoke your soul by catching a smooth, perfect wave.",
	"$n stokes $s soul by catching a smooth, perfect wave.",
	"You stoke your soul by catching a smooth, perfect wave.",
	"$n stokes $s soul by catching a smooth, perfect wave.",
	"$n stokes $s soul by catching a smooth, perfect wave.",
	"You stoke your soul by catching a smooth, perfect wave.",
	"$n stokes $s soul by catching a smooth, perfect wave."
    },
    
    {
	"swoon",
	"You swoon in ecstacy.",
	"$n swoons in ecstacy.",
	"You swoon in ecstacy at the thought of $M.",
	"$n swoons in ecstacy at the thought of $N.",
	"$n swoons in ecstacy as $e thinks of you.",
	"You swoon in ecstacy.",
	"$n swoons in ecstacy."
    },

    {
	"tackle",
	"You can't tackle the AIR!",
	NULL,
	"You run over to $M and bring $M down!",
	"$n runs over to $N and tackles $M to the ground!",
	"$n runs over to you and tackles you to the ground!",
	"You wrap your arms around yourself, and throw yourself to the ground.",
	"$n wraps $s arms around $mself and brings $mself down!?"
    },
    
    {
	"tap",
	"You tap your foot impatiently.",
	"$n taps $s foot impatiently.",
	"You tap your foot impatiently.  Will $E ever be ready?",
	"$n taps $s foot impatiently as $e waits for $N.",
	"$n taps $s foot impatiently as $e waits for you.",
	"You tap yourself on the head.  Ouch!",
	"$n taps $mself on the head."
    },

    {
	"tender",
	"You will enjoy it more if you choose someone to kiss.",
	NULL,
	"You give $M a soft, tender kiss.",
	"$n gives $N a soft, tender kiss.",
	"$n gives you a soft, tender kiss.",
	"You'd better not, people may start to talk!",
	NULL
     },
     
    {
	"thank",
	"Thank you too.",
	NULL,
	"You thank $N heartily.",
	"$n thanks $N heartily.",
	"$n thanks you heartily.",
	"You thank yourself since nobody else wants to !",
	"$n thanks $mself since you won't."
    },

    {
	"think",
	"You think about times past and friends forgotten.",
	"$n thinks deeply and is lost in thought.",
	"You think about times past and friends forgotten.",
	"$n thinks deeply and is lost in thought.",
	"$n thinks deeply and is lost in thought.  Maybe $e is thinking of you?",
	"You think about times past and friends forgotten.",
	"$n thinks deeply and is lost in thought."
    },
   
    {
	"throttle",
	"Whom do you want to throttle?",
	NULL,
	"You throttle $M till $E is blue in the face.",
	"$n throttles $N about the neck, until $E passes out.  THUNK!",
	"$n throttles you about the neck until you pass out.  THUNK!",
	"That might hurt!  Better not do it!",
	"$n is getting a crazy look in $s eye again."
    },

    {
	"tickle",
	"Whom do you want to tickle?",
	NULL,
	"You tickle $N.",
	"$n tickles $N.",
	"$n tickles you - hee hee hee.",
	"You tickle yourself, how funny!",
	"$n tickles $mself."
    },

    {
	"timeout",
	"You take a 'T' and drink some Gatorade (tm).",
	"$n takes a 'T' and drinks some Gatorade (tm).",
	"You take a 'T' and offer $M some Gatorade (tm).",
	"$n takes a 'T' and offers $N some Gatorade (tm).",
	"$n takes a 'T' and offers you some Gatorade (tm).",
	"You take a 'T' and drink some Gatorade (tm).",
	"$n takes a 'T' and drinks some Gatorade (tm)."
    },
    
    {
	"tongue",
	"You stick out your tongue.",
	"$n sticks out $s tongue.",
	"You stick your tongue out at $M.",
	"$n sticks $s tongue out at $N.",
	"$n sticks $s tongue out at you.",
	"You stick out your tongue and touch your nose.",
	"$n sticks out $s tongue and touches $s nose."
    },

    {
	"torture",
	"You have to torture someone!",
	NULL,
	"You torture $M with rusty weapons, Mwaahhhhh!!",
	"$n tortures $N with rusty weapons, $E must have been REAL bad!",
	"$n tortures you with rusty weapons!  What did you DO!?!",
	"You torture yourself with rusty weapons.  Was it good for you?",
	"$n tortures $mself with rusty weapons.  Looks like $e enjoys it!?"
    },

    {   
	"tummy",
	"You rub your tummy and wish you'd bought a pie at the bakery.",
	"$n rubs $s tummy and wishes $e'd bought a pie at the bakery.",
	"You rub your tummy and ask $M for some food.",
	"$n rubs $s tummy and asks $N for some food.",
	"$n rubs $s tummy and asks you for some food.  Please?",
	"You rub your tummy and wish you'd bought a pie at the bakery.",
	"$n rubs $s tummy and wishes $e'd bought a pie at the bakery."
    },

    {
	"tweety",
	"You exclaim 'I TAWT I TAW A PUTTY TAT!!'",
	"$n exclaims 'I TAWT I TAW A PUTTY TAT!!'",
	"You exclaim to $M, 'I TAWT I TAW A PUTTY TAT!!'",
	"$n exclaims to $N, 'I TAWT I TAW A PUTTY TAT!!'",
	"$n exclaims to you, 'I TAWT I TAW A PUTTY TAT!!'",
	"You exclaim to yourself, 'I TAWT I TAW A PUTTY TAT!!'",
	"$n exclaims to $mself, 'I TAWT I TAW A PUTTY TAT!!'"
    },
    
    {
	"twiddle",
	"You patiently twiddle your thumbs.",
	"$n patiently twiddles $s thumbs.",
	"You twiddle $S ears.",
	"$n twiddles $N's ears.",
	"$n twiddles your ears.",
	"You twiddle your ears like Dumbo.",
	"$n twiddles $s own ears like Dumbo."
    },

    {
	"type",
	"You throw up yor handz in dizgust at yur losy typing skils.",
	"$n couldn't type a period if there was only one key on the keyboard.",
	"You throw up yor handz in dizgust at yur losy typing skils.",
	"$n couldn't type a period if there was only one key on the keyboard.",
	"$n couldn't type a period if there was only one key on the keyboard.",
	"You throw up yor handz in dizgust at yur losy typing skils.",
	"$n couldn't type a period if there was only one key on the keyboard."
    },

    {
	"wager",
	"You wager you can name that tune in ONE NOTE.",
	"$n bets $e can name that tune in ONE NOTE.",
	"You wager $M that you can name that tune in ONE NOTE.",
	"$n bets $N that $e can name that tune in ONE NOTE.",
	"$n bets you that $e can name that tune in ONE NOTE.",
	"You wager you can name that tune in ONE NOTE.",
	"$n bets $e can name that tune in ONE NOTE.",
    },
    
    {
	"wave",
	"You wave.",
	"$n waves happily.",
	"You wave goodbye to $N.",
	"$n waves goodbye to $N.",
	"$n waves goodbye to you.  Have a good journey.",
	"Are you going on adventures as well?",
	"$n waves goodbye to $mself."
    },

    {
	"wedgie",
	"You look around for someone to wedgie.",
	"$n is looking around for someone to wedgie!  Run!",
	"You wedgie $M.  Must be fun! ",
	"$n wedgies $N to the heavens.",
	"$n wedgies you!  Ouch!",
	"You delight in pinning your underwear to the sky.",
	"$n wedgies $mself and revels with glee."
    },

    {
	"whine",
	"You whine like the great whiners of the century.",
	"$n whines 'I want to be a god already.  I need more hitpoints..I...'",
	"You whine to $M like the great whiners of the century.",
	"$n whines to $N 'I want to be an immortal already.  I need more hp...I..'",
	"$n whines to you 'I want to be an immortal already.  I need more hp...I...'",
	"You whine like the great whiners of the century.",
	"$n whines 'I want to be a god already.  I need more hitpoints..I...'"
    },

    {
	"whistle",
	"You whistle appreciatively.",
	"$n whistles appreciatively.",
	"You whistle at the sight of $M.",
	"$n whistles at the sight of $N.",
	"$n whistles at the sight of you.",
	"You whistle a little tune to yourself.",
	"$n whistles a little tune to $mself."
    },

    {
	"wiggle",
	"Your wiggle your bottom.",
	"$n wiggles $s bottom.",
	"You wiggle your bottom toward $M.",
	"$n wiggles $s bottom toward $N.",
	"$n wiggles $s bottom toward you.",
	"You wiggle about like a fish.",
	"$n wiggles about like a fish."
    },

    {
	"wince",
	"You wince.  Ouch!",
	"$n winces.  Ouch!",
	"You wince at $M.",
	"$n winces at $N.",
	"$n winces at you.",
	"You wince at yourself.  Ouch!",
	"$n winces at $mself.  Ouch!"
    },

    {
	"wink",
	"You wink suggestively.",
	"$n winks suggestively.",
	"You wink suggestively at $N.",
	"$n winks at $N.",
	"$n winks suggestively at you.",
	"You wink at yourself ?? - what are you up to ?",
	"$n winks at $mself - something strange is going on..."
    },

    {
	"worship",
	"You worship the powers that be.",
	"$n worships the powers that be.",
	"You drop to your knees in homage of $M.",
	"$n prostrates $mself before $N.",
	"$n believes you are all powerful.",
	"You worship yourself.",
	"$n worships $mself - ah, the conceitedness of it all."
    },

    {
	"wrap",
	"You wrap a present for your love.",
	"$n wraps a present for someone special.",
	"You wrap your legs around $M.",
	"$n wraps $s legs around $N.",
	"$n wraps $s legs around you.  Wonder what's coming next?",
	"You wrap yourself with some paper.",
	"$n wraps $mself with some wrapping paper.  Is it Christmas?"
    },

    {
	"yabba",
	"YABBA-DABBA-DOO!",
	"$n hollers 'Hey Wilma -- YABBA DABBA DOO!'",
	"You holler 'Hey $N -- YABBA DABBA DOO!'",
	"$n hollers 'Hey $N -- YABBA DABBA DOO!'",
	"$n hollers 'Hey $N -- YABBA DABBA DOO!'",
	"YABBA-DABBA-DOO!",
	"$n hollers 'Hey Wilma -- YABBA DABBA DOO!'"
    },
   
    {
	"yahoo",
	"You do your best Han Solo impression.",
	"$n exclaims, 'YAHOO!  Great shot, kid, that was one in a million!'",
	"You do your best Han Solo impression.",
	"$n exclaims, 'YAHOO!  Great shot, $N, that was one in a million!'",
	"$n exclaims, 'YAHOO!  Great shot, $N, that was one in a million!'",
	"You do your best Han Solo impression.",
	"$n exclaims, 'YAHOO!  Great shot, $n, that was one in a million!'"
    },
    
    {
	"yawn",
	"You must be tired.",
	"$n yawns.",
	"You must be tired.",
	"$n yawns at $N.  Maybe you should let them go to bed?",
	"$n yawns at you.  Maybe $e wants you to go to bed with $m?",
	"You must be tired.",
	"$n yawns."
    },
	 
    {
	"yeehaw",
	"You mount your white pony (?) and shout 'YEEEEEEEEEEHAW!'",
	"$n mounts $s white pony (?) and shouts 'YEEEEHHHAAAAAAWWWW!'",
	"You mount your white pony (?) and shout 'YEEEEEEEEEEHAW!'",
	"$n mounts $s white pony (?) and shouts 'YEEEEHHHAAAAAAWWWW!'",
	"$n mounts $s white pony (?) and shouts 'YEEEEHHHAAAAAAWWWW!'",
	"You mount your white pony (?) and shout 'YEEEEEEEEEEHAW!'",
	"$n mounts $s white pony (?) and shouts 'YEEEEHHHAAAAAAWWWW!'"
    },

    {
	"fear",
	"You fear.",
	"$n fears.",
	"You fear $M.",
	"$n fears $N.",
	"$n fears you.  You RULE!",
	"You fear yourself.  Kind of paranoid?",
	"$n fears $mself.  $e must psycho."
    },

    {
	"flaf",
	"You fucking laf.",
	"$n fucking lafs.",
	"You fucking laf at $M.",
	"$n fucking lafs at $N.",
	"$n fucking lafs at you.  You should pound $m, no doubt about it!",
	"You fucking laf at yourself.  Are you whacked!?",
	"$n fucking lafs at $mself.  $e must be whacked!"
    },

    {
	"fnog",
	"You fucking nog.",
	"$n fucking nogs.",
	"You fucking nog at $M.",
	"$n fucking nogs at $N.",
	"$n fucking nogs at you.  You agree with $m, right?",
	"You fucking nog at yourself.  Are you whacked!?",
	"$n fucking nogs at $mself.  $e must be whacked!"
    },

    {
	"laf",
	"You laf.",
	"$n lafs.",
	"You laf at $M.",
	"$n lafs at $N.",
	"$n lafs at you.  You should pound $m, right?",
	"You laf at yourself.  Are you whacked!?",
	"$n lafs at $mself.  $e must be whacked!"
    },

    {
	"mfear",
	"You take a moment fear!.",
	"$n takes a moment fear!.",
	"You take a moment fear $M!",
	"$n takes a moment fear $N!",
	"$n takes a moment fear you!.  Enjoy it while it lasts.",
	"You take a moment fear yourself.  You're whacked dude!",
	"$n takes a moment fear $mself.  $e is really whacked!"
    },

    {
	"mhfnog",
	"You take a moment to let out some hard f__king nogs!.",
	"$n takes a moment to let out some hard f__king nogs!.",
	"You take a moment to let out some hard f__king nogs at $M.",
	"$n takes a moment to let out some hard f__king nogs at $N.",
	"$n takes a moment to let out some hard f__king nogs at you.  You better agree with $m!",
	"You take a moment to let out some hard f__king nogs at yourself.  You're whacked dude!",
	"$n takes a moment to let out some hard f__king nogs at $mself.  $e is really whacked!"
    },

    {
	"nog",
	"You nog.",
	"$n nogs.",
	"You nog at $M.",
	"$n nogs at $N.",
	"$n nogs at you.  You agree with $m, right?",
	"You nog at yourself.  Are you whacked!?",
	"$n nogs at $mself.  $e must be whacked!"
    },

    {
	"",
	NULL, NULL, NULL, NULL, NULL, NULL, NULL
    }
};


/*
 * The X-social table.
 * Add new X-socials here.
 * Alphabetical order is not required.
 */
const	struct	xsocial_type	xsocial_table [] =
{

    {
	"x-earlobe",
	"On whom do you wish to do this?",
	NULL,
	"You gently tug on $M earlobe with your teeth.",
	"$n gently tugs on $N's earlobe with $s teeth.",
	"$n gently tugs on your earlobe with $s teeth.",
	"Not on yourself!",
	NULL,
	0, 0, 0, 1, 1, FALSE
    },

{
"x-kneel",
"Drop to your knees before who?",
NULL,
"You drop to your knees before $M, begging for mercy.",
"$n drops to $s knees before $N, begging for $M mercy.",
"$n drops to $s knees before you, begging for mercy.",
"Nope.",
NULL,
0, 0, 0, 7, 7, FALSE
},
    {
	"x-french",
	"On whom do you wish to do this?",
	NULL,
	"You give $M a deep throbbing kiss, rolling your tongue around $S.",
	"$n gives $N a deep throbbing kiss.",
	"$n gives you a deep throbbing kiss, rolling $s tongue around yours.",
	"Not on yourself!",
	NULL,
	0, 0, 0, 1, 1, FALSE
    },

    {
	"x-kissneck",
	"On whom do you wish to do this?",
	NULL,
	"You slowly and softly kiss and nuzzle $M neck.",
	"$n slowly and softly kisses and nuzzles $N's neck.",
	"$n slowly and softly kisses and nuzzles your neck.",
	"Not on yourself!",
	NULL,
	0, 0, 0, 1, 1, FALSE
    },

{
"x-wcream",
"On whom do you wish to do this?",
NULL,
"You spray whipped cream all over $M body, licking it up with your tongue.",
"$n coats $N's body in whipped cream and then licks it up with their tongue.",
"$n covers your body in whipped cream, and you moan as it gets licked up with their tongue.",
"No.",
NULL,
0, 0, 0, 5, 5, FALSE
},
{
"x-ice",
"On who?",
NULL,
"You run a cold piece of ice down $M back, following up with your tongue.",
"$n runs a piece of ice over $N's back, following up with their tongue.",
"$n runs a piece of ice over your burning hot flesh, following up with their tongue.",
"No.",
NULL,
0, 0, 0, 6, 8, FALSE
},

{
"x-whip",
"Who's been bad?",
NULL,
"You smirk slightly as you crack a whip over $N's tender skin, making $M whimper.",
"$n grins slightly as he whips $N's tender flesh, making $M whimper.",
"$n grins wickedly as they whip your tender flesh, making you whimper slightly in fear.",
"No.",
NULL,
0, 0, 0, 9, 2, FALSE
},
    {
	"x-moan",
	"On whom do you wish to do this?",
	NULL,
	"You start moaning 'Oh $N...oh yes...don't stop...mmMMmm...'",
	"$n starts moaning 'Oh $N...oh yes...don't stop...mmMMmm...'",
	"$n starts moaning 'Oh $N...oh yes...don't stop...mmMMmm...'",
	"Not on yourself!",
	NULL,
	0, 2, 0, 1, 1, FALSE
    },

    {
	"x-nuttella",
	"On whom do you wish to do this?",
	NULL,
	"You cover $N's naked flesh with a popular choc spread, before licking it off.",
	"$n smears a chocolate spread over $N's body, licking $M clean with relish",
	"$n smears a popular choc spread on your naked flesh, licking it off you",
	"Not on yourself!",
	NULL,
	0, 0, 0, 5, 20, FALSE
    },

    {
	"x-stroke",
	"On whom do you wish to do this?",
	NULL,
	"You lightly run your fingers along the insides of $S thighs.",
	"$n lightly runs $s fingers along the insides of $N's thighs.",
	"$n lightly runs $s fingers along the insides of your thighs.",
	"Not on yourself!",
	NULL,
	0, 0, 0, 5, 10, FALSE
    },

    {
	"x-tender",
	"On whom do you wish to do this?",
	NULL,
	"You run your fingers through $S hair and kiss $M tenderly on the lips.",
	"$n runs $s fingers through $N's hair and kisses $M tenderly on the lips.",
	"$n runs $s fingers through your hair and kisses you tenderly on the lips.",
	"Not on yourself!",
	NULL,
	0, 0, 0, 1, 1, FALSE
    },

    {
	"x-tie",
	"On whom do you wish to do this?",
	NULL,
	"You tie $N to the bed posts!",
	"$n ties $N's body, fixing $M helplessly on the bed.  Oh!! Kinky!",
	"$n ties you to the bed post, leaving you completely at $s mercy",
	"Not on yourself!",
	NULL,
	0, 0, 0, 15, 10, FALSE
    },

    {
	"x-withdraw",
	"On whom do you wish to do this?",
	NULL,
	"You gently pull yourself free of $M.",
	"$n gently pulls $mself free of $N.",
	"$n gently pulls $mself free of you.",
	"Not on yourself!",
	NULL,
	0, 1, 0, 0, 0, FALSE
    },

    {
	"xf-oral",
	"On whom do you wish to do this?",
	NULL,
	"You take $N's hot member in your hands, licking his cock from base to tip.",
	"$n takes $N's penis in $s hands, licking $N's cock from base to tip.",
"You let out a small moan as $n takes your cock into her hands, licking it from your balls to the tip.",
	"On yourself? I'm impressed!",
	NULL,
	2, 0, 0, 5, 15, FALSE
    },

{
"xf-spank",
"Who's been naughty?",
NULL,
"You take $N over your knee and spank him hard, making him squirm.",
"$n bends $N over her knees and spanks him hard on the ass, making him squirm.",
"You whimper softly as $n takes you over her knee, spanking you hard on the ass, making it sting.",
"Nah.",
NULL,
2, 0, 0, 25, 4, FALSE
},
{
"xf-urine",
"On whom do you wish to do this?",
NULL,
"You maliciously lean $N's head back and stand over him with his mouth open before letting a hard stream of piss shoot down his throat.",
"$n shoots a golden stream of urine down $N's throat, making him choke and swallow.",
"You eyes widen as your mistress shoots a stream of piss odown your throat, making you swallow it all.",
"Nope.",
NULL,
2, 0, 0, 37, -10, FALSE
},
    {
"xf-beg",
"Beg who, you stupid slut?",
NULL,
"You drop to your kneees before $N, begging for him to abuse you and fuck you hard.",
"$n drops to her knees and begs for $N to take her and use her for his pleasure.",
"$n drops to her knees before you, begging for you to abuse her worthless slut body.",
"It doesn't work that way, you stupid whore.",
NULL,
2, 0, 0, -10, 12, FALSE
},
{
	"xf-blowjob",
	"On whom do you wish to do this?",
	NULL,
	"You take $N's hot member in your mouth, sucking $S shaft.",
	"$n takes $N's throbbing penis in $s mouth, sucking $N's cock.",
	"You gasp as $n takes your penis in $s mouth, licking your head.",
	"On yourself? I'm impressed!",
	NULL,
	2, 1, 250, 10, 25, FALSE
    },

{
       "xf-tip",
       "On whom do you wish to do this?",
       NULL,
       "You gently run the tip of your tongue along the underside of $N's hot cock.",
       "$n runs the tip of $s tongue along the bottom of $N's pulsing cock.",
       "You let out a low moan as $N runs the tip of her tongue along the underside of your cock.",
       "I think not.",
       NULL,
         2, 0, 0, 5, 59, FALSE
},
{
"xf-handjob",
"On who?",
NULL,
"You take his hot cock in your hand and wrap your fingers around it, slowly pumping up and down.",
"$n takes $N's hot cock in her hands, wrapping her fingers around it as she slowly pumps up and down.",
"$n takes your hot cock into her hands, and you moan softly as she wraps her fingers around it, slowly pumping up and down.",
"No.",
NULL,
2, 0, 0, 9, 14, FALSE
},

{
"xf-sitface",
"Who gets to taste your sweet juice?",
NULL,
"You push $N onto his back and crawl up his body, sitting down on his face as he licks at your pussy.",
"$n pushes $N onto his back and straddles his face, moaning as he licks her hot pussy.",
"$n pushes you onto your back and straddles your face, moaning and squirming as you eagerly lap at her hot, wet cunt.",
"No.",
NULL,
2, 1, 250, 15, 0, FALSE
},

{
"xf-69",
"Who?",
NULL,
"You crawl on top of $N and takes his hot cock between your lips, moaning as he laps at your cunt.",
"$n pushes $N onto his back and crawls on top of him, sucking his cock while he wriggles his tongue about in her cunt.",
"$n pushes you onto your back, crawling on top of you as she sucks on your cock, moaning while you lick her pussy.",
"No.",
NULL,
2, 1, 250, 20, 20, TRUE
},
    {
	"xf-breasts",
	"On whom do you wish to do this?",
	NULL,
	"You take $S hands and press them to your breasts.",
	"$n takes $N's hands and presses them to $m breasts.",
	"$n takes your hands and presses them to $m breasts.",
	"Not on yourself!",
	NULL,
	2, 0, 0, 5, 10, FALSE
    },

{
      "xf-rub",
      "Who gets to feel the magic touch?",
NULL,
      "You genltly run your finegers over $N's hardening cock.",
      "$n gently runs her fingers over $N's hardening cock.",
      "$n gently runs her fingers over your hardening cock.",
      "You don't have a penis.  At least, I hope not.",
      NULL,
      2, 0 , 0, 15, 20, FALSE
},
    {
	"xf-contract",
	"On whom do you wish to do this?",
	NULL,
	"You contract your vaginal muscles, driving $M wild.",
	"$n contracts $m vaginal muscles, driving $N wild.",
	"$n contracts $m vaginal muscles, driving you wild.",
	"Not on yourself!",
	NULL,
	2, 2, 0, 10, 15, TRUE
    },

    {
	"xf-finger",
	"On whom do you wish to do this?",
	NULL,
	"You put your hands between your legs and begin to masterbate for $N.",
	"$n puts $m hands between $m legs and begins to masterbate for $N.",
	"$n puts $m hands between $m legs and begins to masterbate for your viewing pleasure.  What a turn on!.",
	"Not on yourself!",
	NULL,
	2, 0, 0, 20, 10, FALSE
    },
    {
	"xf-floor",
	"On whom do you wish to do this?",
	NULL,
	"You lie on your back, and pull $M between your parted legs.",
	"$n lies on $m back, and pulls $N between $m parted legs.",
	"$n lies on $m back, and pulls you between $m parted legs.",
	"Not on yourself!",
	NULL,
	2, 1, 250, 25, 20, TRUE
    },

    {
	"xf-grind",
	"On whom do you wish to do this?",
	NULL,
	"You grind your hips up to meet $S thrusts.",
	"$n grinds $m hips up to meet $N's thrusts.",
	"$n grinds $m hips up to meet your thrusts.",
	"Not on yourself!",
	NULL,
	2, 2, 0, 15, 10, TRUE
    },

    {
	"xf-mount",
	"On whom do you wish to do this?",
	NULL,
	"You push $M onto $S back, and slowly lower yourself onto $S erection.",
	"$n pushes $N onto $S back, and slowly lowers $mself onto $S erection.",
	"$n pushes you onto your back, and slowly lowers $mself onto your erection.",
	"Not on yourself!",
	NULL,
	2, 1, 250, 25, 20, TRUE
    },

    {
	"xf-nails",
	"On whom do you wish to do this?",
	NULL,
	"You scratch your nails down $S back.",
	"$n scratches $m nails down $N's back.",
	"$n scratches $m nails down your back.",
	"Not on yourself!",
	NULL,
	2, 2, 0, 5, 1, TRUE
    },

    {
	"xf-pull",
	"On whom do you wish to do this?",
	NULL,
	"You wrap your arms and legs around $M and pull $M into you.",
	"$n wraps $m arms and legs around $N and pulls $M into $m.",
	"$n wraps $m arms and legs around you and pulls you into $m.",
	"Not on yourself!",
	NULL,
	2, 2, 0, 15, 10, TRUE
    },

    {
	"xf-squeeze",
	"On whom do you wish to do this?",
	NULL,
	"Your wrap your legs around $M and squeeze tightly.",
	"$n wraps $m legs around $N and squeezes tightly.",
	"$n wraps $m legs around you and squeezes tightly.",
	"Not on yourself!",
	NULL,
	2, 2, 0, 15, 10, TRUE
    },

    {
	"xf-titfuck",
	"Whom do you wish to treat to this?",
	NULL,
	"You take $N's cock and place it between your breasts, as $N gently thrusts.",
	"$n takes $N's penis, places it between $s breasts, and wanks $M off.",
	"$n takes your cock, places it between her breasts, and wanks you gently with them.",
	"Not on yourself!",
	NULL,
	2, 1, 0, 10, 20, FALSE
    },

{
"xf-fondle",
"On whom do you wish to perform this?",
NULL,
"You reach down and gently fondle $N's warm penis.",
"$n takes $N's cock into her hands, fondling it gently.",
"$n takes your warm cock into her hands, fondling you gently.",
"No.",
NULL,
2, 0, 0, 5, 13, FALSE
},

{
"xf-bob",
"On whom do you wish to perform this?",
NULL,
"You wrap your lips tight around $N's cock and bob your head back and forth, forcing him into your mouth.",
"$n wraps her lips over $N's cock and bobs her head back and forth, making him fuck her mouth.",
"$n wraps her lips tight around your cock and bobs her head back and forth, pumping your length in and out of her mouth.",
"No.",
NULL,
2, 2, 0, 20, 25, TRUE
},
    {
	"xf-undress",
	"On whom do you wish to do this?",
	NULL,
	"You push $N onto the floor, a gleam in your eyes, and tear $S clothes off.",
	"$n pushes $N to the floor, tears $S clothes from $S body.",
	"$n pushes you to the floor, grins, and rips your clothes from your body.",
	"Not on yourself!",
	NULL,
	2, 0, 0, 1, 1, FALSE
    },

    {
	"xm-anal",
	"On whom do you wish to do this?",
	NULL,
	"$N screams in extacy as you come from behind and penetrate $M tight ass from behind.",
	"$n comes from behind $N and penetrates $M tight ass from behind.",
	"You scream as $n comes from behind and penetrates your tight ass from behind!",
	"Not on yourself!",
	NULL,
	1, 1, 250, 25, 25, FALSE
    },

    {
"xm-spank",
"Who's the naughty whore?",
NULL,
"You grab $N by the hair and throw her over your knees, slapping her hard on the ass.",
"$n visciously throws $N over his knee, spanking her relentlessly on her tight ass.",
"You cry out softly as $n visciously takes you over his knee, spanking you mercilessly.",
"Nah.",
NULL,
1, 0, 0, 33, -14, FALSE
},
{
"xm-69",
"Whom do you wish to perform this on?",
NULL,
"You pull $N on top of you and spread her legs, burying your face in her pussy as she sucks on your hard cock.",
"$n pulls $N on top of him and buries his face between her legs, eating her out as she goes down on his cock.",
"$n pulls you on top of him and spreads your legs, burying his face between your legs and sucking on your clit as you takes his cock into your mouth.",
"No.",
NULL,
1, 2, 0, 24, 24, TRUE
},

{
"xm-urine",
"Who gets to taste it?",
NULL,
"You force open $N's slutty mouth and shoot a hot stream of piss into it, making her swallow.",
"$n forces open $Ns mouth and shoots a hot stream of golden piss into it, making her swallow.",
"$n forces open your slutty mouth and shoots a hot, golden stream of his piss into it, making you swallow.",
"No.",
NULL,
1, 0, 0, 40, -19, FALSE
},
{
"xm-beg",
"Beg who, you worthless bitchboy?",
NULL,
"You drop to your knees, tears in your eyes, and beg for $N to take you as hers.",
"$n drops to his knees before $N, begging for her to take him as hers.",
"$n drops to his knees before you with tears in his eyes, sobbing as he begs for you to take him as your own personal toy.",
"You worthless slut, you can't even do this right.",
NULL,
1, 0, 0, -15, 30, FALSE
},
{
"xm-facial",
"Who gets to have their slutty face done over?",
NULL,
"You groan as you shoot your load across her delicate features, your hot cum coating her face and dripping from her chin.",
"$n grits his teeth as he shoots his sticky cum over $N's face, moaning as she licks her lips and lets it drip down.",
"$n's eyes widen as he shoots his hot, sticky cum over your face, letting it drip from your chin and trickle over your lips.",
"Nope.",
NULL,
1, 2, 0, 300, 20, TRUE
},
{
"xm-cum",
"So close, yet, so far away?",
NULL,
"You let out a low moan as you release your load into $N, filling her up with your hot cum.",
"$n cries out as he shoots his hot, sticky cum all inside of $N, his creamy load shooting home.",
"$n grits his teeth and shoots his sticky cum inside of yor whorish body, filling you up until it drips out.",
"Nopers.",
NULL,
1, 2, 0, 300, 20, TRUE
},
{
	"xm-breasts",
	"On whom do you wish to do this?",
	NULL,
	"You gently run the tip of your tongue across $M naked breasts.",
	"$n gently runs the tip of $s tongue across $N's naked breasts.",
	"$n gently runs the tip of $s tongue across your naked breasts.",
	"Not on yourself!",
	NULL,
	1, 0, 0, 5, 10, FALSE
    },

    {
	"xm-cup",
	"On whom do you wish to do this?",
	NULL,
	"You cup $N's breasts in your hands, and caress $S nipples.",
	"$n cups $N's breasts in $s hands and caress' $S nipples.",
	"$n cups your breasts in $s palms and caress' your nipples.",
	"ON YOURSELF??",
	NULL,
	1, 0, 0, 1, 5, FALSE
    },

    {
	"xm-doggy",
	"On whom do you wish to do this?",
	NULL,
	"You roll $M onto all fours and penetrate $M hot flesh from behind.",
	"$n rolls $N onto all fours and penetrates $M hot flesh from behind.",
	"$n rolls you onto all fours and penetrates your hot flesh from behind.",
	"Not on yourself!",
	NULL,
	1, 1, 250, 25, 15, FALSE
    },

    {
	"xm-finger",
	"On whom do you wish to do this?",
	NULL,
	"You slide your fingers between $M legs, gently stroking $M clitoris.",
	"$n slides $s fingers between $N's legs, gently stroking $M clitoris.",
	"$n slides $s fingers between your legs, gently stroking your clitoris.",
	"Not on yourself!",
	NULL,
	1, 0, 250, 0, 10, FALSE
    },

    {
	"xm-fist",
	"On whom do you wish to do this? I hope you asked!",
	NULL,
	"You make a fist and thrust it up $N's spread wide vagina as she screams with pleasure.",
	"$N gasps as $n pushes $s hand up between $S legs into $S vagina.",
	"$n spreads your legs wide, and thrusts $s hand up your vagina making you cry out in pleasure.",
	"C'est non possible.. I hope...",
	NULL,
        1, 1, 250, 5, 15, FALSE
    },

    {
	"xm-floor",
	"On whom do you wish to do this?",
	NULL,
	"You lower $M to the floor, and slide your body between $M parted legs.",
	"$n lowers $N to the floor, and slides $s body between $M parted legs.",
	"$n lowers you to the floor, and slides $s body between your parted legs.",
	"Not on yourself!",
	NULL,
	1, 1, 250, 15, 10, TRUE
    },

    {
	"xm-jerkoff",
	"On whom do you wish to do this?",
	NULL,
	"You grab your penis and begin to jerkoff for $N.",
	"$n grabs your penis and begins to jerkoff for $N.",
	"$n grab his penis and begin to jerkoff for your viewing pleasure.  What a turn on!.",
	"Not on yourself!",
	NULL,
	1, 1, 0, 25, 5, FALSE
    },

	{
        "xm-rape",
        "On whom do you wish to do this?",
        NULL,
        "You grab $S and rape her!",
        "$n grabs $S and rapes her!",
        "$n grab $S and rapes her, don't watch!.",
        "Not on yourself!",
        NULL,
        1, 1, 0, 25, 5, FALSE
    },
	
    {
	"xm-nipple",
	"On whom do you wish to do this?",
	NULL,
	"You gently twist $M nipple between your thumb and forefinger.",
	"$n gently twists $N's nipple between $s thumb and forefinger.",
	"$n gently twists your nipple between $s thumb and forefinger.",
	"Not on yourself!",
	NULL,
	1, 0, 0, 5, 10, FALSE
    },

    {
	"xm-oral",
	"On whom do you wish to do this?",
	NULL,
	"$N squirms in delight as you bend down and run your tongue along and into $S vagina.",
	"$N squirms ecstatically as $n licks and kisses $S loveslit.",
	"$n wriggles $s tongue about between your legs, making you squirm in ecstacy.",
	"Biologically impossible I think you'll find!",
	NULL,
	1, 0, 0, 10, 25, FALSE
    },

    {
	"xm-press",
	"On whom do you wish to do this?",
	NULL,
	"You press $M against the wall, pulling $M legs around your hips.",
	"$n presses $N against the wall, pulling $M legs around $s hips.",
	"$n presses you against the wall, pulling your legs around $s hips.",
	"Not on yourself!",
	NULL,
	1, 1, 250, 25, 20, TRUE
    },

    {
	"xm-pull",
	"On whom do you wish to do this?",
	NULL,
	"You grab $M around the hips and pull $M firmly onto your erection.",
	"$n grabs $N around the hips and pull $M firmly onto $s erection.",
	"$n grabs you around the hips and pulls you firmly onto $s erection.",
	"Not on yourself!",
	NULL,
	1, 2, 0, 10, 10, TRUE
    },

    {
	"xm-spoon",
	"On whom do you wish to do this?",
	NULL,
	"You roll $M onto $S side and penetrate $M hot flesh from behind.",
	"$n rolls $N onto $S side and penetrates $M hot flesh from behind.",
	"$n rolls you onto your side and penetrates your hot flesh from behind.",
	"Not on yourself!",
	NULL,
	1, 1, 250, 20, 20, TRUE
    },

    {
	"xm-suck",
	"On whom do you wish to do this?",
	NULL,
	"You suck slowly on $M nipple, feeling it harden between your lips.",
	"$n suck slowly on $N's nipple.",
	"$n sucks slowly on your nipple, and you feel it harden between $s lips.",
	"Not on yourself!",
	NULL,
	1, 0, 0, 5, 10, FALSE
    },

    {
	"xm-thrust",
	"On whom do you wish to do this?",
	NULL,
	"You thrust deeply between $M warm, slippery thighs.",
	"$n thrusts deeply between $N's warm, slippery thighs.",
	"$n thrusts deeply between your warm, slippery thighs.",
	"Not on yourself!",
	NULL,
	1, 2, 0, 15, 10, TRUE
    },
{
"xm-hump",
"On whom do you wish to do this?",
NULL,
"You push $M onto all fours and mount her, madly shoving your hard cock in and out of her tiny hole.",
"$n mounts $N like she was a bitch in heat, madly pumping in and out of her hole.",
"$n pushes you onto all fours like you were a bitch and heat and mounts you as he rapidly shoves his cock in and out of your slutty hole.",
"No!.",
NULL,
1, 2, 0, 35, 65, TRUE
},

{
"xm-mfuck",
"Fuck who?",
NULL,
"You have $N wrap her lips tight around your cock, and you thrust gently, pumping your cock in and out of her warm, wet mouth.",
"$N wraps her lips tight aroudn $n's cock, and he thrusts gently, pumping in and out from between her lips.",
"You wrap your lips tight around $n's cock and he thrusts gently, pumping in and out from between your ruby red lips.",
"No.",
NULL,
1, 2, 0, 12, 20, TRUE
},

{
"xm-feed",
"Feed who?",
NULL,
"You gently stick your fingers in $N's hot cunt and bring them to her lips, making her suck them clean.",
"$n sticks his fingers in $N's twat and then brings them to her lips, making her lick them clean.",
"$n sticks his fingers in your dripping wet pussy and then brings them to your lips, where you suck them clean.",
"No.",
NULL,
1, 2, 0, 5, 10, FALSE
},

{
"xm-gag",
"Who gets to taste it?",
NULL,
"You ram your cock deep into $M mouth, making her gag and try to swallow.",
"$n rams his cock deep into $N's throat, making her gag and try to swallow.",
"$n shoves his cock deep into your throat, making you gag and try to swallow.",
"No.",
NULL,
1, 2, 0, 5, 13, FALSE
},
    {
	"xm-tug",
	"On whom do you wish to do this?",
	NULL,
	"You gently tug $M nipple between your teeth.",
	"$n gently tugs $N's nipple between $s teeth.",
	"$n gently tugs your nipple between $s teeth.",
	"Not on yourself!",
	NULL,
	1, 0, 0, 5, 10, FALSE
    },

{
"xm-nibble",
"On whom do you wish to do this?",
NULL,
"You push $M onto her back and bury your face in her cunt, nibbling gently on her clit.",
"$n pushes $N onto her back and buries his face between her legs, nibbling gently on her clit.",
"$n pushes you onto your back and buries his face in your womanhood, nibbling gently on your clit.",
"Nope.",
NULL,
1, 1, 0, 10, 45, FALSE
},
    {
	"xm-undress",
	"Who do you wish to undress?",
	NULL,
	"You gently tug at $N's garments with your teeth, until $E stands naked before you.",
	"$n gently tugs at $N's clothes with his teeth, until $E stands naked infront of $m.",
	"$n gently tugs at your clothing with his teeth, you stand naked before $m.",
	"Not on yourself!",
	NULL,
	1, 0, 0, 1, 1, FALSE
    },

    {
	"",
	NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0, FALSE
    }
};

/*
 * The main entry point for executing commands.
 * Can be recursively called from 'at', 'order', 'force'.
 */
void interpret( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *unveil;
    char arg[MAX_STRING_LENGTH];
    char argu[MAX_STRING_LENGTH];
    char buf[MAX_INPUT_LENGTH];
    char command[MAX_STRING_LENGTH];
    char logline[MAX_STRING_LENGTH];
    int cmd;
    int trust;
    bool found, foundstar = FALSE;
    sh_int col = 0;
    int star = 0;

//int string_count = nAllocString ;
//int perm_count = nAllocPerm ;
char cmd_copy[MAX_INPUT_LENGTH] ;
//char buf2[MAX_STRING_LENGTH] ;




    sprintf(argu,"%s %s",arg,one_argument( argument, arg));

    /*
     * Strip leading spaces.
     */
    while ( isspace(*argument) )
	argument++;
    if ( argument[0] == '\0' )
	return;

	strcpy(cmd_copy,argument);


    /*
     * Implement freeze command.
     */
    if ( !IS_NPC(ch) && IS_SET(ch->act, PLR_FREEZE) )
    {
	send_to_char( "You're totally frozen!\n\r", ch );
	return;
    }

    if ( !IS_NPC(ch) && IS_SET(ch->extra, EXTRA_AFK) )
	do_afk(ch,"");

    /*
     * Grab the command word.
     * Special parsing so ' can be a command,
     *   also no spaces needed after punctuation.
     */
    strcpy( logline, argument );
    if ( !isalpha(argument[0]) && !isdigit(argument[0]) )
    {
	command[0] = argument[0];
	command[1] = '\0';
	argument++;
	while ( isspace(*argument) )
	    argument++;
    }
    else
    {
	argument = one_argument( argument, command );
    }


    /*
    *    Do my weird star thingy
    */ 
    if (command[strlen(command) - 1] == '*')
    {
	command[strlen(command) - 1] = '\0';

        for ( cmd = 0; cmd_table[cmd].name[0] != '\0'; cmd++ )
        {
	    if ((!str_prefix(command, cmd_table[cmd].name) || strlen(command) == 0)
		&& can_interpret(ch, cmd))
	    {
		foundstar = TRUE;
		star++;
	        sprintf( buf, "%-15s", cmd_table[cmd].name );
	        send_to_char( buf, ch );
	        if ( ++col % 5 == 0 )
		    send_to_char( "\n\r", ch );
	    }
	}
	if (col % 5 != 0 && foundstar)
	    send_to_char("\n\r", ch);

	if (foundstar && star != 0)
  	{
	    sprintf(buf, "\n%d command%s found.\n\r", star,
		(star > 1) ? "s" : "");
	    stc(buf, ch);
	}

	if (!foundstar)
	{
	    stc("No commands found.\n\r", ch);
  	}
	return;
    }


    /*
     * Look for command in command table.
     */
    found = FALSE;
    trust = get_trust( ch );
    for ( cmd = 0; cmd_table[cmd].name[0] != '\0'; cmd++ )
    {
	if ( command[0] == cmd_table[cmd].name[0]
	&&   !str_prefix( command, cmd_table[cmd].name )
	&&   cmd_table[cmd].level <= trust )
	{
	    if (IS_HEAD(ch,LOST_HEAD) || IS_EXTRA(ch,EXTRA_OSWITCH) )
	    {
		if      (!str_cmp( cmd_table[cmd].name, "say"     )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "'"       )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "immtalk" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, ":"       )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "chat"    )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "."       )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "look"    )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "save"    )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "exits"   )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "emote"   )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "tell"    )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "order"   )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "who"     )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "weather" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "where"   )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "relevel" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "safe"    )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "scan"    )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "spy"     )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "score"   )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "save"    )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "inventory" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "oreturn" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "roll" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "leap" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "lifespan" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "nightsight" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "truesight" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "horns" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "fangs" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "cast" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "plasma" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "ashes" )) found = TRUE;
                else if (!str_cmp(cmd_table[cmd].name,"obj")&&
                  !IS_NPC(ch) && ch->pcdata->obj_vnum!=0)found=TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "quit" ) &&
			!IS_NPC(ch) && ch->pcdata->obj_vnum != 0) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "humanform" ) &&
			!IS_NPC(ch) && ch->pcdata->obj_vnum != 0) found = TRUE;
		else {
		    send_to_char( "Not without a body!\n\r", ch ); return; }
	    }
            else if (IS_EXTRA(ch,EXTRA_EARTHMELD) )
	    {
                if      (!str_cmp( cmd_table[cmd].name, "earthmeld"  )) found = TRUE;
      else if (!str_cmp(cmd_table[cmd].name,"burrow")) found= TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "look" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "save" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "exits")) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "inventory" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "who" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "weather" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "where" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "relevel" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "safe" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "scan" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "spy"  )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "shadowsight" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "vclan" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "upkeep" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "score" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "immune" )) found = TRUE;
                else if (!str_cmp( cmd_table[cmd].name, "clandisc" ))
found = TRUE;
                else {
                    send_to_char( "Not while in the ground.\n\r", ch );
		    return; }
	    }
            else if (ch->embracing!=NULL
                  || ch->embraced!=NULL)
	    {
		if      (!str_cmp( cmd_table[cmd].name, "say"  )) found =
TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "'"    )) found =
TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "chat" )) found =
TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "."    )) found =
TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "look" )) found =
TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "inventory" ))
found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "who" )) found =
TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "relevel" )) found
= TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "score" )) found =
TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "report" )) found
= TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "goto" )) found =
TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "kill" )) found
= TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "berserk" )) found
= TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "testemb" )) found
= TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "reboot" )) found
= TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "save" )) found
= TRUE;
 else if (!str_cmp(cmd_table[cmd].name,"diablerize") && ch->embracing
!=NULL) found=TRUE;
else if(!str_cmp(cmd_table[cmd].name,"restore"))found=TRUE;
		else {
                    send_to_char( "Not while in an embrace.\n\r", ch );
		    return; }
	    }

            else if (IS_EXTRA(ch,TIED_UP) )
	    {
		if      (!str_cmp( cmd_table[cmd].name, "say"  )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "'"    )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "chat" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "."    )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "yell" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "shout")) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "look" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "save" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "exits")) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "inventory" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "tell" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "restore" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "order" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "who" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "weather" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "where" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "introduce" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "relevel" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "safe" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "scan" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "spy"  )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "darkness" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "sleep" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "wake" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "fangs" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "claws" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "nightsight" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "shadowsight" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "shadowplane" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "regenerate" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "shield" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "vclan" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "upkeep" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "score" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "immune" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "consent" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "report" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "goto" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "flex" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "change" )) found = TRUE;
		else if (!str_cmp( cmd_table[cmd].name, "drink" )) found = TRUE;
		else {
		    send_to_char( "Not while tied up.\n\r", ch );
		    if (ch->position > POS_STUNNED)
		    	act("$n strains against $s bonds.",ch,NULL,NULL,TO_ROOM);
		    return; }
	    }
	    found = TRUE;
	    break;
	}
    }

    /*
     * Log and snoop.
     */
    if ( cmd_table[cmd].log == LOG_NEVER )
	strcpy( logline, "XXXXXXXX XXXXXXXX XXXXXXXX" );
    if ( ( !IS_NPC(ch) && IS_SET(ch->act, PLR_LOG) )
    ||   fLogAll
    ||   cmd_table[cmd].log == LOG_ALWAYS )
    {
	if (!IS_CREATOR(ch))
	{
	sprintf( log_buf, "Log %s: %s", ch->pcdata->switchname, logline );
	log_string( log_buf );
	}
    }

    if ( ch->desc != NULL && ch->desc->snoop_by != NULL )
    {
	write_to_buffer( ch->desc->snoop_by, "% ",    2 );
	write_to_buffer( ch->desc->snoop_by, logline, 0 );
	write_to_buffer( ch->desc->snoop_by, "\n\r",  2 );
    }

    if ( ch != NULL && ch->unveil != NULL )
    {
	unveil = ch->unveil;
	
	if ( unveil->in_room->vnum != ch->in_room->vnum )
	{
	  sprintf(buf, "You lose your mental link with %s.\n\r",ch->name);
	  stc(buf,unveil);
	}
	else
	{
	  stc("% ", unveil);
	  stc(logline, unveil);
	  stc("\n\r", unveil);
	}
    }

       if (ch->desc != NULL)
       write_to_buffer(ch->desc,"\n\r",2);	
    if ( !found )
    {
	/*
	 * Look for command in socials table.
	 */
	if ( !check_social( ch, command, argument ) )
	{
	    if ( !check_xsocial( ch, command, argument ) )
		send_to_char( "Huh?\n\r", ch );
	}
/*
	else
	{
	    sprintf(kavirarg,">>>%s",argu);
	    room_text( ch, kavirarg );
	}
*/
	return;
    }
    else /* a normal valid command.. check if it is disabled */
      if (check_disabled (&cmd_table[cmd]))
      {
              send_to_char ("This command has been temporarily disabled.\n\r", ch );
             return;
      }

    /*
     * Character not in position for command?
     */
    if ( ch->position < cmd_table[cmd].position )
    {
	switch( ch->position )
	{

	case POS_DEAD:
	    send_to_char( "Lie still; you are DEAD.\n\r", ch );
	    break;

	case POS_MORTAL:
	case POS_INCAP:
	{
	if (IS_CLASS(ch, CLASS_VAMPIRE) 
          && (ch->pcdata->powers[VPOWER_PROTEAN] >= 8 )
	  && (cmd_table[cmd].name == "south"
	  || cmd_table[cmd].name == "east"
	  || cmd_table[cmd].name == "west"
	  || cmd_table[cmd].name == "down"
	  || cmd_table[cmd].name == "north"
          || cmd_table[cmd].name == "up"
          || cmd_table[cmd].name == "flex"))
		{
             (*cmd_table[cmd].do_fun) ( ch, argument );
              tail_chain( );
		WAIT_STATE(ch, 24);
                } 
	else  
	 send_to_char( "You are hurt far too bad for that.\n\r", ch );
	    break;
	}
	case POS_STUNNED:
	{
        if (IS_CLASS(ch, CLASS_VAMPIRE)
          && (ch->pcdata->powers[VPOWER_PROTEAN] >= 8 )
          && (cmd_table[cmd].name == "south"
          || cmd_table[cmd].name == "east"
          || cmd_table[cmd].name == "west"
          || cmd_table[cmd].name == "down"
          || cmd_table[cmd].name == "north"
          || cmd_table[cmd].name == "up"
          || cmd_table[cmd].name == "flex")) 
	    {
	     (*cmd_table[cmd].do_fun) ( ch, argument );
    	      tail_chain( );
		WAIT_STATE(ch, 24); 
	    }
	   else 
	    send_to_char( "You are too stunned to do that.\n\r", ch );
	    break;
	}
	case POS_SLEEPING:
	    send_to_char( "In your dreams, or what?\n\r", ch );
	    break;

	case POS_MEDITATING:
	case POS_SITTING:
	case POS_RESTING:
	    send_to_char( "Nah... You feel too relaxed...\n\r", ch);
	    break;

	case POS_FIGHTING:
	    send_to_char( "No way!  You are still fighting!\n\r", ch);
	    break;

	}
	return;
    }

    /*
     * Dispatch the command.
     */

    (*cmd_table[cmd].do_fun) ( ch, argument );
/*
if (string_count < nAllocString)
{
sprintf(buf2,
"Memcheck : Increase in strings :: %s : %s", ch->pcdata->switchname,
cmd_copy) ;
bug(buf2,0);
}

if (perm_count < nAllocPerm)
{
sprintf(buf2,
"Increase in perms :: %s : %s", ch->pcdata->switchname, cmd_copy) ;
bug(buf2,0);
}
*/

    tail_chain( );
/*
    if (!str_cmp(arg,"say"))
    {
    	sprintf(kavirarg,"%s",argu);
    	room_text( ch, strlower(kavirarg) );
    }
    else
    {
    	sprintf(kavirarg,">>>%s",argu);
    	room_text( ch, kavirarg );
    }
*/
    return;
}



bool check_social( CHAR_DATA *ch, char *command, char *argument )
{
    char arg[MAX_STRING_LENGTH];
    CHAR_DATA *victim;
    int cmd;
    bool found;

    found  = FALSE;
    for ( cmd = 0; social_table[cmd].name[0] != '\0'; cmd++ )
    {
	if ( command[0] == social_table[cmd].name[0]
	&&   !str_prefix( command, social_table[cmd].name ) )
	{
	    found = TRUE;
	    break;
	}
    }


    if ( !found )
	return FALSE;

/*
    if ( IS_HEAD(ch,LOST_HEAD) || IS_EXTRA(ch,EXTRA_OSWITCH))
    {
	send_to_char( "You cannot socialise in this form!\n\r", ch );
	return TRUE;
    }
*/
    switch ( ch->position )
    {

    case POS_DEAD:
	send_to_char( "Lie still; you are DEAD.\n\r", ch );
	return TRUE;

    case POS_INCAP:
    case POS_MORTAL:
	send_to_char( "You are hurt far too bad for that.\n\r", ch );
	return TRUE;

    case POS_STUNNED:
	send_to_char( "You are too stunned to do that.\n\r", ch );
	return TRUE;

    case POS_SLEEPING:
	/*
	 * I just know this is the path to a 12" 'if' statement.  :(
	 * But two players asked for it already!  -- Furey
	 */
	if ( !str_cmp( social_table[cmd].name, "snore" ) )
	    break;
	send_to_char( "In your dreams, or what?\n\r", ch );
	return TRUE;

    }

    one_argument( argument, arg );
    victim = NULL;

    if ( arg[0] == '\0' )
    {
	act( social_table[cmd].others_no_arg, ch, NULL, victim, TO_ROOM    );
	act( social_table[cmd].char_no_arg,   ch, NULL, victim, TO_CHAR    );
    }
    else if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
    }
    else if ( victim == ch )
    {
	act( social_table[cmd].others_auto,   ch, NULL, victim, TO_ROOM    );
	act( social_table[cmd].char_auto,     ch, NULL, victim, TO_CHAR    );
    }
    else
    {
	act( social_table[cmd].others_found,  ch, NULL, victim, TO_NOTVICT );
	act( social_table[cmd].char_found,    ch, NULL, victim, TO_CHAR    );
	act( social_table[cmd].vict_found,    ch, NULL, victim, TO_VICT    );

	if ( !IS_NPC(ch) && IS_NPC(victim)
	&&   !IS_AFFECTED(victim, AFF_CHARM)
	&&   IS_AWAKE(victim) )
	{
	    switch ( number_bits( 4 ) )
	    {
	    case 0:
		multi_hit( victim, ch, TYPE_UNDEFINED );
		break;

	    case 1: case 2: case 3: case 4:
	    case 5: case 6: case 7: case 8:
		act( social_table[cmd].others_found,
		    victim, NULL, ch, TO_NOTVICT );
		act( social_table[cmd].char_found,
		    victim, NULL, ch, TO_CHAR    );
		act( social_table[cmd].vict_found,
		    victim, NULL, ch, TO_VICT    );
		break;

	    case 9: case 10: case 11: case 12:
		act( "$n slaps $N.",  victim, NULL, ch, TO_NOTVICT );
		act( "You slap $N.",  victim, NULL, ch, TO_CHAR    );
		act( "$n slaps you.", victim, NULL, ch, TO_VICT    );
		break;
	    }
	}
    }
    return TRUE;
}



bool check_xsocial( CHAR_DATA *ch, char *command, char *argument )
{
    char arg[MAX_STRING_LENGTH];
    CHAR_DATA *victim;
    CHAR_DATA *partner = NULL;
    int cmd;
    int stage;
    int amount;
    bool is_ok = FALSE;
    bool found = FALSE;
    bool one = FALSE;
    bool two = FALSE;

    if (IS_NPC(ch)) return FALSE;

    for ( cmd = 0; xsocial_table[cmd].name[0] != '\0'; cmd++ )
    {
	if ( command[0] == xsocial_table[cmd].name[0]
	&&   !str_prefix( command, xsocial_table[cmd].name ) )
	{
	    found = TRUE;
	    break;
	}
    }

    if ( !found )
	return FALSE;

    switch ( ch->position )
    {

    case POS_DEAD:
	send_to_char( "Lie still; you are DEAD.\n\r", ch );
	return TRUE;

    case POS_INCAP:
    case POS_MORTAL:
	send_to_char( "You are hurt far too bad for that.\n\r", ch );
	return TRUE;

    case POS_STUNNED:
	send_to_char( "You are too stunned to do that.\n\r", ch );
	return TRUE;

    case POS_SLEEPING:
	send_to_char( "In your dreams, or what?\n\r", ch );
	return TRUE;

    }

    one_argument( argument, arg );
    victim = NULL;

    if (IS_EXTRA(ch, TIED_UP))
    {
	send_to_char("You wiggle and strain but the ropes only tighten.\n\r",ch);
        act("$n strains helplessly against $m bonds.",ch,NULL,NULL,TO_ROOM);
	return FALSE;
    }
    else if ( arg[0] == '\0' )
    {
	act( xsocial_table[cmd].others_no_arg, ch, NULL, victim, TO_ROOM    );
	act( xsocial_table[cmd].char_no_arg,   ch, NULL, victim, TO_CHAR    );
    }
    else if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
    }
    else if ( victim == ch )
    {
	act( xsocial_table[cmd].others_auto,   ch, NULL, victim, TO_ROOM );
	act( xsocial_table[cmd].char_auto,     ch, NULL, victim, TO_CHAR );
    }
    else if (IS_NPC(victim))
    {
	send_to_char("You can only perform xsocials on players.\n\r",ch);
    }
    else if (ch->sex != SEX_MALE && ch->sex != SEX_FEMALE)
    {
	send_to_char("You must be either male or female to use these socials.\n\r",ch);
    }
    else if (victim->sex != SEX_MALE && victim->sex != SEX_FEMALE)
    {
	send_to_char("They must be either male or female for these socials.\n\r",ch);
    }
    else if (ch->sex == victim->sex)
    {
	send_to_char("Please stick to people of the opposite gender.\n\r",ch);
    }
    else
    {
	if (xsocial_table[cmd].gender == SEX_MALE && ch->sex != SEX_MALE)
	{
	    send_to_char("Only men can perform this type of social.\n\r",ch);
	}
	else if (xsocial_table[cmd].gender == SEX_FEMALE && ch->sex != SEX_FEMALE)
	{
	    send_to_char("Only women can perform this type of social.\n\r",ch);
	}
	else if (xsocial_table[cmd].gender == SEX_MALE && victim->sex != SEX_FEMALE)
	{
	    send_to_char("You can only perform this social on a woman.\n\r",ch);
	}
	else if (xsocial_table[cmd].gender == SEX_FEMALE && victim->sex != SEX_MALE)
	{
	    send_to_char("You can only perform this social on a man.\n\r",ch);
	}
	else if ((partner = victim->pcdata->partner) == NULL || partner != ch)
	{
	    send_to_char("You cannot perform an xsocial on someone without their CONSENT.\n\r",ch);
	}
	else if (xsocial_table[cmd].stage == 0 && ch->pcdata->stage[0] < 1
	    && ch->pcdata->stage[2] > 0 && ch->sex == SEX_MALE)
	    send_to_char("You have not yet recovered from last time!\n\r",ch);
	else if (xsocial_table[cmd].stage == 0 && victim->pcdata->stage[0] < 1
	    && victim->pcdata->stage[2] > 0 && victim->sex == SEX_MALE)
	    send_to_char("They have not yet recovered from last time!\n\r",ch);
	else if (xsocial_table[cmd].stage > 0 && ch->pcdata->stage[0] < 100)
	    send_to_char("You are not sufficiently aroused.\n\r",ch);
	else if (xsocial_table[cmd].stage > 0 && victim->pcdata->stage[0] < 100)
	    send_to_char("They are not sufficiently aroused.\n\r",ch);
	else if (xsocial_table[cmd].stage > 1 && ch->pcdata->stage[1] < 1)
	    send_to_char("You are not in the right position.\n\r",ch);
	else if (xsocial_table[cmd].stage > 1 && victim->pcdata->stage[1] < 1)
	    send_to_char("They are not in the right position.\n\r",ch);
	else
	{
	    act(xsocial_table[cmd].others_found,  ch, NULL, victim, TO_NOTVICT);
	    act(xsocial_table[cmd].char_found,    ch, NULL, victim, TO_CHAR   );
	    act(xsocial_table[cmd].vict_found,    ch, NULL, victim, TO_VICT   );
	    if (xsocial_table[cmd].chance)
	    {
		if (ch->sex == SEX_FEMALE && 
		    !IS_EXTRA(ch, EXTRA_PREGNANT) && number_range(1,3) == 1) 
		make_preg(ch,victim);
		else if (victim->sex == SEX_FEMALE && 
		    !IS_EXTRA(victim, EXTRA_PREGNANT) && 
		    number_range(1,3) == 1) 
		make_preg(victim,ch);
	    }
	    if (!str_prefix(xsocial_table[cmd].name,"x-tie"))
	    {
		SET_BIT(victim->extra, TIED_UP);
	    }
	    if (xsocial_table[cmd].stage == 1)
	    {
		ch->pcdata->stage[1] = xsocial_table[cmd].position;
		victim->pcdata->stage[1] = xsocial_table[cmd].position;
		if (!IS_SET(ch->extra, EXTRA_DONE))
		{
		    SET_BIT(ch->extra, EXTRA_DONE);
		    if (ch->sex == SEX_FEMALE)
		    {
			act("You feel $n bleed as you enter $m.",ch,NULL,victim,TO_VICT);
			act("You feel yourself bleed as $N enters you.",ch,NULL,victim,TO_CHAR);
			ch->in_room->blood += 1;
		    }
		}
		if (!IS_SET(victim->extra, EXTRA_DONE))
		{
		    SET_BIT(victim->extra, EXTRA_DONE);
		    if (victim->sex == SEX_FEMALE)
		    {
			act("You feel $N bleed as you enter $M.",ch,NULL,victim,TO_CHAR);
			act("You feel yourself bleed as $n enters you.",ch,NULL,victim,TO_VICT);
			ch->in_room->blood += 1;
		    }
		}
		stage = 2;
	    }
	    else stage = xsocial_table[cmd].stage;
	    if (stage == 2) amount = ch->pcdata->stage[1];
		else amount = 100;
	    if (xsocial_table[cmd].self > 0)
	    {
		is_ok = FALSE;
		if (ch->pcdata->stage[stage] >= amount) is_ok = TRUE;
		ch->pcdata->stage[stage] += xsocial_table[cmd].self;
		if (!is_ok && ch->pcdata->stage[stage] >= amount) 
		{
		    stage_update(ch,victim,stage);
		    one = TRUE;
		}
	    }
	    if (xsocial_table[cmd].other > 0)
	    {
		is_ok = FALSE;
		if (victim->pcdata->stage[stage] >= amount) is_ok = TRUE;
		victim->pcdata->stage[stage] += xsocial_table[cmd].other;
		if (!is_ok && victim->pcdata->stage[stage] >= amount) 
		{
		    stage_update(victim,ch,stage);
		    two = TRUE;
		}
	    }
	    if ( one && two )
	    {
		ch->pcdata->stage[0] = 0;
		victim->pcdata->stage[0] = 0;
		if (!IS_EXTRA(ch, EXTRA_EXP))
		{
		    send_to_char("Congratulations on achieving a simultanious orgasm!  Recieve 100000 exp!\n\r",ch);
		    SET_BIT(ch->extra, EXTRA_EXP);
		    ch->exp += 100000;
		}
		if (!IS_EXTRA(victim, EXTRA_EXP))
		{
		    send_to_char("Congratulations on achieving a simultanious orgasm!  Recieve 100000 exp!\n\r",victim);
		    SET_BIT(victim->extra, EXTRA_EXP);
		    victim->exp += 100000;
		}
	    }
	}
    }
    return TRUE;
}

void stage_update( CHAR_DATA *ch, CHAR_DATA *victim, int stage )
{
    if (IS_NPC(ch) || IS_NPC(victim)) return;
    if (stage == 0)
    {
	if (ch->sex == SEX_MALE)
	{
	    send_to_char("You feel yourself harden.\n\r",ch);
	    act("You feel $n harden.",ch,NULL,victim,TO_VICT);
	    return;
	}
	else if (ch->sex == SEX_FEMALE)
	{
	    send_to_char("You feel moist.\n\r",ch);
	    act("You feel $n dampen.",ch,NULL,victim,TO_VICT);
	    return;
	}
    }
    else if (stage == 2)
    {
	if (ch->sex == SEX_MALE)
	{
	    act("You grit your teeth as you shoot your creamy load inside of $M.",ch,NULL,victim,TO_CHAR);
	    act("$n grits his teeth as he shoots his load inside of you.",ch,NULL,victim,TO_VICT);
	    act("$n grits his teeth as he shoots a load of cum inside of $N.",ch,NULL,victim,TO_NOTVICT);
	    ch->pcdata->stage[0] = 0;
	    ch->pcdata->stage[1] = 0;
	    ch->pcdata->genes[8] += 1;
	    victim->pcdata->genes[8] += 1;
	    save_char_obj(ch);
	    save_char_obj(victim);
	    if (ch->pcdata->stage[0] <= 250) ch->pcdata->stage[0] = 0;
		else victim->pcdata->stage[0] -= 250;
	    victim->pcdata->stage[1] = 0;
	    if (victim->sex == SEX_FEMALE && 
		!IS_EXTRA(victim, EXTRA_PREGNANT) && number_percent() <= 8) 
	    make_preg(victim,ch);
	    return;
	}
	else if (ch->sex == SEX_FEMALE)
	{
	    act("You whimper as you cum.",ch,NULL,victim,TO_CHAR);
	    act("$n whimpers as $e cums.",ch,NULL,victim,TO_ROOM);
	    if (victim->pcdata->stage[2] < 1 || victim->pcdata->stage[2] >= 250)
	    {
		ch->pcdata->stage[2] = 0;
		if (ch->pcdata->stage[0] >= 200) ch->pcdata->stage[0] -= 100;
	    }
	    else ch->pcdata->stage[2] = 200;
	    return;
	}
    }
    return;
}

void make_preg( CHAR_DATA *mother, CHAR_DATA *father )
{
    char *strtime;
    char buf [MAX_STRING_LENGTH];

    if (IS_NPC(mother) || IS_NPC(father)) return;
/*
    if (IS_AFFECTED(mother, AFF_CONTRACEPTION)) return;
*/  
  strtime = ctime( &current_time );
    strtime[strlen(strtime)-1] = '\0';
    free_string(mother->pcdata->conception);
    mother->pcdata->conception = str_dup(strtime);
    sprintf(buf,"%s %s",mother->name,father->name);
    free_string(mother->pcdata->cparents);
    mother->pcdata->cparents = str_dup(buf);
    SET_BIT(mother->extra, EXTRA_PREGNANT);
    mother->pcdata->genes[0] = (mother->max_hit + father->max_hit) * 0.5;
    mother->pcdata->genes[1] = (mother->max_mana + father->max_mana) * 0.5;
    mother->pcdata->genes[2] = (mother->max_move + father->max_move) * 0.5;
    if (IS_IMMUNE(mother, IMM_SLASH) && IS_IMMUNE(father, IMM_SLASH))
	SET_BIT(mother->pcdata->genes[3], IMM_SLASH);
    if (IS_IMMUNE(mother, IMM_STAB) && IS_IMMUNE(father, IMM_STAB))
	SET_BIT(mother->pcdata->genes[3], IMM_STAB);
    if (IS_IMMUNE(mother, IMM_SMASH) && IS_IMMUNE(father, IMM_SMASH))
	SET_BIT(mother->pcdata->genes[3], IMM_SMASH);
    if (IS_IMMUNE(mother, IMM_ANIMAL) && IS_IMMUNE(father, IMM_ANIMAL))
	SET_BIT(mother->pcdata->genes[3], IMM_ANIMAL);
    if (IS_IMMUNE(mother, IMM_MISC) && IS_IMMUNE(father, IMM_MISC))
	SET_BIT(mother->pcdata->genes[3], IMM_MISC);
    if (IS_IMMUNE(mother, IMM_CHARM) && IS_IMMUNE(father, IMM_CHARM))
	SET_BIT(mother->pcdata->genes[3], IMM_CHARM);
    if (IS_IMMUNE(mother, IMM_HEAT) && IS_IMMUNE(father, IMM_HEAT))
	SET_BIT(mother->pcdata->genes[3], IMM_HEAT);
    if (IS_IMMUNE(mother, IMM_COLD) && IS_IMMUNE(father, IMM_COLD))
	SET_BIT(mother->pcdata->genes[3], IMM_COLD);
    if (IS_IMMUNE(mother, IMM_LIGHTNING) && IS_IMMUNE(father, IMM_LIGHTNING))
	SET_BIT(mother->pcdata->genes[3], IMM_LIGHTNING);
    if (IS_IMMUNE(mother, IMM_ACID) && IS_IMMUNE(father, IMM_ACID))
	SET_BIT(mother->pcdata->genes[3], IMM_ACID);
    if (IS_IMMUNE(mother, IMM_VOODOO) && IS_IMMUNE(father, IMM_VOODOO))
	SET_BIT(mother->pcdata->genes[3], IMM_VOODOO);
    if (IS_IMMUNE(mother, IMM_HURL) && IS_IMMUNE(father, IMM_HURL))
	SET_BIT(mother->pcdata->genes[3], IMM_HURL);
    if (IS_IMMUNE(mother, IMM_BACKSTAB) && IS_IMMUNE(father, IMM_BACKSTAB))
	SET_BIT(mother->pcdata->genes[3], IMM_BACKSTAB);
    if (IS_IMMUNE(mother, IMM_KICK) && IS_IMMUNE(father, IMM_KICK))
	SET_BIT(mother->pcdata->genes[3], IMM_KICK);
    if (IS_IMMUNE(mother, IMM_DISARM) && IS_IMMUNE(father, IMM_DISARM))
	SET_BIT(mother->pcdata->genes[3], IMM_DISARM);
    if (IS_IMMUNE(mother, IMM_STEAL) && IS_IMMUNE(father, IMM_STEAL))
	SET_BIT(mother->pcdata->genes[3], IMM_STEAL);
    if (IS_IMMUNE(mother, IMM_SLEEP) && IS_IMMUNE(father, IMM_SLEEP))
	SET_BIT(mother->pcdata->genes[3], IMM_SLEEP);
    if (IS_IMMUNE(mother, IMM_DRAIN) && IS_IMMUNE(father, IMM_DRAIN))
	SET_BIT(mother->pcdata->genes[3], IMM_DRAIN);
    mother->pcdata->genes[4] = number_range(1,2);
    return;
}

/*
 * Return true if an argument is completely numeric.
 */
bool is_number( char *arg )
{
    if ( *arg == '\0' )
	return FALSE;

    for ( ; *arg != '\0'; arg++ )
    {
	if ( !isdigit(*arg) )
	    return FALSE;
    }

    return TRUE;
}



/*
 * Given a string like 14.foo, return 14 and 'foo'
 */
int number_argument( char *argument, char *arg )
{
    char *pdot;
    int number;
    
    for ( pdot = argument; *pdot != '\0'; pdot++ )
    {
	if ( *pdot == '.' )
	{
	    *pdot = '\0';
	    number = atoi( argument );
	    *pdot = '.';
	    strcpy( arg, pdot+1 );
	    return number;
	}
    }

    strcpy( arg, argument );
    return 1;
}



/*
 * Pick off one argument from a string and return the rest.
 * Understands quotes.
 */
char *one_argument( char *argument, char *arg_first )
{
    char cEnd;

    while ( isspace(*argument) )
	argument++;

    cEnd = ' ';
    if ( *argument == '\'' || *argument == '"' )
	cEnd = *argument++;

    while ( *argument != '\0' )
    {
	if ( *argument == cEnd )
	{
	    argument++;
	    break;
	}
	*arg_first = LOWER(*argument);
	arg_first++;
	argument++;
    }
    *arg_first = '\0';

    while ( isspace(*argument) )
	argument++;

    return argument;
}

/* Syntax is:
disable - shows disabled commands
disable <command> - toggles disable status of command
*/

void do_disable (CHAR_DATA *ch, char *argument)
{
	int i;
	DISABLED_DATA *p,*q;
	char buf[100];
	
	if (IS_NPC(ch))
	{
		send_to_char ("RETURN first.\n\r",ch);
		return;
	}
	
	if (!argument[0]) /* Nothing specified. Show disabled commands. */
	{
		if (!disabled_first) /* Any disabled at all ? */
		{
			send_to_char ("There are no commands disabled.\n\r",ch);
			return;
		}

		send_to_char ("Disabled commands:\n\r"
		              "Command      Level   Disabled by\n\r",ch);
		                
		for (p = disabled_first; p; p = p->next)
		{
			sprintf (buf, "%-12s %5d   %-12s\n\r",p->command->name, p->level, p->disabled_by);
			send_to_char (buf,ch);
		}
		return;
	}
	
	/* command given */

	/* First check if it is one of the disabled commands */
	for (p = disabled_first; p ; p = p->next)
		if (!str_cmp(argument, p->command->name))
			break;
			
	if (p) /* this command is disabled */
	{
	/* Optional: The level of the imm to enable the command must equal or exceed level
	   of the one that disabled it */
	
		if (get_trust(ch) < p->level)
		{
			send_to_char ("This command was disabled by a higher power.\n\r",ch);
			return;
		}
		
		/* Remove */
		
		if (disabled_first == p) /* node to be removed == head ? */
			disabled_first = p->next;
		else /* Find the node before this one */
		{
			for (q = disabled_first; q->next != p; q = q->next); /* empty for */
			q->next = p->next;
		}
		
		free_string (p->disabled_by); /* free name of disabler */
		free_mem (p,sizeof(DISABLED_DATA)); /* free node */
		
		save_disabled(); /* save to disk */
		send_to_char ("Command enabled.\n\r",ch);
	}
	else /* not a disabled command, check if that command exists */
	{
		/* IQ test */
		if (!str_cmp(argument,"disable"))
		{
			send_to_char ("You cannot disable the disable command.\n\r",ch);
			return;
		}

		/* Search for the command */
		for (i = 0; cmd_table[i].name[0] != '\0'; i++)
			if (!str_cmp(cmd_table[i].name, argument))
				break;

		/* Found? */				
		if (cmd_table[i].name[0] == '\0')
		{
			send_to_char ("No such command.\n\r",ch);
			return;
		}

		/* Can the imm use this command at all ? */				
		if (cmd_table[i].level > get_trust(ch))
		{
			send_to_char ("You dot have access to that command; you cannot disable it.\n\r",ch);
			return;
		}
		
		/* Disable the command */
		
		p = alloc_mem (sizeof(DISABLED_DATA));

		p->command = &cmd_table[i];
		p->disabled_by = str_dup (ch->pcdata->switchname); /* save name of disabler */
		p->level = get_trust(ch); /* save trust */
		p->next = disabled_first;
		disabled_first = p; /* add before the current first element */
		
		send_to_char ("Command disabled.\n\r",ch);
		save_disabled(); /* save to disk */
	}
}

/* Check if that command is disabled 
   Note that we check for equivalence of the do_fun pointers; this means
   that disabling 'chat' will also disable the '.' command
*/   
bool check_disabled (const struct cmd_type *command)
{
	DISABLED_DATA *p;
	
	for (p = disabled_first; p ; p = p->next)
		if (p->command->do_fun == command->do_fun)
			return TRUE;

	return FALSE;
}

/* Load disabled commands */
void load_disabled()
{
	FILE *fp;
	DISABLED_DATA *p;
	char *name;
	int i;
	
	disabled_first = NULL;
	
	fp = fopen (DISABLED_FILE, "r");
	
	if (!fp) /* No disabled file.. no disabled commands : */
		return;
		
	name = fread_word (fp);
	
	while (str_cmp(name, END_MARKER)) /* as long as name is NOT END_MARKER :) */
	{
		/* Find the command in the table */
		for (i = 0; cmd_table[i].name[0] ; i++)
			if (!str_cmp(cmd_table[i].name, name))
				break;
				
		if (!cmd_table[i].name[0]) /* command does not exist? */
		{
			bug ("Skipping uknown command in " DISABLED_FILE " file.",0);
			fread_number(fp); /* level */
			fread_word(fp); /* disabled_by */
		}
		else /* add new disabled command */
		{
			p = alloc_mem(sizeof(DISABLED_DATA));
			p->command = &cmd_table[i];
			p->level = fread_number(fp);
			p->disabled_by = str_dup(fread_word(fp)); 
			p->next = disabled_first;
			
			disabled_first = p;

		}
		
		name = fread_word(fp);
	}

	fclose (fp);		
}

/* Save disabled commands */
void save_disabled()
{
	FILE *fp;
	DISABLED_DATA *p;
	
	if (!disabled_first) /* delete file if no commands are disabled */
	{
		unlink (DISABLED_FILE);
		return;
	}
	
	fp = fopen (DISABLED_FILE, "w");
	
	if (!fp)
	{
		bug ("Could not open " DISABLED_FILE " for writing",0);
		return;
	}
	
	for (p = disabled_first; p ; p = p->next)
		fprintf (fp, "%s %d %s\n", p->command->name, p->level, p->disabled_by);
		
	fprintf (fp, "%s\n",END_MARKER);
		
	fclose (fp);
}


void load_bans() 

{
        FILE *fp;
        BAN_DATA *p;
        char *name;

	ban_first = NULL;
	fp = fopen (BAN_LIST, "r");

	if (!fp) return;

	name = fread_word(fp);
	
	while (str_cmp(name, END_MARKER)) {
		p = alloc_mem(sizeof(BAN_DATA));
		p->name = name;
		p->next = ban_first;
		ban_first = p;
		name = fread_word(fp);}

	fclose(fp);
}
/*
{
	FILE *fp;
	BAN_DATA *p;
	char *name;
	
	ban_first = NULL;
	
	fp = fopen (BAN_LIST, "r");
	
	if (!fp) 
		return;
		
	name = fread_word (fp);
	
	while (str_cmp(name, END_MARKER)) * as long as name is NOT END_MARKER :) *
	{
			p = alloc_mem(sizeof(BAN_DATA));
			p->name  = name; 
			p->next = ban_first;
			ban_first = p;

		
		
		name = fread_word(fp);
		}

	fclose (fp);		
}
*/
void save_bans()
{
        FILE *fp;
        BAN_DATA *p;

        if (!ban_first)       {
                unlink (BAN_LIST);
                return;
        }

        fp = fopen (BAN_LIST, "w");

        if (!fp) {bug("could not open ban.txt",0);
		return;}

	for (p = ban_first; p; p = p->next)
	fprintf(fp, "%s\n", p->name);


        fprintf (fp, "%s\n",END_MARKER);

        fclose (fp);
}



void do_dagger( CHAR_DATA *ch, char *argument )
 
{
OBJ_DATA *obj;
 
if (IS_NPC(ch)) return;
 
if (!IS_CLASS(ch, CLASS_NINJA))
{
send_to_char("Huh?\n\r",ch);
return;
}
 
if ( 60 > ch->practice)
{
send_to_char("It costs 60 points of primal to create a ninjitsu dagger.\n\r",ch);
return;
}
ch->practice   -= 60;
obj = create_object(get_obj_index(29700)  ,0 );
obj->level = 70;
obj_to_char(obj, ch);
act("A ninjitsu dagger appears in your hands in a flash of light.",ch,NULL,NULL,TO_CHAR);
act("A ninjitsu dagger appears in $n's hands in a flash of light.",ch,NULL,NULL,TO_ROOM);
return;
}

void do_sword( CHAR_DATA *ch, char *argument )
 
{
OBJ_DATA *obj;
 
if (IS_NPC(ch)) return;
 
if (!IS_CLASS(ch, CLASS_NINJA))
{
send_to_char("Huh?\n\r",ch);
return;
}
 
if ( 60 > ch->practice)
{
send_to_char("It costs 60 points of primal to create a ninjitsu sword.\n\r",ch);
return;
}
ch->practice   -= 60;
obj = create_object(get_obj_index(29701)  ,0 );
obj->level = 70;
obj_to_char(obj, ch);
act("A ninjitsu sword appears in your hands in a flash of light.",ch,NULL,NULL,TO_CHAR);
act("A ninjitsu sword appears in $n's hands in a flash of light.",ch,NULL,NULL,TO_ROOM);
return;
}






*******
 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
 *                                                                         *
 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
 *  Chastain, Michael Quan, and Mitchell Tse.                              *
 *                                                                         *
 *  In order to use any part of this Merc Diku Mud, you must comply with   *
 *  both the original Diku license in 'license.doc' as well the Merc       *
 *  license in 'license.txt'.  In particular, you may not remove either of *
 *  these copyright notices.                                               *
 *                                                                         *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 ***************************************************************************/

#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"

/*
 * Local functions.
 */
void	special_hurl	args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );




void improve_wpn( CHAR_DATA *ch, int dtype, int right_hand )
{
    OBJ_DATA *wield;
    char bufskill [20];
    char buf [MAX_INPUT_LENGTH];
    int dice1;
    int dice2;
    int trapper;
    int max_skl = 200;

    dice1 = number_percent();
    dice2 = number_percent();

    if (IS_NPC(ch)) return;

    if (IS_CLASS(ch, CLASS_HIGHLANDER)) max_skl = 1000;
	else 
	if (IS_CLASS(ch, CLASS_DROW) && IS_SET(ch->special, SPC_DROW_WAR))
		max_skl = 300;
	else if (IS_CLASS(ch, CLASS_MONK))
	max_skl = 450;
	else if (IS_CLASS(ch, CLASS_CYBORG) && ch->pcdata->powers[CYBORG_LIMBS] > 3)
	max_skl = 400;
         if (right_hand == 1) 
	    wield = get_eq_char( ch, WEAR_WIELD );
    else if (right_hand == 2)           
	    wield = get_eq_char( ch, WEAR_HOLD );
    else if (right_hand == 4)
	    wield = get_eq_char( ch, WEAR_THIRD);
    else
	    wield = get_eq_char( ch, WEAR_FOURTH);

    if (wield == NULL) dtype = TYPE_HIT;
    if ( dtype == TYPE_UNDEFINED )
    {
	dtype = TYPE_HIT;
	if ( wield != NULL && wield->item_type == ITEM_WEAPON )
	    dtype += wield->value[3];
    }
    if ( dtype < 1000 || dtype > 1012 ) return;
    dtype -= 1000;
    if (ch->wpn[dtype] >= max_skl) return;
    trapper = ch->wpn[dtype];
    if ((dice1 > ch->wpn[dtype] && dice2 > ch->wpn[dtype]) || (dice1==100 || dice2==100)) ch->wpn[dtype] += 1;
    else return;
    if (trapper == ch->wpn[dtype]) return;

         if (ch->wpn[dtype] == 1   ) sprintf(bufskill,"slightly skilled");
    else if (ch->wpn[dtype] == 26  ) sprintf(bufskill,"reasonable");
    else if (ch->wpn[dtype] == 51  ) sprintf(bufskill,"fairly competent");
    else if (ch->wpn[dtype] == 76  ) sprintf(bufskill,"highly skilled");
    else if (ch->wpn[dtype] == 101 ) sprintf(bufskill,"very dangerous");
    else if (ch->wpn[dtype] == 126 ) sprintf(bufskill,"extremely deadly");
    else if (ch->wpn[dtype] == 151 ) sprintf(bufskill,"an expert");
    else if (ch->wpn[dtype] == 176 ) sprintf(bufskill,"a master");
    else if (ch->wpn[dtype] == 200 ) sprintf(bufskill,"a grand master");
    else if (ch->wpn[dtype] == 201 ) sprintf(bufskill,"supremely skilled");
    else if (ch->wpn[dtype] == 1000 ) sprintf(bufskill,"divinely skilled");
    else return;
    if (wield == NULL || dtype == 0)
	sprintf(buf,"You are now %s at unarmed combat.\n\r",bufskill);
    else
	sprintf(buf,"You are now %s with %s.\n\r",bufskill,wield->short_descr);
    ADD_COLOUR(ch,buf,WHITE);
    send_to_char(buf,ch);
    return;
}

void improve_stance( CHAR_DATA *ch )
{
    char buf        [MAX_INPUT_LENGTH];
    char bufskill   [25];
    char stancename [10];
    int dice1;
    int dice2;
    int stance;

    dice1 = number_percent();
    dice2 = number_percent();

    if (IS_NPC(ch)) return;

    stance = ch->stance[0];
    if (stance < 1 || stance > 12) return;
    if (ch->stance[stance] >= 200) {ch->stance[stance] = 200; return;}
    if ((dice1 > ch->stance[stance] && dice2 > ch->stance[stance]) || (dice1==100 || dice2==100)) ch->stance[stance] += 1;
    else return;
    if (stance == ch->stance[stance]) return;

         if (ch->stance[stance] == 1  ) sprintf(bufskill,"an apprentice of");
    else if (ch->stance[stance] == 26 ) sprintf(bufskill,"a trainee of");
    else if (ch->stance[stance] == 51 ) sprintf(bufskill,"a student of");
    else if (ch->stance[stance] == 76 ) sprintf(bufskill,"fairly experienced in");
    else if (ch->stance[stance] == 101) sprintf(bufskill,"well trained in");
    else if (ch->stance[stance] == 126) sprintf(bufskill,"highly skilled in");
    else if (ch->stance[stance] == 151) sprintf(bufskill,"an expert of");
    else if (ch->stance[stance] == 176) sprintf(bufskill,"a master of");
    else if (ch->stance[stance] == 200) sprintf(bufskill,"a grand master of");
    else return;
         if (stance == STANCE_VIPER   ) sprintf(stancename,"viper"   );
    else if (stance == STANCE_CRANE   ) sprintf(stancename,"crane"   );
    else if (stance == STANCE_CRAB    ) sprintf(stancename,"crab"    );
    else if (stance == STANCE_MONGOOSE) sprintf(stancename,"mongoose");
    else if (stance == STANCE_BULL    ) sprintf(stancename,"bull"    );
    else if (stance == STANCE_MANTIS  ) sprintf(stancename,"mantis"  );
    else if (stance == STANCE_DRAGON  ) sprintf(stancename,"dragon"  );
    else if (stance == STANCE_TIGER   ) sprintf(stancename,"tiger"   );
    else if (stance == STANCE_MONKEY  ) sprintf(stancename,"monkey"  );
    else if (stance == STANCE_SWALLOW ) sprintf(stancename,"swallow" );
    else if (stance == STANCE_WOLF )    sprintf(stancename,"wolf"    );
    else if (stance == STANCE_KOZUDO )  sprintf(stancename,"kozudo"  );
    else return;
    sprintf(buf,"You are now %s the %s stance.\n\r",bufskill,stancename);
    ADD_COLOUR(ch,buf,WHITE);
    send_to_char(buf,ch);
    return;
}

void do_alignment( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];

    one_argument( argument, arg );

    if (IS_NPC(ch)) return;
/*
    if (ch->level > 2)
    {
	send_to_char( "Only mortals have the power to change alignment.\n\r", ch );
	return;
    }
*/
    if ( arg[0] == '\0' )
    {
	send_to_char( "Please enter 'good', 'neutral', or 'evil'.\n\r", ch );
	return;
    }
	if (IS_CLASS(ch, CLASS_DEMON) && str_cmp(arg,"evil")) {
	send_to_char("Demon's must be evil.\n\r", ch );
	return;}

    if      (!str_cmp(arg,"good"))
    {
	ch->alignment = 1000;
	send_to_char( "Alignment is now angelic.\n\r", ch );
    }
    else if (!str_cmp(arg,"neutral"))
    {
	ch->alignment = 0;
	send_to_char( "Alignment is now neutral.\n\r", ch );
    }
    else if (!str_cmp(arg,"evil"))
    {
	ch->alignment = -1000;
	send_to_char( "Alignment is now satanic.\n\r", ch );
    }
    else     send_to_char( "Please enter 'good', 'neutral', or 'evil'.\n\r", ch );
    return;
}

/*
void do_side( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_INPUT_LENGTH];
    char arg[MAX_INPUT_LENGTH];

    one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if ( arg[0] != '\0' && !str_cmp(arg,"renegade") && 
	( ch->class == 1 || ch->class == 2 ))
    {
	ch->class = 3;
	send_to_char( "You are now a renegade.\n\r", ch );
	sprintf(buf,"%s has turned renegade!",ch->name);
	do_info(ch,buf);
	return;
    }

    if (ch->class == 1)
    {
	send_to_char( "You are a scavenger.\n\r", ch );
	return;
    }
    else if (ch->class == 2)
    {
	send_to_char( "You are a mutant.\n\r", ch );
	return;
    }
    else if (ch->class == 3)
    {
	send_to_char( "You are a renegade.\n\r", ch );
	return;
    }

    if ( arg[0] == '\0' )
    {
	send_to_char( "You have not yet picked a side to fight on.\n\r", ch );
	send_to_char( "Please enter 'Scavenger' or 'Mutant'.\n\r", ch );
	return;
    }
    if (!str_cmp(arg,"scavenger"))
    {
	ch->class = 1;
	send_to_char( "You are now a scavenger.\n\r", ch );
	sprintf(buf,"%s has sided with the scavengers!",ch->name);
	do_info(ch,buf);
    }
    else if (!str_cmp(arg,"mutant"))
    {
	ch->class = 2;
	send_to_char( "You are now a mutant.\n\r", ch );
	sprintf(buf,"%s has sided with the mutants!",ch->name);
	do_info(ch,buf);
    }
    else send_to_char( "Please enter 'Scavenger' or 'Mutant'.\n\r", ch );
    return;
}
*/

void do_skill( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char buf       [MAX_STRING_LENGTH];
    char buf2      [MAX_STRING_LENGTH];
    char bufskill  [25];
    char bufskill2 [25];
    char arg       [MAX_INPUT_LENGTH];
    OBJ_DATA *wield;
    OBJ_DATA *wield2;
    int dtype;
    int dtype2;

    one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if ( arg[0] == '\0' )
	sprintf(arg,"self");

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if (IS_NPC(victim))
    {
	send_to_char( "Not on NPC's.\n\r", ch );
	return;
    }

    wield = get_eq_char( victim, WEAR_WIELD );
    wield2 = get_eq_char( victim, WEAR_HOLD );

    dtype = TYPE_HIT;
    dtype2 = TYPE_HIT;
    if ( wield != NULL && wield->item_type == ITEM_WEAPON )
	dtype += wield->value[3];
    if ( wield2 != NULL && wield2->item_type == ITEM_WEAPON )
	dtype2 += wield2->value[3];
    dtype -= 1000;
    dtype2 -= 1000;

    if      (victim->wpn[dtype] == 0   ) sprintf(bufskill,"totally unskilled");
    else if (victim->wpn[dtype] <= 25  ) sprintf(bufskill,"slightly skilled");
    else if (victim->wpn[dtype] <= 50  ) sprintf(bufskill,"reasonable");
    else if (victim->wpn[dtype] <= 75  ) sprintf(bufskill,"fairly competent");
    else if (victim->wpn[dtype] <= 100 ) sprintf(bufskill,"highly skilled");
    else if (victim->wpn[dtype] <= 125 ) sprintf(bufskill,"very dangerous");
    else if (victim->wpn[dtype] <= 150 ) sprintf(bufskill,"extremely deadly");
    else if (victim->wpn[dtype] <= 175 ) sprintf(bufskill,"an expert");
    else if (victim->wpn[dtype] <= 199 ) sprintf(bufskill,"a master");
    else if (victim->wpn[dtype] == 200 ) sprintf(bufskill,"a grand master");
    else if (victim->wpn[dtype] <= 999) sprintf(bufskill,"supremely skilled");
    else if (victim->wpn[dtype] == 1000) sprintf(bufskill,"divinely skilled");
    else return;

    if      (victim->wpn[dtype2] == 0   ) sprintf(bufskill2,"totally unskilled");
    else if (victim->wpn[dtype2] <= 25  ) sprintf(bufskill2,"slightly skilled");
    else if (victim->wpn[dtype2] <= 50  ) sprintf(bufskill2,"reasonable");
    else if (victim->wpn[dtype2] <= 75  ) sprintf(bufskill2,"fairly competent");
    else if (victim->wpn[dtype2] <= 100 ) sprintf(bufskill2,"highly skilled");
    else if (victim->wpn[dtype2] <= 125 ) sprintf(bufskill2,"very dangerous");
    else if (victim->wpn[dtype2] <= 150 ) sprintf(bufskill2,"extremely deadly");
    else if (victim->wpn[dtype2] <= 175 ) sprintf(bufskill2,"an expert");
    else if (victim->wpn[dtype2] <= 199 ) sprintf(bufskill2,"a master");
    else if (victim->wpn[dtype2] == 200 ) sprintf(bufskill2,"a grand master");
    else if (victim->wpn[dtype2] <= 999 ) sprintf(bufskill2,"supremely skilled");
    else if (victim->wpn[dtype2] == 1000) sprintf(bufskill2,"divinely skilled");
    else return;

    if (ch == victim)
    {
    	if (dtype == 0 && dtype2 == 0)
	    sprintf(buf,"You are %s at unarmed combat.\n\r",bufskill);
    	else
	{
	    if (dtype != 0)
		sprintf(buf,"You are %s with %s.\n\r",bufskill,wield->short_descr);
	    if (dtype2 != 0)
		sprintf(buf2,"You are %s with %s.\n\r",bufskill2,wield2->short_descr);
	}
    }
    else
    {
    	if (dtype == 0 && dtype2 == 0)
	    sprintf(buf,"%s is %s at unarmed combat.\n\r",victim->name,bufskill);
    	else
	{
	    if (dtype != 0)
		sprintf(buf,"%s is %s with %s.\n\r",victim->name,bufskill,wield->short_descr);
	    if (dtype2 != 0)
		sprintf(buf2,"%s is %s with %s.\n\r",victim->name,bufskill2,wield2->short_descr);
	}
    }
    if (!(dtype == 0 && dtype2 != 0)) send_to_char(buf,ch);
    if (dtype2 != 0) send_to_char(buf2,ch);
    skillstance(ch,victim);
    return;
}

void do_throw( CHAR_DATA *ch, char *argument )
{
    ROOM_INDEX_DATA *location;
    ROOM_INDEX_DATA *to_room;
    EXIT_DATA       *pexit;
    CHAR_DATA       *victim = NULL;
    OBJ_DATA        *obj;
    char            arg1      [MAX_INPUT_LENGTH];
    char            arg2      [MAX_INPUT_LENGTH];
    char            buf       [MAX_INPUT_LENGTH];
    char            revdoor   [MAX_INPUT_LENGTH];
    int             door;

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if ( ( obj = get_eq_char( ch, WEAR_WIELD ) ) == NULL )
    {
    	if ( ( obj = get_eq_char( ch, WEAR_HOLD ) ) == NULL )
	{
	    send_to_char( "You are not holding anything to throw.\n\r", ch );
	    return;
	}
    }

    if ( arg1[0] == '\0' )
    {
	send_to_char("Which direction do you wish to throw?\n\r", ch);
	return;
    }

    if      ( !str_cmp( arg1, "n" ) || !str_cmp( arg1, "north" ) )
	{door = 0;sprintf(arg1,"north");}
    else if ( !str_cmp( arg1, "e" ) || !str_cmp( arg1, "east" ) )
	{door = 1;sprintf(arg1,"east");}
    else if ( !str_cmp( arg1, "s" ) || !str_cmp( arg1, "south" ) )
	{door = 2;sprintf(arg1,"south");}
    else if ( !str_cmp( arg1, "w" ) || !str_cmp( arg1, "west" ) )
	{door = 3;sprintf(arg1,"west");}
    else if ( !str_cmp( arg1, "u" ) || !str_cmp( arg1, "up" ) )
	{door = 4;sprintf(arg1,"up");}
    else if ( !str_cmp( arg1, "d" ) || !str_cmp( arg1, "down" ) )
	{door = 5;sprintf(arg1,"down");}
    else
    {
	send_to_char("You can only throw north, south, east, west, up or down.\n\r", ch);
	return;
    }

    if      ( !str_cmp( arg1, "north" ) ) {door = 0;sprintf(revdoor,"south");}
    else if ( !str_cmp( arg1, "east"  ) ) {door = 1;sprintf(revdoor,"west" );}
    else if ( !str_cmp( arg1, "south" ) ) {door = 2;sprintf(revdoor,"north");}
    else if ( !str_cmp( arg1, "west"  ) ) {door = 3;sprintf(revdoor,"east" );}
    else if ( !str_cmp( arg1, "up"    ) ) {door = 4;sprintf(revdoor,"down" );}
    else if ( !str_cmp( arg1, "down"  ) ) {door = 5;sprintf(revdoor,"up"   );}
    else return;

    location = ch->in_room;

    sprintf(buf,"You hurl $p %s.",arg1);
    act(buf,ch,obj,NULL,TO_CHAR);
    sprintf(buf,"$n hurls $p %s.",arg1);
    act(buf,ch,obj,NULL,TO_ROOM);
    /* First room */
    if (( pexit = ch->in_room->exit[door]) == NULL || (to_room = pexit->to_room) == NULL)
    {
	sprintf(buf,"$p bounces off the %s wall.",arg1);
	act(buf,ch,obj,NULL,TO_ROOM);
	act(buf,ch,obj,NULL,TO_CHAR);
	obj_from_char(obj);
	obj_to_room(obj, ch->in_room);
	return;
    }
    pexit = ch->in_room->exit[door];
    if (IS_SET(pexit->exit_info, EX_CLOSED) )
    {
	sprintf(buf,"$p bounces off the %s door.",arg1);
	act(buf,ch,obj,NULL,TO_ROOM);
	act(buf,ch,obj,NULL,TO_CHAR);
	obj_from_char(obj);
	obj_to_room(obj, ch->in_room);
	return;
    }
    char_from_room(ch);
    char_to_room(ch,to_room);
    if ( ( victim = get_char_room( ch, arg2 ) ) != NULL )
    {
	sprintf(buf,"$p comes flying in from the %s and lands in $N's hands.",revdoor);
	act(buf,ch,obj,victim,TO_NOTVICT);
	sprintf(buf,"$p comes flying in from the %s and lands in your hands.",revdoor);
	act(buf,ch,obj,victim,TO_VICT);
	obj_from_char(obj);
	obj_to_char(obj, victim);
    	char_from_room(ch);
    	char_to_room(ch,location);
	return;
    }

    /* Second room */
    if (( pexit = ch->in_room->exit[door]) == NULL || (to_room = pexit->to_room) == NULL)
    {
	sprintf(buf,"$p comes flying in from the %s and strikes %s wall.",revdoor,arg1);
	act(buf,ch,obj,NULL,TO_ROOM);
	obj_from_char(obj);
	obj_to_room(obj, ch->in_room);
    	char_from_room(ch);
    	char_to_room(ch,location);
	return;
    }
    pexit = ch->in_room->exit[door];
    if (IS_SET(pexit->exit_info, EX_CLOSED) )
    {
	sprintf(buf,"$p comes flying in from the %s and strikes the %s door.",revdoor,arg1);
	act(buf,ch,obj,NULL,TO_ROOM);
	obj_from_char(obj);
	obj_to_room(obj, ch->in_room);
    	char_from_room(ch);
    	char_to_room(ch,location);
	return;
    }
    sprintf(buf,"$p comes flying in from the %s and carries on %s.",revdoor, arg1);
    act(buf,ch,obj,NULL,TO_ROOM);
    char_from_room(ch);
    char_to_room(ch,to_room);
    if ( ( victim = get_char_room( ch, arg2 ) ) != NULL )
    {
	sprintf(buf,"$p comes flying in from the %s and lands in $N's hands.",revdoor);
	act(buf,ch,obj,victim,TO_NOTVICT);
	sprintf(buf,"$p comes flying in from the %s and lands in your hands.",revdoor);
	act(buf,ch,obj,victim,TO_VICT);
	obj_from_char(obj);
	obj_to_char(obj, victim);
    	char_from_room(ch);
    	char_to_room(ch,location);
	return;
    }

    /* Third room */
    if (( pexit = ch->in_room->exit[door]) == NULL || (to_room = pexit->to_room) == NULL)
    {
	sprintf(buf,"$p comes flying in from the %s and strikes %s wall.",revdoor,arg1);
	act(buf,ch,obj,NULL,TO_ROOM);
	obj_from_char(obj);
	obj_to_room(obj, ch->in_room);
    	char_from_room(ch);
    	char_to_room(ch,location);
	return;
    }
    pexit = ch->in_room->exit[door];
    if (IS_SET(pexit->exit_info, EX_CLOSED) )
    {
	sprintf(buf,"$p comes flying in from the %s and strikes the %s door.",revdoor,arg1);
	act(buf,ch,obj,NULL,TO_ROOM);
	obj_from_char(obj);
	obj_to_room(obj, ch->in_room);
    	char_from_room(ch);
    	char_to_room(ch,location);
	return;
    }
    sprintf(buf,"$p comes flying in from the %s and carries on %s.",revdoor, arg1);
    act(buf,ch,obj,NULL,TO_ROOM);
    char_from_room(ch);
    char_to_room(ch,to_room);
    if ( ( victim = get_char_room( ch, arg2 ) ) != NULL )
    {
	sprintf(buf,"$p comes flying in from the %s and lands in $N's hands.",revdoor);
	act(buf,ch,obj,victim,TO_NOTVICT);
	sprintf(buf,"$p comes flying in from the %s and lands in your hands.",revdoor);
	act(buf,ch,obj,victim,TO_VICT);
	obj_from_char(obj);
	obj_to_char(obj, victim);
    	char_from_room(ch);
    	char_to_room(ch,location);
	return;
    }

    sprintf(buf,"$p comes flying in from the %s and drops at your feet.",revdoor);
    act(buf,ch,obj,NULL,TO_ROOM);
    obj_from_char(obj);
    obj_to_room(obj, ch->in_room);

    /* Move them back */
    char_from_room(ch);
    char_to_room(ch,location);

    do_autosave(ch,"");
    if (victim != NULL && !IS_NPC(victim)) do_autosave(victim,"");
    return;
}

void do_shoot( CHAR_DATA *ch, char *argument )
{
    ROOM_INDEX_DATA *location;
    ROOM_INDEX_DATA *to_room;
    EXIT_DATA       *pexit;
    CHAR_DATA       *victim;
    OBJ_DATA        *obj;
    OBJ_DATA        *ammo;
    char            arg1      [MAX_INPUT_LENGTH];
    char            arg2      [MAX_INPUT_LENGTH];
    char            buf       [MAX_INPUT_LENGTH];
    char            revdoor   [MAX_INPUT_LENGTH];
    int             door;
    bool	    missed;

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if ( ( obj = get_eq_char( ch, WEAR_WIELD ) ) == NULL
	|| obj->item_type != ITEM_MISSILE )
    {
    	if ( ( obj = get_eq_char( ch, WEAR_HOLD ) ) == NULL
	    || obj->item_type != ITEM_MISSILE )
	{
	    send_to_char( "You are not holding anything to shoot.\n\r", ch );
	    return;
	}
    }

    if ( obj->value[1] < 1 )
    {
	send_to_char("First you need to load it.\n\r", ch);
	return;
    }

    if ( arg1[0] == '\0' )
    {
	send_to_char("Please specify a direction to shoot.\n\r", ch);
	return;
    }

    if ( arg2[0] == '\0' )
    {
	send_to_char("Please specify a target to shoot at.\n\r", ch);
	return;
    }

    if      ( !str_cmp( arg1, "n" ) || !str_cmp( arg1, "north" ) )
	{door = 0;sprintf(arg1,"north");}
    else if ( !str_cmp( arg1, "e" ) || !str_cmp( arg1, "east" ) )
	{door = 1;sprintf(arg1,"east");}
    else if ( !str_cmp( arg1, "s" ) || !str_cmp( arg1, "south" ) )
	{door = 2;sprintf(arg1,"south");}
    else if ( !str_cmp( arg1, "w" ) || !str_cmp( arg1, "west" ) )
	{door = 3;sprintf(arg1,"west");}
    else if ( !str_cmp( arg1, "u" ) || !str_cmp( arg1, "up" ) )
	{door = 4;sprintf(arg1,"up");}
    else if ( !str_cmp( arg1, "d" ) || !str_cmp( arg1, "down" ) )
	{door = 5;sprintf(arg1,"down");}
    else
    {
	send_to_char("You can only shoot north, south, east, west, up or down.\n\r", ch);
	return;
    }

    if      ( !str_cmp( arg1, "north" ) ) {door = 0;sprintf(revdoor,"south");}
    else if ( !str_cmp( arg1, "east"  ) ) {door = 1;sprintf(revdoor,"west" );}
    else if ( !str_cmp( arg1, "south" ) ) {door = 2;sprintf(revdoor,"north");}
    else if ( !str_cmp( arg1, "west"  ) ) {door = 3;sprintf(revdoor,"east" );}
    else if ( !str_cmp( arg1, "up"    ) ) {door = 4;sprintf(revdoor,"down" );}
    else if ( !str_cmp( arg1, "down"  ) ) {door = 5;sprintf(revdoor,"up"   );}
    else return;

    if ( get_obj_index( obj->value[0] ) == NULL ) return;

    location = ch->in_room;
    ammo = create_object( get_obj_index( obj->value[0] ), 0 );

    if ( number_percent() <= ammo->value[0] ) missed = FALSE;
    else missed = TRUE;
    obj->value[1] -= 1;

    sprintf(buf,"You point $p %s and shoot.",arg1);
    act(buf,ch,obj,NULL,TO_CHAR);
    sprintf(buf,"$n points $p %s and shoots.",arg1);
    act(buf,ch,obj,NULL,TO_ROOM);
    /* First room */
    if (( pexit = ch->in_room->exit[door]) == NULL || (to_room = pexit->to_room) == NULL)
    {
	sprintf(buf,"$p bounces off the %s wall.",arg1);
	act(buf,ch,ammo,NULL,TO_ROOM);
	act(buf,ch,ammo,NULL,TO_CHAR);
	obj_to_room(ammo, ch->in_room);
	return;
    }
    pexit = ch->in_room->exit[door];
    if (IS_SET(pexit->exit_info, EX_CLOSED) )
    {
	sprintf(buf,"$p bounces off the %s door.",arg1);
	act(buf,ch,ammo,NULL,TO_ROOM);
	act(buf,ch,ammo,NULL,TO_CHAR);
	obj_to_room(ammo, ch->in_room);
	return;
    }
    char_from_room(ch);
    char_to_room(ch,to_room);
    if ( ( victim = get_char_room( ch, arg2 ) ) != NULL )
    {
	if (missed)
	{
	    sprintf(buf,"$p flies in from the %s, just missing $N, and carrying on %s.",revdoor, arg1);
	    act(buf,ch,ammo,victim,TO_NOTVICT);
	    sprintf(buf,"$p flies in from the %s, just missing you, and carrying on %s.",revdoor, arg1);
	    act(buf,ch,ammo,victim,TO_VICT);
	}
	else
	{
	    sprintf(buf,"$p comes flying in from the %s and strikes $N.",revdoor);
	    act(buf,ch,ammo,victim,TO_NOTVICT);
	    sprintf(buf,"$p comes flying in from the %s and strikes you.",revdoor);
	    act(buf,ch,ammo,victim,TO_VICT);
	    obj_to_char(ammo, victim);
    	    char_from_room(ch);
    	    char_to_room(ch,location);
	    victim->hit -= number_range(ammo->value[1],ammo->value[2]);
	    update_pos(victim);
	    if (victim->position == POS_DEAD && !IS_HERO(victim))
	    {
		send_to_char( "You have been KILLED!!\n\r\n\r", victim );
		raw_kill(victim);
	    }
	    return;
	}
    }

    /* Second room */
    if (( pexit = ch->in_room->exit[door]) == NULL || (to_room = pexit->to_room) == NULL)
    {
	sprintf(buf,"$p comes flying in from the %s and strikes %s wall.",revdoor,arg1);
	act(buf,ch,ammo,NULL,TO_ROOM);
	obj_to_room(ammo, ch->in_room);
    	char_from_room(ch);
    	char_to_room(ch,location);
	return;
    }
    pexit = ch->in_room->exit[door];
    if (IS_SET(pexit->exit_info, EX_CLOSED) )
    {
	sprintf(buf,"$p comes flying in from the %s and strikes the %s door.",revdoor,arg1);
	act(buf,ch,ammo,NULL,TO_ROOM);
	obj_to_room(ammo, ch->in_room);
    	char_from_room(ch);
    	char_to_room(ch,location);
	return;
    }
    if (!missed)
    {
    	sprintf(buf,"$p comes flying in from the %s and carries on %s.",revdoor, arg1);
    	act(buf,ch,ammo,NULL,TO_ROOM);
    }
    char_from_room(ch);
    char_to_room(ch,to_room);
    if ( ( victim = get_char_room( ch, arg2 ) ) != NULL )
    {
	if (missed)
	{
	    sprintf(buf,"$p flies in from the %s, just missing $N, and carrying on %s.",revdoor, arg1);
	    act(buf,ch,ammo,victim,TO_NOTVICT);
	    sprintf(buf,"$p flies in from the %s, just missing you, and carrying on %s.",revdoor, arg1);
	    act(buf,ch,ammo,victim,TO_VICT);
	}
	else
	{
	    sprintf(buf,"$p comes flying in from the %s and strikes $N.",revdoor);
	    act(buf,ch,ammo,victim,TO_NOTVICT);
	    sprintf(buf,"$p comes flying in from the %s and strikes you.",revdoor);
	    act(buf,ch,ammo,victim,TO_VICT);
	    obj_to_char(ammo, victim);
    	    char_from_room(ch);
    	    char_to_room(ch,location);
	    victim->hit -= number_range(ammo->value[1],ammo->value[2]);
	    update_pos(victim);
	    if (victim->position == POS_DEAD && !IS_HERO(victim))
	    {
		send_to_char( "You have been KILLED!!\n\r\n\r", victim );
		raw_kill(victim);
	    }
	    return;
	}
    }

    /* Third room */
    if (( pexit = ch->in_room->exit[door]) == NULL || (to_room = pexit->to_room) == NULL)
    {
	sprintf(buf,"$p comes flying in from the %s and strikes %s wall.",revdoor,arg1);
	act(buf,ch,ammo,NULL,TO_ROOM);
	obj_to_room(ammo, ch->in_room);
    	char_from_room(ch);
    	char_to_room(ch,location);
	return;
    }
    pexit = ch->in_room->exit[door];
    if (IS_SET(pexit->exit_info, EX_CLOSED) )
    {
	sprintf(buf,"$p comes flying in from the %s and strikes the %s door.",revdoor,arg1);
	act(buf,ch,ammo,NULL,TO_ROOM);
	obj_to_room(ammo, ch->in_room);
    	char_from_room(ch);
    	char_to_room(ch,location);
	return;
    }
    if (!missed)
    {
    	sprintf(buf,"$p comes flying in from the %s and carries on %s.",revdoor, arg1);
    	act(buf,ch,ammo,NULL,TO_ROOM);
    }
    char_from_room(ch);
    char_to_room(ch,to_room);
    if ( ( victim = get_char_room( ch, arg2 ) ) != NULL )
    {
	if (missed)
	{
	    sprintf(buf,"$p flies in from the %s, just missing $N, and carrying on %s.",revdoor, arg1);
	    act(buf,ch,ammo,victim,TO_NOTVICT);
	    sprintf(buf,"$p flies in from the %s, just missing you, and carrying on %s.",revdoor, arg1);
	    act(buf,ch,ammo,victim,TO_VICT);
	}
	else
	{
	    sprintf(buf,"$p comes flying in from the %s and strikes $N.",revdoor);
	    act(buf,ch,ammo,victim,TO_NOTVICT);
	    sprintf(buf,"$p comes flying in from the %s and strikes you.",revdoor);
	    act(buf,ch,ammo,victim,TO_VICT);
	    obj_to_char(ammo, victim);
    	    char_from_room(ch);
    	    char_to_room(ch,location);
	    victim->hit -= number_range(ammo->value[1],ammo->value[2]);
	    update_pos(victim);
	    if (victim->position == POS_DEAD && !IS_HERO(victim))
	    {
		send_to_char( "You have been KILLED!!\n\r\n\r", victim );
		raw_kill(victim);
	    }
	    return;
	}
    }

    sprintf(buf,"$p comes flying in from the %s and drops at your feet.",revdoor);
    act(buf,ch,ammo,NULL,TO_ROOM);
    obj_to_room(ammo, ch->in_room);

    /* Move them back */
    char_from_room(ch);
    char_to_room(ch,location);
    return;
}

void do_reload( CHAR_DATA *ch, char *argument )
{
    OBJ_DATA *obj;
    OBJ_DATA *obj2;
    OBJ_DATA *ammo;
    OBJ_DATA *missile;

    obj = get_eq_char( ch, WEAR_WIELD );
    obj2 = get_eq_char( ch, WEAR_HOLD );

    if ( obj == NULL || obj2 == NULL )
    {
	send_to_char( "You must hold the weapon to reload in one hand and the ammo in the other.\n\r", ch );
	return;
    }

    if ( !(obj->item_type  == ITEM_MISSILE && obj2->item_type == ITEM_AMMO)
    &&   !(obj2->item_type == ITEM_MISSILE && obj->item_type  == ITEM_AMMO) )
    {
	send_to_char( "You must hold the weapon to reload in one hand and the ammo in the other.\n\r", ch );
	return;
    }

    if ( obj->item_type == ITEM_MISSILE )
    {
	missile = obj;
	ammo = obj2;
    }
    else
    {
	missile = obj2;
	ammo = obj;
    }

    if ( missile->value[1] >= missile->value[2] )
    {
	send_to_char( "It is already fully loaded.\n\r", ch );
	return;
    }

    if ( missile->value[3] != ammo->value[3] )
    {
	send_to_char( "That weapon doesn't take that sort of ammo.\n\r", ch );
	return;
    }

    if ( missile->value[0] != 0 && missile->value[1] != 0 &&
	 missile->value[0] != ammo->pIndexData->vnum )
    {
	send_to_char( "You cannot mix ammo types.\n\r", ch );
	return;
    }

    act("You load $p into $P.",ch,ammo,missile,TO_CHAR);
    act("$n loads $p into $P.",ch,ammo,missile,TO_ROOM);
    missile->value[1] += 1;
    missile->value[0] = ammo->pIndexData->vnum;
    obj_from_char( ammo );
    extract_obj( ammo );
    return;
}

void do_unload( CHAR_DATA *ch, char *argument )
{
    OBJ_DATA *missile;
    OBJ_DATA *ammo;

    if ( ( missile = get_eq_char( ch, WEAR_WIELD ) ) == NULL
	|| missile->item_type != ITEM_MISSILE )
    {
    	if ( ( missile = get_eq_char( ch, WEAR_HOLD ) ) == NULL
	    || missile->item_type != ITEM_MISSILE )
	{
	    send_to_char( "You are not holding anything to unload.\n\r", ch );
	    return;
	}
    }

    if ( missile->value[1] <= 0 )
    {
	send_to_char( "But it is already empty!\n\r", ch );
	return;
    }

    if ( get_obj_index( missile->value[0] ) == NULL ) return;

    ammo = create_object( get_obj_index( missile->value[0] ), 0 );
    act("You remove $p from $P.",ch,ammo,missile,TO_CHAR);
    act("$n removes $p from $P.",ch,ammo,missile,TO_ROOM);
    missile->value[1] -= 1;
    obj_to_char(ammo, ch);
    return;
}

void do_stance( CHAR_DATA *ch, char *argument )
{
    char            arg      [MAX_INPUT_LENGTH];
    int             selection;

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;
    if (IS_SET(ch->mounted, IS_RIDING))
    {
	send_to_char("Not while mounted.\n\r",ch);
	return;
    }
    if (IS_AFFECTED(ch, AFF_POLYMORPH) && !IS_VAMPAFF(ch, VAM_DISGUISED)
 && !IS_POLYAFF(ch,POLY_ZULOFORM) && !IS_POLYAFF(ch, POLY_SPIDER)
	&& !IS_SET(ch->flag2, VAMP_OBJMASK))
    {
	send_to_char("Not while polymorphed.\n\r",ch);
	return;
    }
    if ( arg[0] == '\0' )
    {
	if (ch->stance[0] == -1)
	{
	    ch->stance[0] = 0;
	    send_to_char("You drop into a fighting stance.\n\r",ch);
	    act("$n drops into a fighting stance.",ch,NULL,NULL,TO_ROOM);
	}
	else
	{
	    ch->stance[0] = -1;
	    send_to_char("You relax from your fighting stance.\n\r",ch);
	    act("$n relaxes from $s fighting stance.",ch,NULL,NULL,TO_ROOM);
	}
	return;
    }
    if (ch->stance[0] > 0)
    {
	send_to_char("You cannot change stances until you come up from the one you are currently in.\n\r",ch);
	return;
    }
    if (!str_cmp(arg,"none")    ) {selection = STANCE_NONE;
	send_to_char("You drop into a general fighting stance.\n\r",ch);
	act("$n drops into a general fighting stance.",ch,NULL,NULL,TO_ROOM);}
    else if (!str_cmp(arg,"viper")   ) {selection = STANCE_VIPER;
	send_to_char("You arch your body into the viper fighting stance.\n\r",ch);
	act("$n arches $s body into the viper fighting stance.",ch,NULL,NULL,TO_ROOM);}
    else if (!str_cmp(arg,"crane")   ) {selection = STANCE_CRANE;
	send_to_char("You swing your body into the crane fighting stance.\n\r",ch);
	act("$n swings $s body into the crane fighting stance.",ch,NULL,NULL,TO_ROOM);}
    else if (!str_cmp(arg,"crab")    ) {selection = STANCE_CRAB;
	send_to_char("You squat down into the crab fighting stance.\n\r",ch);
	act("$n squats down into the crab fighting stance. ",ch,NULL,NULL,TO_ROOM);}
    else if (!str_cmp(arg,"mongoose")) {selection = STANCE_MONGOOSE;
	send_to_char("You twist into the mongoose fighting stance.\n\r",ch);
	act("$n twists into the mongoose fighting stance. ",ch,NULL,NULL,TO_ROOM);}
    else if (!str_cmp(arg,"bull")    ) {selection = STANCE_BULL;
	send_to_char("You hunch down into the bull fighting stance.\n\r",ch);
	act("$n hunches down into the bull fighting stance. ",ch,NULL,NULL,TO_ROOM);}
    else
    {
	if (!str_cmp(arg,"mantis") && ch->stance[STANCE_CRANE] >= 200 &&
	    ch->stance[STANCE_VIPER] >= 200)
	{
	    selection = STANCE_MANTIS;
	    send_to_char("You spin your body into the mantis fighting stance.\n\r",ch);
	    act("$n spins $s body into the mantis fighting stance.",ch,NULL,NULL,TO_ROOM);
	}
	else if (!str_cmp(arg,"dragon") && ch->stance[STANCE_BULL] >= 200 &&
	    ch->stance[STANCE_CRAB] >= 200)
	{
	    selection = STANCE_DRAGON;
	    send_to_char("You coil your body into the dragon fighting stance.\n\r",ch);
	    act("$n coils $s body into the dragon fighting stance.",ch,NULL,NULL,TO_ROOM);
	}
	else if (!str_cmp(arg,"tiger") && ch->stance[STANCE_BULL] >= 200 &&
	    ch->stance[STANCE_VIPER] >= 200)
	{
	    selection = STANCE_TIGER;
	    send_to_char("You lunge into the tiger fighting stance.\n\r",ch);
	    act("$n lunges into the tiger fighting stance.",ch,NULL,NULL,TO_ROOM);
	}

	else if (!str_cmp(arg,"monkey") && ch->stance[STANCE_CRANE] >= 200 &&
	    ch->stance[STANCE_MONGOOSE] >= 200)
	{
	    selection = STANCE_MONKEY;
	    send_to_char("You rotate your body into the monkey fighting stance.\n\r",ch);
	    act("$n rotates $s body into the monkey fighting stance.",ch,NULL,NULL,TO_ROOM);
	}
	else if (!str_cmp(arg,"swallow") && ch->stance[STANCE_CRAB] >= 200 &&
	    ch->stance[STANCE_MONGOOSE] >= 200)
	{
	    selection = STANCE_SWALLOW;
	    send_to_char("You slide into the swallow fighting stance.\n\r",ch);
	    act("$n slides into the swallow fighting stance.",ch,NULL,NULL,TO_ROOM);
	}
        else if (!str_cmp(arg,"kozudo") && ch->stance[STANCE_SWALLOW] >= 200
	&& ch->stance[STANCE_TIGER] >= 200 && ch->stance[STANCE_MANTIS] >= 200 &&
	ch->stance[STANCE_DRAGON] >= 200 && ch->stance[STANCE_MONKEY] >= 200 )
        {
            selection = STANCE_KOZUDO;
            send_to_char("You shift into the Kozudo fighting stance.\n\r",ch);
            act("$n shifts into the Kozudo fighting stance.",ch,NULL,NULL,TO_ROOM);
        }
	else if (!str_cmp(arg,"wolf") && ch->stance[STANCE_SWALLOW] >= 200
&& ch->stance[STANCE_TIGER] >= 200 && ch->stance[STANCE_MANTIS] >= 200 &&
ch->stance[STANCE_DRAGON] >= 200 && ch->stance[STANCE_MONKEY] >= 200 &&
ch->power[DISC_WERE_WOLF]> 4 )
	{
	    selection = STANCE_WOLF;
	    send_to_char("You fling into the wolf fighting stance.\n\r",ch);
	    act("$n flings into the wolf fighting stance.",ch,NULL,NULL,TO_ROOM);
	}

	else
	{
	    send_to_char("Syntax is: stance <style>.\n\r",ch);
	    send_to_char("Stance being one of: None, Viper, Crane, Crab, Mongoose, Bull.\n\r",ch);
	    return;
	}
    }
    ch->stance[0] = selection;
    WAIT_STATE( ch, 12 );
    return;
}

void do_fightstyle( CHAR_DATA *ch, char *argument )
{
    char            arg1     [MAX_INPUT_LENGTH];
    char            arg2     [MAX_INPUT_LENGTH];
    char            buf      [MAX_INPUT_LENGTH];
    bool	    blah = FALSE;
    int             selection;
    int             value;

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if ( !IS_CLASS(ch, CLASS_MONK) && !IS_CREATOR(ch) )
    {
	stc("Huh?\n\r",ch);
	return;
    }

    if ( arg1[0] == '\0' || arg2[0] == '\0' )
    {
	send_to_char("Syntax is: fightstyle <number> <style>.\n\r",ch);
	send_to_char("Style can be selected from the following (enter style in text form):\n\r",ch);
	send_to_char("==================================================================\n\r",ch);
	send_to_char("[ 1] Trip      [ 2] Kick      [ 3] Bash      [ 4] Elbow [ 5] Knee\n\r",ch);
	send_to_char("[ 6] Headbutt  [ 7] Disarm    [ 8] Bite      [ 9] Dirt  [10] Grapple\n\r",ch);
	send_to_char("[11] Punch     [12] Gouge     [13] Rip       [14] Stamp [15] Backfist\n\r",ch);
	send_to_char("[16] Jumpkick  [17] Spinkick  [18] Hurl      [19] Sweep [20] Charge\n\r",ch);
	send_to_char("==================================================================\n\r",ch);
	sprintf(buf,"Selected options: 1:[%d] 2:[%d] 3:[%d] 4:[%d] 5:[%d] 6:[%d] 7:[%d] 8:[%d].\n\r",ch->cmbt[0],ch->cmbt[1],
	ch->cmbt[2],ch->cmbt[3],ch->cmbt[4],ch->cmbt[5],ch->cmbt[6],ch->cmbt[7]);
	send_to_char(buf,ch);
	return;
    }
    value = is_number( arg1 ) ? atoi( arg1 ) : -1;
    if (value < 1 || value > 8)
    {
	send_to_char("Please enter a value between 1 and 8.\n\r",ch);
	return;
    }
         if (!str_cmp(arg2,"clear")   ) selection = 0;
    else if (!str_cmp(arg2,"trip")    ) selection = 1;
    else if (!str_cmp(arg2,"kick")    ) selection = 2;
    else if (!str_cmp(arg2,"bash")    ) selection = 3;
    else if (!str_cmp(arg2,"elbow")   ) selection = 4;
    else if (!str_cmp(arg2,"knee")    ) selection = 5;
    else if (!str_cmp(arg2,"headbutt")) selection = 6;
    else if (!str_cmp(arg2,"disarm")  ) selection = 7;
    else if (!str_cmp(arg2,"bite")    ) selection = 8;
    else if (!str_cmp(arg2,"dirt")    ) selection = 9;
    else if (!str_cmp(arg2,"grapple") ) selection = 10;
    else if (!str_cmp(arg2,"punch")   ) selection = 11;
    else if (!str_cmp(arg2,"gouge")   ) selection = 12;
    else if (!str_cmp(arg2,"rip")     ) selection = 13;
    else if (!str_cmp(arg2,"stamp")   ) selection = 14;
    else if (!str_cmp(arg2,"backfist")) selection = 15;
    else if (!str_cmp(arg2,"jumpkick")) selection = 16;
    else if (!str_cmp(arg2,"spinkick")) selection = 17;
    else if (!str_cmp(arg2,"hurl")    ) selection = 18;
    else if (!str_cmp(arg2,"sweep")   ) selection = 19;
    else if (!str_cmp(arg2,"charge")  ) selection = 20;
    else
    {
	do_fightstyle(ch, "");
	return;
    }

         if ( selection == 1 && !IS_FS(ch, FS_TRIP) )
        blah = TRUE;
    else if ( selection == 2 && !IS_FS(ch, FS_KICK) )
        blah = TRUE;
    else if ( selection == 3 && !IS_FS(ch, FS_BASH) )
	blah = TRUE;
    else if ( selection == 4 && !IS_FS(ch, FS_ELBOW) )
	blah = TRUE;
    else if ( selection == 5 && !IS_FS(ch, FS_KNEE) )
	blah = TRUE;
    else if ( selection == 6 && !IS_FS(ch, FS_HEADBUTT))
	blah = TRUE;
    else if ( selection == 7 && !IS_FS(ch, FS_DISARM) )
	blah = TRUE;
    else if ( selection == 8 && !IS_FS(ch, FS_BITE) )
	blah = TRUE;
    else if ( selection == 9 && !IS_FS(ch, FS_DIRT) )
	blah = TRUE;
    else if ( selection == 10 && !IS_FS(ch, FS_GRAPPLE) )
	blah = TRUE;
    else if ( selection == 11 && !IS_FS(ch, FS_PUNCH) )
	blah = TRUE;
    else if ( selection == 12 && !IS_FS(ch, FS_GOUGE ) )
	blah = TRUE;
    else if ( selection == 13 && !IS_FS(ch, FS_RIP ) )
	blah = TRUE;
    else if ( selection == 14 && !IS_FS(ch, FS_STAMP) )
	blah = TRUE;
    else if ( selection == 15 && !IS_FS(ch, FS_BACKFIST))
	blah = TRUE;
    else if ( selection == 16 && !IS_FS(ch, FS_JUMPKICK) )
	blah = TRUE;
    else if ( selection == 17 && !IS_FS(ch, FS_SPINKICK) )
	blah = TRUE;
    else if ( selection == 18 && !IS_FS(ch, FS_HURL) )
	blah = TRUE;
    else if ( selection == 19 && !IS_FS(ch, FS_SWEEP) )
	blah = TRUE;
    else if ( selection == 20 && !IS_FS(ch, FS_CHARGE) )
	blah = TRUE;
    else
	blah = FALSE;

    if ( blah )
    {
	stc("You have not learned that fighting style.\n\r",ch);
	return;
    }

    ch->cmbt[(value-1)] = selection;
    sprintf(buf,"Combat option %d now set to %s (%d).\n\r",value,arg2,ch->cmbt[0]);
    send_to_char(buf,ch);
    return;
}

void fightaction( CHAR_DATA *ch, CHAR_DATA *victim, int actype, int dtype, int wpntype)
{
    AFFECT_DATA af;
    OBJ_DATA *obj;

    if ( IS_NPC(ch) ) return;
    if ( actype < 1 || actype > 20 ) return;
    if ( victim == NULL ) return;

    /* Trip */
    if ( actype == 1 )
    {
	if ( number_percent( ) <= ch->wpn[0] )
	    trip( ch, victim );
    	return;
    }
    else if ( actype == 2 && number_percent() < 75 )
    {
	do_kick(ch,"");
    	return;
    }
    else if ( actype == 3 )
    {
	act("You slam into $N, sending $M sprawling.",ch,NULL,victim,TO_CHAR);
        if ( !IS_NPC(victim))
	act("$n slams into you, sending you sprawling.",ch,NULL,victim,TO_VICT);
	act("$n slams into $N, sending $M sprawling.",ch,NULL,victim,TO_NOTVICT);
	WAIT_STATE(victim,4);
	return;
    }
    else if ( actype == 4 )
    {
	act("You spin around and ram your elbow into $N's forehead.",ch,NULL,victim,TO_CHAR);
	if ( !IS_NPC(victim))
	act("$n spins around and rams his elbow into your forehead.",ch,NULL,victim,TO_VICT);
	act("$n spins around and rams $s elbow into $N's face.",ch,NULL,victim,TO_NOTVICT);
	one_hit( ch, victim, gsn_elbow, wpntype );
	return;
    }
    else if ( actype == 5 )
    {
	act("You slam your knee into $N's stomach.",ch,NULL,victim,TO_CHAR);
	act("$n slams $s knee into your stomach.",ch,NULL,victim,TO_VICT);
	act("$n slams $s knee into $N's stomach.",ch,NULL,victim,TO_NOTVICT);
        one_hit( ch, victim, gsn_knee, wpntype );
	return;
    }
    else if ( actype == 6 )
    {
        one_hit( ch, victim, gsn_headbutt, wpntype );
	return;
    }
    else if ( actype == 7 )
    {
	if ( number_percent() < 25 )
	    disarm( ch, victim );
    	return;
    }
    else if ( actype == 8 )
    {
	multi_hit( ch, victim, gsn_fangs);
	return;
    }
    else if ( actype == 9 )
    {
	act( "You kick a spray of dirt into $N's face.",ch,NULL,victim,TO_CHAR );
	act( "$n kicks a spray of dirt into your face.",ch,NULL,victim,TO_VICT );
	act( "$n kicks a spray of dirt into $N's face.",ch,NULL,victim,TO_NOTVICT );
    	if ( IS_AFFECTED(victim, AFF_BLIND) || number_percent() < 25 )
	    return;
    	af.type      = 4;
    	af.location  = APPLY_HITROLL;
    	af.modifier  = -4;
    	af.duration  = 1;
    	af.bitvector = AFF_BLIND;
    	affect_to_char( victim, &af );
	act( "$n is blinded!",victim,NULL,NULL,TO_ROOM );
    	send_to_char( "You are blinded!\n\r", victim );
    	return;
    }
    else if ( actype == 11 )
    {
	act( "You punch $N in the face.",ch,NULL,victim,TO_CHAR );
	act( "$n punches you in the face.",ch,NULL,victim,TO_VICT );
	act( "$n punches $N in the face.",ch,NULL,victim,TO_NOTVICT );
	victim->position = POS_STUNNED;
	return;
    }
    else if ( actype == 12 )
    {
	act( "You gouge your fingers into $N's eyes.",ch,NULL,victim,TO_CHAR );
	act( "$n gouges $s fingers into your eyes.",ch,NULL,victim,TO_VICT );
	act( "$n gouges $s fingers into $N's eyes.",ch,NULL,victim,TO_NOTVICT );
    	if ( IS_AFFECTED(victim, AFF_BLIND) || number_percent() < 75 )
	{
	    one_hit( ch, victim, dtype, wpntype );
	    return;
	}
    	af.type      = 4;
    	af.location  = APPLY_HITROLL;
    	af.modifier  = -4;
    	af.duration  = 1;
    	af.bitvector = AFF_BLIND;
    	affect_to_char( victim, &af );
	act( "$n is blinded!",victim,NULL,NULL,TO_ROOM );
    	send_to_char( "You are blinded!\n\r", victim );
    	return;
    }
    else if ( actype == 13 )
    {
	if ( number_percent() > 85 )
	{
	  if (!IS_ARM_L(victim,LOST_ARM))
            SET_BIT(victim->loc_hp[2],LOST_ARM);
        else return;
        if (!IS_BLEEDING(victim,BLEEDING_ARM_L))
            SET_BIT(victim->loc_hp[6],BLEEDING_ARM_L);
        if (IS_BLEEDING(victim,BLEEDING_HAND_L))
            REMOVE_BIT(victim->loc_hp[6],BLEEDING_HAND_L);
	  act("You dodge $N's attack, grab $S arm and rip it from it's socket.",ch,NULL,victim,TO_CHAR);
	  act("$n dodges your attack, grabs your arm and rips it from its socket.",ch,NULL,victim, TO_VICT);
	  act("$n dodges $N's attack, grabs $N's arm and rips it from its socket.",ch,NULL,victim, TO_NOTVICT);
	make_part(victim,"arm");
        if (IS_ARM_L(victim,LOST_ARM) && IS_ARM_R(victim,LOST_ARM))
        {
            if ((obj = get_eq_char( victim, WEAR_ARMS )) != NULL)
                take_item(victim,obj);
        }
        if ((obj = get_eq_char( victim, WEAR_HOLD )) != NULL)
            take_item(victim,obj);
        if ((obj = get_eq_char( victim, WEAR_HANDS )) != NULL)
            take_item(victim,obj);
        if ((obj = get_eq_char( victim, WEAR_WRIST_L )) != NULL)
            take_item(victim,obj);
        if ((obj = get_eq_char( victim, WEAR_FINGER_L )) != NULL)
            take_item(victim,obj);
	  return;
	}
    }
    else if ( actype == 14 )
    {
    	if ( victim->move < 1 ) return;
	act( "You leap in the air and stamp on $N's feet.",ch,NULL,victim,TO_CHAR );
	act( "$n leaps in the air and stamps on your feet.",ch,NULL,victim,TO_VICT );
	act( "$n leaps in the air and stamps on $N's feet.",ch,NULL,victim,TO_NOTVICT );
	victim->move -= number_range(25,50);
	if ( victim->move < 0 ) victim->move = 0;
    	return;
    }
    else if ( actype == 15 )
    {
	one_hit( ch, victim, gsn_backfist, wpntype );
	return;
    }
    else if ( actype == 16 )
    {
	one_hit( ch, victim, gsn_jumpkick, wpntype );
	return;
    }
    else if ( actype == 17 )
    {
	one_hit( ch, victim, gsn_spinkick, wpntype );
	return;
    }
    else if ( actype == 18 )
    {
	if ( number_percent() > 1 )
	{
	  act("You grab on to $N and hurl $M to  the ground.",ch,NULL,victim,TO_CHAR);
	  act("$n grabs you and throws you to the ground.",ch,NULL,victim,TO_VICT);
	  victim->position = POS_STUNNED;
	  return;
	}
    }
    else if ( actype == 19 )
    {
	one_hit( ch, victim, gsn_monksweep, wpntype );
	return;
    }
    else if ( actype == 20 )
    {
	act("You charge into $N, knocking $M from his feet.",ch,NULL,victim,TO_CHAR);
	act("$n charges into you, knocking you off your feet.",ch,NULL,victim,TO_VICT);
	act("$n charges into $N, knocking $M off $S feet.",ch,NULL,victim,TO_NOTVICT);
	victim->position = POS_STUNNED;
	return;
    }
    return;
}

void critical_hit( CHAR_DATA *ch, CHAR_DATA *victim, int dt, int dam)
{
    OBJ_DATA *obj;
    OBJ_DATA *damaged;
    char buf  [MAX_STRING_LENGTH];
    char buf2 [20];
    int dtype;
    int critical = 0;
    int wpn = 0;
    int wpn2 = 0;
    int count;
    int count2;

    dtype = dt - 1000;
    if (dtype < 0 || dtype > 12) return;
    if (IS_NPC(ch)) critical += ((ch->level+1) / 5);
    if (!IS_NPC(ch)) critical += ((ch->wpn[dtype]+1)/10);
    if (IS_NPC(victim)) critical -= ((victim->level+1) / 5);
    if (!IS_NPC(victim))
    {
    	obj = get_eq_char( victim, WEAR_WIELD );
    	dtype = TYPE_HIT;
    	if ( obj != NULL && obj->item_type == ITEM_WEAPON )
	    dtype += obj->value[3];
    	wpn = dtype - 1000;
	if (wpn < 0 || wpn > 12) wpn = 0;
    	obj = get_eq_char( victim, WEAR_HOLD );
    	dtype = TYPE_HIT;
    	if ( obj != NULL && obj->item_type == ITEM_WEAPON )
	    dtype += obj->value[3];
    	wpn2 = dtype - 1000;
	if (wpn2 < 0 || wpn2 > 12) wpn2 = 0;

	if (victim->wpn[wpn] > victim->wpn[wpn2])
	    critical -= ((victim->wpn[wpn]+1)/10);
	else
	    critical -= ((victim->wpn[wpn2]+1)/10);
    }
if (!IS_NPC(ch) && IS_SET(ch->newbits,NEW_REND)&& number_range(1,25)==1)
critical=100;
         if (critical < 1 ) critical = 1;
    else if (IS_NPC(ch) && critical > 5) critical = 5;
  
    if (number_percent() > critical) return;
	if (IS_CLASS(victim, CLASS_DROW) && IS_POLYAFF(victim, POLY_SPIDER))
		return;
    critical = number_range(1,23);
    if (critical == 1)
    {
	if (IS_HEAD(victim,LOST_EYE_L) && IS_HEAD(victim,LOST_EYE_R)) return;
	if ( (damaged = get_eq_char(victim,WEAR_FACE) ) != NULL &&
		damaged->toughness > 0 && !IS_ITEMAFF(ch, ITEMA_VORPAL))
	{
	    act("$p prevents you from loosing an eye.",victim,damaged,NULL,TO_CHAR);
	    act("$p prevents $n from loosing an eye.",victim,damaged,NULL,TO_ROOM);
	    if (dam - damaged->toughness < 0) return;
	    if ((dam - damaged->toughness > damaged->resistance))
	    	damaged->condition -= damaged->resistance;
	    else
	    	damaged->condition -= (dam - damaged->toughness);
	    if (damaged->condition < 1)
	    {
	    	act("$p falls broken to the ground.",ch,damaged,NULL,TO_CHAR);
	    	act("$p falls broken to the ground.",ch,damaged,NULL,TO_ROOM);
	    	obj_from_char(damaged);
	    	extract_obj(damaged);
	    }
	    return;
	}
	if (!IS_HEAD(victim,LOST_EYE_L) && number_percent() < 50)
	    SET_BIT(victim->loc_hp[0],LOST_EYE_L);
	else if (!IS_HEAD(victim,LOST_EYE_R))
	    SET_BIT(victim->loc_hp[0],LOST_EYE_R);
	else if (!IS_HEAD(victim,LOST_EYE_L))
	    SET_BIT(victim->loc_hp[0],LOST_EYE_L);
	else return;
	act("Your skillful blow takes out $N's eye!",ch,NULL,victim,TO_CHAR);
	act("$n's skillful blow takes out $N's eye!",ch,NULL,victim,TO_NOTVICT);
	act("$n's skillful blow takes out your eye!",ch,NULL,victim,TO_VICT);
	make_part(victim,"eyeball");
	return;
    }
    else if (critical == 2)
    {
	if (IS_HEAD(victim,LOST_EAR_L) && IS_HEAD(victim,LOST_EAR_R)) return;
	if ( (damaged = get_eq_char(victim,WEAR_HEAD) ) != NULL &&
		damaged->toughness > 0 && !IS_ITEMAFF(ch, ITEMA_VORPAL))
	{
	    act("$p prevents you from loosing an ear.",victim,damaged,NULL,TO_CHAR);
	    act("$p prevents $n from loosing an ear.",victim,damaged,NULL,TO_ROOM);
	    if (dam - damaged->toughness < 0) return;
	    if ((dam - damaged->toughness > damaged->resistance))
	    	damaged->condition -= damaged->resistance;
	    else
	    	damaged->condition -= (dam - damaged->toughness);
	    if (damaged->condition < 1)
	    {
	    	act("$p falls broken to the ground.",ch,damaged,NULL,TO_CHAR);
	    	act("$p falls broken to the ground.",ch,damaged,NULL,TO_ROOM);
	    	obj_from_char(damaged);
	    	extract_obj(damaged);
	    }
	    return;
	}
	if (!IS_HEAD(victim,LOST_EAR_L) && number_percent() < 50)
	    SET_BIT(victim->loc_hp[0],LOST_EAR_L);
	else if (!IS_HEAD(victim,LOST_EAR_R))
	    SET_BIT(victim->loc_hp[0],LOST_EAR_R);
	else if (!IS_HEAD(victim,LOST_EAR_L))
	    SET_BIT(victim->loc_hp[0],LOST_EAR_L);
	else return;
	act("Your skillful blow cuts off $N's ear!",ch,NULL,victim,TO_CHAR);
	act("$n's skillful blow cuts off $N's ear!",ch,NULL,victim,TO_NOTVICT);
	act("$n's skillful blow cuts off your ear!",ch,NULL,victim,TO_VICT);
	make_part(victim,"ear");
	return;
    }
    else if (critical == 3)
    {
	if (IS_HEAD(victim,LOST_NOSE)) return;
	if ( (damaged = get_eq_char(victim,WEAR_FACE) ) != NULL &&
		damaged->toughness > 0 && !IS_ITEMAFF(ch, ITEMA_VORPAL))
	{
	    act("$p prevents you from loosing your nose.",victim,damaged,NULL,TO_CHAR);
	    act("$p prevents $n from loosing $s nose.",victim,damaged,NULL,TO_ROOM);
	    if (dam - damaged->toughness < 0) return;
	    if ((dam - damaged->toughness > damaged->resistance))
	    	damaged->condition -= damaged->resistance;
	    else
	    	damaged->condition -= (dam - damaged->toughness);
	    if (damaged->condition < 1)
	    {
	    	act("$p falls broken to the ground.",ch,damaged,NULL,TO_CHAR);
	    	act("$p falls broken to the ground.",ch,damaged,NULL,TO_ROOM);
	    	obj_from_char(damaged);
	    	extract_obj(damaged);
	    }
	    return;
	}
	SET_BIT(victim->loc_hp[0],LOST_NOSE);
	act("Your skillful blow cuts off $N's nose!",ch,NULL,victim,TO_CHAR);
	act("$n's skillful blow cuts off $N's nose!",ch,NULL,victim,TO_NOTVICT);
	act("$n's skillful blow cuts off your nose!",ch,NULL,victim,TO_VICT);
	make_part(victim,"nose");
	return;
    }
    else if (critical == 4)
    {
	if (IS_HEAD(victim,LOST_NOSE) || IS_HEAD(victim,BROKEN_NOSE)) return;
	if ( (damaged = get_eq_char(victim,WEAR_FACE) ) != NULL &&
		damaged->toughness > 0 && !IS_ITEMAFF(ch, ITEMA_VORPAL))
	{
	    act("$p prevents you from breaking your nose.",victim,damaged,NULL,TO_CHAR);
	    act("$p prevents $n from breaking $s nose.",victim,damaged,NULL,TO_ROOM);
	    if (dam - damaged->toughness < 0) return;
	    if ((dam - damaged->toughness > damaged->resistance))
	    	damaged->condition -= damaged->resistance;
	    else
	    	damaged->condition -= (dam - damaged->toughness);
	    if (damaged->condition < 1)
	    {
	    	act("$p falls broken to the ground.",ch,damaged,NULL,TO_CHAR);
	    	act("$p falls broken to the ground.",ch,damaged,NULL,TO_ROOM);
	    	obj_from_char(damaged);
	    	extract_obj(damaged);
	    }
	    return;
	}
	if (!IS_HEAD(victim,LOST_NOSE) && !IS_HEAD(victim,BROKEN_NOSE))
	    SET_BIT(victim->loc_hp[0],BROKEN_NOSE);
	else return;
	act("Your skillful blow breaks $N's nose!",ch,NULL,victim,TO_CHAR);
	act("$n's skillful blow breaks $N's nose!",ch,NULL,victim,TO_NOTVICT);
	act("$n's skillful blow breaks your nose!",ch,NULL,victim,TO_VICT);
	return;
    }
    else if (critical == 5)
    {
	if (IS_HEAD(victim,BROKEN_JAW)) return;
	if ( (damaged = get_eq_char(victim,WEAR_FACE) ) != NULL &&
		damaged->toughness > 0 && !IS_ITEMAFF(ch, ITEMA_VORPAL))
	{
	    act("$p prevents you from breaking your jaw.",victim,damaged,NULL,TO_CHAR);
	    act("$p prevents $n from breaking $s jaw.",victim,damaged,NULL,TO_ROOM);
	    if (dam - damaged->toughness < 0) return;
	    if ((dam - damaged->toughness > damaged->resistance))
	    	damaged->condition -= damaged->resistance;
	    else
	    	damaged->condition -= (dam - damaged->toughness);
	    if (damaged->condition < 1)
	    {
	    	act("$p falls broken to the ground.",ch,damaged,NULL,TO_CHAR);
	    	act("$p falls broken to the ground.",ch,damaged,NULL,TO_ROOM);
	    	obj_from_char(damaged);
	    	extract_obj(damaged);
	    }
	    return;
	}
	if (!IS_HEAD(victim,BROKEN_JAW))
	    SET_BIT(victim->loc_hp[0],BROKEN_JAW);
	else return;
	act("Your skillful blow breaks $N's jaw!",ch,NULL,victim,TO_CHAR);
	act("$n's skillful blow breaks $N's jaw!",ch,NULL,victim,TO_NOTVICT);
	act("$n's skillful blow breaks your jaw!",ch,NULL,victim,TO_VICT);
	return;
    }
    else if (critical == 6)
    {
	if (IS_ARM_L(victim,LOST_ARM)) return;
	if ( (damaged = get_eq_char(victim,WEAR_ARMS) ) != NULL &&
		damaged->toughness > 0 && !IS_ITEMAFF(ch, ITEMA_VORPAL))
	{
	    act("$p prevent you from loosing your left arm.",victim,damaged,NULL,TO_CHAR);
	    act("$p prevent $n from loosing $s left arm.",victim,damaged,NULL,TO_ROOM);
	    if (dam - damaged->toughness < 0) return;
	    if ((dam - damaged->toughness > damaged->resistance))
	    	damaged->condition -= damaged->resistance;
	    else
	    	damaged->condition -= (dam - damaged->toughness);
	    if (damaged->condition < 1)
	    {
	    	act("$p fall broken to the ground.",ch,damaged,NULL,TO_CHAR);
	    	act("$p fall broken to the ground.",ch,damaged,NULL,TO_ROOM);
	    	obj_from_char(damaged);
	    	extract_obj(damaged);
	    }
	    return;
	}
	if (!IS_ARM_L(victim,LOST_ARM))
	    SET_BIT(victim->loc_hp[2],LOST_ARM);
	else return;
	if (!IS_BLEEDING(victim,BLEEDING_ARM_L))
	    SET_BIT(victim->loc_hp[6],BLEEDING_ARM_L);
	if (IS_BLEEDING(victim,BLEEDING_HAND_L))
	    REMOVE_BIT(victim->loc_hp[6],BLEEDING_HAND_L);
	act("Your skillful blow cuts off $N's left arm!",ch,NULL,victim,TO_CHAR);
	act("$n's skillful blow cuts off $N's left arm!",ch,NULL,victim,TO_NOTVICT);
	act("$n's skillful blow cuts off your left arm!",ch,NULL,victim,TO_VICT);
	make_part(victim,"arm");
	if (IS_ARM_L(victim,LOST_ARM) && IS_ARM_R(victim,LOST_ARM))
	{
	    if ((obj = get_eq_char( victim, WEAR_ARMS )) != NULL)
		take_item(victim,obj);
	}
	if ((obj = get_eq_char( victim, WEAR_HOLD )) != NULL)
	    take_item(victim,obj);
	if ((obj = get_eq_char( victim, WEAR_HANDS )) != NULL)
	    take_item(victim,obj);
	if ((obj = get_eq_char( victim, WEAR_WRIST_L )) != NULL)
	    take_item(victim,obj);
	if ((obj = get_eq_char( victim, WEAR_FINGER_L )) != NULL)
	    take_item(victim,obj);
	return;
    }
    else if (critical == 7)
    {
	if (IS_ARM_R(victim,LOST_ARM)) return;
	if ( (damaged = get_eq_char(victim,WEAR_ARMS) ) != NULL &&
		damaged->toughness > 0 && !IS_ITEMAFF(ch, ITEMA_VORPAL))
	{
	    act("$p prevent you from loosing your right arm.",victim,damaged,NULL,TO_CHAR);
	    act("$p prevent $n from loosing $s right arm.",victim,damaged,NULL,TO_ROOM);
	    if (dam - damaged->toughness < 0) return;
	    if ((dam - damaged->toughness > damaged->resistance))
	    	damaged->condition -= damaged->resistance;
	    else
	    	damaged->condition -= (dam - damaged->toughness);
	    if (damaged->condition < 1)
	    {
	    	act("$p fall broken to the ground.",ch,damaged,NULL,TO_CHAR);
	    	act("$p fall broken to the ground.",ch,damaged,NULL,TO_ROOM);
	    	obj_from_char(damaged);
	    	extract_obj(damaged);
	    }
	    return;
	}
	if (!IS_ARM_R(victim,LOST_ARM))
	    SET_BIT(victim->loc_hp[3],LOST_ARM);
	else return;
	if (!IS_BLEEDING(victim,BLEEDING_ARM_R))
	    SET_BIT(victim->loc_hp[6],BLEEDING_ARM_R);
	if (IS_BLEEDING(victim,BLEEDING_HAND_R))
	    REMOVE_BIT(victim->loc_hp[6],BLEEDING_HAND_R);
	act("Your skillful blow cuts off $N's right arm!",ch,NULL,victim,TO_CHAR);
	act("$n's skillful blow cuts off $N's right arm!",ch,NULL,victim,TO_NOTVICT);
	act("$n's skillful blow cuts off your right arm!",ch,NULL,victim,TO_VICT);
	make_part(victim,"arm");
	if (IS_ARM_L(victim,LOST_ARM) && IS_ARM_R(victim,LOST_ARM))
	{
	    if ((obj = get_eq_char( victim, WEAR_ARMS )) != NULL)
		take_item(victim,obj);
	}
	if ((obj = get_eq_char( victim, WEAR_WIELD )) != NULL)
	    take_item(victim,obj);
	if ((obj = get_eq_char( victim, WEAR_HANDS )) != NULL)
	    take_item(victim,obj);
	if ((obj = get_eq_char( victim, WEAR_WRIST_R )) != NULL)
	    take_item(victim,obj);
	if ((obj = get_eq_char( victim, WEAR_FINGER_R )) != NULL)
	    take_item(victim,obj);
	return;
    }
    else if (critical == 8)
    {
	if (IS_ARM_L(victim,LOST_ARM) || IS_ARM_L(victim,BROKEN_ARM)) return;
	if ( (damaged = get_eq_char(victim,WEAR_ARMS) ) != NULL &&
		damaged->toughness > 0 && !IS_ITEMAFF(ch, ITEMA_VORPAL))
	{
	    act("$p prevent you from breaking your left arm.",victim,damaged,NULL,TO_CHAR);
	    act("$p prevent $n from breaking $s left arm.",victim,damaged,NULL,TO_ROOM);
	    if (dam - damaged->toughness < 0) return;
	    if ((dam - damaged->toughness > damaged->resistance))
	    	damaged->condition -= damaged->resistance;
	    else
	    	damaged->condition -= (dam - damaged->toughness);
	    if (damaged->condition < 1)
	    {
	    	act("$p fall broken to the ground.",ch,damaged,NULL,TO_CHAR);
	    	act("$p fall broken to the ground.",ch,damaged,NULL,TO_ROOM);
	    	obj_from_char(damaged);
	    	extract_obj(damaged);
	    }
	    return;
	}
	if (!IS_ARM_L(victim,BROKEN_ARM) && !IS_ARM_L(victim,LOST_ARM))
	    SET_BIT(victim->loc_hp[2],BROKEN_ARM);
	else return;
	act("Your skillful blow breaks $N's left arm!",ch,NULL,victim,TO_CHAR);
	act("$n's skillful blow breaks $N's left arm!",ch,NULL,victim,TO_NOTVICT);
	act("$n's skillful blow breaks your left arm!",ch,NULL,victim,TO_VICT);
	if ((obj = get_eq_char( victim, WEAR_HOLD )) != NULL)
	    take_item(victim,obj);
	return;
    }
    else if (critical == 9)
    {
	if (IS_ARM_R(victim,LOST_ARM) || IS_ARM_R(victim,BROKEN_ARM)) return;
	if ( (damaged = get_eq_char(victim,WEAR_ARMS) ) != NULL &&
		damaged->toughness > 0 && !IS_ITEMAFF(ch, ITEMA_VORPAL))
	{
	    act("$p prevent you from breaking your right arm.",victim,damaged,NULL,TO_CHAR);
	    act("$p prevent $n from breaking $s right arm.",victim,damaged,NULL,TO_ROOM);
	    if (dam - damaged->toughness < 0) return;
	    if ((dam - damaged->toughness > damaged->resistance))
	    	damaged->condition -= damaged->resistance;
	    else
	    	damaged->condition -= (dam - damaged->toughness);
	    if (damaged->condition < 1)
	    {
	    	act("$p fall broken to the ground.",ch,damaged,NULL,TO_CHAR);
	    	act("$p fall broken to the ground.",ch,damaged,NULL,TO_ROOM);
	    	obj_from_char(damaged);
	    	extract_obj(damaged);
	    }
	    return;
	}
	if (!IS_ARM_R(victim,BROKEN_ARM) && !IS_ARM_R(victim,LOST_ARM))
	    SET_BIT(victim->loc_hp[3],BROKEN_ARM);
	else return;
	act("Your skillful blow breaks $N's right arm!",ch,NULL,victim,TO_CHAR);
	act("$n's skillful blow breaks $N's right arm!",ch,NULL,victim,TO_NOTVICT);
	act("$n's skillful blow breaks your right arm!",ch,NULL,victim,TO_VICT);
	if ((obj = get_eq_char( victim, WEAR_WIELD )) != NULL)
	    take_item(victim,obj);
	return;
    }
    else if (critical == 10)
    {
	if (IS_ARM_L(victim,LOST_HAND) || IS_ARM_L(victim,LOST_ARM)) return;
	if ( (damaged = get_eq_char(victim,WEAR_HANDS) ) != NULL &&
		damaged->toughness > 0 && !IS_ITEMAFF(ch, ITEMA_VORPAL))
	{
	    act("$p prevent you from loosing your left hand.",victim,damaged,NULL,TO_CHAR);
	    act("$p prevent $n from loosing $s left hand.",victim,damaged,NULL,TO_ROOM);
	    if (dam - damaged->toughness < 0) return;
	    if ((dam - damaged->toughness > damaged->resistance))
	    	damaged->condition -= damaged->resistance;
	    else
	    	damaged->condition -= (dam - damaged->toughness);
	    if (damaged->condition < 1)
	    {
	    	act("$p fall broken to the ground.",ch,damaged,NULL,TO_CHAR);
	    	act("$p fall broken to the ground.",ch,damaged,NULL,TO_ROOM);
	    	obj_from_char(damaged);
	    	extract_obj(damaged);
	    }
	    return;
	}
	if (!IS_ARM_L(victim,LOST_HAND) && !IS_ARM_L(victim,LOST_ARM))
	    SET_BIT(victim->loc_hp[2],LOST_HAND);
	else return;
	if (IS_BLEEDING(victim,BLEEDING_ARM_L))
	    REMOVE_BIT(victim->loc_hp[6],BLEEDING_ARM_L);
	if (!IS_BLEEDING(victim,BLEEDING_HAND_L))
	    SET_BIT(victim->loc_hp[6],BLEEDING_HAND_L);
	act("Your skillful blow cuts off $N's left hand!",ch,NULL,victim,TO_CHAR);
	act("$n's skillful blow cuts off $N's left hand!",ch,NULL,victim,TO_NOTVICT);
	act("$n's skillful blow cuts off your left hand!",ch,NULL,victim,TO_VICT);
	make_part(victim,"hand");
	if ((obj = get_eq_char( victim, WEAR_HOLD )) != NULL)
	    take_item(victim,obj);
	if ((obj = get_eq_char( victim, WEAR_HANDS )) != NULL)
	    take_item(victim,obj);
	if ((obj = get_eq_char( victim, WEAR_WRIST_L )) != NULL)
	    take_item(victim,obj);
	if ((obj = get_eq_char( victim, WEAR_FINGER_L )) != NULL)
	    take_item(victim,obj);
	return;
    }
    else if (critical == 11)
    {
	if (IS_ARM_R(victim,LOST_HAND) || IS_ARM_R(victim,LOST_ARM)) return;
	if ( (damaged = get_eq_char(victim,WEAR_HANDS) ) != NULL &&
		damaged->toughness > 0 && !IS_ITEMAFF(ch, ITEMA_VORPAL))
	{
	    act("$p prevent you from loosing your right hand.",victim,damaged,NULL,TO_CHAR);
	    act("$p prevent $n from loosing $s right hand.",victim,damaged,NULL,TO_ROOM);
	    if (dam - damaged->toughness < 0) return;
	    if ((dam - damaged->toughness > damaged->resistance))
	    	damaged->condition -= damaged->resistance;
	    else
	    	damaged->condition -= (dam - damaged->toughness);
	    if (damaged->condition < 1)
	    {
	    	act("$p fall broken to the ground.",ch,damaged,NULL,TO_CHAR);
	    	act("$p fall broken to the ground.",ch,damaged,NULL,TO_ROOM);
	    	obj_from_char(damaged);
	    	extract_obj(damaged);
	    }
	    return;
	}
	if (!IS_ARM_R(victim,LOST_HAND) && !IS_ARM_R(victim,LOST_ARM))
	    SET_BIT(victim->loc_hp[3],LOST_HAND);
	else return;
	if (IS_BLEEDING(victim,BLEEDING_ARM_R))
	    REMOVE_BIT(victim->loc_hp[6],BLEEDING_ARM_R);
	if (!IS_BLEEDING(victim,BLEEDING_HAND_R))
	    SET_BIT(victim->loc_hp[6],BLEEDING_HAND_R);
	act("Your skillful blow cuts off $N's right hand!",ch,NULL,victim,TO_CHAR);
	act("$n's skillful blow cuts off $N's right hand!",ch,NULL,victim,TO_NOTVICT);
	act("$n's skillful blow cuts off your right hand!",ch,NULL,victim,TO_VICT);
	make_part(victim,"hand");
	if ((obj = get_eq_char( victim, WEAR_WIELD )) != NULL)
	    take_item(victim,obj);
	if ((obj = get_eq_char( victim, WEAR_HANDS )) != NULL)
	    take_item(victim,obj);
	if ((obj = get_eq_char( victim, WEAR_WRIST_R )) != NULL)
	    take_item(victim,obj);
	if ((obj = get_eq_char( victim, WEAR_FINGER_R )) != NULL)
	    take_item(victim,obj);
	return;
    }
    else if (critical == 12)
    {
	if (IS_ARM_L(victim,LOST_ARM)) return;
	if (IS_ARM_L(victim,LOST_HAND)) return;
	if (IS_ARM_L(victim,LOST_THUMB) && IS_ARM_L(victim,LOST_FINGER_I) &&
	IS_ARM_L(victim,LOST_FINGER_M) && IS_ARM_L(victim,LOST_FINGER_R) &&
	IS_ARM_L(victim,LOST_FINGER_L)) return;
	if ( (damaged = get_eq_char(victim,WEAR_HANDS) ) != NULL &&
		damaged->toughness > 0 && !IS_ITEMAFF(ch, ITEMA_VORPAL))
	{
	    act("$p prevent you from loosing some fingers from your left hand.",victim,damaged,NULL,TO_CHAR);
	    act("$p prevent $n from loosing some fingers from $s left hand.",victim,damaged,NULL,TO_ROOM);
	    if (dam - damaged->toughness < 0) return;
	    if ((dam - damaged->toughness > damaged->resistance))
	    	damaged->condition -= damaged->resistance;
	    else
	    	damaged->condition -= (dam - damaged->toughness);
	    if (damaged->condition < 1)
	    {
	    	act("$p fall broken to the ground.",ch,damaged,NULL,TO_CHAR);
	    	act("$p fall broken to the ground.",ch,damaged,NULL,TO_ROOM);
	    	obj_from_char(damaged);
	    	extract_obj(damaged);
	    }
	    return;
	}
	count = 0;
	count2 = 0;
	if (!IS_ARM_L(victim,LOST_THUMB) && number_percent() < 25)
	    {SET_BIT(victim->loc_hp[2],LOST_THUMB);count2 += 1;
	    make_part(victim,"thumb");}
	if (!IS_ARM_L(victim,LOST_FINGER_I) && number_percent() < 25)
	    {SET_BIT(victim->loc_hp[2],LOST_FINGER_I);count += 1;
	    make_part(victim,"index");}
	if (!IS_ARM_L(victim,LOST_FINGER_M) && number_percent() < 25)
	    {SET_BIT(victim->loc_hp[2],LOST_FINGER_M);count += 1;
	    make_part(victim,"middle");}
	if (!IS_ARM_L(victim,LOST_FINGER_R) && number_percent() < 25)
	    {SET_BIT(victim->loc_hp[2],LOST_FINGER_R);count += 1;
	    make_part(victim,"ring");
	    if ((obj = get_eq_char( victim, WEAR_FINGER_L )) != NULL)
	        take_item(victim,obj);}
	if (!IS_ARM_L(victim,LOST_FINGER_L) && number_percent() < 25)
	    {SET_BIT(victim->loc_hp[2],LOST_FINGER_L);count += 1;
	    make_part(victim,"little");}
	if (count == 1) sprintf(buf2,"finger");
	else            sprintf(buf2,"fingers");
	if (count > 0 && count2 > 0)
	{
	    sprintf(buf,"Your skillful blow cuts off %d %s and the thumb from $N's left hand.",count,buf2);
	    act(buf,ch,NULL,victim,TO_CHAR);
	    sprintf(buf,"$n's skillful blow cuts off %d %s and the thumb from $N's left hand.",count,buf2);
	    act(buf,ch,NULL,victim,TO_NOTVICT);
	    sprintf(buf,"$n's skillful blow cuts off %d %s and the thumb from your left hand.",count,buf2);
	    act(buf,ch,NULL,victim,TO_VICT);
	    if ((obj = get_eq_char( victim, WEAR_HOLD )) != NULL)
		take_item(victim,obj);
	    return;
	}
	else if (count > 0)
	{
	    sprintf(buf,"Your skillful blow cuts off %d %s from $N's left hand.",count,buf2);
	    act(buf,ch,NULL,victim,TO_CHAR);
	    sprintf(buf,"$n's skillful blow cuts off %d %s from $N's left hand.",count,buf2);
	    act(buf,ch,NULL,victim,TO_NOTVICT);
	    sprintf(buf,"$n's skillful blow cuts off %d %s from your left hand.",count,buf2);
	    act(buf,ch,NULL,victim,TO_VICT);
	    if ((obj = get_eq_char( victim, WEAR_HOLD )) != NULL)
		take_item(victim,obj);
	    return;
	}
	else if (count2 > 0)
	{
	    sprintf(buf,"Your skillful blow cuts off the thumb from $N's left hand.");
	    act(buf,ch,NULL,victim,TO_CHAR);
	    sprintf(buf,"$n's skillful blow cuts off the thumb from $N's left hand.");
	    act(buf,ch,NULL,victim,TO_NOTVICT);
	    sprintf(buf,"$n's skillful blow cuts off the thumb from your left hand.");
	    act(buf,ch,NULL,victim,TO_VICT);
	    if ((obj = get_eq_char( victim, WEAR_HOLD )) != NULL)
		take_item(victim,obj);
	    return;
	}
	return;
    }
    else if (critical == 13)
    {
	if (IS_ARM_L(victim,LOST_ARM)) return;
	if (IS_ARM_L(victim,LOST_HAND)) return;
	if ((IS_ARM_L(victim,LOST_THUMB) || IS_ARM_L(victim,BROKEN_THUMB)) &&
	    (IS_ARM_L(victim,LOST_FINGER_I) || IS_ARM_L(victim,BROKEN_FINGER_I)) &&
	    (IS_ARM_L(victim,LOST_FINGER_M) || IS_ARM_L(victim,BROKEN_FINGER_M)) &&
	    (IS_ARM_L(victim,LOST_FINGER_R) || IS_ARM_L(victim,BROKEN_FINGER_R)) &&
	    (IS_ARM_L(victim,LOST_FINGER_L) || IS_ARM_L(victim,BROKEN_FINGER_L)))
		return;
	if ( (damaged = get_eq_char(victim,WEAR_HANDS) ) != NULL &&
		damaged->toughness > 0 && !IS_ITEMAFF(ch, ITEMA_VORPAL))
	{
	    act("$p prevent you from breaking some fingers on your left hand.",victim,damaged,NULL,TO_CHAR);
	    act("$p prevent $n from breaking some fingers on $s left hand.",victim,damaged,NULL,TO_ROOM);
	    if (dam - damaged->toughness < 0) return;
	    if ((dam - damaged->toughness > damaged->resistance))
	    	damaged->condition -= damaged->resistance;
	    else
	    	damaged->condition -= (dam - damaged->toughness);
	    if (damaged->condition < 1)
	    {
	    	act("$p fall broken to the ground.",ch,damaged,NULL,TO_CHAR);
	    	act("$p fall broken to the ground.",ch,damaged,NULL,TO_ROOM);
	    	obj_from_char(damaged);
	    	extract_obj(damaged);
	    }
	    return;
	}
	count = 0;
	count2 = 0;
	if (IS_ARM_L(victim,LOST_ARM)) return;
	if (IS_ARM_L(victim,LOST_HAND)) return;

	if (!IS_ARM_L(victim,BROKEN_THUMB) && !IS_ARM_L(victim,LOST_THUMB) && number_percent() < 25)
	    {SET_BIT(victim->loc_hp[2],BROKEN_THUMB);count2 += 1;}
	if (!IS_ARM_L(victim,BROKEN_FINGER_I) && !IS_ARM_L(victim,LOST_FINGER_I) && number_percent() < 25)
	    {SET_BIT(victim->loc_hp[2],BROKEN_FINGER_I);count += 1;}
	if (!IS_ARM_L(victim,BROKEN_FINGER_M) && !IS_ARM_L(victim,LOST_FINGER_M) && number_percent() < 25)
	    {SET_BIT(victim->loc_hp[2],BROKEN_FINGER_M);count += 1;}
	if (!IS_ARM_L(victim,BROKEN_FINGER_R) && !IS_ARM_L(victim,LOST_FINGER_R) && number_percent() < 25)
	    {SET_BIT(victim->loc_hp[2],BROKEN_FINGER_R);count += 1;}
	if (!IS_ARM_L(victim,BROKEN_FINGER_L) && !IS_ARM_L(victim,LOST_FINGER_L) && number_percent() < 25)
	    {SET_BIT(victim->loc_hp[2],BROKEN_FINGER_L);count += 1;}
	if (count == 1) sprintf(buf2,"finger");
	else            sprintf(buf2,"fingers");
	if (count > 0 && count2 > 0)
	{
	    sprintf(buf,"Your skillful breaks %d %s and the thumb on $N's left hand.",count,buf2);
	    act(buf,ch,NULL,victim,TO_CHAR);
	    sprintf(buf,"$n's skillful blow breaks %d %s and the thumb on $N's left hand.",count,buf2);
	    act(buf,ch,NULL,victim,TO_NOTVICT);
	    sprintf(buf,"$n's skillful blow breaks %d %s and the thumb on your left hand.",count,buf2);
	    act(buf,ch,NULL,victim,TO_VICT);
	    if ((obj = get_eq_char( victim, WEAR_HOLD )) != NULL)
		take_item(victim,obj);
	    return;
	}
	else if (count > 0)
	{
	    sprintf(buf,"Your skillful blow breaks %d %s on $N's left hand.",count,buf2);
	    act(buf,ch,NULL,victim,TO_CHAR);
	    sprintf(buf,"$n's skillful blow breaks %d %s on $N's left hand.",count,buf2);
	    act(buf,ch,NULL,victim,TO_NOTVICT);
	    sprintf(buf,"$n's skillful blow breaks %d %s on your left hand.",count,buf2);
	    act(buf,ch,NULL,victim,TO_VICT);
	    if ((obj = get_eq_char( victim, WEAR_HOLD )) != NULL)
		take_item(victim,obj);
	    return;
	}
	else if (count2 > 0)
	{
	    sprintf(buf,"Your skillful blow breaks the thumb on $N's left hand.");
	    act(buf,ch,NULL,victim,TO_CHAR);
	    sprintf(buf,"$n's skillful blow breaks the thumb on $N's left hand.");
	    act(buf,ch,NULL,victim,TO_NOTVICT);
	    sprintf(buf,"$n's skillful blow breaks the thumb on your left hand.");
	    act(buf,ch,NULL,victim,TO_VICT);
	    if ((obj = get_eq_char( victim, WEAR_HOLD )) != NULL)
		take_item(victim,obj);
	    return;
	}
	return;
    }
    else if (critical == 14)
    {
	if (IS_ARM_R(victim,LOST_ARM)) return;
	if (IS_ARM_R(victim,LOST_HAND)) return;
	if (IS_ARM_R(victim,LOST_THUMB) && IS_ARM_R(victim,LOST_FINGER_I) &&
	IS_ARM_R(victim,LOST_FINGER_M) && IS_ARM_R(victim,LOST_FINGER_R) &&
	IS_ARM_R(victim,LOST_FINGER_L)) return;
	if ( (damaged = get_eq_char(victim,WEAR_HANDS) ) != NULL &&
		damaged->toughness > 0 && !IS_ITEMAFF(ch, ITEMA_VORPAL))
	{
	    act("$p prevent you from loosing some fingers from your right hand.",victim,damaged,NULL,TO_CHAR);
	    act("$p prevent $n from loosing some fingers from $s right hand.",victim,damaged,NULL,TO_ROOM);
	    if (dam - damaged->toughness < 0) return;
	    if ((dam - damaged->toughness > damaged->resistance))
	    	damaged->condition -= damaged->resistance;
	    else
	    	damaged->condition -= (dam - damaged->toughness);
	    if (damaged->condition < 1)
	    {
	    	act("$p fall broken to the ground.",ch,damaged,NULL,TO_CHAR);
	    	act("$p fall broken to the ground.",ch,damaged,NULL,TO_ROOM);
	    	obj_from_char(damaged);
	    	extract_obj(damaged);
	    }
	    return;
	}
	count = 0;
	count2 = 0;
	if (IS_ARM_R(victim,LOST_ARM)) return;
	if (IS_ARM_R(victim,LOST_HAND)) return;

	if (!IS_ARM_R(victim,LOST_THUMB) && number_percent() < 25)
	    {SET_BIT(victim->loc_hp[3],LOST_THUMB);count2 += 1;
	    make_part(victim,"thumb");}
	if (!IS_ARM_R(victim,LOST_FINGER_I) && number_percent() < 25)
	    {SET_BIT(victim->loc_hp[3],LOST_FINGER_I);count += 1;
	    make_part(victim,"index");}
	if (!IS_ARM_R(victim,LOST_FINGER_M) && number_percent() < 25)
	    {SET_BIT(victim->loc_hp[3],LOST_FINGER_M);count += 1;
	    make_part(victim,"middle");}
	if (!IS_ARM_R(victim,LOST_FINGER_R) && number_percent() < 25)
	    {SET_BIT(victim->loc_hp[3],LOST_FINGER_R);count += 1;
	    make_part(victim,"ring");
	    if ((obj = get_eq_char( victim, WEAR_FINGER_R )) != NULL)
	        take_item(victim,obj);}
	if (!IS_ARM_R(victim,LOST_FINGER_L) && number_percent() < 25)
	    {SET_BIT(victim->loc_hp[3],LOST_FINGER_L);count += 1;
	    make_part(victim,"little");}
	if (count == 1) sprintf(buf2,"finger");
	else            sprintf(buf2,"fingers");
	if (count > 0 && count2 > 0)
	{
	    sprintf(buf,"Your skillful blow cuts off %d %s and the thumb from $N's right hand.",count,buf2);
	    act(buf,ch,NULL,victim,TO_CHAR);
	    sprintf(buf,"$n's skillful blow cuts off %d %s and the thumb from $N's right hand.",count,buf2);
	    act(buf,ch,NULL,victim,TO_NOTVICT);
	    sprintf(buf,"$n's skillful blow cuts off %d %s and the thumb from your right hand.",count,buf2);
	    act(buf,ch,NULL,victim,TO_VICT);
	    if ((obj = get_eq_char( victim, WEAR_WIELD )) != NULL)
		take_item(victim,obj);
	    return;
	}
	else if (count > 0)
	{
	    sprintf(buf,"Your skillful blow cuts off %d %s from $N's right hand.",count,buf2);
	    act(buf,ch,NULL,victim,TO_CHAR);
	    sprintf(buf,"$n's skillful blow cuts off %d %s from $N's right hand.",count,buf2);
	    act(buf,ch,NULL,victim,TO_NOTVICT);
	    sprintf(buf,"$n's skillful blow cuts off %d %s from your right hand.",count,buf2);
	    act(buf,ch,NULL,victim,TO_VICT);
	    if ((obj = get_eq_char( victim, WEAR_WIELD )) != NULL)
		take_item(victim,obj);
	    return;
	}
	else if (count2 > 0)
	{
	    sprintf(buf,"Your skillful blow cuts off the thumb from $N's right hand.");
	    act(buf,ch,NULL,victim,TO_CHAR);
	    sprintf(buf,"$n's skillful blow cuts off the thumb from $N's right hand.");
	    act(buf,ch,NULL,victim,TO_NOTVICT);
	    sprintf(buf,"$n's skillful blow cuts off the thumb from your right hand.");
	    act(buf,ch,NULL,victim,TO_VICT);
	    if ((obj = get_eq_char( victim, WEAR_WIELD )) != NULL)
		take_item(victim,obj);
	    return;
	}
	return;
    }
    else if (critical == 15)
    {
	if (IS_ARM_R(victim,LOST_ARM)) return;
	if (IS_ARM_R(victim,LOST_HAND)) return;
	if ((IS_ARM_R(victim,LOST_THUMB) || IS_ARM_R(victim,BROKEN_THUMB)) &&
	    (IS_ARM_R(victim,LOST_FINGER_I) || IS_ARM_R(victim,BROKEN_FINGER_I)) &&
	    (IS_ARM_R(victim,LOST_FINGER_M) || IS_ARM_R(victim,BROKEN_FINGER_M)) &&
	    (IS_ARM_R(victim,LOST_FINGER_R) || IS_ARM_R(victim,BROKEN_FINGER_R)) &&
	    (IS_ARM_R(victim,LOST_FINGER_L) || IS_ARM_R(victim,BROKEN_FINGER_L)))
		return;
	if ( (damaged = get_eq_char(victim,WEAR_HANDS) ) != NULL &&
		damaged->toughness > 0 && !IS_ITEMAFF(ch, ITEMA_VORPAL))
	{
	    act("$p prevent you from breaking some fingers on your right hand.",victim,damaged,NULL,TO_CHAR);
	    act("$p prevent $n from breaking some fingers on $s right hand.",victim,damaged,NULL,TO_ROOM);
	    if (dam - damaged->toughness < 0) return;
	    if ((dam - damaged->toughness > damaged->resistance))
	    	damaged->condition -= damaged->resistance;
	    else
	    	damaged->condition -= (dam - damaged->toughness);
	    if (damaged->condition < 1)
	    {
	    	act("$p fall broken to the ground.",ch,damaged,NULL,TO_CHAR);
	    	act("$p fall broken to the ground.",ch,damaged,NULL,TO_ROOM);
	    	obj_from_char(damaged);
	    	extract_obj(damaged);
	    }
	    return;
	}
	count = 0;
	count2 = 0;
	if (IS_ARM_R(victim,LOST_ARM)) return;
	if (IS_ARM_R(victim,LOST_HAND)) return;

	if (!IS_ARM_R(victim,BROKEN_THUMB) && !IS_ARM_R(victim,LOST_THUMB) && number_percent() < 25)
	    {SET_BIT(victim->loc_hp[3],BROKEN_THUMB);count2 += 1;}
	if (!IS_ARM_R(victim,BROKEN_FINGER_I) && !IS_ARM_R(victim,LOST_FINGER_I) && number_percent() < 25)
	    {SET_BIT(victim->loc_hp[3],BROKEN_FINGER_I);count += 1;}
	if (!IS_ARM_R(victim,BROKEN_FINGER_M) && !IS_ARM_R(victim,LOST_FINGER_M) && number_percent() < 25)
	    {SET_BIT(victim->loc_hp[3],BROKEN_FINGER_M);count += 1;}
	if (!IS_ARM_R(victim,BROKEN_FINGER_R) && !IS_ARM_R(victim,LOST_FINGER_R) && number_percent() < 25)
	    {SET_BIT(victim->loc_hp[3],BROKEN_FINGER_R);count += 1;}
	if (!IS_ARM_R(victim,BROKEN_FINGER_L) && !IS_ARM_R(victim,LOST_FINGER_L) && number_percent() < 25)
	    {SET_BIT(victim->loc_hp[3],BROKEN_FINGER_L);count += 1;}
	if (count == 1) sprintf(buf2,"finger");
	else            sprintf(buf2,"fingers");
	if (count > 0 && count2 > 0)
	{
	    sprintf(buf,"Your skillful breaks %d %s and the thumb on $N's right hand.",count,buf2);
	    act(buf,ch,NULL,victim,TO_CHAR);
	    sprintf(buf,"$n's skillful blow breaks %d %s and the thumb on $N's right hand.",count,buf2);
	    act(buf,ch,NULL,victim,TO_NOTVICT);
	    sprintf(buf,"$n's skillful blow breaks %d %s and the thumb on your right hand.",count,buf2);
	    act(buf,ch,NULL,victim,TO_VICT);
	    if ((obj = get_eq_char( victim, WEAR_WIELD )) != NULL)
		take_item(victim,obj);
	    return;
	}
	else if (count > 0)
	{
	    sprintf(buf,"Your skillful blow breaks %d %s on $N's right hand.",count,buf2);
	    act(buf,ch,NULL,victim,TO_CHAR);
	    sprintf(buf,"$n's skillful blow breaks %d %s on $N's right hand.",count,buf2);
	    act(buf,ch,NULL,victim,TO_NOTVICT);
	    sprintf(buf,"$n's skillful blow breaks %d %s on your right hand.",count,buf2);
	    act(buf,ch,NULL,victim,TO_VICT);
	    if ((obj = get_eq_char( victim, WEAR_WIELD )) != NULL)
		take_item(victim,obj);
	    return;
	}
	else if (count2 > 0)
	{
	    sprintf(buf,"Your skillful blow breaks the thumb on $N's right hand.");
	    act(buf,ch,NULL,victim,TO_CHAR);
	    sprintf(buf,"$n's skillful blow breaks the thumb on $N's right hand.");
	    act(buf,ch,NULL,victim,TO_NOTVICT);
	    sprintf(buf,"$n's skillful blow breaks the thumb on your right hand.");
	    act(buf,ch,NULL,victim,TO_VICT);
	    if ((obj = get_eq_char( victim, WEAR_WIELD )) != NULL)
		take_item(victim,obj);
	    return;
	}
	return;
    }
    else if (critical == 16)
    {
	if (IS_LEG_L(victim,LOST_LEG)) return;
	if ( (damaged = get_eq_char(victim,WEAR_LEGS) ) != NULL &&
		damaged->toughness > 0 && !IS_ITEMAFF(ch, ITEMA_VORPAL))
	{
	    act("$p prevent you from loosing your left leg.",victim,damaged,NULL,TO_CHAR);
	    act("$p prevent $n from loosing $s left leg.",victim,damaged,NULL,TO_ROOM);
	    if (dam - damaged->toughness < 0) return;
	    if ((dam - damaged->toughness > damaged->resistance))
	    	damaged->condition -= damaged->resistance;
	    else
	    	damaged->condition -= (dam - damaged->toughness);
	    if (damaged->condition < 1)
	    {
	    	act("$p fall broken to the ground.",ch,damaged,NULL,TO_CHAR);
	    	act("$p fall broken to the ground.",ch,damaged,NULL,TO_ROOM);
	    	obj_from_char(damaged);
	    	extract_obj(damaged);
	    }
	    return;
	}
	if (!IS_LEG_L(victim,LOST_LEG))
	    SET_BIT(victim->loc_hp[4],LOST_LEG);
	else return;
	if (!IS_BLEEDING(victim,BLEEDING_LEG_L))
	    SET_BIT(victim->loc_hp[6],BLEEDING_LEG_L);
	if (IS_BLEEDING(victim,BLEEDING_FOOT_L))
	    REMOVE_BIT(victim->loc_hp[6],BLEEDING_FOOT_L);
	act("Your skillful blow cuts off $N's left leg!",ch,NULL,victim,TO_CHAR);
	act("$n's skillful blow cuts off $N's left leg!",ch,NULL,victim,TO_NOTVICT);
	act("$n's skillful blow cuts off your left leg!",ch,NULL,victim,TO_VICT);
	make_part(victim,"leg");
	if (IS_LEG_L(victim,LOST_LEG) && IS_LEG_R(victim,LOST_LEG))
	{
	    if ((obj = get_eq_char( victim, WEAR_LEGS )) != NULL)
		take_item(victim,obj);
	}
	if ((obj = get_eq_char( victim, WEAR_FEET )) != NULL)
	    take_item(victim,obj);
	return;
    }
    else if (critical == 17)
    {
	if (IS_LEG_R(victim,LOST_LEG)) return;
	if ( (damaged = get_eq_char(victim,WEAR_LEGS) ) != NULL &&
		damaged->toughness > 0 && !IS_ITEMAFF(ch, ITEMA_VORPAL))
	{
	    act("$p prevent you from loosing your right leg.",victim,damaged,NULL,TO_CHAR);
	    act("$p prevent $n from loosing $s right leg.",victim,damaged,NULL,TO_ROOM);
	    if (dam - damaged->toughness < 0) return;
	    if ((dam - damaged->toughness > damaged->resistance))
	    	damaged->condition -= damaged->resistance;
	    else
	    	damaged->condition -= (dam - damaged->toughness);
	    if (damaged->condition < 1)
	    {
	    	act("$p fall broken to the ground.",ch,damaged,NULL,TO_CHAR);
	    	act("$p fall broken to the ground.",ch,damaged,NULL,TO_ROOM);
	    	obj_from_char(damaged);
	    	extract_obj(damaged);
	    }
	    return;
	}
	if (!IS_LEG_R(victim,LOST_LEG))
	    SET_BIT(victim->loc_hp[5],LOST_LEG);
	else return;
	if (!IS_BLEEDING(victim,BLEEDING_LEG_R))
	    SET_BIT(victim->loc_hp[6],BLEEDING_LEG_R);
	if (IS_BLEEDING(victim,BLEEDING_FOOT_R))
	    REMOVE_BIT(victim->loc_hp[6],BLEEDING_FOOT_R);
	act("Your skillful blow cuts off $N's right leg!",ch,NULL,victim,TO_CHAR);
	act("$n's skillful blow cuts off $N's right leg!",ch,NULL,victim,TO_NOTVICT);
	act("$n's skillful blow cuts off your right leg!",ch,NULL,victim,TO_VICT);
	make_part(victim,"leg");
	if (IS_LEG_L(victim,LOST_LEG) && IS_LEG_R(victim,LOST_LEG))
	{
	    if ((obj = get_eq_char( victim, WEAR_LEGS )) != NULL)
		take_item(victim,obj);
	}
	if ((obj = get_eq_char( victim, WEAR_FEET )) != NULL)
	    take_item(victim,obj);
	return;
    }
    else if (critical == 18)
    {
	if (IS_LEG_L(victim,BROKEN_LEG) || IS_LEG_L(victim,LOST_LEG)) return;
	if ( (damaged = get_eq_char(victim,WEAR_LEGS) ) != NULL &&
		damaged->toughness > 0 && !IS_ITEMAFF(ch, ITEMA_VORPAL))
	{
	    act("$p prevent you from breaking your left leg.",victim,damaged,NULL,TO_CHAR);
	    act("$p prevent $n from breaking $s left leg.",victim,damaged,NULL,TO_ROOM);
	    if (dam - damaged->toughness < 0) return;
	    if ((dam - damaged->toughness > damaged->resistance))
	    	damaged->condition -= damaged->resistance;
	    else
	    	damaged->condition -= (dam - damaged->toughness);
	    if (damaged->condition < 1)
	    {
	    	act("$p fall broken to the ground.",ch,damaged,NULL,TO_CHAR);
	    	act("$p fall broken to the ground.",ch,damaged,NULL,TO_ROOM);
	    	obj_from_char(damaged);
	    	extract_obj(damaged);
	    }
	    return;
	}
	if (!IS_LEG_L(victim,BROKEN_LEG) && !IS_LEG_L(victim,LOST_LEG))
	    SET_BIT(victim->loc_hp[4],BROKEN_LEG);
	else return;
	act("Your skillful blow breaks $N's left leg!",ch,NULL,victim,TO_CHAR);
	act("$n's skillful blow breaks $N's left leg!",ch,NULL,victim,TO_NOTVICT);
	act("$n's skillful blow breaks your left leg!",ch,NULL,victim,TO_VICT);
	return;
    }
    else if (critical == 19)
    {
	if (IS_LEG_R(victim,BROKEN_LEG) || IS_LEG_R(victim,LOST_LEG)) return;
	if ( (damaged = get_eq_char(victim,WEAR_LEGS) ) != NULL &&
		damaged->toughness > 0 && !IS_ITEMAFF(ch, ITEMA_VORPAL))
	{
	    act("$p prevent you from breaking your right leg.",victim,damaged,NULL,TO_CHAR);
	    act("$p prevent $n from breaking $s right leg.",victim,damaged,NULL,TO_ROOM);
	    if (dam - damaged->toughness < 0) return;
	    if ((dam - damaged->toughness > damaged->resistance))
	    	damaged->condition -= damaged->resistance;
	    else
	    	damaged->condition -= (dam - damaged->toughness);
	    if (damaged->condition < 1)
	    {
	    	act("$p fall broken to the ground.",ch,damaged,NULL,TO_CHAR);
	    	act("$p fall broken to the ground.",ch,damaged,NULL,TO_ROOM);
	    	obj_from_char(damaged);
	    	extract_obj(damaged);
	    }
	    return;
	}
	if (!IS_LEG_R(victim,BROKEN_LEG) && !IS_LEG_R(victim,LOST_LEG))
	    SET_BIT(victim->loc_hp[5],BROKEN_LEG);
	else return;
	act("Your skillful blow breaks $N's right leg!",ch,NULL,victim,TO_CHAR);
	act("$n's skillful blow breaks $N's right leg!",ch,NULL,victim,TO_NOTVICT);
	act("$n's skillful blow breaks your right leg!",ch,NULL,victim,TO_VICT);
	return;
    }
    else if (critical == 20)
    {
	if (IS_LEG_L(victim,LOST_LEG) || IS_LEG_L(victim,LOST_FOOT)) return;
	if ( (damaged = get_eq_char(victim,WEAR_FEET) ) != NULL &&
		damaged->toughness > 0 && !IS_ITEMAFF(ch, ITEMA_VORPAL))
	{
	    act("$p prevent you from loosing your left foot.",victim,damaged,NULL,TO_CHAR);
	    act("$p prevent $n from loosing $s left foot.",victim,damaged,NULL,TO_ROOM);
	    if (dam - damaged->toughness < 0) return;
	    if ((dam - damaged->toughness > damaged->resistance))
	    	damaged->condition -= damaged->resistance;
	    else
	    	damaged->condition -= (dam - damaged->toughness);
	    if (damaged->condition < 1)
	    {
	    	act("$p fall broken to the ground.",ch,damaged,NULL,TO_CHAR);
	    	act("$p fall broken to the ground.",ch,damaged,NULL,TO_ROOM);
	    	obj_from_char(damaged);
	    	extract_obj(damaged);
	    }
	    return;
	}
	if (!IS_LEG_L(victim,LOST_LEG) && !IS_LEG_L(victim,LOST_FOOT))
	    SET_BIT(victim->loc_hp[4],LOST_FOOT);
	else return;
	if (IS_BLEEDING(victim,BLEEDING_LEG_L))
	    REMOVE_BIT(victim->loc_hp[6],BLEEDING_LEG_L);
	if (!IS_BLEEDING(victim,BLEEDING_FOOT_L))
	    SET_BIT(victim->loc_hp[6],BLEEDING_FOOT_L);
	act("Your skillful blow cuts off $N's left foot!",ch,NULL,victim,TO_CHAR);
	act("$n's skillful blow cuts off $N's left foot!",ch,NULL,victim,TO_NOTVICT);
	act("$n's skillful blow cuts off your left foot!",ch,NULL,victim,TO_VICT);
	make_part(victim,"foot");
	if ((obj = get_eq_char( victim, WEAR_FEET )) != NULL)
	    take_item(victim,obj);
	return;
    }
    else if (critical == 21)
    {
	if (IS_LEG_R(victim,LOST_LEG) || IS_LEG_R(victim,LOST_FOOT)) return;
	if ( (damaged = get_eq_char(victim,WEAR_FEET) ) != NULL &&
		damaged->toughness > 0 && !IS_ITEMAFF(ch, ITEMA_VORPAL))
	{
	    act("$p prevent you from loosing your right foot.",victim,damaged,NULL,TO_CHAR);
	    act("$p prevent $n from loosing $s right foot.",victim,damaged,NULL,TO_ROOM);
	    if (dam - damaged->toughness < 0) return;
	    if ((dam - damaged->toughness > damaged->resistance))
	    	damaged->condition -= damaged->resistance;
	    else
	    	damaged->condition -= (dam - damaged->toughness);
	    if (damaged->condition < 1)
	    {
	    	act("$p fall broken to the ground.",ch,damaged,NULL,TO_CHAR);
	    	act("$p fall broken to the ground.",ch,damaged,NULL,TO_ROOM);
	    	obj_from_char(damaged);
	    	extract_obj(damaged);
	    }
	    return;
	}
	if (!IS_LEG_R(victim,LOST_LEG) && !IS_LEG_R(victim,LOST_FOOT))
	    SET_BIT(victim->loc_hp[5],LOST_FOOT);
	else return;
	if (IS_BLEEDING(victim,BLEEDING_LEG_R))
	    REMOVE_BIT(victim->loc_hp[6],BLEEDING_LEG_R);
	if (!IS_BLEEDING(victim,BLEEDING_FOOT_R))
	    SET_BIT(victim->loc_hp[6],BLEEDING_FOOT_R);
	act("Your skillful blow cuts off $N's right foot!",ch,NULL,victim,TO_CHAR);
	act("$n's skillful blow cuts off $N's right foot!",ch,NULL,victim,TO_NOTVICT);
	act("$n's skillful blow cuts off your right foot!",ch,NULL,victim,TO_VICT);
	make_part(victim,"foot");
	if ((obj = get_eq_char( victim, WEAR_FEET )) != NULL)
	    take_item(victim,obj);
	return;
    }
    else if (critical == 22)
    {
	int bodyloc = 0;
	int broken = number_range(1,3);
	if (IS_BODY(victim,BROKEN_RIBS_1 )) bodyloc += 1;
	if (IS_BODY(victim,BROKEN_RIBS_2 )) bodyloc += 2;
	if (IS_BODY(victim,BROKEN_RIBS_4 )) bodyloc += 4;
	if (IS_BODY(victim,BROKEN_RIBS_8 )) bodyloc += 8;
	if (IS_BODY(victim,BROKEN_RIBS_16)) bodyloc += 16;
	if (bodyloc >= 24) return;

	if ( (damaged = get_eq_char(victim,WEAR_BODY) ) != NULL &&
		damaged->toughness > 0 && !IS_ITEMAFF(ch, ITEMA_VORPAL))
	{
	    act("$p prevents you from breaking some ribs.",victim,damaged,NULL,TO_CHAR);
	    act("$p prevents $n from breaking some ribs.",victim,damaged,NULL,TO_ROOM);
	    if (dam - damaged->toughness < 0) return;
	    if ((dam - damaged->toughness > damaged->resistance))
	    	damaged->condition -= damaged->resistance;
	    else
	    	damaged->condition -= (dam - damaged->toughness);
	    if (damaged->condition < 1)
	    {
	    	act("$p fall broken to the ground.",ch,damaged,NULL,TO_CHAR);
	    	act("$p fall broken to the ground.",ch,damaged,NULL,TO_ROOM);
	    	obj_from_char(damaged);
	    	extract_obj(damaged);
	    }
	    return;
	}
	if (IS_BODY(victim,BROKEN_RIBS_1 ))
	    REMOVE_BIT(victim->loc_hp[1],BROKEN_RIBS_1);
	if (IS_BODY(victim,BROKEN_RIBS_2 ))
	    REMOVE_BIT(victim->loc_hp[1],BROKEN_RIBS_2);
	if (IS_BODY(victim,BROKEN_RIBS_4 ))
	    REMOVE_BIT(victim->loc_hp[1],BROKEN_RIBS_4);
	if (IS_BODY(victim,BROKEN_RIBS_8 ))
	    REMOVE_BIT(victim->loc_hp[1],BROKEN_RIBS_8);
	if (IS_BODY(victim,BROKEN_RIBS_16))
	    REMOVE_BIT(victim->loc_hp[1],BROKEN_RIBS_16);
	if (bodyloc+broken > 24) broken -= 1;
	if (bodyloc+broken > 24) broken -= 1;
	bodyloc += broken;
	if (bodyloc >= 16) {bodyloc -= 16;
	    SET_BIT(victim->loc_hp[1],BROKEN_RIBS_16);}
	if (bodyloc >= 8) {bodyloc -= 8;
	    SET_BIT(victim->loc_hp[1],BROKEN_RIBS_8);}
	if (bodyloc >= 4) {bodyloc -= 4;
	    SET_BIT(victim->loc_hp[1],BROKEN_RIBS_4);}
	if (bodyloc >= 2) {bodyloc -= 2;
	    SET_BIT(victim->loc_hp[1],BROKEN_RIBS_2);}
	if (bodyloc >= 1) {bodyloc -= 1;
	    SET_BIT(victim->loc_hp[1],BROKEN_RIBS_1);}
	sprintf(buf,"Your skillful blow breaks %d of $N's ribs!",broken);
	act(buf,ch,NULL,victim,TO_CHAR);
	sprintf(buf,"$n's skillful blow breaks %d of $N's ribs!",broken);
	act(buf,ch,NULL,victim,TO_NOTVICT);
	sprintf(buf,"$n's skillful blow breaks %d of your ribs!",broken);
	act(buf,ch,NULL,victim,TO_VICT);
	return;
    }
    else if (critical == 23)
    {
	int bodyloc = 0;
	int broken = number_range(1,3);
	if (IS_HEAD(victim,LOST_TOOTH_1 )) bodyloc += 1;
	if (IS_HEAD(victim,LOST_TOOTH_2 )) bodyloc += 2;
	if (IS_HEAD(victim,LOST_TOOTH_4 )) bodyloc += 4;
	if (IS_HEAD(victim,LOST_TOOTH_8 )) bodyloc += 8;
	if (IS_HEAD(victim,LOST_TOOTH_16)) bodyloc += 16;
	if (bodyloc >= 28) return;

	if ( (damaged = get_eq_char(victim,WEAR_FACE) ) != NULL &&
		damaged->toughness > 0 && !IS_ITEMAFF(ch, ITEMA_VORPAL))
	{
	    act("$p prevents you from loosing some teeth.",victim,damaged,NULL,TO_CHAR);
	    act("$p prevents $n from loosing some teeth.",victim,damaged,NULL,TO_ROOM);
	    if (dam - damaged->toughness < 0) return;
	    if ((dam - damaged->toughness > damaged->resistance))
	    	damaged->condition -= damaged->resistance;
	    else
	    	damaged->condition -= (dam - damaged->toughness);
	    if (damaged->condition < 1)
	    {
	    	act("$p fall broken to the ground.",ch,damaged,NULL,TO_CHAR);
	    	act("$p fall broken to the ground.",ch,damaged,NULL,TO_ROOM);
	    	obj_from_char(damaged);
	    	extract_obj(damaged);
	    }
	    return;
	}
	if (IS_HEAD(victim,LOST_TOOTH_1 ))
	    REMOVE_BIT(victim->loc_hp[LOC_HEAD],LOST_TOOTH_1);
	if (IS_HEAD(victim,LOST_TOOTH_2 ))
	    REMOVE_BIT(victim->loc_hp[LOC_HEAD],LOST_TOOTH_2);
	if (IS_HEAD(victim,LOST_TOOTH_4 ))
	    REMOVE_BIT(victim->loc_hp[LOC_HEAD],LOST_TOOTH_4);
	if (IS_HEAD(victim,LOST_TOOTH_8 ))
	    REMOVE_BIT(victim->loc_hp[LOC_HEAD],LOST_TOOTH_8);
	if (IS_HEAD(victim,LOST_TOOTH_16))
	    REMOVE_BIT(victim->loc_hp[LOC_HEAD],LOST_TOOTH_16);
	if (bodyloc+broken > 28) broken -= 1;
	if (bodyloc+broken > 28) broken -= 1;
	bodyloc += broken;
	if (bodyloc >= 16) {bodyloc -= 16;
	    SET_BIT(victim->loc_hp[LOC_HEAD],LOST_TOOTH_16);}
	if (bodyloc >= 8) {bodyloc -= 8;
	    SET_BIT(victim->loc_hp[LOC_HEAD],LOST_TOOTH_8);}
	if (bodyloc >= 4) {bodyloc -= 4;
	    SET_BIT(victim->loc_hp[LOC_HEAD],LOST_TOOTH_4);}
	if (bodyloc >= 2) {bodyloc -= 2;
	    SET_BIT(victim->loc_hp[LOC_HEAD],LOST_TOOTH_2);}
	if (bodyloc >= 1) {bodyloc -= 1;
	    SET_BIT(victim->loc_hp[LOC_HEAD],LOST_TOOTH_1);}
	sprintf(buf,"Your skillful blow knocks out %d of $N's teeth!",broken);
	act(buf,ch,NULL,victim,TO_CHAR);
	sprintf(buf,"$n's skillful blow knocks out %d of $N's teeth!",broken);
	act(buf,ch,NULL,victim,TO_NOTVICT);
	sprintf(buf,"$n's skillful blow knocks out %d of your teeth!",broken);
	act(buf,ch,NULL,victim,TO_VICT);
	if (broken >= 1) make_part(victim,"tooth");
	if (broken >= 2) make_part(victim,"tooth");
	if (broken >= 3) make_part(victim,"tooth");
	return;
    }
    return;
}

void special_move( CHAR_DATA *ch, CHAR_DATA *victim )
{
    int dam = number_range(5,10) + char_damroll(ch);

    if (dam < 10) dam = 10;

    switch (number_range(1,7))
    {
    default:
	return;
    case 1:
	act("You pull your hands into your waist then snap them into $N's stomach.",ch,NULL,victim,TO_CHAR);
	act("$n pulls $s hands into $s waist then snaps them into your stomach.",ch,NULL,victim,TO_VICT);
	act("$n pulls $s hands into $s waist then snaps them into $N's stomach.",ch,NULL,victim,TO_NOTVICT);
	damage(ch,victim,dam,gsn_punch);
	if (victim == NULL || victim->position == POS_DEAD) return;
	act("You double over in agony, and fall to the ground gasping for breath.",victim,NULL,NULL,TO_CHAR);
	act("$n doubles over in agony, and falls to the ground gasping for breath.",victim,NULL,NULL,TO_ROOM);
	stop_fighting(victim, TRUE);
	victim->position = POS_STUNNED;
	break;
    case 2:
	act("You spin in a low circle, catching $N behind $S ankle.",ch,NULL,victim,TO_CHAR);
	act("$n spins in a low circle, catching you behind your ankle.",ch,NULL,victim,TO_VICT);
	act("$n spins in a low circle, catching $N behind $S ankle.",ch,NULL,victim,TO_NOTVICT);
	damage(ch,victim,dam,gsn_sweep);
	if (victim == NULL || victim->position == POS_DEAD) return;
	if (number_percent() <= 25 && !IS_LEG_L(victim,BROKEN_LEG) && !IS_LEG_L(victim,LOST_LEG))
	{act("Your left leg shatters under the impact of the blow!",victim,NULL,NULL,TO_CHAR);
    	act("$n's left leg shatters under the impact of the blow!",victim,NULL,NULL,TO_ROOM);
	SET_BIT(victim->loc_hp[LOC_LEG_L],BROKEN_LEG);}
	else if (number_percent() <= 25 && !IS_LEG_R(victim,BROKEN_LEG) && !IS_LEG_R(victim,LOST_LEG))
	{act("Your right leg shatters under the impact of the blow!",victim,NULL,NULL,TO_CHAR);
    	act("$n's right leg shatters under the impact of the blow!",victim,NULL,NULL,TO_ROOM);
	SET_BIT(victim->loc_hp[LOC_LEG_R],BROKEN_LEG);}
	act("You crash to the ground, stunned.",victim,NULL,NULL,TO_CHAR);
	act("$n crashes to the ground, stunned.",victim,NULL,NULL,TO_ROOM);
	stop_fighting(victim, TRUE);
	victim->position = POS_STUNNED;
	break;
    case 3:
	act("You roll between $N's legs and flip to your feet.",ch,NULL,victim,TO_CHAR);
	act("$n rolls between your legs and flips to $s feet.",ch,NULL,victim,TO_VICT);
	act("$n rolls between $N's legs and flips to $s feet.",ch,NULL,victim,TO_NOTVICT);
	act("You spin around and smash your elbow into the back of $N's head.",ch,NULL,victim,TO_CHAR);
	act("$n spins around and smashes $s elbow into the back of your head.",ch,NULL,victim,TO_VICT);
	act("$n spins around and smashes $s elbow into the back of $N's head.",ch,NULL,victim,TO_NOTVICT);
	damage(ch,victim,dam,gsn_elbow);
	if (victim == NULL || victim->position == POS_DEAD) return;
	act("You fall to the ground, stunned.",victim,NULL,NULL,TO_CHAR);
	act("$n falls to the ground, stunned.",victim,NULL,NULL,TO_ROOM);
	stop_fighting(victim, TRUE);
	victim->position = POS_STUNNED;
	break;
    case 4:
	act("You somersault over $N's head and land lightly on your toes.",ch,NULL,victim,TO_CHAR);
	act("$n somersaults over your head and lands lightly on $s toes.",ch,NULL,victim,TO_VICT);
	act("$n somersaults over $N's head and lands lightly on $s toes.",ch,NULL,victim,TO_NOTVICT);
	act("You roll back onto your shoulders and kick both feet into $N's back.",ch,NULL,victim,TO_CHAR);
	act("$n rolls back onto $s shoulders and kicks both feet into your back.",ch,NULL,victim,TO_VICT);
	act("$n rolls back onto $s shoulders and kicks both feet into $N's back.",ch,NULL,victim,TO_NOTVICT);
	damage(ch,victim,dam,gsn_kick);
	if (victim == NULL || victim->position == POS_DEAD) return;
	if (number_percent() <= 25 && !IS_BODY(victim,BROKEN_SPINE))
	{act("Your spine shatters under the impact of the blow!",victim,NULL,NULL,TO_CHAR);
    	act("$n's spine shatters under the impact of the blow!",victim,NULL,NULL,TO_ROOM);
	SET_BIT(victim->loc_hp[LOC_BODY],BROKEN_SPINE);}
	act("You fall to the ground, stunned.",victim,NULL,NULL,TO_CHAR);
	act("$n falls to the ground, stunned.",victim,NULL,NULL,TO_ROOM);
	act("You flip back up to your feet.",ch,NULL,NULL,TO_CHAR);
	act("$n flips back up to $s feet.",ch,NULL,NULL,TO_ROOM);
	stop_fighting(victim, TRUE);
	victim->position = POS_STUNNED;
	break;
    case 5:
	act("You grab $N by the neck and slam your head into $S face.",ch,NULL,victim,TO_CHAR);
	act("$n grabs $N by the neck and slams $s head into $S face.",ch,NULL,victim,TO_NOTVICT);
	act("$n grabs you by the neck and slams $s head into your face.",ch,NULL,victim,TO_VICT);
	damage(ch,victim,dam,gsn_headbutt);
	if (victim == NULL || victim->position == POS_DEAD) return;
	if (number_percent() <= 25 && !IS_HEAD(victim,BROKEN_NOSE) && !IS_HEAD(victim,LOST_NOSE))
	{act("Your nose shatters under the impact of the blow!",victim,NULL,NULL,TO_CHAR);
    	act("$n's nose shatters under the impact of the blow!",victim,NULL,NULL,TO_ROOM);
	SET_BIT(victim->loc_hp[LOC_HEAD],BROKEN_NOSE);}
	else if (number_percent() <= 25 && !IS_HEAD(victim,BROKEN_JAW))
	{act("Your jaw shatters under the impact of the blow!",victim,NULL,NULL,TO_CHAR);
    	act("$n's jaw shatters under the impact of the blow!",victim,NULL,NULL,TO_ROOM);
	SET_BIT(victim->loc_hp[LOC_HEAD],BROKEN_JAW);}
	else if (number_percent() <= 25 && !IS_BODY(victim,BROKEN_NECK))
	{act("Your neck shatters under the impact of the blow!",victim,NULL,NULL,TO_CHAR);
    	act("$n's neck shatters under the impact of the blow!",victim,NULL,NULL,TO_ROOM);
	SET_BIT(victim->loc_hp[LOC_BODY],BROKEN_NECK);}
	act("You grab $N by the waist and hoist $M above your head.",ch,NULL,victim,TO_CHAR);
	act("$n grabs $N by the waist and hoists $M above $s head.",ch,NULL,victim,TO_NOTVICT);
	act("$n grabs you by the waist and hoists you above $s head.",ch,NULL,victim,TO_VICT);
	special_hurl(ch,victim);
	if (victim == NULL || victim->position == POS_DEAD) return;
	act("You crash to the ground, stunned.",victim,NULL,NULL,TO_CHAR);
	act("$n crashes to the ground, stunned.",victim,NULL,NULL,TO_ROOM);
	stop_fighting(victim, TRUE);
	victim->position = POS_STUNNED;
	break;
    case 6:
	act("You slam your fist into $N's stomach, who doubles over in agony.",ch,NULL,victim,TO_CHAR);
	act("$n slams $s fist into your stomach, and you double over in agony.",ch,NULL,victim,TO_VICT);
	act("$n slams $s fist into $N's stomach, who doubles over in agony.",ch,NULL,victim,TO_NOTVICT);
	act("You grab $N by the head and slam $S face into your knee.",ch,NULL,victim,TO_CHAR);
	act("$n grabs you by the head and slams your face into $s knee.",ch,NULL,victim,TO_VICT);
	act("$n grabs $N by the head and slams $S face into $s knee.",ch,NULL,victim,TO_NOTVICT);
	damage(ch,victim,dam,gsn_knee);
	if (victim == NULL || victim->position == POS_DEAD) return;
	if (number_percent() <= 25 && !IS_HEAD(victim,BROKEN_NOSE) && !IS_HEAD(victim,LOST_NOSE))
	{act("Your nose shatters under the impact of the blow!",victim,NULL,NULL,TO_CHAR);
    	act("$n's nose shatters under the impact of the blow!",victim,NULL,NULL,TO_ROOM);
	SET_BIT(victim->loc_hp[LOC_HEAD],BROKEN_NOSE);}
	else if (number_percent() <= 25 && !IS_HEAD(victim,BROKEN_JAW))
	{act("Your jaw shatters under the impact of the blow!",victim,NULL,NULL,TO_CHAR);
    	act("$n's jaw shatters under the impact of the blow!",victim,NULL,NULL,TO_ROOM);
	SET_BIT(victim->loc_hp[LOC_HEAD],BROKEN_JAW);}
	else if (number_percent() <= 25 && !IS_BODY(victim,BROKEN_NECK))
	{act("Your neck shatters under the impact of the blow!",victim,NULL,NULL,TO_CHAR);
    	act("$n's neck shatters under the impact of the blow!",victim,NULL,NULL,TO_ROOM);
	SET_BIT(victim->loc_hp[LOC_BODY],BROKEN_NECK);}
	act("You roll onto your back and smash your feet into $N's chest.",ch,NULL,victim,TO_CHAR);
	act("$n rolls onto $s back and smashes $s feet into your chest.",ch,NULL,victim,TO_VICT);
	act("$n rolls onto $s back and smashes $s feet into $N's chest.",ch,NULL,victim,TO_NOTVICT);
	damage(ch,victim,dam,gsn_kick);
	if (victim == NULL || victim->position == POS_DEAD) return;
	act("You crash to the ground, stunned.",victim,NULL,NULL,TO_CHAR);
	act("$n crashes to the ground, stunned.",victim,NULL,NULL,TO_ROOM);
	act("You flip back up to your feet.",ch,NULL,NULL,TO_CHAR);
	act("$n flips back up to $s feet.",ch,NULL,NULL,TO_ROOM);
	stop_fighting(victim, TRUE);
	victim->position = POS_STUNNED;
	break;
    case 7:
	act("You duck under $N's attack and pound your fist into $S stomach.",ch,NULL,victim,TO_CHAR);
	act("$n ducks under your attack and pounds $s fist into your stomach.",ch,NULL,victim,TO_VICT);
	act("$n ducks under $N's attack and pounds $s fist into $N's stomach.",ch,NULL,victim,TO_NOTVICT);
	damage(ch,victim,dam,gsn_punch);
	if (victim == NULL || victim->position == POS_DEAD) return;
	act("You double over in agony.",victim,NULL,NULL,TO_CHAR);
	act("$n doubles over in agony.",victim,NULL,NULL,TO_ROOM);

	act("You grab $M by the head and smash your knee into $S face.",ch,NULL,victim,TO_CHAR);
	act("$n grabs you by the head and smashes $s knee into your face.",ch,NULL,victim,TO_VICT);
	act("$n grabs $M by the head and smashes $s knee into $N's face.",ch,NULL,victim,TO_NOTVICT);
	damage(ch,victim,dam,gsn_knee);
	if (victim == NULL || victim->position == POS_DEAD) return;
	if (number_percent() <= 25 && !IS_HEAD(victim,BROKEN_NOSE) && !IS_HEAD(victim,LOST_NOSE))
	{act("Your nose shatters under the impact of the blow!",victim,NULL,NULL,TO_CHAR);
    	act("$n's nose shatters under the impact of the blow!",victim,NULL,NULL,TO_ROOM);
	SET_BIT(victim->loc_hp[LOC_HEAD],BROKEN_NOSE);}
	else if (number_percent() <= 25 && !IS_HEAD(victim,BROKEN_JAW))
	{act("Your jaw shatters under the impact of the blow!",victim,NULL,NULL,TO_CHAR);
    	act("$n's jaw shatters under the impact of the blow!",victim,NULL,NULL,TO_ROOM);
	SET_BIT(victim->loc_hp[LOC_HEAD],BROKEN_JAW);}
	else if (number_percent() <= 25 && !IS_BODY(victim,BROKEN_NECK))
	{act("Your neck shatters under the impact of the blow!",victim,NULL,NULL,TO_CHAR);
    	act("$n's neck shatters under the impact of the blow!",victim,NULL,NULL,TO_ROOM);
	SET_BIT(victim->loc_hp[LOC_BODY],BROKEN_NECK);}

	act("You stamp on the back of $N's leg, forcing $M to drop to one knee.",ch,NULL,victim,TO_CHAR);
	act("$n stamps on the back of your leg, forcing you to drop to one knee.",ch,NULL,victim,TO_VICT);
	act("$n stamps on the back of $N's leg, forcing $M to drop to one knee.",ch,NULL,victim,TO_NOTVICT);

	act("You grab $N by the hair and yank $S head back.",ch,NULL,victim,TO_CHAR);
	act("$n grabs you by the hair and yank your head back.",ch,NULL,victim,TO_VICT);
	act("$n grabs $N by the hair and yank $S head back.",ch,NULL,victim,TO_NOTVICT);

	act("You hammer your elbow down into $N's face.",ch,NULL,victim,TO_CHAR);
	act("$n hammers $s elbow down into your face.",ch,NULL,victim,TO_VICT);
	act("$n hammers $s elbow down into $N's face.",ch,NULL,victim,TO_NOTVICT);
	damage(ch,victim,dam,gsn_elbow);
	if (victim == NULL || victim->position == POS_DEAD) return;
	if (number_percent() <= 25 && !IS_HEAD(victim,BROKEN_NOSE) && !IS_HEAD(victim,LOST_NOSE))
	{act("Your nose shatters under the impact of the blow!",victim,NULL,NULL,TO_CHAR);
    	act("$n's nose shatters under the impact of the blow!",victim,NULL,NULL,TO_ROOM);
	SET_BIT(victim->loc_hp[LOC_HEAD],BROKEN_NOSE);}
	else if (number_percent() <= 25 && !IS_HEAD(victim,BROKEN_JAW))
	{act("Your jaw shatters under the impact of the blow!",victim,NULL,NULL,TO_CHAR);
    	act("$n's jaw shatters under the impact of the blow!",victim,NULL,NULL,TO_ROOM);
	SET_BIT(victim->loc_hp[LOC_HEAD],BROKEN_JAW);}
	else if (number_percent() <= 25 && !IS_BODY(victim,BROKEN_NECK))
	{act("Your neck shatters under the impact of the blow!",victim,NULL,NULL,TO_CHAR);
    	act("$n's neck shatters under the impact of the blow!",victim,NULL,NULL,TO_ROOM);
	SET_BIT(victim->loc_hp[LOC_BODY],BROKEN_NECK);}
	act("You crash to the ground, stunned.",victim,NULL,NULL,TO_CHAR);
	act("$n crashes to the ground, stunned.",victim,NULL,NULL,TO_ROOM);
	stop_fighting(victim, TRUE);
	victim->position = POS_STUNNED;
	break;
    }
    return;
}

void special_hurl( CHAR_DATA *ch, CHAR_DATA *victim )
{
    ROOM_INDEX_DATA *to_room;
    EXIT_DATA       *pexit;
    EXIT_DATA       *pexit_rev;
    char            buf       [MAX_INPUT_LENGTH];
    char            direction [MAX_INPUT_LENGTH];
    int             door;
    int             rev_dir;
    int             dam;

    rev_dir = 0;

    door = number_range(0,3);

    if (door == 0) {sprintf(direction,"north");rev_dir = 2;}
    if (door == 1) {sprintf(direction,"east");rev_dir = 3;}
    if (door == 2) {sprintf(direction,"south");rev_dir = 0;}
    if (door == 3) {sprintf(direction,"west");rev_dir = 1;}

    if (( pexit = ch->in_room->exit[door]) == NULL || (to_room = pexit->to_room) == NULL)
    {
	sprintf(buf,"$n hurls $N into the %s wall.", direction);
	act(buf,ch,NULL,victim,TO_NOTVICT);
	sprintf(buf,"You hurl $N into the %s wall.", direction);
	act(buf,ch,NULL,victim,TO_CHAR);
	sprintf(buf,"$n hurls you into the %s wall.", direction);
	act(buf,ch,NULL,victim,TO_VICT);
	dam = number_range(ch->level, (ch->level * 4));
	victim->hit = victim->hit - dam;
	update_pos(victim);
    	if (IS_NPC(victim) && !IS_NPC(ch)) ch->mkill = ch->mkill + 1;
    	if (!IS_NPC(victim) && IS_NPC(ch)) victim->mdeath = victim->mdeath + 1;
	if (victim->position == POS_DEAD) {raw_kill(victim);return;}
	return;
    }

    pexit = victim->in_room->exit[door];
    if (IS_SET(pexit->exit_info, EX_CLOSED) && 
	!IS_AFFECTED(victim,AFF_PASS_DOOR ) &&
	!IS_AFFECTED(victim,AFF_ETHEREAL  ) )
    {
	if (IS_SET(pexit->exit_info, EX_LOCKED))
	    REMOVE_BIT(pexit->exit_info, EX_LOCKED);
	if (IS_SET(pexit->exit_info, EX_CLOSED))
	    REMOVE_BIT(pexit->exit_info, EX_CLOSED);
	sprintf(buf,"$n hurls $N %s.", direction);
	act(buf,ch,NULL,victim,TO_NOTVICT);
	sprintf(buf,"You hurl $N %s.", direction);
	act(buf,ch,NULL,victim,TO_CHAR);
	sprintf(buf,"$n hurls you %s, smashing you through the %s.", direction,pexit->keyword);
	act(buf,ch,NULL,victim,TO_VICT);
	sprintf(buf,"There is a loud crash as $n smashes through the $d.");
	act(buf,victim,NULL,pexit->keyword,TO_ROOM);

	if ( ( to_room   = pexit->to_room               ) != NULL
	&&   ( pexit_rev = to_room->exit[rev_dir] ) != NULL
	&&   pexit_rev->to_room == ch->in_room
	&&   pexit_rev->keyword != NULL )
	{
	    if (IS_SET(pexit_rev->exit_info, EX_LOCKED))
		REMOVE_BIT( pexit_rev->exit_info, EX_LOCKED );
	    if (IS_SET(pexit_rev->exit_info, EX_CLOSED))
		REMOVE_BIT( pexit_rev->exit_info, EX_CLOSED );
	    if (door == 0) sprintf(direction,"south");
	    if (door == 1) sprintf(direction,"west");
	    if (door == 2) sprintf(direction,"north");
	    if (door == 3) sprintf(direction,"east");
	    char_from_room(victim);
	    char_to_room(victim,to_room);
	    sprintf(buf,"$n comes smashing in through the %s $d.", direction);
	    act(buf,victim,NULL,pexit->keyword,TO_ROOM);
	    dam = number_range(ch->level, (ch->level * 6));
	    victim->hit = victim->hit - dam;
	    update_pos(victim);
    	    if (IS_NPC(victim) && !IS_NPC(ch)) ch->mkill = ch->mkill + 1;
    	    if (!IS_NPC(victim) && IS_NPC(ch)) victim->mdeath = victim->mdeath + 1;
	    if (victim->position == POS_DEAD) {raw_kill(victim);return;}
	}
    }
    else
    {
	sprintf(buf,"$n hurls $N %s.", direction);
	act(buf,ch,NULL,victim,TO_NOTVICT);
	sprintf(buf,"You hurl $N %s.", direction);
	act(buf,ch,NULL,victim,TO_CHAR);
	sprintf(buf,"$n hurls you %s.", direction);
	act(buf,ch,NULL,victim,TO_VICT);
	if (door == 0) sprintf(direction,"south");
	if (door == 1) sprintf(direction,"west");
	if (door == 2) sprintf(direction,"north");
	if (door == 3) sprintf(direction,"east");
	char_from_room(victim);
	char_to_room(victim,to_room);
	sprintf(buf,"$n comes flying in from the %s.", direction);
	act(buf,victim,NULL,NULL,TO_ROOM);
	dam = number_range(ch->level, (ch->level * 2));
	victim->hit = victim->hit - dam;
	update_pos(victim);
    	if (IS_NPC(victim) && !IS_NPC(ch)) ch->mkill = ch->mkill + 1;
    	if (!IS_NPC(victim) && IS_NPC(ch)) victim->mdeath = victim->mdeath + 1;
	if (victim->position == POS_DEAD) {raw_kill(victim);return;}
    }
    return;
}




******


 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *


 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *


 *                                                                         *


 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *


 *  Chastain, Michael Quan, and Mitchell Tse.                              *


 *                                                                         *


 *  In order to use any part of this Merc Diku Mud, you must comply with   *


 *  both the original Diku license in 'license.doc' as well the Merc       *


 *  license in 'license.txt'.  In particular, you may not remove either of *


 *  these copyright notices.                                               *


 *                                                                         *


 *  Much time and thought has gone into this software and you are          *


 *  benefitting.  We hope that you share your changes too.  What goes      *


 *  around, comes around.                                                  *


 ***************************************************************************/





#if defined(macintosh)


#include <types.h>


#else


#include <sys/types.h>


#endif


#include <stdio.h>


#include <stdlib.h>


#include <string.h>


#include <time.h>


#include "merc.h"








void do_immune( CHAR_DATA *ch, char *argument )


{


    char      arg [MAX_INPUT_LENGTH];


    argument = one_argument( argument, arg );





    if (IS_NPC(ch)) return;





    send_to_char("----------------------------------------------------------------------------\n\r",ch);


    send_to_char("                                -= Immunities =-\n\r",ch);


    send_to_char("----------------------------------------------------------------------------\n\r",ch);


    /* Display weapon resistances */


    send_to_char("Weapons:",ch);


    if (!(!IS_IMMUNE(ch,IMM_SLASH) && !IS_IMMUNE(ch,IMM_STAB) && 


	  !IS_IMMUNE(ch,IMM_SMASH) && !IS_IMMUNE(ch,IMM_ANIMAL) &&


	  !IS_IMMUNE(ch,IMM_MISC )) )


    {


    	if (IS_IMMUNE(ch,IMM_SLASH )) send_to_char(" Slash Slice",ch);


    	if (IS_IMMUNE(ch,IMM_STAB  )) send_to_char(" Stab Pierce",ch);


    	if (IS_IMMUNE(ch,IMM_SMASH )) send_to_char(" Blast Crush Pound",ch);


    	if (IS_IMMUNE(ch,IMM_ANIMAL)) send_to_char(" Claw Bite",ch);


    	if (IS_IMMUNE(ch,IMM_MISC  )) send_to_char(" Grep Whip Suck",ch);


    }


    else


	send_to_char(" None",ch);


    send_to_char(".\n\r",ch);





    /* Display spell immunities */


    send_to_char("Spells :",ch);


    if (!(!IS_IMMUNE(ch,IMM_CHARM)  && !IS_IMMUNE(ch,IMM_HEAT)      && 


	  !IS_IMMUNE(ch,IMM_COLD)   && !IS_IMMUNE(ch,IMM_LIGHTNING) &&


	  !IS_IMMUNE(ch,IMM_ACID)   && !IS_IMMUNE(ch,IMM_SUMMON)    &&


	  !IS_IMMUNE(ch,IMM_VOODOO) && !IS_IMMUNE(ch,IMM_SLEEP)    &&


	  !IS_IMMUNE(ch,IMM_DRAIN)))


    {


    	if (IS_IMMUNE(ch,IMM_CHARM     )) send_to_char(" Charm",ch);


    	if (IS_IMMUNE(ch,IMM_HEAT      )) send_to_char(" Heat",ch);


    	if (IS_IMMUNE(ch,IMM_COLD      )) send_to_char(" Cold",ch);


    	if (IS_IMMUNE(ch,IMM_LIGHTNING )) send_to_char(" Lightning",ch);


    	if (IS_IMMUNE(ch,IMM_ACID      )) send_to_char(" Acid",ch);


    	if (!IS_IMMUNE(ch,IMM_SUMMON   )) send_to_char(" Summon",ch);


    	if (IS_IMMUNE(ch,IMM_VOODOO    )) send_to_char(" Voodoo",ch);


    	if (IS_IMMUNE(ch,IMM_SLEEP     )) send_to_char(" Sleep",ch);


    	if (IS_IMMUNE(ch,IMM_DRAIN     )) send_to_char(" Drain",ch);


    	if (IS_IMMUNE(ch,IMM_TRANSPORT )) send_to_char(" Transport",ch);


    }


    else


	send_to_char(" None",ch);


    send_to_char(".\n\r",ch);





    /* Display skill immunities */


    send_to_char("Skills :",ch);


    if (!(!IS_IMMUNE(ch,IMM_HURL) && !IS_IMMUNE(ch,IMM_BACKSTAB) && 


	  !IS_IMMUNE(ch,IMM_KICK) && !IS_IMMUNE(ch,IMM_DISARM)   &&


	  !IS_IMMUNE(ch,IMM_STEAL)))


    {


    	if (IS_IMMUNE(ch,IMM_HURL      )) send_to_char(" Hurl",ch);


    	if (IS_IMMUNE(ch,IMM_BACKSTAB  )) send_to_char(" Backstab",ch);


    	if (IS_IMMUNE(ch,IMM_KICK      )) send_to_char(" Kick",ch);


    	if (IS_IMMUNE(ch,IMM_DISARM    )) send_to_char(" Disarm",ch);


    	if (IS_IMMUNE(ch,IMM_STEAL     )) send_to_char(" Steal",ch);


    }


    else


	send_to_char(" None",ch);


    send_to_char(".\n\r",ch);





    /* Display vampire immunities */


    send_to_char("Vampire:",ch);


    if (!( IS_IMMUNE(ch,IMM_VAMPIRE) && !IS_IMMUNE(ch,IMM_STAKE) && 


	  !IS_IMMUNE(ch,IMM_SUNLIGHT)))


    {


    	if (!IS_IMMUNE(ch,IMM_VAMPIRE  )) send_to_char(" Bite",ch);


    	if  (IS_IMMUNE(ch,IMM_STAKE    )) send_to_char(" Stake",ch);


    	if  (IS_IMMUNE(ch,IMM_SUNLIGHT )) send_to_char(" Sunlight",ch);


    }


    else


	send_to_char(" None",ch);


    send_to_char(".\n\r",ch);


    send_to_char("----------------------------------------------------------------------------\n\r",ch);


    return;


}








void skillstance( CHAR_DATA *ch, CHAR_DATA *victim )


{


    char buf        [MAX_INPUT_LENGTH];


    char bufskill   [25];


    char stancename [10];


    int stance;





    if (IS_NPC(victim)) return;





    stance = victim->stance[0];


    if (stance < 1 || stance > 11) return;


         if (victim->stance[stance] <= 0  ) sprintf(bufskill,"completely unskilled in");


    else if (victim->stance[stance] <= 25 ) sprintf(bufskill,"an apprentice of");


    else if (victim->stance[stance] <= 50 ) sprintf(bufskill,"a trainee of");


    else if (victim->stance[stance] <= 75 ) sprintf(bufskill,"a student of");


    else if (victim->stance[stance] <= 100) sprintf(bufskill,"fairly experienced in");


    else if (victim->stance[stance] <= 125) sprintf(bufskill,"well trained in");


    else if (victim->stance[stance] <= 150) sprintf(bufskill,"highly skilled in");


    else if (victim->stance[stance] <= 175) sprintf(bufskill,"an expert of");


    else if (victim->stance[stance] <= 199) sprintf(bufskill,"a master of");


    else if (victim->stance[stance] >= 200) sprintf(bufskill,"a grand master of");


    else return;


         if (stance == STANCE_VIPER   ) sprintf(stancename,"viper"   );


    else if (stance == STANCE_CRANE   ) sprintf(stancename,"crane"   );


    else if (stance == STANCE_CRAB    ) sprintf(stancename,"crab"    );


    else if (stance == STANCE_MONGOOSE) sprintf(stancename,"mongoose");


    else if (stance == STANCE_BULL    ) sprintf(stancename,"bull"    );


    else if (stance == STANCE_MANTIS  ) sprintf(stancename,"mantis"  );


    else if (stance == STANCE_DRAGON  ) sprintf(stancename,"dragon"  );


    else if (stance == STANCE_TIGER   ) sprintf(stancename,"tiger"   );


    else if (stance == STANCE_MONKEY  ) sprintf(stancename,"monkey"  );


    else if (stance == STANCE_SWALLOW ) sprintf(stancename,"swallow" );


    else if (stance == STANCE_WOLF) sprintf(stancename,"WereWolf" );


    else return;


    if (ch == victim)


    	sprintf(buf,"You are %s the %s stance.",bufskill,stancename);


    else


    	sprintf(buf,"$N is %s the %s stance.",bufskill,stancename);


    act(buf,ch,NULL,victim,TO_CHAR);


    return;


}





void do_spell( CHAR_DATA *ch, char *argument )


{


    char arg[MAX_INPUT_LENGTH];





    one_argument( argument, arg );





    if ( arg[0] == '\0' )


    {


	show_spell(ch,0);


	show_spell(ch,1);


	show_spell(ch,2);


	show_spell(ch,3);


	show_spell(ch,4);


    }


    else if (!str_cmp(arg,"purple")) show_spell(ch,0);


    else if (!str_cmp(arg,"red"))    show_spell(ch,1);


    else if (!str_cmp(arg,"blue"))   show_spell(ch,2);


    else if (!str_cmp(arg,"green"))  show_spell(ch,3);


    else if (!str_cmp(arg,"yellow")) show_spell(ch,4);


    else send_to_char("You know of no such magic.\n\r",ch);


    return;


}





void show_spell( CHAR_DATA *ch, int dtype )


{


    char buf[MAX_INPUT_LENGTH];


    char bufskill[MAX_INPUT_LENGTH];





    if (IS_NPC(ch)) return;





    if      (ch->spl[dtype] == 00 ) sprintf(bufskill,"untrained at");


    else if (ch->spl[dtype] <= 25 ) sprintf(bufskill,"an apprentice at");


    else if (ch->spl[dtype] <= 50 ) sprintf(bufskill,"a student at");


    else if (ch->spl[dtype] <= 75 ) sprintf(bufskill,"a scholar at");


    else if (ch->spl[dtype] <= 100) sprintf(bufskill,"a magus at");


    else if (ch->spl[dtype] <= 125) sprintf(bufskill,"an adept at");


    else if (ch->spl[dtype] <= 150) sprintf(bufskill,"a mage at");


    else if (ch->spl[dtype] <= 175) sprintf(bufskill,"a warlock at");


    else if (ch->spl[dtype] <= 199) sprintf(bufskill,"a master wizard at");


    else if (ch->spl[dtype] >= 240) sprintf(bufskill,"the complete master of");


    else if (ch->spl[dtype] >= 200) sprintf(bufskill,"a grand sorcerer at");


    else return;


    if      (dtype == 0)


	sprintf(buf,"You are %s purple magic.\n\r",bufskill);


    else if (dtype == 1)


	sprintf(buf,"You are %s red magic.\n\r",bufskill);


    else if (dtype == 2)


	sprintf(buf,"You are %s blue magic.\n\r",bufskill);


    else if (dtype == 3)


	sprintf(buf,"You are %s green magic.\n\r",bufskill);


    else if (dtype == 4)


	sprintf(buf,"You are %s yellow magic.\n\r",bufskill);


    else return;


    send_to_char(buf,ch);


    return;


}





void do_scan( CHAR_DATA *ch, char *argument )


{


    ROOM_INDEX_DATA *location;





    location = ch->in_room;





    send_to_char("[North]\n\r",ch);


    do_spydirection(ch,"n");


    char_from_room(ch);


    char_to_room(ch,location);





    send_to_char("[East]\n\r",ch);


    do_spydirection(ch,"e");


    char_from_room(ch);


    char_to_room(ch,location);





    send_to_char("[South]\n\r",ch);


    do_spydirection(ch,"s");


    char_from_room(ch);


    char_to_room(ch,location);





    send_to_char("[West]\n\r",ch);


    do_spydirection(ch,"w");


    char_from_room(ch);


    char_to_room(ch,location);





    send_to_char("[Up]\n\r",ch);


    do_spydirection(ch,"u");


    char_from_room(ch);


    char_to_room(ch,location);





    send_to_char("[Down]\n\r",ch);


    do_spydirection(ch,"d");


    char_from_room(ch);


    char_to_room(ch,location);


    return;


}





void do_spy( CHAR_DATA *ch, char *argument )


{


    ROOM_INDEX_DATA *location;


    char            arg1      [MAX_INPUT_LENGTH];


    int             door;





    argument = one_argument( argument, arg1 );





    if ( arg1[0] == '\0' )


    {


	send_to_char("Which direction do you wish to spy?\n\r", ch);


	return;


    }





    if      ( !str_cmp( arg1, "n" ) || !str_cmp( arg1, "north" ) )


	door = 0;


    else if ( !str_cmp( arg1, "e" ) || !str_cmp( arg1, "east" ) )


	door = 1;


    else if ( !str_cmp( arg1, "s" ) || !str_cmp( arg1, "south" ) )


	door = 2;


    else if ( !str_cmp( arg1, "w" ) || !str_cmp( arg1, "west" ) )


	door = 3;


    else if ( !str_cmp( arg1, "u" ) || !str_cmp( arg1, "up" ) )


	door = 4;


    else if ( !str_cmp( arg1, "d" ) || !str_cmp( arg1, "down" ) )


	door = 5;


    else


    {


	send_to_char("You can only spy people north, south, east, west, up or down.\n\r", ch);


	return;


    }





    location = ch->in_room;





    send_to_char("[Short Range]\n\r",ch);


    do_spydirection(ch,arg1);


    send_to_char("\n\r",ch);


    send_to_char("[Medium Range]\n\r",ch);


    do_spydirection(ch,arg1);


    send_to_char("\n\r",ch);


    send_to_char("[Long Range]\n\r",ch);


    do_spydirection(ch,arg1);


    send_to_char("\n\r",ch);





    /* Move them back */


    char_from_room(ch);


    char_to_room(ch,location);


    return;


}





void do_spydirection( CHAR_DATA *ch, char *argument )


{


    ROOM_INDEX_DATA *to_room;


    EXIT_DATA       *pexit;


    CHAR_DATA       *vch;


    CHAR_DATA       *vch_next;


    char            arg      [MAX_INPUT_LENGTH];


    char            buf      [MAX_INPUT_LENGTH];


    int             door;


    bool            is_empty;





    argument = one_argument( argument, arg );





    is_empty = TRUE;





    if ( arg[0] == '\0' )


	return;





    if      ( !str_cmp( arg, "n" ) || !str_cmp( arg, "north" ) ) door = 0;


    else if ( !str_cmp( arg, "e" ) || !str_cmp( arg, "east"  ) ) door = 1;


    else if ( !str_cmp( arg, "s" ) || !str_cmp( arg, "south" ) ) door = 2;


    else if ( !str_cmp( arg, "w" ) || !str_cmp( arg, "west"  ) ) door = 3;


    else if ( !str_cmp( arg, "u" ) || !str_cmp( arg, "up"    ) ) door = 4;


    else if ( !str_cmp( arg, "d" ) || !str_cmp( arg, "down"  ) ) door = 5;


    else return;





    if (( pexit = ch->in_room->exit[door]) == NULL || (to_room = pexit->to_room) == NULL)


    {


	send_to_char("   No exit.\n\r",ch);


	return;


    }


    pexit = ch->in_room->exit[door];


    if (IS_SET(pexit->exit_info, EX_CLOSED) )


    {


	send_to_char("   Closed door.\n\r",ch);


	return;


    }


    char_from_room(ch);


    char_to_room(ch,to_room);


    for ( vch = char_list; vch != NULL; vch = vch_next )


    {


	vch_next	= vch->next;


	if ( vch->in_room == NULL )


	    continue;


	if ( vch == ch )


	    continue;


	if ( !can_see(ch,vch) )


	    continue;


	if ( vch->in_room == ch->in_room )


	{


	    if (!IS_NPC(vch) && !IS_AFFECTED(vch,AFF_POLYMORPH))


		sprintf(buf,"   %s (Player)\n\r",vch->name);


	    else if (!IS_NPC(vch) && IS_AFFECTED(vch,AFF_POLYMORPH))


		sprintf(buf,"   %s (Player)\n\r",vch->morph);


            else if (!IS_NPC(vch) && IS_AFFECTED(vch,AFF_SHIFT))


		sprintf(buf,"   %s (Player)\n\r",vch->morph);





            else if (IS_NPC(vch))


		sprintf(buf,"   %s\n\r",capitalize(vch->short_descr));


	    send_to_char(buf,ch);


	    is_empty = FALSE;


	    continue;


	}


    }


    if (is_empty)


    {


	send_to_char("   Nobody here.\n\r",ch);


	return;


    }


    return;


}








void take_item( CHAR_DATA *ch, OBJ_DATA *obj )


{


    if (obj == NULL) return;


    obj_from_char(obj);


    obj_to_room(obj,ch->in_room);


    act("You wince in pain and $p falls to the ground.",ch,obj,NULL,TO_CHAR);


    act("$n winces in pain and $p falls to the ground.",ch,obj,NULL,TO_ROOM);


    return;


}





void birth_date( CHAR_DATA *ch, bool is_self )


{


    char buf[MAX_STRING_LENGTH];


    char buf2[MAX_STRING_LENGTH];


    char mstatus[20];


    char dstatus[20];


    char omin[3];


    char cmin[3];


    char ohour[3];


    char chour[3];


    char oday0[2];


    char cday0[2];


    char oday1[2];


    char cday1[2];


    char omonth[4];


    char cmonth[4];


    char oyear[5];


    char cyear[5];


    char *strtime;


    int oyear2 = 0;


    int cyear2 = 0;


    int omonth2 = 0;


    int cmonth2 = 0;


    int oday2 = 0;


    int cday2 = 0;


    int total = 0;


    int dd = 0;


    int mm = 0;


    int yy = 0;


    bool o_month = FALSE;


    bool c_month = FALSE;





    if (IS_NPC(ch)) return;





    if (is_self)


	strcpy(buf,ch->createtime);


    else


	strcpy(buf,ch->pcdata->conception);


    if (strlen(buf) < 24) return;


    strtime = ctime( &current_time );


    strtime[strlen(strtime)-1] = '\0';


    strcpy(buf2,strtime);


    oyear[0] = buf[20];


    oyear[1] = buf[21];


    oyear[2] = buf[22];


    oyear[3] = buf[23];


    oyear[4] = '\0';


    omonth[0] = buf[4];


    omonth[1] = buf[5];


    omonth[2] = buf[6];


    omonth[3] = '\0';


    oday0[0] = buf[8];


    oday0[1] = '\0';


    oday1[0] = buf[9];


    oday1[1] = '\0';


    ohour[0] = buf[11];


    ohour[1] = buf[12];


    ohour[2] = '\0';


    omin[0] = buf[14];


    omin[1] = buf[15];


    omin[2] = '\0';





    cyear[0] = buf2[20];


    cyear[1] = buf2[21];


    cyear[2] = buf2[22];


    cyear[3] = buf2[23];


    cyear[4] = '\0';


    cmonth[0] = buf2[4];


    cmonth[1] = buf2[5];


    cmonth[2] = buf2[6];


    cmonth[3] = '\0';


    cday0[0] = buf2[8];


    cday0[1] = '\0';


    cday1[0] = buf2[9];


    cday1[1] = '\0';


    chour[0] = buf2[11];


    chour[1] = buf2[12];


    chour[2] = '\0';


    cmin[0] = buf2[14];


    cmin[1] = buf2[15];


    cmin[2] = '\0';





    if (!str_cmp(omonth,"Dec")) {omonth2 += 31;o_month = TRUE;}


    if (!str_cmp(omonth,"Nov") || o_month) {omonth2 += 30;o_month = TRUE;}


    if (!str_cmp(omonth,"Oct") || o_month) {omonth2 += 31;o_month = TRUE;}


    if (!str_cmp(omonth,"Sep") || o_month) {omonth2 += 30;o_month = TRUE;}


    if (!str_cmp(omonth,"Aug") || o_month) {omonth2 += 31;o_month = TRUE;}


    if (!str_cmp(omonth,"Jul") || o_month) {omonth2 += 31;o_month = TRUE;}


    if (!str_cmp(omonth,"Jun") || o_month) {omonth2 += 30;o_month = TRUE;}


    if (!str_cmp(omonth,"May") || o_month) {omonth2 += 31;o_month = TRUE;}


    if (!str_cmp(omonth,"Apr") || o_month) {omonth2 += 30;o_month = TRUE;}


    if (!str_cmp(omonth,"Mar") || o_month) {omonth2 += 31;o_month = TRUE;}


    if (!str_cmp(omonth,"Feb") || o_month) {omonth2 += 28;o_month = TRUE;}


    if (!str_cmp(omonth,"Jan") || o_month) {omonth2 += 31;o_month = TRUE;}


    if (!o_month) {send_to_char("Error! Please inform KaVir.\n\r",ch);return;}


    if (!str_cmp(cmonth,"Dec")) {cmonth2 += 31;c_month = TRUE;}


    if (!str_cmp(cmonth,"Nov") || c_month) {cmonth2 += 30;c_month = TRUE;}


    if (!str_cmp(cmonth,"Oct") || c_month) {cmonth2 += 31;c_month = TRUE;}


    if (!str_cmp(cmonth,"Sep") || c_month) {cmonth2 += 30;c_month = TRUE;}


    if (!str_cmp(cmonth,"Aug") || c_month) {cmonth2 += 31;c_month = TRUE;}


    if (!str_cmp(cmonth,"Jul") || c_month) {cmonth2 += 31;c_month = TRUE;}


    if (!str_cmp(cmonth,"Jun") || c_month) {cmonth2 += 30;c_month = TRUE;}


    if (!str_cmp(cmonth,"May") || c_month) {cmonth2 += 31;c_month = TRUE;}


    if (!str_cmp(cmonth,"Apr") || c_month) {cmonth2 += 30;c_month = TRUE;}


    if (!str_cmp(cmonth,"Mar") || c_month) {cmonth2 += 31;c_month = TRUE;}


    if (!str_cmp(cmonth,"Feb") || c_month) {cmonth2 += 28;c_month = TRUE;}


    if (!str_cmp(cmonth,"Jan") || c_month) {cmonth2 += 31;c_month = TRUE;}


    if (!c_month) {send_to_char("Error! Please inform KaVir.\n\r",ch);return;}


    if (is_number(oyear)) oyear2 += atoi(oyear);


    if (is_number(cyear)) cyear2 += atoi(cyear);


    if (is_number(oday0)) oday2 += (atoi(oday0) * 10);


    if (is_number(oday1)) oday2 += atoi(oday1);


    if (is_number(cday0)) cday2 += (atoi(cday0) * 10);


    if (is_number(cday1)) cday2 += atoi(cday1);


    total += ((cyear2 - oyear2) * 365);


    total += (cmonth2 - omonth2);


    total += (cday2 - oday2);


    total *= 24; /* Total playing time is now in hours */


    if (is_number(chour) && is_number(ohour))


	total += (atoi(chour) - atoi(ohour));


    total *= 60; /* Total now in minutes */


    if (is_number(cmin) && is_number(omin))


	total += (atoi(cmin) - atoi(omin));


    if (total < 1) total = 0;


	else total /= 12; /* Time now in game days */


    for ( ;; )


    {


	if (total >= 365)


	{


	    total -= 365;


	    yy += 1;


	}


	else if (total >= 30)


	{


	    total -= 30;


	    mm += 1;


	}


	else


	{


	    dd += total;


	    break;


	}


    }


    if (mm == 1) strcpy(mstatus,"month");


	else strcpy(mstatus,"months");


    if (dd == 1) strcpy(dstatus,"day");


	else strcpy(dstatus,"days");


    if (is_self)


    {


	if (!IS_EXTRA(ch, EXTRA_BORN)) yy += 17;


	sprintf(buf,"You are %d years, %d %s and %d %s old.\n\r",


	    yy,mm,mstatus,dd,dstatus);


	send_to_char(buf,ch);


    }


    else


    {


	if (yy > 0 || (dd > 0 && mm >= 9) || IS_EXTRA(ch, EXTRA_LABOUR))


	{


	    if (!IS_EXTRA(ch, EXTRA_LABOUR)) SET_BIT(ch->extra, EXTRA_LABOUR);


	    sprintf(buf,"You are ready to give birth.\n\r");


	    send_to_char(buf,ch);


	}


	else if (yy > 0 || mm > 0)


	{


	    sprintf(buf,"You are %d %s and %d %s pregnant.\n\r",


	    mm,mstatus,dd,dstatus);


	    send_to_char(buf,ch);


	}


    }


    return;


}





void other_age( CHAR_DATA *ch, int extra, bool is_preg, char *argument )


{


    char buf[MAX_STRING_LENGTH];


    char buf2[MAX_STRING_LENGTH];


    char mstatus[20];


    char dstatus[20];


    char omin[3];


    char cmin[3];


    char ohour[3];


    char chour[3];


    char oday0[2];


    char cday0[2];


    char oday1[2];


    char cday1[2];


    char omonth[4];


    char cmonth[4];


    char oyear[5];


    char cyear[5];


    char *strtime;


    int oyear2 = 0;


    int cyear2 = 0;


    int omonth2 = 0;


    int cmonth2 = 0;


    int oday2 = 0;


    int cday2 = 0;


    int total = 0;


    int dd = 0;


    int mm = 0;


    int yy = 0;


    bool o_month = FALSE;


    bool c_month = FALSE;





    strcpy(buf,argument);


    if (strlen(buf) < 24) return;


    strtime = ctime( &current_time );


    strtime[strlen(strtime)-1] = '\0';


    strcpy(buf2,strtime);


    oyear[0] = buf[20];


    oyear[1] = buf[21];


    oyear[2] = buf[22];


    oyear[3] = buf[23];


    oyear[4] = '\0';


    omonth[0] = buf[4];


    omonth[1] = buf[5];


    omonth[2] = buf[6];


    omonth[3] = '\0';


    oday0[0] = buf[8];


    oday0[1] = '\0';


    oday1[0] = buf[9];


    oday1[1] = '\0';


    ohour[0] = buf[11];


    ohour[1] = buf[12];


    ohour[2] = '\0';


    omin[0] = buf[14];


    omin[1] = buf[15];


    omin[2] = '\0';





    cyear[0] = buf2[20];


    cyear[1] = buf2[21];


    cyear[2] = buf2[22];


    cyear[3] = buf2[23];


    cyear[4] = '\0';


    cmonth[0] = buf2[4];


    cmonth[1] = buf2[5];


    cmonth[2] = buf2[6];


    cmonth[3] = '\0';


    cday0[0] = buf2[8];


    cday0[1] = '\0';


    cday1[0] = buf2[9];


    cday1[1] = '\0';


    chour[0] = buf2[11];


    chour[1] = buf2[12];


    chour[2] = '\0';


    cmin[0] = buf2[14];


    cmin[1] = buf2[15];


    cmin[2] = '\0';





    if (!str_cmp(omonth,"Dec")) {omonth2 += 31;o_month = TRUE;}


    if (!str_cmp(omonth,"Nov") || o_month) {omonth2 += 30;o_month = TRUE;}


    if (!str_cmp(omonth,"Oct") || o_month) {omonth2 += 31;o_month = TRUE;}


    if (!str_cmp(omonth,"Sep") || o_month) {omonth2 += 30;o_month = TRUE;}


    if (!str_cmp(omonth,"Aug") || o_month) {omonth2 += 31;o_month = TRUE;}


    if (!str_cmp(omonth,"Jul") || o_month) {omonth2 += 31;o_month = TRUE;}


    if (!str_cmp(omonth,"Jun") || o_month) {omonth2 += 30;o_month = TRUE;}


    if (!str_cmp(omonth,"May") || o_month) {omonth2 += 31;o_month = TRUE;}


    if (!str_cmp(omonth,"Apr") || o_month) {omonth2 += 30;o_month = TRUE;}


    if (!str_cmp(omonth,"Mar") || o_month) {omonth2 += 31;o_month = TRUE;}


    if (!str_cmp(omonth,"Feb") || o_month) {omonth2 += 28;o_month = TRUE;}


    if (!str_cmp(omonth,"Jan") || o_month) {omonth2 += 31;o_month = TRUE;}


    if (!o_month) {send_to_char("Error! Please inform KaVir.\n\r",ch);return;}


    if (!str_cmp(cmonth,"Dec")) {cmonth2 += 31;c_month = TRUE;}


    if (!str_cmp(cmonth,"Nov") || c_month) {cmonth2 += 30;c_month = TRUE;}


    if (!str_cmp(cmonth,"Oct") || c_month) {cmonth2 += 31;c_month = TRUE;}


    if (!str_cmp(cmonth,"Sep") || c_month) {cmonth2 += 30;c_month = TRUE;}


    if (!str_cmp(cmonth,"Aug") || c_month) {cmonth2 += 31;c_month = TRUE;}


    if (!str_cmp(cmonth,"Jul") || c_month) {cmonth2 += 31;c_month = TRUE;}


    if (!str_cmp(cmonth,"Jun") || c_month) {cmonth2 += 30;c_month = TRUE;}


    if (!str_cmp(cmonth,"May") || c_month) {cmonth2 += 31;c_month = TRUE;}


    if (!str_cmp(cmonth,"Apr") || c_month) {cmonth2 += 30;c_month = TRUE;}


    if (!str_cmp(cmonth,"Mar") || c_month) {cmonth2 += 31;c_month = TRUE;}


    if (!str_cmp(cmonth,"Feb") || c_month) {cmonth2 += 28;c_month = TRUE;}


    if (!str_cmp(cmonth,"Jan") || c_month) {cmonth2 += 31;c_month = TRUE;}


    if (!c_month) {send_to_char("Error! Please inform KaVir.\n\r",ch);return;}


    if (is_number(oyear)) oyear2 += atoi(oyear);


    if (is_number(cyear)) cyear2 += atoi(cyear);


    if (is_number(oday0)) oday2 += (atoi(oday0) * 10);


    if (is_number(oday1)) oday2 += atoi(oday1);


    if (is_number(cday0)) cday2 += (atoi(cday0) * 10);


    if (is_number(cday1)) cday2 += atoi(cday1);


    total += ((cyear2 - oyear2) * 365);


    total += (cmonth2 - omonth2);


    total += (cday2 - oday2);


    total *= 24; /* Total playing time is now in hours */


    if (is_number(chour) && is_number(ohour))


	total += (atoi(chour) - atoi(ohour));


    total *= 60; /* Total now in minutes */


    if (is_number(cmin) && is_number(omin))


	total += (atoi(cmin) - atoi(omin));


    if (total < 1) total = 0;


	else total /= 12; /* Time now in game days */


    for ( ;; )


    {


	if (total >= 365)


	{


	    total -= 365;


	    yy += 1;


	}


	else if (total >= 30)


	{


	    total -= 30;


	    mm += 1;


	}


	else


	{


	    dd += total;


	    break;


	}


    }


    if (mm == 1) strcpy(mstatus,"month");


	else strcpy(mstatus,"months");


    if (dd == 1) strcpy(dstatus,"day");


	else strcpy(dstatus,"days");


    if (!is_preg)


    {


	if (!IS_EXTRA(ch, EXTRA_BORN)) yy += 17;


	sprintf(buf,"Age: %d years, %d %s and %d %s old.\n\r",


	    yy,mm,mstatus,dd,dstatus);


	send_to_char(buf,ch);


    }


    else


    {


	if (yy > 0 || (dd > 0 && mm >= 9) || IS_SET(extra, EXTRA_LABOUR))


	{


	    sprintf(buf,"She is ready to give birth.\n\r");


	    send_to_char(buf,ch);


	}


	else if (yy > 0 || mm > 0)


	{


	    sprintf(buf,"She is %d %s and %d %s pregnant.\n\r",


	    mm,mstatus,dd,dstatus);


	    send_to_char(buf,ch);


	}


    }


    return;


}





int years_old( CHAR_DATA *ch )


{


    char buf[MAX_STRING_LENGTH];


    char buf2[MAX_STRING_LENGTH];


    char omin[3];


    char cmin[3];


    char ohour[3];


    char chour[3];


    char oday0[2];


    char cday0[2];


    char oday1[2];


    char cday1[2];


    char omonth[4];


    char cmonth[4];


    char oyear[5];


    char cyear[5];


    char *strtime;


    int oyear2 = 0;


    int cyear2 = 0;


    int omonth2 = 0;


    int cmonth2 = 0;


    int oday2 = 0;


    int cday2 = 0;


    int total = 0;


    int yy = 0;


    bool o_month = FALSE;


    bool c_month = FALSE;





    if (IS_NPC(ch)) return 0;





    strcpy(buf,ch->createtime);


    if (strlen(buf) < 24) return 0;


    strtime = ctime( &current_time );


    strtime[strlen(strtime)-1] = '\0';


    strcpy(buf2,strtime);


    oyear[0] = buf[20];


    oyear[1] = buf[21];


    oyear[2] = buf[22];


    oyear[3] = buf[23];


    oyear[4] = '\0';


    omonth[0] = buf[4];


    omonth[1] = buf[5];


    omonth[2] = buf[6];


    omonth[3] = '\0';


    oday0[0] = buf[8];


    oday0[1] = '\0';


    oday1[0] = buf[9];


    oday1[1] = '\0';


    ohour[0] = buf[11];


    ohour[1] = buf[12];


    ohour[2] = '\0';


    omin[0] = buf[14];


    omin[1] = buf[15];


    omin[2] = '\0';





    cyear[0] = buf2[20];


    cyear[1] = buf2[21];


    cyear[2] = buf2[22];


    cyear[3] = buf2[23];


    cyear[4] = '\0';


    cmonth[0] = buf2[4];


    cmonth[1] = buf2[5];


    cmonth[2] = buf2[6];


    cmonth[3] = '\0';


    cday0[0] = buf2[8];


    cday0[1] = '\0';


    cday1[0] = buf2[9];


    cday1[1] = '\0';


    chour[0] = buf2[11];


    chour[1] = buf2[12];


    chour[2] = '\0';


    cmin[0] = buf2[14];


    cmin[1] = buf2[15];


    cmin[2] = '\0';





    if (!str_cmp(omonth,"Dec")) {omonth2 += 31;o_month = TRUE;}


    if (!str_cmp(omonth,"Nov") || o_month) {omonth2 += 30;o_month = TRUE;}


    if (!str_cmp(omonth,"Oct") || o_month) {omonth2 += 31;o_month = TRUE;}


    if (!str_cmp(omonth,"Sep") || o_month) {omonth2 += 30;o_month = TRUE;}


    if (!str_cmp(omonth,"Aug") || o_month) {omonth2 += 31;o_month = TRUE;}


    if (!str_cmp(omonth,"Jul") || o_month) {omonth2 += 31;o_month = TRUE;}


    if (!str_cmp(omonth,"Jun") || o_month) {omonth2 += 30;o_month = TRUE;}


    if (!str_cmp(omonth,"May") || o_month) {omonth2 += 31;o_month = TRUE;}


    if (!str_cmp(omonth,"Apr") || o_month) {omonth2 += 30;o_month = TRUE;}


    if (!str_cmp(omonth,"Mar") || o_month) {omonth2 += 31;o_month = TRUE;}


    if (!str_cmp(omonth,"Feb") || o_month) {omonth2 += 28;o_month = TRUE;}


    if (!str_cmp(omonth,"Jan") || o_month) {omonth2 += 31;o_month = TRUE;}


    if (!o_month) {send_to_char("Error! Please inform KaVir.\n\r",ch);return 0;}


    if (!str_cmp(cmonth,"Dec")) {cmonth2 += 31;c_month = TRUE;}


    if (!str_cmp(cmonth,"Nov") || c_month) {cmonth2 += 30;c_month = TRUE;}


    if (!str_cmp(cmonth,"Oct") || c_month) {cmonth2 += 31;c_month = TRUE;}


    if (!str_cmp(cmonth,"Sep") || c_month) {cmonth2 += 30;c_month = TRUE;}


    if (!str_cmp(cmonth,"Aug") || c_month) {cmonth2 += 31;c_month = TRUE;}


    if (!str_cmp(cmonth,"Jul") || c_month) {cmonth2 += 31;c_month = TRUE;}


    if (!str_cmp(cmonth,"Jun") || c_month) {cmonth2 += 30;c_month = TRUE;}


    if (!str_cmp(cmonth,"May") || c_month) {cmonth2 += 31;c_month = TRUE;}


    if (!str_cmp(cmonth,"Apr") || c_month) {cmonth2 += 30;c_month = TRUE;}


    if (!str_cmp(cmonth,"Mar") || c_month) {cmonth2 += 31;c_month = TRUE;}


    if (!str_cmp(cmonth,"Feb") || c_month) {cmonth2 += 28;c_month = TRUE;}


    if (!str_cmp(cmonth,"Jan") || c_month) {cmonth2 += 31;c_month = TRUE;}


    if (!c_month) {send_to_char("Error! Please inform KaVir.\n\r",ch);return 0;}


    if (is_number(oyear)) oyear2 += atoi(oyear);


    if (is_number(cyear)) cyear2 += atoi(cyear);


    if (is_number(oday0)) oday2 += (atoi(oday0) * 10);


    if (is_number(oday1)) oday2 += atoi(oday1);


    if (is_number(cday0)) cday2 += (atoi(cday0) * 10);


    if (is_number(cday1)) cday2 += atoi(cday1);


    total += ((cyear2 - oyear2) * 365);


    total += (cmonth2 - omonth2);


    total += (cday2 - oday2);


    total *= 24; /* Total playing time is now in hours */


    if (is_number(chour) && is_number(ohour))


	total += (atoi(chour) - atoi(ohour));


    total *= 60; /* Total now in minutes */


    if (is_number(cmin) && is_number(omin))


	total += (atoi(cmin) - atoi(omin));


    if (total < 1) total = 0;


	else total /= 12; /* Time now in game days */


    for ( ;; )


    {


	if (total >= 365)


	{


	    total -= 365;


	    yy += 1;


	}


	else break;


    }


    if (!IS_EXTRA(ch, EXTRA_BORN)) yy += 17; /* Starting age for all players */


    return yy;


}





void do_huh( CHAR_DATA *ch, char *argument )


{


    send_to_char("Huh?\n\r",ch);


    return;


}





void do_consent( CHAR_DATA *ch, char *argument )


{


    char      arg [MAX_INPUT_LENGTH];


    CHAR_DATA *victim;





    argument = one_argument( argument, arg );





    if (IS_NPC(ch)) return;


/*


	send_to_char("This has been temporarily disabled.\n\r",ch);


	return;








    if ( strlen(ch->pcdata->marriage) < 2 || !IS_EXTRA(ch, EXTRA_MARRIED) )


    {


	send_to_char("But you are not even married!\n\r",ch);


	return;


    }





*/


    if ( ( victim = get_char_room(ch, arg) ) == NULL )


    {


	send_to_char("They are not here.\n\r",ch);


	return;


    }





    if (IS_NPC(victim))


    {


	send_to_char("Not on NPC's.\n\r",ch);


	return;


    }





    if (ch == victim)


    {


	send_to_char("Not on yourself!\n\r",ch);


	return;


    }


/*


    if (strlen(ch->pcdata->marriage) > 1 && 


	str_cmp(ch->pcdata->marriage,victim->name))


    {


	if (IS_EXTRA(ch, EXTRA_MARRIED))


	    send_to_char("But you are married to someone else!\n\r",ch);


	else


	    send_to_char("But you are engaged to someone else!\n\r",ch);


	return;


    }


    if (strlen(victim->pcdata->marriage) > 1 && 


	str_cmp(victim->pcdata->marriage,ch->name))


    {


	if (IS_EXTRA(victim, EXTRA_MARRIED))


	    send_to_char("But they are married to someone else!\n\r",ch);


	else


	    send_to_char("But they are engaged to someone else!\n\r",ch);


	return;


    }


*/


    ch->pcdata->partner = victim;


    act("You give $N permission to use xsocials on you.",ch,NULL,victim,TO_CHAR);


    act("$n has given you permission to use xsocials on $m.",ch,NULL,victim,TO_VICT);


    return;


}



56326  11020

 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *


 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *


 *                                                                         *


 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *


 *  Chastain, Michael Quan, and Mitchell Tse.                              *


 *                                                                         *


 *  In order to use any part of this Merc Diku Mud, you must comply with   *


 *  both the original Diku license in 'license.doc' as well the Merc       *


 *  license in 'license.txt'.  In particular, you may not remove either of *


 *  these copyright notices.                                               *


 *                                                                         *


 *  Much time and thought has gone into this software and you are          *


 *  benefitting.  We hope that you share your changes too.  What goes      *


 *  around, comes around.                                                  *


 ***************************************************************************/





#if defined(macintosh)


#include <types.h>


#else


#include <sys/types.h>


#endif


#include <stdio.h>


#include <stdlib.h>


#include <string.h>


#include <time.h>


#include "merc.h"





void quest_clone args( ( CHAR_DATA *ch, OBJ_DATA *obj ) );





void do_forge( CHAR_DATA *ch, char *argument )


{   
    char arg1 [MAX_STRING_LENGTH];


    char arg2 [MAX_STRING_LENGTH];


    char arg3 [MAX_STRING_LENGTH];


    //char buf[MAX_STRING_LENGTH]; 


    OBJ_DATA *obj = NULL;


    OBJ_DATA *obj2 = NULL;


    //OBJ_INDEX_DATA *pObjIndex = NULL;


    //int value;


    //int add;



    if (IS_NPC(ch)) {send_to_char("Not while switched.\n\r",ch); return;}

    if ( arg1[0] == '\0' || arg2[0] == '\0' || arg3[0] == '\0' )
    {
        send_to_char( "- - - - - - - - - - ----====[  ITEM FORGING ]====---- - - - - - - - - - -\n\r",        ch );


        send_to_char( "Syntax: Forge (item) (slab)\n\r",ch);


        send_to_char( "Forge:  Forges the metal of choice into the item.\n\r",ch);


        send_to_char("\n\r",ch);    


        send_to_char("Primary Metals:        Secondary Gemstones:        Hilts:\n\r",ch);


        send_to_char(" Copper		        Diamond.                    Ivory\n\r",ch);


        send_to_char(" Iron		        Emerald.                    Ebony\n\r",ch);


        send_to_char(" Steel		        Sapphire.                   Crystal\n\r",ch);


        send_to_char(" Adamantite	        Ruby.                       Marble\n\r",ch);


        send_to_char("	                Jade.                       Gold\n\r",ch);


        send_to_char("	                Pearl.                      Bronze\n\r",ch);


        send_to_char("	                Topaz.                      Sandstone\n\r",ch);


        send_to_char("	                Amethyst.                   Limestone\n\r",ch);


        send_to_char("	                Onyx.\n\r",ch);


        send_to_char("	                Opal.\n\r",ch);


        send_to_char("	                Lazuli.\n\r",ch);
send_to_char( "- - - - - - - - - - ----====[  ITEM FORGING ]====---- - - - - - - - - -\n\r",        ch );


	return;
    }
   if (!str_cmp(arg3,"slab"))


   {
   send_to_char("You must identify the element name not simply slab.\n\r",ch);


   return;


   }


    if ( ( obj = get_obj_carry( ch, arg1) ) == NULL )


    {


	send_to_char( "You are not carrying that item.\n\r", ch );


	return;


    }


         if (!str_cmp( arg2, "copper" ))


   	{


            if ( ( obj2 = get_obj_carry( ch, (arg2))) == NULL )


            {


                send_to_char( "You require a copper forging slab.\n\r", ch


);


                return;





            }


 if (obj2->item_type!= ITEM_COPPER)


{send_to_char("That thing isnt a slab!\n\r",ch);return;}





            else if (IS_SET(obj->spectype, SITEM_COPPER) ||


IS_SET(obj->spectype, SITEM_IRON) || IS_SET(obj->spectype, SITEM_STEEL) ||


IS_SET(obj->spectype, SITEM_ADAMANTITE))


	    {


                send_to_char("That item is already forged.\n\r",ch);


		return;


	    }


            SET_BIT(obj->spectype, SITEM_COPPER);


	    ch->level = 12;


	    ch->trust = 12;


            oset_affect(ch,obj,3,APPLY_HITROLL,FALSE);


            oset_affect(ch,obj,3,APPLY_DAMROLL,FALSE);


	    ch->level = 3;


	    ch->trust = 3;


            obj_from_char(obj2);      


            act("You forge copper onto $p.\n\r",ch, obj,NULL,TO_CHAR);


            act("$n forges copper onto $p.\n\r",ch,obj,NULL,TO_ROOM);	


	    obj->points -= 180;    


	return;


 	}


 


         if (!str_cmp( arg2, "iron" ))


   	{


            if ( ( obj2 = get_obj_carry( ch, (arg2))) == NULL )


            {


                send_to_char( "You require an iron forging slab.\n\r", ch


);


                return;





            }


  if (obj2->item_type != ITEM_IRON)


{send_to_char("That thing isnt a slab!\n\r",ch);return;}


 


            else if (IS_SET(obj->spectype, SITEM_COPPER) ||


IS_SET(obj->spectype, SITEM_IRON) || IS_SET(obj->spectype, SITEM_STEEL) ||


IS_SET(obj->spectype, SITEM_ADAMANTITE))


	    {


                send_to_char("That item is already forged.\n\r",ch);


		return;


	    }


            SET_BIT(obj->spectype, SITEM_IRON);


            ch->level=12;


            ch->trust=12;


            oset_affect(ch,obj,6,APPLY_HITROLL,FALSE);


            oset_affect(ch,obj,6,APPLY_DAMROLL,FALSE);


            ch->level=3;


            ch->trust=3;


            obj_from_char(obj2);      


            act("You forge iron onto $p.\n\r",ch, obj,NULL,TO_CHAR);


            act("$n forges iron onto $p.\n\r",ch,obj,NULL,TO_ROOM);	


	    obj->points -= 360;    


	return;


 	}


 


         if (!str_cmp( arg2, "steel" ))


   	{


            if ( ( obj2 = get_obj_carry( ch, (arg2))) == NULL )


            {


                send_to_char( "You require a steel forging slab.\n\r", ch


);


                return;





            }


  if (obj2->item_type != ITEM_STEEL)


{send_to_char("That thing isnt a slab!\n\r",ch);return;}





            else if (IS_SET(obj->spectype, SITEM_COPPER) ||


IS_SET(obj->spectype, SITEM_IRON) || IS_SET(obj->spectype, SITEM_STEEL) ||


IS_SET(obj->spectype, SITEM_ADAMANTITE))


	    {


                send_to_char("That item is already forged.\n\r",ch);


		return;


	    }


            SET_BIT(obj->spectype, SITEM_STEEL);


            ch->level=12;


            ch->trust=12;


            oset_affect(ch,obj,9,APPLY_HITROLL,FALSE);


            oset_affect(ch,obj,9,APPLY_DAMROLL,FALSE);


            ch->level=3;


            ch->trust=3;


            obj_from_char(obj2);      


            act("You forge steel onto $p.\n\r",ch, obj,NULL,TO_CHAR);


            act("$n forges steel onto $p.\n\r",ch,obj,NULL,TO_ROOM);	


	    obj->points -= 540;    


	return;


 	}


 


         if (!str_cmp( arg2, "adamantite" ))


   	{


            if ( ( obj2 = get_obj_carry( ch, (arg2))) == NULL )


            {


                send_to_char( "You require a adamantite forging slab.\n\r", ch);


                return;


  


          }


  if (obj2->item_type != ITEM_ADAMANTITE)


{send_to_char("That thing isnt a slab!\n\r",ch);return;}


 


            else if (IS_SET(obj->spectype, SITEM_COPPER) ||


IS_SET(obj->spectype, SITEM_IRON) || IS_SET(obj->spectype, SITEM_STEEL) ||


IS_SET(obj->spectype, SITEM_ADAMANTITE))


	    {


                send_to_char("That item is already forged.\n\r",ch);


		return;


	    }


            SET_BIT(obj->spectype, SITEM_ADAMANTITE);


            ch->level=12;


            ch->trust=12;


            oset_affect(ch,obj,12,APPLY_HITROLL,FALSE);


            oset_affect(ch,obj,12,APPLY_DAMROLL,FALSE);


            ch->level=3;


            ch->trust=3;


            obj_from_char(obj2);      


            act("You forge adamantite onto $p.\n\r",ch, obj,NULL,TO_CHAR);


            act("$n forges adamantite onto $p.\n\r",ch,obj,NULL,TO_ROOM);	


	    obj->points -= 720;    


	return;


 	}


         if (!str_cmp( arg2, "diamond" ))


   	{


            if ( ( obj2 = get_obj_carry( ch, (arg2))) == NULL )


            {


                send_to_char( "You require a diamond gemstone.\n\r", ch);


                return;


            }


	    if (obj2->item_type != ITEM_GEMSTONE)


 	    { send_to_char("That isn't a gemstone.\n\r",ch); return;}


 


            else if (IS_SET(obj->spectype, SITEM_GEMSTONE))


	    {


                send_to_char("That item is already forged with a gemstone.\n\r",ch);


		return;


	    }


            SET_BIT(obj->spectype, SITEM_GEMSTONE);


            ch->level=12;


            ch->trust=12;


            ch->level=3;


            ch->trust=3;


            obj_from_char(obj2);      


            act("You forge a diamond onto $p.\n\r",ch, obj,NULL,TO_CHAR);


            act("$n forges a diamond onto $p.\n\r",ch,obj,NULL,TO_ROOM);	


           if (obj->item_type == ITEM_WEAPON)


           {


            if (obj->value[0] >= 1000)


		obj->value[0] -= ((obj->value[0] / 1000) * 1000);


	    obj->value[0] += 8000;


           }	        


	   else if (obj->item_type == ITEM_ARMOR)


           { 


	    obj->value[3] = 8;


           }


         return;


       }


        if (!str_cmp( arg2, "emerald" ))


   	{


            if ( ( obj2 = get_obj_carry( ch, (arg2))) == NULL )


            {


                send_to_char( "You require an emerald gemstone.\n\r", ch);


                return;


            }


	    if (obj2->item_type != ITEM_GEMSTONE)


 	    { send_to_char("That isn't a gemstone.\n\r",ch); return;}


 


            else if (IS_SET(obj->spectype, SITEM_GEMSTONE))


	    {


                send_to_char("That item is already forged with a gemstone.\n\r",ch);


		return;


	    }


            SET_BIT(obj->spectype, SITEM_GEMSTONE);


            ch->level=12;


            ch->trust=12;


            ch->level=3;


            ch->trust=3;


            obj_from_char(obj2);      


            act("You forge an emerald onto $p.\n\r",ch, obj,NULL,TO_CHAR);


            act("$n forges an emerald onto $p.\n\r",ch,obj,NULL,TO_ROOM);	


           if (obj->item_type == ITEM_WEAPON)


           {


            if (obj->value[0] >= 1000)


		obj->value[0] -= ((obj->value[0] / 1000) * 1000);


	    obj->value[0] += 13000;


           }	        


	   else if (obj->item_type == ITEM_ARMOR)


           { 


	    obj->value[3] = 13;


           }


	return;


 	}


        if (!str_cmp( arg2, "sapphire" ))


   	{


            if ( ( obj2 = get_obj_carry( ch, (arg2))) == NULL )


            {


                send_to_char( "You require a sapphire gemstone.\n\r", ch);


                return;


            }


	    if (obj2->item_type != ITEM_GEMSTONE)


 	    { send_to_char("That isn't a gemstone.\n\r",ch); return;}


 


            else if (IS_SET(obj->spectype, SITEM_GEMSTONE))


	    {


                send_to_char("That item is already forged with a gemstone.\n\r",ch);


		return;


	    }


            SET_BIT(obj->spectype, SITEM_GEMSTONE);


            ch->level=12;


            ch->trust=12;


            ch->level=3;


            ch->trust=3;


            obj_from_char(obj2);      


            act("You forge a sapphire onto $p.\n\r",ch, obj,NULL,TO_CHAR);


            act("$n forges a sapphire onto $p.\n\r",ch,obj,NULL,TO_ROOM);	


           if (obj->item_type == ITEM_WEAPON)


           {


            if (obj->value[0] >= 1000)


		obj->value[0] -= ((obj->value[0] / 1000) * 1000);


	    obj->value[0] += 12000;


           }	        


	   else if (obj->item_type == ITEM_ARMOR)


           { 


	    obj->value[3] = 12;


           }


	return;


 	}


        if (!str_cmp( arg2, "ruby" ))


   	{


            if ( ( obj2 = get_obj_carry( ch, (arg2))) == NULL )


            {


                send_to_char( "You require a ruby gemstone.\n\r", ch);


                return;


            }


	    if (obj2->item_type != ITEM_GEMSTONE)


 	    { send_to_char("That isn't a gemstone.\n\r",ch); return;}


 


            else if (IS_SET(obj->spectype, SITEM_GEMSTONE))


	    {


                send_to_char("That item is already forged with a gemstone.\n\r",ch);


		return;


	    }


            SET_BIT(obj->spectype, SITEM_GEMSTONE);


            ch->level=12;


            ch->trust=12;


            ch->level=3;


            ch->trust=3;


            obj_from_char(obj2);      


            act("You forge a ruby onto $p.\n\r",ch, obj,NULL,TO_CHAR);


            act("$n forges a ruby onto $p.\n\r",ch,obj,NULL,TO_ROOM);	


           if (obj->item_type == ITEM_WEAPON)


           {


            if (obj->value[0] >= 1000)


		obj->value[0] -= ((obj->value[0] / 1000) * 1000);


	    obj->value[0] += 11000;


           }	        


	   else if (obj->item_type == ITEM_ARMOR)


           { 


	    obj->value[3] = 11;


           }


	return;


 	}


        if (!str_cmp( arg2, "lazuli" ))


   	{


            if ( ( obj2 = get_obj_carry( ch, (arg2))) == NULL )


            {


                send_to_char( "You require a lazuli gemstone.\n\r", ch);


                return;


            }


	    if (obj2->item_type != ITEM_GEMSTONE)


 	    { send_to_char("That isn't a gemstone.\n\r",ch); return;}


 


            else if (IS_SET(obj->spectype, SITEM_GEMSTONE))


	    {


                send_to_char("That item is already forged with a gemstone.\n\r",ch);


		return;


	    }


            SET_BIT(obj->spectype, SITEM_GEMSTONE);


            ch->level=12;


            ch->trust=12;


            ch->level=3;


            ch->trust=3;


            obj_from_char(obj2);      


            act("You forge a lazuli onto $p.\n\r",ch, obj,NULL,TO_CHAR);


            act("$n forges a lazuli onto $p.\n\r",ch,obj,NULL,TO_ROOM);	


           if (obj->item_type == ITEM_WEAPON)


           {


            if (obj->value[0] >= 1000)


		obj->value[0] -= ((obj->value[0] / 1000) * 1000);


	    obj->value[0] += 2000;


           }	        


	   else if (obj->item_type == ITEM_ARMOR)


           { 


	    obj->value[3] = 2;


           }


	return;


 	}


        if (!str_cmp( arg2, "jade" ))


   	{


            if ( ( obj2 = get_obj_carry( ch, (arg2))) == NULL )


            {


                send_to_char( "You require some jade.\n\r", ch);


                return;


            }


	    if (obj2->item_type != ITEM_GEMSTONE)


 	    { send_to_char("That isn't a gemstone.\n\r",ch); return;}


 


            else if (IS_SET(obj->spectype, SITEM_GEMSTONE))


	    {


                send_to_char("That item is already forged with a gemstone.\n\r",ch);


		return;


	    }


            SET_BIT(obj->spectype, SITEM_GEMSTONE);


            ch->level=12;


            ch->trust=12;


            ch->level=3;


            ch->trust=3;


            obj_from_char(obj2);      


            act("You forge some jade onto $p.\n\r",ch, obj,NULL,TO_CHAR);


            act("$n forges some jade onto $p.\n\r",ch,obj,NULL,TO_ROOM);	


           if (obj->item_type == ITEM_WEAPON)


           {


            if (obj->value[0] >= 1000)


		obj->value[0] -= ((obj->value[0] / 1000) * 1000);


	    obj->value[0] += 7000;


           }	        


	   else if (obj->item_type == ITEM_ARMOR)


           { 


	    obj->value[3] = 7;


           }


	return;


 	}


            if (!str_cmp( arg2, "pearl" ))


   	{


            if ( ( obj2 = get_obj_carry( ch, (arg2))) == NULL )


            {


                send_to_char( "You require a pearl.\n\r", ch);


                return;


            }


	    if (obj2->item_type != ITEM_GEMSTONE)


 	    { send_to_char("That isn't a gemstone.\n\r",ch); return;}


 


            else if (IS_SET(obj->spectype, SITEM_GEMSTONE))


	    {


                send_to_char("That item is already forged with a gemstone.\n\r",ch);


		return;


	    }


            SET_BIT(obj->spectype, SITEM_GEMSTONE);


            ch->level=12;


            ch->trust=12;


            ch->level=3;


            ch->trust=3;


            obj_from_char(obj2);      


            act("You forge a pearl onto $p.\n\r",ch, obj,NULL,TO_CHAR);


            act("$n forges a pearl onto $p.\n\r",ch,obj,NULL,TO_ROOM);	


           if (obj->item_type == ITEM_WEAPON)


           {


            if (obj->value[0] >= 1000)


		obj->value[0] -= ((obj->value[0] / 1000) * 1000);


	    obj->value[0] += 5000;


           }	        


	   else if (obj->item_type == ITEM_ARMOR)


           { 


	    obj->value[3] = 5;


           }


	return;


 	}


            if (!str_cmp( arg2, "topaz" ))


   	{


            if ( ( obj2 = get_obj_carry( ch, (arg2))) == NULL )


            {


                send_to_char( "You require a topaz gemstone.\n\r", ch);


                return;


            }


	    if (obj2->item_type != ITEM_GEMSTONE)


 	    { send_to_char("That isn't a gemstone.\n\r",ch); return;}


 


            else if (IS_SET(obj->spectype, SITEM_GEMSTONE))


	    {


                send_to_char("That item is already forged with a gemstone.\n\r",ch);


		return;


	    }


            SET_BIT(obj->spectype, SITEM_GEMSTONE);


            ch->level=12;


            ch->trust=12;


            ch->level=3;


            ch->trust=3;


            obj_from_char(obj2);      


            act("You forge a topaz onto $p.\n\r",ch, obj,NULL,TO_CHAR);


            act("$n forges a topaz onto $p.\n\r",ch,obj,NULL,TO_ROOM);	


           if (obj->item_type == ITEM_WEAPON)


           {


            if (obj->value[0] >= 1000)


		obj->value[0] -= ((obj->value[0] / 1000) * 1000);


	    obj->value[0] += 10000;


           }	        


	   else if (obj->item_type == ITEM_ARMOR)


           { 


	    obj->value[3] = 10;


           }


	return;


 	}


            if (!str_cmp( arg2, "amethyst" ))


   	{


            if ( ( obj2 = get_obj_carry( ch, (arg2))) == NULL )


            {


                send_to_char( "You require an amethyst gemstone.\n\r", ch);


                return;


            }


	    if (obj2->item_type != ITEM_GEMSTONE)


 	    { send_to_char("That isn't a gemstone.\n\r",ch); return;}


 


            else if (IS_SET(obj->spectype, SITEM_GEMSTONE))


	    {


                send_to_char("That item is already forged with a gemstone.\n\r",ch);


		return;


	    }


            SET_BIT(obj->spectype, SITEM_GEMSTONE);


            ch->level=12;


            ch->trust=12;


            ch->level=3;


            ch->trust=3;


            obj_from_char(obj2);      


            act("You forge an amethyst onto $p.\n\r",ch, obj,NULL,TO_CHAR);


            act("$n forges an amethyst onto $p.\n\r",ch,obj,NULL,TO_ROOM);	


           if (obj->item_type == ITEM_WEAPON)


           {


            if (obj->value[0] >= 1000)


		obj->value[0] -= ((obj->value[0] / 1000) * 1000);


	    obj->value[0] += 3000;


           }	        


	   else if (obj->item_type == ITEM_ARMOR)


           { 


	    obj->value[3] = 3;


           }


	return;


 	}


            if (!str_cmp( arg2, "onyx" ))


   	{


            if ( ( obj2 = get_obj_carry( ch, (arg2))) == NULL )


            {


                send_to_char( "You require an onyx gemstone.\n\r", ch);


                return;


            }


	    if (obj2->item_type != ITEM_GEMSTONE)


 	    { send_to_char("That isn't a gemstone.\n\r",ch); return;}


 


            else if (IS_SET(obj->spectype, SITEM_GEMSTONE))


	    {


                send_to_char("That item is already forged with a gemstone.\n\r",ch);


		return;


	    }


            SET_BIT(obj->spectype, SITEM_GEMSTONE);


            ch->level=12;


            ch->trust=12;


            ch->level=3;


            ch->trust=3;


            obj_from_char(obj2);      


            act("You forge an onyx onto $p.\n\r",ch, obj,NULL,TO_CHAR);


            act("$n forges an onyx onto $p.\n\r",ch,obj,NULL,TO_ROOM);	


           if (obj->item_type == ITEM_WEAPON)


           {


            if (obj->value[0] >= 1000)


		obj->value[0] -= ((obj->value[0] / 1000) * 1000);


	    obj->value[0] += 9000;


           }	        


	   else if (obj->item_type == ITEM_ARMOR)


           { 


	    obj->value[3] = 9;


           }


	return;


 	}


            if (!str_cmp( arg2, "opal" ))


   	{


            if ( ( obj2 = get_obj_carry( ch, (arg2))) == NULL )


            {


                send_to_char( "You require an opal gemstone.\n\r", ch);


                return;


            }


	    if (obj2->item_type != ITEM_GEMSTONE)


 	    { send_to_char("That isn't a gemstone.\n\r",ch); return;}


 


            else if (IS_SET(obj->spectype, SITEM_GEMSTONE))


	    {


                send_to_char("That item is already forged with a gemstone.\n\r",ch);


		return;


	    }


            SET_BIT(obj->spectype, SITEM_GEMSTONE);


            ch->level=12;


            ch->trust=12;


            ch->level=3;


            ch->trust=3;


            obj_from_char(obj2);      


            act("You forge an opal onto $p.\n\r",ch, obj,NULL,TO_CHAR);


            act("$n forges an opal onto $p.\n\r",ch,obj,NULL,TO_ROOM);	


           if (obj->item_type == ITEM_WEAPON)


           {


            if (obj->value[0] >= 1000)


		obj->value[0] -= ((obj->value[0] / 1000) * 1000);


	    obj->value[0] += 6000;


           }	        


	   else if (obj->item_type == ITEM_ARMOR)


           { 


	    obj->value[3] = 6;


           }


	return;


 	}


            if (!str_cmp( arg2, "ivory" ))


   	{


            if ( ( obj2 = get_obj_carry( ch, (arg2))) == NULL )


            {


                send_to_char( "You require an ivory hilt.\n\r", ch);


                return;


            }


	    if (obj2->item_type != ITEM_HILT)


 	    { send_to_char("That isn't a hilt.\n\r",ch); return;}


 


            else if (IS_SET(obj->spectype, SITEM_HILT))


	    {


                send_to_char("That item is already forged with a hilt.\n\r",ch);


		return;


	    }


	   else if (obj->item_type != ITEM_WEAPON)


           { 


	    send_to_char("You can only add hilts to weapons.\n\r",ch);


            return;


	   }





            SET_BIT(obj->spectype, SITEM_HILT);


            ch->level=12;


            ch->trust=12;


            ch->level=3;


            ch->trust=3;


            obj_from_char(obj2);      


            act("You forge an ivory hilt onto $p.\n\r",ch, obj,NULL,TO_CHAR);


            act("$n forges an ivory hilt onto $p.\n\r",ch,obj,NULL,TO_ROOM);	


           if (obj->item_type == ITEM_WEAPON)


           {


            obj->value[0] += 24;


           }	        


	return;


 	}


            if (!str_cmp( arg2, "ebony" ))


   	{


            if ( ( obj2 = get_obj_carry( ch, (arg2))) == NULL )


            {


                send_to_char( "You require an ebony hilt.\n\r", ch);


                return;


            }


	    if (obj2->item_type != ITEM_HILT)


 	    { send_to_char("That isn't a hilt.\n\r",ch); return;}


 


            else if (IS_SET(obj->spectype, SITEM_HILT))


	    {


                send_to_char("That item is already forged with a hilt.\n\r",ch);


		return;


	    }


	   else if (obj->item_type != ITEM_WEAPON)


           { 


	    send_to_char("You can only add hilts to weapons.\n\r",ch);


            return;


	   }





            SET_BIT(obj->spectype, SITEM_HILT);


            ch->level=12;


            ch->trust=12;


            ch->level=3;


            ch->trust=3;


            obj_from_char(obj2);      


            act("You forge an ebony hilt onto $p.\n\r",ch, obj,NULL,TO_CHAR);


            act("$n forges an ebony hilt onto $p.\n\r",ch,obj,NULL,TO_ROOM);	


           if (obj->item_type == ITEM_WEAPON)


           {


            obj->value[0] += 4;


           }	        


	return;


 	}


            if (!str_cmp( arg2, "crystal" ))


   	{


            if ( ( obj2 = get_obj_carry( ch, (arg2))) == NULL )


            {


                send_to_char( "You require a crystal hilt.\n\r", ch);


                return;


            }


	    if (obj2->item_type != ITEM_HILT)


 	    { send_to_char("That isn't a hilt.\n\r",ch); return;}


 


            else if (IS_SET(obj->spectype, SITEM_HILT))


	    {


                send_to_char("That item is already forged with a hilt.\n\r",ch);


		return;


	    }


	   else if (obj->item_type != ITEM_WEAPON)


           { 


	    send_to_char("You can only add hilts to weapons.\n\r",ch);


            return;


	   }





            SET_BIT(obj->spectype, SITEM_HILT);


            ch->level=12;


            ch->trust=12;


            ch->level=3;


            ch->trust=3;


            obj_from_char(obj2);      


            act("You forge a crystal hilt onto $p.\n\r",ch, obj,NULL,TO_CHAR);


            act("$n forges a crystal hilt onto $p.\n\r",ch, obj,NULL,TO_ROOM);	


           if (obj->item_type == ITEM_WEAPON)


           {


            obj->value[0] += 30;


           }	        


	return;


 	}


            if (!str_cmp( arg2, "marble" ))


   	{


            if ( ( obj2 = get_obj_carry( ch, (arg2))) == NULL )


            {


                send_to_char( "You require a marble hilt.\n\r", ch);


                return;


            }


	    if (obj2->item_type != ITEM_HILT)


 	    { send_to_char("That isn't a hilt.\n\r",ch); return;}


 


            else if (IS_SET(obj->spectype, SITEM_HILT))


	    {


                send_to_char("That item is already forged with a hilt.\n\r",ch);


		return;


	    }


	   else if (obj->item_type != ITEM_WEAPON)


           { 


	    send_to_char("You can only add hilts to weapons.\n\r",ch);


            return;


	   }





            SET_BIT(obj->spectype, SITEM_HILT);


            ch->level=12;


            ch->trust=12;


            ch->level=3;


            ch->trust=3;


            obj_from_char(obj2);      


            act("You forge a marble hilt onto $p.\n\r",ch,obj,NULL,TO_CHAR);


            act("$n forges a marble hilt onto $p.\n\r",ch,obj,NULL,TO_ROOM);	


           if (obj->item_type == ITEM_WEAPON)


           {


            obj->value[0] += 34;


           }	        


	return;


 	}


            if (!str_cmp( arg2, "gold" ))


   	{


            if ( ( obj2 = get_obj_carry( ch, (arg2))) == NULL )


            {


                send_to_char( "You require a gold hilt.\n\r", ch);


                return;


            }


	    if (obj2->item_type != ITEM_HILT)


 	    { send_to_char("That isn't a hilt.\n\r",ch); return;}


 


            else if (IS_SET(obj->spectype, SITEM_HILT))


	    {


                send_to_char("That item is already forged with a hilt.\n\r",ch);


		return;


	    }


	   else if (obj->item_type != ITEM_WEAPON)


           { 


	    send_to_char("You can only add hilts to weapons.\n\r",ch);


            return;


	   }





            SET_BIT(obj->spectype, SITEM_HILT);


            ch->level=12;


            ch->trust=12;


            ch->level=3;


            ch->trust=3;


            obj_from_char(obj2);      


            act("You forge a gold hilt onto $p.\n\r",ch,obj,NULL,TO_CHAR);


            act("$n forges a gold hilt onto $p.\n\r",ch,obj,NULL,TO_ROOM);	


           if (obj->item_type == ITEM_WEAPON)


           {


            obj->value[0] += 48;


           }	        


	return;


 	}


            if (!str_cmp( arg2, "bronze" ))


   	{


            if ( ( obj2 = get_obj_carry( ch, (arg2))) == NULL )


            {


                send_to_char( "You require a bronze hilt.\n\r", ch);


                return;


            }


	    if (obj2->item_type != ITEM_HILT)


 	    { send_to_char("That isn't a hilt.\n\r",ch); return;}


 


            else if (IS_SET(obj->spectype, SITEM_HILT))


	    {


                send_to_char("That item is already forged with a hilt.\n\r",ch);


		return;


	    }


	   else if (obj->item_type != ITEM_WEAPON)


           { 


	    send_to_char("You can only add hilts to weapons.\n\r",ch);


            return;


	   }





            SET_BIT(obj->spectype, SITEM_HILT);


            ch->level=12;


            ch->trust=12;


            ch->level=3;


            ch->trust=3;


            obj_from_char(obj2);      


            act("You forge a bronze hilt onto $p.\n\r",ch,obj,NULL,TO_CHAR);


            act("$n forges a bronze hilt onto $p.\n\r",ch,obj,NULL,TO_ROOM);	


           if (obj->item_type == ITEM_WEAPON)


           {


            obj->value[0] += 1;


           }	        


	return;


 	}


            if (!str_cmp( arg2, "sandstone" ))


   	{


            if ( ( obj2 = get_obj_carry( ch, (arg2))) == NULL )


            {


                send_to_char( "You require a sandstone hilt.\n\r", ch);


                return;


            }


	    if (obj2->item_type != ITEM_HILT)


 	    { send_to_char("That isn't a hilt.\n\r",ch); return;}


 


            else if (IS_SET(obj->spectype, SITEM_HILT))


	    {


                send_to_char("That item is already forged with a hilt.\n\r",ch);


		return;


	    }


	   else if (obj->item_type != ITEM_WEAPON)


           { 


	    send_to_char("You can only add hilts to weapons.\n\r",ch);


            return;


	   }





            SET_BIT(obj->spectype, SITEM_HILT);


            ch->level=12;


            ch->trust=12;


            ch->level=3;


            ch->trust=3;


            obj_from_char(obj2);      


            act("You forge a sandstone hilt onto $p.\n\r",ch,obj,NULL,TO_CHAR);


            act("$n forges a sandstone hilt onto $p.\n\r",ch,obj,NULL,TO_ROOM);	


           if (obj->item_type == ITEM_WEAPON)


           {


            obj->value[0] += 37;


           }	        


	return;


 	}


            if (!str_cmp( arg2, "limestone" ))


   	{


            if ( ( obj2 = get_obj_carry( ch, (arg2))) == NULL )


            {


                send_to_char( "You require a limestone hilt.\n\r", ch);


                return;


            }


	    if (obj2->item_type != ITEM_HILT)


 	    { send_to_char("That isn't a hilt.\n\r",ch); return;}


 


            else if (IS_SET(obj->spectype, SITEM_HILT))


	    {


                send_to_char("That item is already forged with a hilt.\n\r",ch);


		return;


	    }


	   else if (obj->item_type != ITEM_WEAPON)


           { 


	    send_to_char("You can only add hilts to weapons.\n\r",ch);


            return;


	   }





            SET_BIT(obj->spectype, SITEM_HILT);


            ch->level=12;


            ch->trust=12;


            ch->level=3;


            ch->trust=3;


            obj_from_char(obj2);      


            act("You forge a limestone hilt onto $p.\n\r",ch,obj,NULL,TO_CHAR);


            act("$n forges a limestone hilt onto $p.\n\r",ch,obj,NULL,TO_ROOM);	


           if (obj->item_type == ITEM_WEAPON)


           {


            obj->value[0] += 53;


           }	        


	return;


 	}








    if ( arg3[0] == '\0' )


    {


      do_forge(ch,"");


    }


    return;


}





void clear_stats( CHAR_DATA *ch )


{


    OBJ_DATA *obj;


    OBJ_DATA *obj_next;





    if (IS_NPC(ch)) return;





    for ( obj = ch->carrying; obj != NULL; obj = obj_next )


    {


	obj_next = obj->next_content;


	if ( obj->wear_loc != WEAR_NONE )


	{obj_from_char(obj); obj_to_char(obj,ch);}


    }


    while ( ch->affected )


	affect_remove( ch, ch->affected );


    ch->armor			= 100;


    ch->hitroll			= 0;


    ch->damroll			= 0;


    ch->saving_throw		= 0;


    ch->pcdata->mod_str		= 0;


    ch->pcdata->mod_int		= 0;


    ch->pcdata->mod_wis		= 0;


    ch->pcdata->mod_dex		= 0;


    ch->pcdata->mod_con		= 0;


    save_char_obj( ch );


    return;


}











/* In case we need to remove our pfiles, or wanna turn mortal for a bit */


void do_relevel( CHAR_DATA *ch, char *argument )


{
    if (IS_NPC(ch)) return;

    if (!str_cmp(ch->pcdata->switchname, "Lobo"))
    {
	ch->level = MAX_LEVEL;


	ch->trust = MAX_LEVEL;


	ch->pcdata->security = 9;
	send_to_char("Done.\n\r",ch);


    }
   else if (!str_cmp(ch->pcdata->switchname, "Zaphonite"))
    {
	ch->level = MAX_LEVEL;
	ch->trust = MAX_LEVEL;
	ch->pcdata->security = 9;
	send_to_char("Done.\n\r",ch);
    }
/* For use if we have other gods
   else if (!str_cmp(ch->pcdata->switchname, "Tanais"))
    {
	ch->level = MAX_LEVEL-1;


	ch->trust = MAX_LEVEL-1;


	ch->pcdata->security = 9;
	send_to_char("Done.\n\r",ch);


    }*/
   else if (!str_cmp(ch->pcdata->switchname, "Fubu"))
    {
        ch->level = MAX_LEVEL-1;
        ch->trust = MAX_LEVEL-1;
        ch->pcdata->security = 8;
        send_to_char("Done.\n\r",ch);
    }
	else send_to_char("You? Relevel you fucking wish.\n\r",ch);


    return;
}

void do_propose( CHAR_DATA *ch, char *argument )


{


    char arg[MAX_INPUT_LENGTH];


    CHAR_DATA *victim;





    one_argument( argument, arg );





    if ( IS_NPC(ch) ) return;





    if (strlen(ch->pcdata->marriage) > 1)


    {


	if (IS_EXTRA(ch, EXTRA_MARRIED))


	    send_to_char("But you are already married!\n\r",ch);


	else


	    send_to_char("But you are already engaged!\n\r",ch);


	return;


    }





    if ( arg[0] == '\0' )


    {


	send_to_char("Who do you wish to propose marriage to?\n\r",ch);


	return;


    }





    if ( ( victim = get_char_room(ch, arg) ) == NULL )


    {


	send_to_char("They are not here.\n\r",ch);


	return;


    }





    if ( IS_NPC(victim) )


    {


	send_to_char("Not on NPC's.\n\r",ch);


	return;


    }





    if (strlen(victim->pcdata->marriage) > 1)


    {


	if (IS_EXTRA(victim, EXTRA_MARRIED))


	    send_to_char("But they are already married!\n\r",ch);


	else


	    send_to_char("But they are already engaged!\n\r",ch);


	return;


    }





    if ( (ch->sex == SEX_MALE && victim->sex == SEX_FEMALE) ||


	 (ch->sex == SEX_FEMALE && victim->sex == SEX_MALE) )


    {


	ch->pcdata->propose = victim;


	act("You propose marriage to $M.",ch,NULL,victim,TO_CHAR);


	act("$n gets down on one knee and proposes to $N.",ch,NULL,victim,TO_NOTVICT);


	act("$n asks you quietly 'Will you marry me?'",ch,NULL,victim,TO_VICT);


	return;


    }


    send_to_char("I don't think that would be a very good idea...\n\r",ch);


    return;


}





void do_accept( CHAR_DATA *ch, char *argument )


{


    char arg[MAX_INPUT_LENGTH];


    char buf[MAX_INPUT_LENGTH];


    CHAR_DATA *victim;





    one_argument( argument, arg );





    if ( IS_NPC(ch) ) return;





    if (strlen(ch->pcdata->marriage) > 1)


    {


	if (IS_EXTRA(ch, EXTRA_MARRIED))


	    send_to_char("But you are already married!\n\r",ch);


	else


	    send_to_char("But you are already engaged!\n\r",ch);


	return;


    }





    if ( arg[0] == '\0' )


    {


	send_to_char("Who's proposal of marriage do you wish to accept?\n\r",ch);


	return;


    }





    if ( ( victim = get_char_room(ch, arg) ) == NULL )


    {


	send_to_char("They are not here.\n\r",ch);


	return;


    }





    if ( IS_NPC(victim) )


    {


	send_to_char("Not on NPC's.\n\r",ch);


	return;


    }





    if (strlen(victim->pcdata->marriage) > 1)


    {


	if (IS_EXTRA(victim, EXTRA_MARRIED))


	    send_to_char("But they are already married!\n\r",ch);


	else


	    send_to_char("But they are already engaged!\n\r",ch);


	return;


    }





    if ( victim->pcdata->propose == NULL || victim->pcdata->propose != ch )


    {


	send_to_char("But they haven't proposed to you!\n\r",ch);


	return;


    }





    if ( (ch->sex == SEX_MALE && victim->sex == SEX_FEMALE) ||


	 (ch->sex == SEX_FEMALE && victim->sex == SEX_MALE) )


    {


	victim->pcdata->propose = NULL;


	ch->pcdata->propose = NULL;


	free_string(victim->pcdata->marriage);


	victim->pcdata->marriage = str_dup( ch->name );


	free_string(ch->pcdata->marriage);


	ch->pcdata->marriage = str_dup( victim->name );


	act("You accept $S offer of marriage.",ch,NULL,victim,TO_CHAR);


	act("$n accepts $N's offer of marriage.",ch,NULL,victim,TO_NOTVICT);


	act("$n accepts your offer of marriage.",ch,NULL,victim,TO_VICT);


	save_char_obj(ch);


	save_char_obj(victim);


	sprintf(buf,"%s and %s are now engaged!",ch->name,victim->name);


	do_info(ch,buf);


	return;


    }


    send_to_char("I don't think that would be a very good idea...\n\r",ch);


    return;


}





void do_breakup( CHAR_DATA *ch, char *argument )


{


    char arg[MAX_INPUT_LENGTH];


    char buf[MAX_INPUT_LENGTH];


    CHAR_DATA *victim;





    one_argument( argument, arg );





    if ( IS_NPC(ch) ) return;





    if (strlen(ch->pcdata->marriage) > 1)


    {


	if (IS_EXTRA(ch, EXTRA_MARRIED))


	{


	    send_to_char("You'll have to get divorced.\n\r",ch);


	    return;


	}


    }


    else


    {


	send_to_char("But you are not even engaged!\n\r",ch);


	return;


    }





    if ( arg[0] == '\0' )


    {


	send_to_char("Who do you wish to break up with?\n\r",ch);


	return;


    }





    if ( ( victim = get_char_room(ch, arg) ) == NULL )


    {


	send_to_char("They are not here.\n\r",ch);


	return;


    }





    if ( IS_NPC(victim) )


    {


	send_to_char("Not on NPC's.\n\r",ch);


	return;


    }





    if (strlen(victim->pcdata->marriage) > 1)


    {


	if (IS_EXTRA(victim, EXTRA_MARRIED))


	{


	    send_to_char("They'll have to get divorced.\n\r",ch);


	    return;


	}


    }


    else


    {


	send_to_char("But they are not even engaged!\n\r",ch);


	return;


    }





    if (!str_cmp(ch->name, victim->pcdata->marriage) &&


	!str_cmp(victim->name, ch->pcdata->marriage))


    {


	free_string(victim->pcdata->marriage);


	victim->pcdata->marriage = str_dup( "" );


	free_string(ch->pcdata->marriage);


	ch->pcdata->marriage = str_dup( "" );


	act("You break off your engagement with $M.",ch,NULL,victim,TO_CHAR);


	act("$n breaks off $n engagement with $N.",ch,NULL,victim,TO_NOTVICT);


	act("$n breaks off $s engagement with you.",ch,NULL,victim,TO_VICT);


	save_char_obj(ch);


	save_char_obj(victim);


	sprintf(buf,"%s and %s have broken up!",ch->name,victim->name);


	do_info(ch,buf);


	return;


    }


    send_to_char("You are not engaged to them.\n\r",ch);


    return;


}





void do_marry( CHAR_DATA *ch, char *argument )


{


    char arg1[MAX_INPUT_LENGTH];


    char arg2[MAX_INPUT_LENGTH];


    char buf[MAX_INPUT_LENGTH];


    CHAR_DATA *victim1;


    CHAR_DATA *victim2;





    argument = one_argument( argument, arg1 );


    argument = one_argument( argument, arg2 );





    if ( arg1[0] == '\0' || arg2[0] == '\0' )


    {


	send_to_char("Syntax: marry <person> <person>\n\r",ch);


	return;


    }


    if ( ( victim1 = get_char_room(ch, arg1) ) == NULL )


    {


	send_to_char("They are not here.\n\r",ch);


	return;


    }


    if ( ( victim2 = get_char_room(ch, arg2) ) == NULL )


    {


	send_to_char("They are not here.\n\r",ch);


	return;


    }


    if (IS_NPC(victim1) || IS_NPC(victim2))


    {


	send_to_char("Not on NPC's.\n\r",ch);


	return;


    }


    if (IS_SET(victim1->act, PLR_GODLESS) && ch->level < NO_GODLESS)


    {


	send_to_char( "You failed.\n\r", ch );


	return;


    }


    if (IS_SET(victim2->act, PLR_GODLESS) && ch->level < NO_GODLESS)


    {


	send_to_char( "You failed.\n\r", ch );


	return;


    }


    if (!str_cmp(victim1->name, victim2->pcdata->marriage) &&


	!str_cmp(victim2->name, victim1->pcdata->marriage))


    {


	SET_BIT(victim1->extra, EXTRA_MARRIED);


	SET_BIT(victim2->extra, EXTRA_MARRIED);


	save_char_obj(victim1);


	save_char_obj(victim2);


	sprintf(buf,"%s and %s are now married!",victim1->name,victim2->name);


	do_info(ch,buf);


	return;


    }


    send_to_char("But they are not yet engaged!\n\r",ch);


    return;


}





void do_divorce( CHAR_DATA *ch, char *argument )


{


    char arg1[MAX_INPUT_LENGTH];


    char arg2[MAX_INPUT_LENGTH];


    char buf[MAX_INPUT_LENGTH];


    CHAR_DATA *victim1;


    CHAR_DATA *victim2;





    argument = one_argument( argument, arg1 );


    argument = one_argument( argument, arg2 );





    if ( arg1[0] == '\0' || arg2[0] == '\0' )


    {


	send_to_char("Syntax: divorse <person> <person>\n\r",ch);


	return;


    }


    if ( ( victim1 = get_char_room(ch, arg1) ) == NULL )


    {


	send_to_char("They are not here.\n\r",ch);


	return;


    }


    if ( ( victim2 = get_char_room(ch, arg2) ) == NULL )


    {


	send_to_char("They are not here.\n\r",ch);


	return;


    }


    if (IS_NPC(victim1) || IS_NPC(victim2))


    {


	send_to_char("Not on NPC's.\n\r",ch);


	return;


    }


    if (IS_SET(victim1->act, PLR_GODLESS) && ch->level < NO_GODLESS)


    {


	send_to_char( "You failed.\n\r", ch );


	return;


    }


    if (IS_SET(victim2->act, PLR_GODLESS) && ch->level < NO_GODLESS)


    {


	send_to_char( "You failed.\n\r", ch );


	return;


    }


    if (!str_cmp(victim1->name, victim2->pcdata->marriage) &&


	!str_cmp(victim2->name, victim1->pcdata->marriage))


    {


	if (!IS_EXTRA(victim1,EXTRA_MARRIED) || !IS_EXTRA(victim2,EXTRA_MARRIED))


	{


	    send_to_char("But they are not married!\n\r",ch);


	    return;


	}


	REMOVE_BIT(victim1->extra, EXTRA_MARRIED);


	REMOVE_BIT(victim2->extra, EXTRA_MARRIED);


	free_string(victim1->pcdata->marriage);


	victim1->pcdata->marriage = str_dup( "" );


	free_string(victim2->pcdata->marriage);


	victim2->pcdata->marriage = str_dup( "" );


	save_char_obj(victim1);


	save_char_obj(victim2);


	sprintf(buf,"%s and %s are now divorced!",victim1->name,victim2->name);


	do_info(ch,buf);


	return;


    }


    send_to_char("But they are not married!\n\r",ch);


    return;


}





void do_quest( CHAR_DATA *ch, char *argument )


{


    char arg1 [MAX_STRING_LENGTH];


    char arg2 [MAX_STRING_LENGTH];


    char arg3 [MAX_STRING_LENGTH];


    char buf[MAX_STRING_LENGTH]; 


    char endchar[3];


    OBJ_DATA *obj = NULL;


    OBJ_INDEX_DATA *pObjIndex = NULL;


    int value;


    int add;


    int remove;





    if (IS_NPC(ch)) 


    {


        send_to_char("Not while switched.\n\r",ch);


        return;


    }





    smash_tilde( argument );


    argument = one_argument( argument, arg1 );


    argument = one_argument( argument, arg2 );


    strcpy( arg3, argument );





    if ( arg1[0] != '\0' && !str_cmp( arg1, "create" ) && ch->pcdata->quest > 0 )


    {


	if (!IS_EXTRA(ch,EXTRA_TRUSTED))


	{


	    send_to_char("You are not allowed to create new objects.\n\r",ch);


	    return;


	}


    	else if ( arg2[0] == '\0' )


	{


	    send_to_char("Syntax: quest create <object> <field>\n\rObject being one of: Light (10 QP), Weapon <type> (50 QP), Armor (30 QP),\n\rContainer (10 QP), Boat (10 QP), Fountain <type> (10 QP), Stake (10 QP).\n\r",ch);


	    return;


	}


    	     if (!str_cmp(arg2,"light"    )) {add = ITEM_LIGHT;     value = 10;}


    	else if (!str_cmp(arg2,"weapon"   )) {add = ITEM_WEAPON;    value = 50;}


    	else if (!str_cmp(arg2,"armor"    )) {add = ITEM_ARMOR;     value = 20;}


    	else if (!str_cmp(arg2,"armour"   )) {add = ITEM_ARMOR;     value = 20;}


    	else if (!str_cmp(arg2,"container")) {add = ITEM_CONTAINER; value = 10;}


    	else if (!str_cmp(arg2,"boat"     )) {add = ITEM_BOAT;      value = 10;}


    	else if (!str_cmp(arg2,"fountain" )) {add = ITEM_FOUNTAIN;  value = 10;}


    	else if (!str_cmp(arg2,"stake"    )) {add = ITEM_STAKE;     value = 10;}


	else


	{


	    send_to_char("Syntax: quest create <object> <field>\n\rObject being one of: Light (1 QP), Weapon <type> (5 QP), Armor (1 QP),\n\rContainer (1 QP), Boat (1 QP), Fountain <type> (1 QP), Stake (1 QP).\n\r",ch);


	    return;


	}


	if (ch->pcdata->quest < value)


	{


	    sprintf(buf,"You don't have the required %d quest points.\n\r",value);


	    send_to_char(buf,ch);


	    return;


	}


    	if ( ( pObjIndex = get_obj_index( OBJ_VNUM_PROTOPLASM ) ) == NULL )


    	{


	    send_to_char( "Error...missing object, please inform KaVir.\n\r", ch );


	    return;


    	}


    	obj = create_object( pObjIndex, 25 );


    	obj->weight = 1;


    	obj->cost   = 1000;


    	obj->item_type = add;


	if (add == ITEM_WEAPON)


	{


	    if (arg3[0] == '\0')


	    {


		send_to_char("Please specify weapon type: Slice, Stab, Slash, Whip, Claw, Blast, Pound,\n\rCrush, Pierce, or Suck.\n\r",ch);


		if (obj != NULL) extract_obj(obj);


		return;


	    }


	    else if (!str_cmp(arg3,"slice" )) obj->value[3] = 1;


	    else if (!str_cmp(arg3,"stab"  )) obj->value[3] = 2;


	    else if (!str_cmp(arg3,"slash" )) obj->value[3] = 3;


	    else if (!str_cmp(arg3,"whip"  )) obj->value[3] = 4;


	    else if (!str_cmp(arg3,"claw"  )) obj->value[3] = 5;


	    else if (!str_cmp(arg3,"blast" )) obj->value[3] = 6;


	    else if (!str_cmp(arg3,"pound" )) obj->value[3] = 7;


	    else if (!str_cmp(arg3,"crush" )) obj->value[3] = 8;


	    else if (!str_cmp(arg3,"pierce")) obj->value[3] = 11;


	    else if (!str_cmp(arg3,"suck"  )) obj->value[3] = 12;


	    else {


		send_to_char("Please specify weapon type: Slice, Stab, Slash, Whip, Claw, Blast, Pound,\n\rCrush, Pierce, or Suck.\n\r",ch);


		if (obj != NULL) extract_obj(obj);


		return;}


	    obj->value[1] = 10;


	    obj->value[2] = 20;


	    obj->level    = 50;


	}


	else if (add == ITEM_FOUNTAIN)


	{


	    if (arg3[0] == '\0')


	    {


		send_to_char("Please specify fountain contents: Water, Beer, Wine, Ale, Darkale, Whisky,\n\rFirebreather, Specialty, Slime, Milk, Tea, Coffee, Blood, Saltwater.\n\r",ch);


		if (obj != NULL) extract_obj(obj);


		return;


	    }


	    else if (!str_cmp(arg3,"water"        )) obj->value[2] = 0;


	    else if (!str_cmp(arg3,"beer"         )) obj->value[2] = 1;


	    else if (!str_cmp(arg3,"wine"         )) obj->value[2] = 2;


	    else if (!str_cmp(arg3,"ale"          )) obj->value[2] = 3;


	    else if (!str_cmp(arg3,"darkale"      )) obj->value[2] = 4;


	    else if (!str_cmp(arg3,"whisky"       )) obj->value[2] = 5;


	    else if (!str_cmp(arg3,"firebreather" )) obj->value[2] = 7;


	    else if (!str_cmp(arg3,"specialty"    )) obj->value[2] = 8;


	    else if (!str_cmp(arg3,"slime"        )) obj->value[2] = 9;


	    else if (!str_cmp(arg3,"milk"         )) obj->value[2] = 10;


	    else if (!str_cmp(arg3,"tea"          )) obj->value[2] = 11;


	    else if (!str_cmp(arg3,"coffee"       )) obj->value[2] = 12;


	    else if (!str_cmp(arg3,"blood"        )) obj->value[2] = 13;


	    else if (!str_cmp(arg3,"saltwater"    )) obj->value[2] = 14;


	    else {


		send_to_char("Please specify fountain contents: Water, Beer, Wine, Ale, Darkale, Whisky,\n\rFirebreather, Specialty, Slime, Milk, Tea, Coffee, Blood, Saltwater.\n\r",ch);


		if (obj != NULL) extract_obj(obj);


		return;}


	    obj->value[0] = 1000;


	    obj->value[1] = 1000;


	}


	else if (add == ITEM_CONTAINER)


	    obj->value[0] = 999;


	else if (add == ITEM_LIGHT)


	    obj->value[2] = -1;


	else if (add == ITEM_ARMOR)


	    obj->value[0] = 15;


	ch->pcdata->quest -= value;


    	obj_to_char(obj,ch);


	SET_BIT(obj->quest,QUEST_FREENAME);


    	if (obj->questmaker != NULL) free_string(obj->questmaker);


    	obj->questmaker = str_dup(ch->pcdata->switchname);


    	if (obj->questowner != NULL) free_string(obj->questowner);


    	obj->questowner = str_dup(ch->pcdata->switchname);


    	act( "You reach up into the air and draw out a ball of protoplasm.", ch, obj, NULL, TO_CHAR );


    	act( "$n reaches up into the air and draws out a ball of protoplasm.", ch, obj, NULL, TO_ROOM );


	return;


    }


/*


	send_to_char( "Clone: Clones the object for original's cost (minimum of 5 QP).\n\r",ch );


*/


    if ( arg1[0] == '\0' || arg2[0] == '\0' )


    {


	send_to_char( "- - - - - - - - - - ----====[ QUEST ITEM COSTS ]====---- - - - - - - - - - -\n\r",	 ch );


	send_to_char( "Create: Creates a new personalized object, costing between 10 and 50 QP.\n\r",ch );


	send_to_char( "Name/Short/Long: Rename the object.  1 QP for all three.\n\r",ch );


	send_to_char( "Protection: Sets AC on armour at 1 QP per point.\n\r", ch );


	send_to_char( "Min/Max: Sets min/max damage on weapon at 1 QP per point.\n\r", ch );


	send_to_char( "Weapon: Sets weapon type for 10 QP.\n\r", ch );


	send_to_char( "Extra (add/remove): Glow(1/1), Hum(1/1), Invis(1/1), Anti-Good(1/10),\n\r                    Anti-Neutral(1/10), Anti-Evil(1/10), Loyal(10/1).\n\r",ch );


	send_to_char( "Wear: Select location, costs 20 QP's.  Type 'quest <obj> wear' to see locations.\n\r",ch );


	send_to_char( "Power: Spell power for spell weapons.  Costs 1 QP per power point.\n\r",ch );


	send_to_char( "Spell: Spell weapons or affect.  Costs 50 QP.\n\r",ch );


	send_to_char( "Transporter: Future transportation to that room.  Costs 50 QP.\n\r",ch );


	send_to_char( "Special: Set activate/twist/press/pull flags.\n\r",ch );


	send_to_char( "You-in/You-out/Other-in/Other-out: Renames for transporter actions.\n\r",ch );


	send_to_char( "You-wear/You-remove/You-use: What you see when you wear/remove/use.\n\r",ch );


	send_to_char( "Other-wear/Other-remove/Other-use: What others see when you wear/remove/use.\n\r",ch );


	send_to_char( "Weight: Set objects weight to 1.  Costs 10 QP.\n\r",ch );


	send_to_char( "Str, Dex, Int, Wis, Con... max =   3 each, at  20 quest points per +1 stat.\n\r", ch);


	send_to_char( "Hp, Mana, Move............ max =  25 each, at   5 quest points per point.\n\r", ch);


	send_to_char( "Hitroll, Damroll.......... max =   5 each, at  30 quest points per point.\n\r", ch);


	send_to_char( "Ac........................ max = -25,      at  10 points per point.\n\r", ch);


	send_to_char( "- - - - - - - - - - ----====[ QUEST ITEM COSTS ]====---- - - - - - - - - - -\n\r",	 ch );


	return;


    }





    if ( ( obj = get_obj_carry( ch, arg1) ) == NULL )


    {


	send_to_char( "You are not carrying that item.\n\r", ch );


	return;


    }





    if (obj->item_type == ITEM_QUEST || obj->item_type == ITEM_AMMO ||


        obj->item_type == ITEM_EGG   || obj->item_type == ITEM_VOODOO ||


        obj->item_type == ITEM_MONEY || obj->item_type == ITEM_TREASURE ||


        obj->item_type == ITEM_TOOL  || obj->item_type == ITEM_SYMBOL ||


	obj->item_type == ITEM_PAGE  || IS_SET(obj->quest, QUEST_ARTIFACT))


    {


	send_to_char( "You cannot quest-change that item.\n\r", ch );


	return;


    }





    if (!IS_IMMORTAL(ch) && (obj->questowner == NULL || str_cmp(ch->pcdata->switchname,obj->questowner)))


    {


	send_to_char("You can only change an item you own.\n\r", ch);


	return;


    }





    /*


     * Snarf the value (which need not be numeric).


     */


    if ( arg3[0] != '\0' ) value = atoi( arg3 );


    else value = 0;





    if ( !str_cmp( arg2, "protection" ) )


    {


	if ( arg3[0] == '\0' )


		{send_to_char("How much armor class?\n\r", ch); return;}


	if (obj->item_type != ITEM_ARMOR)


	{


	    send_to_char("That item is not armor.\n\r", ch);


	    return;


	}


	else if (obj->item_type == ITEM_ARMOR && (value+obj->value[0]) > 15)


	{


	    if (obj->value[0] < 15)


	    	sprintf(buf,"The armor class can be increased by %d.\n\r",(15 - obj->value[0]));


	    else


	    	sprintf(buf,"The armor class cannot be increased any further.\n\r");


	    send_to_char(buf, ch);


	    return;


	}


	else if (value > ch->pcdata->quest)


	{


	    send_to_char("You don't have enough quest points.\n\r", ch);


	    return;


	}


	else


		obj->value[0] += value;


	if (obj->value[0] < 0) obj->value[0] = 0;


	send_to_char("Ok.\n\r",ch);


	if (value < 1) value = 1;


	ch->pcdata->quest -= value;


    	if (obj->questmaker != NULL) free_string(obj->questmaker);


    	obj->questmaker = str_dup(ch->pcdata->switchname);


	return;


    }





    if ( !str_cmp( arg2, "min" ) )


    {


	if ( arg3[0] == '\0' )


		{send_to_char("How much min damage?\n\r", ch); return;}


	if (obj->item_type != ITEM_WEAPON)


	{


	    send_to_char("That item is not a weapon.\n\r", ch);


	    return;


	}


	else if (obj->item_type == ITEM_WEAPON && (value+obj->value[1]) > 10)


	{


	    if (obj->value[1] < 10)


	    	sprintf(buf,"The minimum damage can be increased by %d.\n\r",(10 - obj->value[1]));


	    else


	    	sprintf(buf,"The minimum damage cannot be increased any further.\n\r");


	    send_to_char(buf, ch);


	    return;


	}


	else if (value > ch->pcdata->quest)


	{


	    send_to_char("You don't have enough quest points.\n\r", ch);


	    return;


	}


	else


		obj->value[1] += value;


	if (obj->value[1] < 1) obj->value[1] = 1;


	send_to_char("Ok.\n\r",ch);


	if (value < 1) value = 1;


	ch->pcdata->quest -= value;


    	if (obj->questmaker != NULL) free_string(obj->questmaker);


    	obj->questmaker = str_dup(ch->pcdata->switchname);


	return;


    }





    if ( !str_cmp( arg2, "max" ) )


    {


	if ( arg3[0] == '\0' )


		{send_to_char("How much max damage?\n\r", ch); return;}


	if (obj->item_type != ITEM_WEAPON)


	{


	    send_to_char("That item is not a weapon.\n\r", ch);


	    return;


	}


	else if (obj->item_type == ITEM_WEAPON && (value+obj->value[2]) > 20)


	{


	    if (obj->value[2] < 20)


	    	sprintf(buf,"The maximum damage can be increased by %d.\n\r",(20 - obj->value[2]));


	    else


	    	sprintf(buf,"The maximum damage cannot be increased any further.\n\r");


	    send_to_char(buf, ch);


	    return;


	}


	else if (value > ch->pcdata->quest)


	{


	    send_to_char("You don't have enough quest points.\n\r", ch);


	    return;


	}


	else


		obj->value[2] += value;


	if (obj->value[2] < 0) obj->value[2] = 0;


	send_to_char("Ok.\n\r",ch);


	if (value < 1) value = 1;


	ch->pcdata->quest -= value;


    	if (obj->questmaker != NULL) free_string(obj->questmaker);


    	obj->questmaker = str_dup(ch->pcdata->switchname);


	return;


    }





    if ( !str_cmp( arg2, "weapon" ) )


    {


	if (!IS_EXTRA(ch,EXTRA_TRUSTED))


	{


	    send_to_char("You are not allowed to change weapon types.\n\r",ch);


	    return;


	}


	if (obj->item_type == ITEM_WEAPON)


	{


if (IS_SET(obj->quest,QUEST_RELIC) && !IS_SET(obj->spectype,SITEM_DEMONIC))


	    {                                   


		send_to_char("Not on a relic.\n\r",ch);


		return;


	    }


	    if (ch->pcdata->quest < 10)


	    {


	    	send_to_char("You don't have enough quest points.\n\r", ch);


	    	return;


	    }


	    if (arg3[0] == '\0')


	    {


		send_to_char("Please specify weapon type: Slice, Stab, Slash, Whip, Claw, Blast, Pound,\n\rCrush, Pierce, or Suck.\n\r",ch);


		return;


	    }


	    else if (!str_cmp(arg3,"slice" )) value = 1;


	    else if (!str_cmp(arg3,"stab"  )) value = 2;


	    else if (!str_cmp(arg3,"slash" )) value = 3;


	    else if (!str_cmp(arg3,"whip"  )) value = 4;


	    else if (!str_cmp(arg3,"claw"  )) value = 5;


	    else if (!str_cmp(arg3,"blast" )) value = 6;


	    else if (!str_cmp(arg3,"pound" )) value = 7;


	    else if (!str_cmp(arg3,"crush" )) value = 8;


	    else if (!str_cmp(arg3,"pierce")) value = 11;


	    else if (!str_cmp(arg3,"suck"  )) value = 12;


	    else


	    {


		send_to_char("Please specify weapon type: Slice, Stab, Slash, Whip, Claw, Blast, Pound,\n\rCrush, Pierce, or Suck.\n\r",ch);


		return;


	    }


	    if (obj->value[3] == value)


	    {


		send_to_char("It is already that weapon type.\n\r",ch);


		return;


	    }


	    obj->value[3] = value;


	    ch->pcdata->quest -= 10;


	    send_to_char("Ok.\n\r",ch);


	    if (obj->questmaker != NULL) free_string(obj->questmaker);


	    obj->questmaker = str_dup(ch->pcdata->switchname);


	}


	else


	{


	    send_to_char("That item is not a weapon.\n\r", ch);


	    return;


	}


	return;


    }





    if ( !str_cmp( arg2, "extra" ) )


    {/*


	if (IS_SET(obj->quest, QUEST_RELIC))


	{


	    send_to_char("Not on a relic.\n\r",ch);


	    return;


	}


*/	if ( arg3[0] == '\0' )


	{


	    send_to_char("Enter one of: Glow, Hum, Invis, Anti-good, Anti-evil, Anti-neutral, Loyal,\n\rSilver.\n\r",ch);


	    return;


	}


	if      ( !str_cmp( arg3, "glow"         )) {value = ITEM_GLOW; add = 1; remove = 1;}


	else if ( !str_cmp( arg3, "hum"          )) {value = ITEM_HUM; add = 1; remove = 1;}


	else if ( !str_cmp( arg3, "invis"        )) {value = ITEM_INVIS; add = 1; remove = 1;}


	else if ( !str_cmp( arg3, "anti-good"    )) {value = ITEM_ANTI_GOOD; add = 1; remove = 10;}


	else if ( !str_cmp( arg3, "anti-evil"    )) {value = ITEM_ANTI_EVIL; add = 1; remove = 10;}


	else if ( !str_cmp( arg3, "anti-neutral" )) {value = ITEM_ANTI_NEUTRAL; add = 1; remove = 10;}


	else if ( !str_cmp( arg3, "loyal"        )) {value = ITEM_LOYAL; add = 10; remove = 1;}


	else if ( !str_cmp( arg3, "silver"       )) {value = SITEM_SILVER; add = 100; remove = 0;}


	else


	{


	    send_to_char("Enter one of: Glow, Hum, Invis, Anti-good, Anti-evil, Anti-neutral, Loyal,\n\rSilver.\n\r",ch);


	    return;


	}





	if (!str_cmp( arg3, "silver" ))


	{


	    if (IS_SET(obj->spectype, SITEM_SILVER))


	    {


		send_to_char("That item is already silver.\n\r",ch);


		return;


	    }


	    else if (ch->pcdata->quest < add)


	    {


		sprintf(buf,"Sorry, you need %d quest points to set that flag.\n\r",add);


		send_to_char(buf,ch);return;


	    }


	    ch->pcdata->quest -= add;


	    SET_BIT(obj->spectype, SITEM_SILVER);


	}


	else if (IS_SET(obj->extra_flags,value))


	{


	    if (ch->pcdata->quest < remove)


	    {


		sprintf(buf,"Sorry, you need %d quest points to remove that flag.\n\r",remove);


		send_to_char(buf,ch);return;


	    }


	    ch->pcdata->quest -= remove;


	    REMOVE_BIT(obj->extra_flags, value);


	}


	else


	{


	    if (ch->pcdata->quest < add)


	    {


		sprintf(buf,"Sorry, you need %d quest points to set that flag.\n\r",add);


		send_to_char(buf,ch);return;


	    }


	    ch->pcdata->quest -= add;


	    SET_BIT(obj->extra_flags, value);


	}


	send_to_char("Ok.\n\r",ch);


    	if (obj->questmaker != NULL) free_string(obj->questmaker);


    	obj->questmaker = str_dup(ch->pcdata->switchname);


	return;


    }





    if ( !str_cmp( arg2, "wear" ) )


    {


	if (!IS_EXTRA(ch,EXTRA_TRUSTED))


	{


	    send_to_char("You are not allowed to change object wear locations.\n\r",ch);


	    return;


	}


	if (IS_SET(obj->quest, QUEST_RELIC))


	{


	    send_to_char("Not on a relic.\n\r",ch);


	    return;


	}


        if (obj->item_type == ITEM_BOOK)


	{


	    send_to_char("Not on a book.\n\r",ch);


	    return;


	}


	if ( arg3[0] == '\0' )


	{


	    send_to_char("Wear location can be from: Finger, Neck, Body, Head, Legs, Hands, Arms,\n\rAbout, Waist, Wrist, Hold, Face.\n\r",ch);


	    return;


	}


	if      ( !str_cmp( arg3, "finger" )) value = ITEM_WEAR_FINGER;


	else if ( !str_cmp( arg3, "neck"   )) value = ITEM_WEAR_NECK;


	else if ( !str_cmp( arg3, "body"   )) value = ITEM_WEAR_BODY;


	else if ( !str_cmp( arg3, "head"   )) value = ITEM_WEAR_HEAD;


	else if ( !str_cmp( arg3, "legs"   )) value = ITEM_WEAR_LEGS;


	else if ( !str_cmp( arg3, "feet"   )) value = ITEM_WEAR_FEET;


	else if ( !str_cmp( arg3, "hands"  )) value = ITEM_WEAR_HANDS;


	else if ( !str_cmp( arg3, "arms"   )) value = ITEM_WEAR_ARMS;


	else if ( !str_cmp( arg3, "about"  )) value = ITEM_WEAR_ABOUT;


	else if ( !str_cmp( arg3, "waist"  )) value = ITEM_WEAR_WAIST;


	else if ( !str_cmp( arg3, "wrist"  )) value = ITEM_WEAR_WRIST;


	else if ( !str_cmp( arg3, "hold"   )) value = ITEM_WIELD;


	else if ( !str_cmp( arg3, "face"   )) value = ITEM_WEAR_FACE;


	else {


	    send_to_char("Wear location can be from: Finger, Neck, Body, Head, Legs, Hands, Arms, 


About, Waist, Wrist, Hold, Face.\n\r",ch); return;}


	if (IS_SET(obj->wear_flags,ITEM_TAKE) ) value += 1;


	if (obj->wear_flags == value || obj->wear_flags == (value+1) )


	{


	    act("But $p is already worn in that location!",ch,obj,NULL,TO_CHAR);


	    return;


	}


	else if ( (value != ITEM_WIELD && value != (ITEM_WIELD+1) )


		&& obj->item_type == ITEM_WEAPON)


	{


	    act("You can only HOLD a weapon.",ch,obj,NULL,TO_CHAR);


	    return;


	}


	else if (ch->pcdata->quest < 20 && !(obj->pIndexData->vnum == 30037 && obj->wear_flags == 1))


	{


	    send_to_char("It costs 20 quest points to change a location.\n\r", ch);


	    return;


	}


	if (!(obj->pIndexData->vnum == 30037 && obj->wear_flags == 1)) 


	    ch->pcdata->quest -= 20;


	obj->wear_flags = value;


	send_to_char("Ok.\n\r",ch);


    	if (obj->questmaker != NULL) free_string(obj->questmaker);


    	obj->questmaker = str_dup(ch->pcdata->switchname);


	return;


    }





    if ( !str_cmp( arg2, "replacespell" ) )


    {


	int weapon = 0;


	int affect = 0;


	if (IS_SET(obj->quest, QUEST_RELIC))


	{


	    send_to_char("Not on a relic.\n\r",ch);


	    return;


	}


        if (obj->item_type == ITEM_BOOK)


	{


	    send_to_char("Not on a book.\n\r",ch);


	    return;


	}


	if ( arg3[0] == '\0' )


	{


	    send_to_char("Spell weapons: Acid, Dark, Holy, Vampiric, Flaming, Electrified, Poisonous.\n\r",ch);


	    send_to_char("Spell affects: Blind, Seeinvis, Fly, Infravision, Invis, Passdoor, Protection,\n\rSanct, Sneak, Shockshield, Fireshield, Iceshield, Acidshield.\n\r",ch);


	    return;


	}


	if      ( !str_cmp( arg3, "acid"        )) weapon = 1;


	else if ( !str_cmp( arg3, "dark"        )) weapon = 4;


	else if ( !str_cmp( arg3, "holy"        )) weapon = 30;


	else if ( !str_cmp( arg3, "vampiric"    )) weapon = 34;


	else if ( !str_cmp( arg3, "flaming"     )) weapon = 37;


	else if ( !str_cmp( arg3, "electrified" )) weapon = 48;


	else if ( !str_cmp( arg3, "poisonous"   )) weapon = 53;


	else if ( !str_cmp( arg3, "infravision" )) affect = 1;


	else if ( !str_cmp( arg3, "seeinvis"    )) affect = 2;


	else if ( !str_cmp( arg3, "fly"         )) affect = 3;


	else if ( !str_cmp( arg3, "blind"       )) affect = 4;


	else if ( !str_cmp( arg3, "invis"       )) affect = 5;


	else if ( !str_cmp( arg3, "passdoor"    )) affect = 6;


	else if ( !str_cmp( arg3, "protection"  )) affect = 7;


	else if ( !str_cmp( arg3, "sanct"       )) affect = 8;


	else if ( !str_cmp( arg3, "sneak"       )) affect = 9;


	else if ( !str_cmp( arg3, "shockshield" )) affect = 10;


	else if ( !str_cmp( arg3, "fireshield"  )) affect = 11;


	else if ( !str_cmp( arg3, "iceshield"   )) affect = 12;


	else if ( !str_cmp( arg3, "acidshield"  )) affect = 13;


	else


	{


	    send_to_char("Spell weapons: Dark, Holy, Vampiric, Flaming, Electrified, Poisonous.\n\r",ch);


	    send_to_char("Spell affects: Blind, Seeinvis, Fly, Infravision, Invis, Passdoor, Protection,\n\rSanct, Sneak, Shockshield, Fireshield, Iceshield, Acidshield.\n\r",ch);


	    return;


	}





	if (obj->item_type != ITEM_WEAPON && weapon > 0)


	{


	    send_to_char("You can only put that power on a weapon.\n\r", ch);


	    return;


	}


	else if (obj->item_type != ITEM_WEAPON && obj->item_type != ITEM_ARMOR && affect > 0)


	{


	    send_to_char("You can only put that power on a weapon or a piece of armour.\n\r", ch);


	    return;


	}


	else if (ch->pcdata->quest < 50 )


	{


	    send_to_char("It costs 50 quest points to create a spell weapon or affect.\n\r", ch);


	    return;


	}


	if (weapon > 0)


	{


	    if (obj->value[0] >= 1000)


		obj->value[0] = ((obj->value[0] / 1000) * 1000);


	    else obj->value[0] = 0;


	    obj->value[0] += weapon;


	}


	else if (affect > 0)


	{


	    if (obj->item_type == ITEM_WEAPON)


	    {


	    	if (obj->value[0] >= 1000)


		    obj->value[0] -= ((obj->value[0] / 1000) * 1000);


	    	obj->value[0] += (affect*1000);


	    }


	    else if (obj->item_type == ITEM_ARMOR)


	    	obj->value[3] = affect;


	}


	ch->pcdata->quest -= 50;


	send_to_char("Ok.\n\r",ch);


    	if (obj->questmaker != NULL) free_string(obj->questmaker);


    	obj->questmaker = str_dup(ch->pcdata->switchname);


	return;


    }





    if ( !str_cmp( arg2, "spell" ) )


    {


	int weapon = 0;


	int affect = 0;


	if (IS_SET(obj->quest, QUEST_RELIC) && !IS_SET(obj->spectype,SITEM_DEMONIC))


	{


	    send_to_char("Not on a relic.\n\r",ch);


	    return;


	}


        if (obj->item_type == ITEM_BOOK)


	{


	    send_to_char("Not on a book.\n\r",ch);


	    return;


	}


	if ( arg3[0] == '\0' )


	{


	    send_to_char("Spell weapons: Acid, Dark, Holy, Vampiric, Flaming, Electrified, Poisonous.\n\r",ch);


	    send_to_char("Spell affects: Blind, Seeinvis, Fly, Infravision, Invis, Passdoor, Protection,\n\rSanct, Sneak, Shockshield, Fireshield, Iceshield, Acidshield.\n\r",ch);


	    return;


	}


	if      ( !str_cmp( arg3, "acid"        )) weapon = 1;


	else if ( !str_cmp( arg3, "dark"        )) weapon = 4;


	else if ( !str_cmp( arg3, "holy"        )) weapon = 30;


	else if ( !str_cmp( arg3, "vampiric"    )) weapon = 34;


	else if ( !str_cmp( arg3, "flaming"     )) weapon = 37;


	else if ( !str_cmp( arg3, "electrified" )) weapon = 48;


	else if ( !str_cmp( arg3, "poisonous"   )) weapon = 53;


	else if ( !str_cmp( arg3, "infravision" )) affect = 1;


	else if ( !str_cmp( arg3, "seeinvis"    )) affect = 2;


	else if ( !str_cmp( arg3, "fly"         )) affect = 3;


	else if ( !str_cmp( arg3, "blind"       )) affect = 4;


	else if ( !str_cmp( arg3, "invis"       )) affect = 5;


	else if ( !str_cmp( arg3, "passdoor"    )) affect = 6;


	else if ( !str_cmp( arg3, "protection"  )) affect = 7;


	else if ( !str_cmp( arg3, "sanct"       )) affect = 8;


	else if ( !str_cmp( arg3, "sneak"       )) affect = 9;


	else if ( !str_cmp( arg3, "shockshield" )) affect = 10;


	else if ( !str_cmp( arg3, "fireshield"  )) affect = 11;


	else if ( !str_cmp( arg3, "iceshield"   )) affect = 12;


	else if ( !str_cmp( arg3, "acidshield"  )) affect = 13;


	else


	{


	    send_to_char("Spell weapons: Dark, Holy, Vampiric, Flaming, Electrified, Poisonous.\n\r",ch);


	    send_to_char("Spell affects: Blind, Seeinvis, Fly, Infravision, Invis, Passdoor, Protection,\n\rSanct, Sneak, Shockshield, Fireshield, Iceshield, Acidshield.\n\r",ch);


	    return;


	}





	if (obj->item_type != ITEM_WEAPON && weapon > 0)


	{


	    send_to_char("You can only put that power on a weapon.\n\r", ch);


	    return;


	}


	else if (obj->item_type != ITEM_WEAPON && obj->item_type != ITEM_ARMOR && affect > 0)


	{


	    send_to_char("You can only put that power on a weapon or a piece of armour.\n\r", ch);


	    return;


	}


	else if (ch->pcdata->quest < 50 )


	{


	    send_to_char("It costs 50 quest points to create a spell weapon or affect.\n\r", ch);


	    return;


	}


	if (weapon > 0)


	{


	    if ( obj->value[0] - ((obj->value[0] / 1000) * 1000) != 0 )


	    {


		send_to_char("That item already has a spell weapon power.  If you wish to replace the \n\rcurrent spell power, use the format: quest <object> replacespell <spell>.\n\r",ch);


		return;


	    }


	    if (obj->value[0] >= 1000)


		obj->value[0] = ((obj->value[0] / 1000) * 1000);


	    else obj->value[0] = 0;


	    obj->value[0] += weapon;


	}


	else if (affect > 0)


	{


	    if (obj->item_type == ITEM_WEAPON)


	    {


	    	if ( obj->value[0] >= 1000 )


	    	{


		    send_to_char("That item already has a spell affect power.  If you wish to replace the \n\rcurrent spell power, use the format: quest <object> replacespell <spell>.\n\r",ch);


		    return;


	    	}


	    	if (obj->value[0] >= 1000)


		    obj->value[0] -= ((obj->value[0] / 1000) * 1000);


	    	obj->value[0] += (affect*1000);


	    }


	    else if (obj->item_type == ITEM_ARMOR)


	    {


	    	if ( obj->value[3] > 0 )


	    	{


		    send_to_char("That item already has a spell affect power.  If you wish to replace the \n\rcurrent spell power, use the format: quest <object> replacespell <spell>.\n\r",ch);


		    return;


	    	}


	    	obj->value[3] = affect;


	    }


	}


	ch->pcdata->quest -= 50;


	send_to_char("Ok.\n\r",ch);


    	if (obj->questmaker != NULL) free_string(obj->questmaker);


    	obj->questmaker = str_dup(ch->pcdata->switchname);


	return;


    }





    if ( !str_cmp( arg2, "power" ) )


    {


	if ( arg3[0] == '\0' )


	{


	    send_to_char("Please specify the amount of power.\n\r",ch);


	    return;


	}


	if (obj->item_type != ITEM_WEAPON)


	{


	    send_to_char("Only weapons have a spell power.\n\r",ch);


	    return;


	}


	else if (obj->level >= 50)


	{


	    send_to_char("This weapon can hold no more spell power.\n\r",ch);


	    return;


	}


	else if (value + obj->level > 50)


	{


	    sprintf(buf,"You can only add %d more spell power to this weapon.\n\r",(50 - obj->level));


	    send_to_char(buf,ch);


	    return;


	}


	else if (value > ch->pcdata->quest)


	{


	    send_to_char("You don't have enough quest points to increase the spell power.\n\r",ch);


	    return;


	}


	obj->level += value;


	if (obj->level < 0) obj->level = 0;


	if (value < 1) value = 1;


	ch->pcdata->quest -= value;


	send_to_char("Ok.\n\r",ch);


	if (obj->questmaker != NULL) free_string(obj->questmaker);


	obj->questmaker = str_dup(ch->pcdata->switchname);


	return;


    }


	


    if ( !str_cmp( arg2, "weight" ) )


    {


	if (obj->weight < 2)


	{


	    send_to_char("You cannot reduce the weight of this item any further.\n\r",ch);


	    return;


	}


	else if (ch->pcdata->quest < 10)


	{


	    send_to_char("It costs 10 quest point to remove the weight of an object.\n\r",ch);


	    return;


	}


	obj->weight = 1;


	ch->pcdata->quest -= 10;


	send_to_char("Ok.\n\r",ch);


    	if (obj->questmaker != NULL) free_string(obj->questmaker);


    	obj->questmaker = str_dup(ch->pcdata->switchname);


	return;


    }





    if ( !str_cmp( arg2, "transporter" ) )


    {


	if (IS_SET(obj->quest, QUEST_RELIC))


	{


	    send_to_char("Not on a relic.\n\r",ch);


	    return;


	}


        if (obj->item_type == ITEM_BOOK)


	{


	    send_to_char("Not on a book.\n\r",ch);


	    return;


	}


    	if (IS_SET(obj->spectype, SITEM_TELEPORTER))


	{ send_to_char("This item is already a transporter.\n\r",ch);


	  return;}


    	else if (IS_SET(obj->spectype, SITEM_TRANSPORTER))


	{ send_to_char("This item is already a teleporter.\n\r",ch);


	  return;}


    	else if (IS_SET(obj->spectype, SITEM_SPELL))


	{ send_to_char("This item is already a spell caster.\n\r",ch);


	  return;}


    	else if (IS_SET(obj->spectype, SITEM_OBJECT))


	{ send_to_char("This item is already an object creator.\n\r",ch);


	  return;}


    	else if (IS_SET(obj->spectype, SITEM_MOBILE))


	{ send_to_char("This item is already a creature creator.\n\r",ch);


	  return;}


    	else if (IS_SET(obj->spectype, SITEM_ACTION))


	{ send_to_char("This item is already a commanding device.\n\r",ch);


	  return;}


	else if (ch->pcdata->quest < 50)


	{


	    send_to_char("It costs 50 quest point to create a transporter.\n\r",ch);


	    return;


	}


	SET_BIT(obj->spectype, SITEM_ACTIVATE);


	SET_BIT(obj->spectype, SITEM_TELEPORTER);


	obj->specpower = ch->in_room->vnum;


	ch->pcdata->quest -= 50;


	send_to_char("Ok.\n\r",ch);


    	if (obj->questmaker != NULL) free_string(obj->questmaker);


    	obj->questmaker = str_dup(ch->pcdata->switchname);


    	if (obj->chpoweron != NULL) free_string(obj->chpoweron);


    	obj->chpoweron = str_dup("You transform into a fine mist and seep into the ground.");


    	if (obj->victpoweron != NULL) free_string(obj->victpoweron);


    	obj->victpoweron = str_dup("$n transforms into a fine mist and seeps into the ground.");


    	if (obj->chpoweroff != NULL) free_string(obj->chpoweroff);


    	obj->chpoweroff = str_dup("You seep up from the ground and reform your body.");


    	if (obj->victpoweroff != NULL) free_string(obj->victpoweroff);


    	obj->victpoweroff = str_dup("A fine mist seeps up from the ground and reforms into $n.");


    	if (obj->chpoweruse != NULL) free_string(obj->chpoweruse);


    	obj->chpoweruse = str_dup("You activate $p.");


    	if (obj->victpoweruse != NULL) free_string(obj->victpoweruse);


    	obj->victpoweruse = str_dup("$n activates $p.");


	return;


    }





    if ( !str_cmp( arg2, "retransporter" ) )


    {


	if (IS_SET(obj->quest, QUEST_RELIC))


	{


	    send_to_char("Not on a relic.\n\r",ch);


	    return;


	}


        if (obj->item_type == ITEM_BOOK)


	{


	    send_to_char("Not on a book.\n\r",ch);


	    return;


	}


    	if (!IS_SET(obj->spectype, SITEM_TELEPORTER))


	{ send_to_char("This item is not a transporter.\n\r",ch);


	  return;}


    	else if (IS_SET(obj->spectype, SITEM_TRANSPORTER))


	{ send_to_char("This item is already a teleporter.\n\r",ch);


	  return;}


    	else if (IS_SET(obj->spectype, SITEM_SPELL))


	{ send_to_char("This item is already a spell caster.\n\r",ch);


	  return;}


    	else if (IS_SET(obj->spectype, SITEM_OBJECT))


	{ send_to_char("This item is already an object creator.\n\r",ch);


	  return;}


    	else if (IS_SET(obj->spectype, SITEM_MOBILE))


	{ send_to_char("This item is already a creature creator.\n\r",ch);


	  return;}


    	else if (IS_SET(obj->spectype, SITEM_ACTION))


	{ send_to_char("This item is already a commanding device.\n\r",ch);


	  return;}


	else if (ch->pcdata->quest < 50)


	{


	    send_to_char("It costs 50 quest point to create a transporter.\n\r",ch);


	    return;


	}


	SET_BIT(obj->spectype, SITEM_ACTIVATE);


	SET_BIT(obj->spectype, SITEM_TELEPORTER);


	obj->specpower = ch->in_room->vnum;


	ch->pcdata->quest -= 50;


	send_to_char("Ok.\n\r",ch);


    	if (obj->questmaker != NULL) free_string(obj->questmaker);


    	obj->questmaker = str_dup(ch->pcdata->switchname);


	return;


    }


/*


    if ( !str_cmp( arg2, "clone" ) )


    {


	if (IS_SET(obj->quest, QUEST_RELIC))


	{


	    send_to_char("Not on a relic.\n\r",ch);


	    return;


	}


        if (obj->item_type == ITEM_BOOK)


	{


	    send_to_char("Not on a book.\n\r",ch);


	    return;


	}


	value = obj->points;


	if (value < 5 || obj->item_type == ITEM_PAGE) value = 5;


	if (obj->item_type == ITEM_QUEST || obj->item_type == ITEM_QUESTCARD)


	{


	    send_to_char("I think not...\n\r",ch);


	    return;


	}


	else if (obj->questowner == NULL || str_cmp(obj->questowner,ch->pcdata->switchname))


	{


	    send_to_char("You can only clone something you own.\n\r",ch);


	    return;


	}


	else if (ch->pcdata->quest < value)


	{


	    sprintf(buf,"It will cost you %d quest points to clone %s.\n\r",


		value,obj->short_descr);


	    send_to_char(buf,ch);


	    return;


	}


	ch->pcdata->quest -= value;


	quest_clone(ch,obj);


	return;


    }


*/


    if ( arg3[0] == '\0' )


    {


	send_to_char( "- - - - - - - - - - ----====[ QUEST ITEM COSTS ]====---- - - - - - - - - - -\n\r",	 ch );


	send_to_char( "Create: Creates a new personalized object, costing between 10 and 50 QP.\n\r",ch );


	send_to_char( "Name/Short/Long: Rename the object.  1 QP for all three.\n\r",ch );


	send_to_char( "Protection: Sets AC on armour at 1 QP per point.\n\r", ch );


	send_to_char( "Min/Max: Sets min/max damage on weapon at 1 QP per point.\n\r", ch );


	send_to_char( "Weapon: Sets weapon type for 10 QP.\n\r", ch );


	send_to_char( "Extra (add/remove): Glow(1/1), Hum(1/1), Invis(1/1), Anti-Good(1/10),\n\r                    Anti-Neutral(1/10), Anti-Evil(1/10), Loyal(10/1).\n\r",ch );


	send_to_char( "Wear: Select location, costs 20 QP's.  Type 'quest <obj> wear' to see locations.\n\r",ch );


	send_to_char( "Power: Spell power for spell weapons.  Costs 1 QP per power point.\n\r",ch );


	send_to_char( "Spell: Spell weapons or affect.  Costs 50 QP.\n\r",ch );


	send_to_char( "Transporter: Future transportation to that room.  Costs 50 QP.\n\r",ch );


	send_to_char( "Special: Set activate/twist/press/pull flags.\n\r",ch );


	send_to_char( "You-in/You-out/Other-in/Other-out: Renames for transporter actions.\n\r",ch );


	send_to_char( "You-wear/You-remove/You-use: What you see when you wear/remove/use.\n\r",ch );


	send_to_char( "Other-wear/Other-remove/Other-use: What others see when you wear/remove/use.\n\r",ch );


	send_to_char( "Weight: Set objects weight to 1.  Costs 10 QP.\n\r",ch );


	send_to_char( "Str, Dex, Int, Wis, Con... max =   3 each, at  20 quest points per +1 stat.\n\r", ch);


	send_to_char( "Hp, Mana, Move............ max =  25 each, at   5 quest points per point.\n\r", ch);


	send_to_char( "Hitroll, Damroll.......... max =   5 each, at  30 quest points per point.\n\r", ch);


	send_to_char( "Ac........................ max = -25,      at  10 points per point.\n\r", ch);


	send_to_char( "- - - - - - - - - - ----====[ QUEST ITEM COSTS ]====---- - - - - - - - - - -\n\r",	 ch );


	return;


    }





    if (obj->item_type != ITEM_BOOK)


    {


    	if      ( !str_cmp( arg2, "hitroll" ) || !str_cmp( arg2, "hit" ) )


	    {oset_affect(ch,obj,value,APPLY_HITROLL,TRUE);return;}


    	else if ( !str_cmp( arg2, "damroll" ) || !str_cmp( arg2, "dam" ) )


	    {oset_affect(ch,obj,value,APPLY_DAMROLL,TRUE);return;}


    	else if ( !str_cmp( arg2, "armor" ) || !str_cmp( arg2, "ac" ) )


	    {oset_affect(ch,obj,value,APPLY_AC,TRUE);return;}


    	else if ( !str_cmp( arg2, "hitpoints" ) || !str_cmp( arg2, "hp" ) )


	    {oset_affect(ch,obj,value,APPLY_HIT,TRUE);return;}


    	else if ( !str_cmp( arg2, "mana" ) )


	    {oset_affect(ch,obj,value,APPLY_MANA,TRUE);return;}


    	else if ( !str_cmp( arg2, "move" ) || !str_cmp( arg2, "movement" ) )


	    {oset_affect(ch,obj,value,APPLY_MOVE,TRUE);return;}


    	else if ( !str_cmp( arg2, "str" ) || !str_cmp( arg2, "strength" ) )


	    {oset_affect(ch,obj,value,APPLY_STR,TRUE);return;}


    	else if ( !str_cmp( arg2, "dex" ) || !str_cmp( arg2, "dexterity" ) )


	    {oset_affect(ch,obj,value,APPLY_DEX,TRUE);return;}


    	else if ( !str_cmp( arg2, "int" ) || !str_cmp( arg2, "intelligence" ) )


	    {oset_affect(ch,obj,value,APPLY_INT,TRUE);return;}


    	else if ( !str_cmp( arg2, "wis" ) || !str_cmp( arg2, "wisdom" ) )


	    {oset_affect(ch,obj,value,APPLY_WIS,TRUE);return;}


    	else if ( !str_cmp( arg2, "con" ) || !str_cmp( arg2, "constitution" ) )


	    {oset_affect(ch,obj,value,APPLY_CON,TRUE);return;}


    }





    if ( !str_cmp( arg2, "name" ) )


    {


	value = 1;


	if (!IS_EXTRA(ch,EXTRA_TRUSTED))


	{


	    send_to_char("You are not allowed to rename objects.\n\r",ch);


	    return;


	}


	if (IS_SET(obj->quest, QUEST_RELIC))


	{


	    send_to_char("Not on a relic.\n\r",ch);


	    return;


	}


	if (!IS_SET(obj->quest,QUEST_NAME) && 


	    (IS_SET(obj->quest,QUEST_SHORT) || IS_SET(obj->quest,QUEST_LONG)))


	{


	    SET_BIT(obj->quest,QUEST_NAME);


	    value = 0;


	}


	else if (IS_SET(obj->quest,QUEST_NAME))


	{


	    REMOVE_BIT(obj->quest,QUEST_SHORT);


	    REMOVE_BIT(obj->quest,QUEST_LONG);


	}


	else


	    SET_BIT(obj->quest,QUEST_NAME);


	if (IS_SET(obj->quest,QUEST_FREENAME))


	{


	    value = 0;


	    REMOVE_BIT(obj->quest,QUEST_FREENAME);


	}


	if (ch->pcdata->quest < value)


	{


	    send_to_char("It costs 1 quest point to rename an object.\n\r",ch);


	    return;


	}


	if (strlen(arg3) < 3)


	{


	    send_to_char("Name should be at least 3 characters long.\n\r",ch);


	    return;


	}


	ch->pcdata->quest -= value;


	strcpy(arg3,capitalize(arg3));


	arg3[0] = LOWER(arg3[0]);


	endchar[0] = (arg3[strlen(arg3)-1]);


	endchar[1] = '\0';


	if (!str_cmp(endchar,".")) arg3[strlen(arg3)-1] = '\0';


	free_string( obj->name );


	obj->name = str_dup( arg3 );


	send_to_char("Ok.\n\r",ch);


    	if (obj->questmaker != NULL) free_string(obj->questmaker);


    	obj->questmaker = str_dup(ch->name);


	return;


    }





    if ( !str_cmp( arg2, "short" ) )


    {


	value = 1;


	if (!IS_EXTRA(ch,EXTRA_TRUSTED))


	{


	    send_to_char("You are not allowed to rename objects.\n\r",ch);


	    return;


	}


	if (IS_SET(obj->quest, QUEST_RELIC))


	{


	    send_to_char("Not on a relic.\n\r",ch);


	    return;


	}


	if (!IS_SET(obj->quest,QUEST_SHORT) && 


	    (IS_SET(obj->quest,QUEST_NAME) || IS_SET(obj->quest,QUEST_LONG)))


	{


	    SET_BIT(obj->quest,QUEST_SHORT);


	    value = 0;


	}


	else if (IS_SET(obj->quest,QUEST_SHORT))


	{


	    REMOVE_BIT(obj->quest,QUEST_NAME);


	    REMOVE_BIT(obj->quest,QUEST_LONG);


	}


	else


	    SET_BIT(obj->quest,QUEST_SHORT);


	if (IS_SET(obj->quest,QUEST_FREENAME))


	{


	    value = 0;


	    REMOVE_BIT(obj->quest,QUEST_FREENAME);


	}


	if (ch->pcdata->quest < value)


	{


	    send_to_char("It costs 1 quest point to rename an object.\n\r",ch);


	    return;


	}


	if (strlen(arg3) < 3)


	{


	    send_to_char("Name should be at least 3 characters long.\n\r",ch);


	    return;


	}


	ch->pcdata->quest -= value;


/*


	arg3[0] = LOWER(arg3[0]);


*/


	endchar[0] = (arg3[strlen(arg3)-1]);


	endchar[1] = '\0';


	if (!str_cmp(endchar,".")) arg3[strlen(arg3)-1] = '\0';


	free_string( obj->short_descr );


	obj->short_descr = str_dup( arg3 );


	send_to_char("Ok.\n\r",ch);


    	if (obj->questmaker != NULL) free_string(obj->questmaker);


    	obj->questmaker = str_dup(ch->name);


	return;


    }





    if ( !str_cmp( arg2, "long" ) )


    {


	value = 1;


	if (!IS_EXTRA(ch,EXTRA_TRUSTED))


	{


	    send_to_char("You are not allowed to rename objects.\n\r",ch);


	    return;


	}


	if (IS_SET(obj->quest, QUEST_RELIC))


	{


	    send_to_char("Not on a relic.\n\r",ch);


	    return;


	}


	if (!IS_SET(obj->quest,QUEST_LONG) && 


	    (IS_SET(obj->quest,QUEST_NAME) || IS_SET(obj->quest,QUEST_SHORT)))


	{


	    SET_BIT(obj->quest,QUEST_LONG);


	    value = 0;


	}


	else if (IS_SET(obj->quest,QUEST_LONG))


	{


	    REMOVE_BIT(obj->quest,QUEST_NAME);


	    REMOVE_BIT(obj->quest,QUEST_SHORT);


	}


	else


	    SET_BIT(obj->quest,QUEST_LONG);


	if (IS_SET(obj->quest,QUEST_FREENAME))


	{


	    value = 0;


	    REMOVE_BIT(obj->quest,QUEST_FREENAME);


	}


	if (ch->pcdata->quest < value)


	{


	    send_to_char("It costs 1 quest point to rename an object.\n\r",ch);


	    return;


	}


	if (strlen(arg3) < 3)


	{


	    send_to_char("Name should be at least 3 characters long.\n\r",ch);


	    return;


	}


	ch->pcdata->quest -= value;


	arg3[0] = UPPER(arg3[0]);


	endchar[0] = (arg3[strlen(arg3)-1]);


	endchar[1] = '\0';


	if (str_cmp(endchar,".")) strcat(arg3,".");


	free_string( obj->description );


	obj->description = str_dup( arg3 );


	send_to_char("Ok.\n\r",ch);


    	if (obj->questmaker != NULL) free_string(obj->questmaker);


    	obj->questmaker = str_dup(ch->name);


	return;


    }





    if ( !str_cmp( arg2, "ed" ) )


    {


	EXTRA_DESCR_DATA *ed;





	argument = one_argument( argument, arg3 );


	if (!IS_EXTRA(ch,EXTRA_TRUSTED))


	{


	    send_to_char("You are not allowed to rename objects.\n\r",ch);


	    return;


	}


	if (IS_SET(obj->quest, QUEST_RELIC))


	{


	    send_to_char("Not on a relic.\n\r",ch);


	    return;


	}


	if ( argument == NULL )


	{


	    send_to_char( "Syntax: quest <object> ed <keyword> <string>\n\r",


		ch );


	    return;


	}





	if ( extra_descr_free == NULL )


	{


	    ed			= alloc_perm( sizeof(*ed) );


	}


	else


	{


	    ed			= extra_descr_free;


	    extra_descr_free	= ed;


	}





	strcpy(buf, argument);


	strcat(buf, "\n\r");


	buf[0] = UPPER(buf[0]);





	ed->keyword		= str_dup( arg3 );


	ed->description		= str_dup( buf  );


	ed->next		= obj->extra_descr;


	obj->extra_descr	= ed;


	send_to_char("Ok.\n\r",ch);


    	if (obj->questmaker != NULL) free_string(obj->questmaker);


    	obj->questmaker = str_dup(ch->name);


	return;


    }





    if (!str_cmp(arg2,"special"))


    {


	if (!IS_EXTRA(ch,EXTRA_TRUSTED))


	{


	    send_to_char("You are not permitted to change an object in this way.\n\r",ch);


	    return;


	}


	if (IS_SET(obj->quest, QUEST_RELIC))


	{


	    send_to_char("Not on a relic.\n\r",ch);


	    return;


	}


	if (obj->item_type == ITEM_BOOK)


	{


	    send_to_char("Not on a book.\n\r",ch);


	    return;


	}


	if (arg3[0] == '\0')


	{


	    send_to_char("Please enter ACTIVATE, TWIST, PRESS or PULL.\n\r",ch);


	    return;


	}


	if (str_cmp(arg3,"activate") && str_cmp(arg3,"twist") &&


	    str_cmp(arg3,"press"   ) && str_cmp(arg3,"pull" ))


	{


	    send_to_char("Please enter ACTIVATE, TWIST, PRESS or PULL.\n\r",ch);


	    return;


	}


	if (IS_SET(obj->spectype, SITEM_ACTIVATE))


	    REMOVE_BIT(obj->spectype, SITEM_ACTIVATE);


	if (IS_SET(obj->spectype, SITEM_TWIST))


	    REMOVE_BIT(obj->spectype, SITEM_TWIST);


	if (IS_SET(obj->spectype, SITEM_PRESS))


	    REMOVE_BIT(obj->spectype, SITEM_PRESS);


	if (IS_SET(obj->spectype, SITEM_PULL))


	    REMOVE_BIT(obj->spectype, SITEM_PULL);


	if (!str_cmp(arg3,"activate")) SET_BIT(obj->spectype, SITEM_ACTIVATE);


	if (!str_cmp(arg3,"twist"   )) SET_BIT(obj->spectype, SITEM_TWIST);


	if (!str_cmp(arg3,"press"   )) SET_BIT(obj->spectype, SITEM_PRESS);


	if (!str_cmp(arg3,"pull"    )) SET_BIT(obj->spectype, SITEM_PULL);


	arg3[0] = UPPER(arg3[0]);


	sprintf(buf,"%s flag set.\n\r",arg3);


	send_to_char(buf,ch);


	return;


    }





    if (!str_cmp(arg2,"you-out") || !str_cmp(arg2,"you-wear"))


    {


	if (!IS_EXTRA(ch,EXTRA_TRUSTED))


	{


	    send_to_char("You are not permitted to change an object in this way.\n\r",ch);


	    return;


	}


	if (IS_SET(obj->quest, QUEST_RELIC))


	{


	    send_to_char("Not on a relic.\n\r",ch);


	    return;


	}


	if (obj->item_type == ITEM_BOOK)


	{


	    send_to_char("Not on a book.\n\r",ch);


	    return;


	}


    	if (!str_cmp(arg2,"you-out") && !IS_SET(obj->spectype, SITEM_TELEPORTER))


	{


	    send_to_char("That item is not a transporter.\n\r",ch);


	    return;


	}


    	if (!str_cmp(arg2,"you-wear") && IS_SET(obj->spectype, SITEM_TELEPORTER))


	{


	    send_to_char("Not on a transporter.\n\r",ch);


	    return;


	}


	if (obj->chpoweron != NULL) strcpy(buf,obj->chpoweron);


	else {send_to_char("There is a problem with this item, please inform an implementor.\n\r",ch);return;}


	if (!str_cmp(arg3,"clear"))


	{


	    free_string( obj->chpoweron );


	    obj->chpoweron = str_dup( "(null)" );


	}


	else if (obj->chpoweron != NULL && buf[0] != '\0' && str_cmp(buf,"(null)"))


	{


	    if (strlen(buf)+strlen(arg3) >= MAX_STRING_LENGTH-4)


	    {


		send_to_char("Line too long.\n\r",ch);


		return;


	    }


	    else


	    {


	    	free_string( obj->chpoweron );


	    	strcat( buf, "\n\r" );


	    	strcat( buf, arg3 );


	    	obj->chpoweron = str_dup( buf );


	    }


	}


	else


	{


	    free_string( obj->chpoweron );


	    obj->chpoweron = str_dup( arg3 );


	}


	send_to_char("Ok.\n\r",ch);


    }


    else if (!str_cmp(arg2,"other-out") || !str_cmp(arg2,"other-wear") )


    {


	if (!IS_EXTRA(ch,EXTRA_TRUSTED))


	{


	    send_to_char("You are not permitted to change an object in this way.\n\r",ch);


	    return;


	}


	if (IS_SET(obj->quest, QUEST_RELIC))


	{


	    send_to_char("Not on a relic.\n\r",ch);


	    return;


	}


	if (obj->item_type == ITEM_BOOK)


	{


	    send_to_char("Not on a book.\n\r",ch);


	    return;


	}


    	if (!str_cmp(arg2,"other-out") && !IS_SET(obj->spectype, SITEM_TELEPORTER))


	{


	    send_to_char("That item is not a transporter.\n\r",ch);


	    return;


	}


    	if (!str_cmp(arg2,"other-wear") && IS_SET(obj->spectype, SITEM_TELEPORTER))


	{


	    send_to_char("Not on a transporter.\n\r",ch);


	    return;


	}


	if (obj->victpoweron != NULL) strcpy(buf,obj->victpoweron);


	else {send_to_char("There is a problem with this item, please inform an implementor.\n\r",ch);return;}


	if (!str_cmp(arg3,"clear"))


	{


	    free_string( obj->victpoweron );


	    obj->victpoweron = str_dup( "(null)" );


	}


	else if (obj->victpoweron != NULL && buf[0] != '\0' && str_cmp(buf,"(null)"))


	{


	    if (strlen(buf)+strlen(arg3) >= MAX_STRING_LENGTH-4)


	    {


		send_to_char("Line too long.\n\r",ch);


		return;


	    }


	    else


	    {


	    	free_string( obj->victpoweron );


	    	strcat( buf, "\n\r" );


	    	strcat( buf, arg3 );


	    	obj->victpoweron = str_dup( buf );


	    }


	}


	else


	{


	    free_string( obj->victpoweron );


	    obj->victpoweron = str_dup( arg3 );


	}


	send_to_char("Ok.\n\r",ch);


    }


    else if (!str_cmp(arg2,"you-in") || !str_cmp(arg2,"you-remove") )


    {


	if (!IS_EXTRA(ch,EXTRA_TRUSTED))


	{


	    send_to_char("You are not permitted to change an object in this way.\n\r",ch);


	    return;


	}


	if (IS_SET(obj->quest, QUEST_RELIC))


	{


	    send_to_char("Not on a relic.\n\r",ch);


	    return;


	}


	if (obj->item_type == ITEM_BOOK)


	{


	    send_to_char("Not on a book.\n\r",ch);


	    return;


	}


    	if (!str_cmp(arg2,"you-in") && !IS_SET(obj->spectype, SITEM_TELEPORTER))


	{


	    send_to_char("That item is not a transporter.\n\r",ch);


	    return;


	}


    	if (!str_cmp(arg2,"you-remove") && IS_SET(obj->spectype, SITEM_TELEPORTER))


	{


	    send_to_char("Not on a transporter.\n\r",ch);


	    return;


	}


	if (obj->chpoweroff != NULL) strcpy(buf,obj->chpoweroff);


	else {send_to_char("There is a problem with this item, please inform an implementor.\n\r",ch);return;}


	if (!str_cmp(arg3,"clear"))


	{


	    free_string( obj->chpoweroff );


	    obj->chpoweroff = str_dup( "(null)" );


	}


	else if (obj->chpoweroff != NULL && buf[0] != '\0' && str_cmp(buf,"(null)"))


	{


	    if (strlen(buf)+strlen(arg3) >= MAX_STRING_LENGTH-4)


	    {


		send_to_char("Line too long.\n\r",ch);


		return;


	    }


	    else


	    {


	    	free_string( obj->chpoweroff );


	    	strcat( buf, "\n\r" );


	    	strcat( buf, arg3 );


	    	obj->chpoweroff = str_dup( buf );


	    }


	}


	else


	{


	    free_string( obj->chpoweroff );


	    obj->chpoweroff = str_dup( arg3 );


	}


	send_to_char("Ok.\n\r",ch);


    }


    else if (!str_cmp(arg2,"other-in") || !str_cmp(arg2,"other-remove") )


    {


	if (!IS_EXTRA(ch,EXTRA_TRUSTED))


	{


	    send_to_char("You are not permitted to change an object in this way.\n\r",ch);


	    return;


	}


	if (IS_SET(obj->quest, QUEST_RELIC))


	{


	    send_to_char("Not on a relic.\n\r",ch);


	    return;


	}


	if (obj->item_type == ITEM_BOOK)


	{


	    send_to_char("Not on a book.\n\r",ch);


	    return;


	}


    	if (!str_cmp(arg2,"other-in") && !IS_SET(obj->spectype, SITEM_TELEPORTER))


	{


	    send_to_char("That item is not a transporter.\n\r",ch);


	    return;


	}


    	if (!str_cmp(arg2,"other-remove") && IS_SET(obj->spectype, SITEM_TELEPORTER))


	{


	    send_to_char("Not on a transporter.\n\r",ch);


	    return;


	}


	if (obj->victpoweroff != NULL) strcpy(buf,obj->victpoweroff);


	else {send_to_char("There is a problem with this item, please inform an implementor.\n\r",ch);return;}


	if (!str_cmp(arg3,"clear"))


	{


	    free_string( obj->victpoweroff );


	    obj->victpoweroff = str_dup( "(null)" );


	}


	else if (obj->victpoweroff != NULL && buf[0] != '\0' && str_cmp(buf,"(null)"))


	{


	    if (strlen(buf)+strlen(arg3) >= MAX_STRING_LENGTH-4)


	    {


		send_to_char("Line too long.\n\r",ch);


		return;


	    }


	    else


	    {


	    	free_string( obj->victpoweroff );


	    	strcat( buf, "\n\r" );


	    	strcat( buf, arg3 );


	    	obj->victpoweroff = str_dup( buf );


	    }


	}


	else


	{


	    free_string( obj->victpoweroff );


	    obj->victpoweroff = str_dup( arg3 );


	}


	send_to_char("Ok.\n\r",ch);


    }


    else if (!str_cmp(arg2,"you-use") )


    {


	if (!IS_EXTRA(ch,EXTRA_TRUSTED))


	{


	    send_to_char("You are not permitted to change an object in this way.\n\r",ch);


	    return;


	}


	if (IS_SET(obj->quest, QUEST_RELIC))


	{


	    send_to_char("Not on a relic.\n\r",ch);


	    return;


	}


	if (obj->item_type == ITEM_BOOK)


	{


	    send_to_char("Not on a book.\n\r",ch);


	    return;


	}


	if (obj->chpoweruse != NULL) strcpy(buf,obj->chpoweruse);


	else {send_to_char("There is a problem with this item, please inform an implementor.\n\r",ch);return;}


	if (!str_cmp(arg3,"clear"))


	{


	    free_string( obj->chpoweruse );


	    obj->chpoweruse = str_dup( "(null)" );


	}


	else if (obj->chpoweruse != NULL && buf[0] != '\0' && str_cmp(buf,"(null)"))


	{


	    if (strlen(buf)+strlen(arg3) >= MAX_STRING_LENGTH-4)


	    {


		send_to_char("Line too long.\n\r",ch);


		return;


	    }


	    else


	    {


	    	free_string( obj->chpoweruse );


	    	strcat( buf, "\n\r" );


	    	strcat( buf, arg3 );


	    	obj->chpoweruse = str_dup( buf );


	    }


	}


	else


	{


	    free_string( obj->chpoweruse );


	    obj->chpoweruse = str_dup( arg3 );


	}


	send_to_char("Ok.\n\r",ch);


    }


    else if (!str_cmp(arg2,"other-use") )


    {


	if (!IS_EXTRA(ch,EXTRA_TRUSTED))


	{


	    send_to_char("You are not permitted to change an object in this way.\n\r",ch);


	    return;


	}


	if (IS_SET(obj->quest, QUEST_RELIC))


	{


	    send_to_char("Not on a relic.\n\r",ch);


	    return;


	}


	if (obj->item_type == ITEM_BOOK)


	{


	    send_to_char("Not on a book.\n\r",ch);


	    return;


	}


	if (obj->victpoweruse != NULL) strcpy(buf,obj->victpoweruse);


	else {send_to_char("There is a problem with this item, please inform an implementor.\n\r",ch);return;}


	if (!str_cmp(arg3,"clear"))


	{


	    free_string( obj->victpoweruse );


	    obj->victpoweruse = str_dup( "(null)" );


	}


	else if (obj->victpoweruse != NULL && buf[0] != '\0' && str_cmp(buf,"(null)"))


	{


	    if (strlen(buf)+strlen(arg3) >= MAX_STRING_LENGTH-4)


	    {


		send_to_char("Line too long.\n\r",ch);


		return;


	    }


	    else


	    {


	    	free_string( obj->victpoweruse );


	    	strcat( buf, "\n\r" );


	    	strcat( buf, arg3 );


	    	obj->victpoweruse = str_dup( buf );


	    }


	}


	else


	{


	    free_string( obj->victpoweruse );


	    obj->victpoweruse = str_dup( arg3 );


	}


	send_to_char("Ok.\n\r",ch);


    }


    return;


}





void quest_clone( CHAR_DATA *ch, OBJ_DATA *obj )


{


    OBJ_INDEX_DATA *pObjIndex;


    OBJ_DATA *obj2;


    AFFECT_DATA *paf;


    AFFECT_DATA *paf2;





    pObjIndex = get_obj_index( obj->pIndexData->vnum);


    obj2 = create_object( pObjIndex, obj->level );


    /* Copy any changed parts of the object. */


    free_string(obj2->name);


    obj2->name=str_dup(obj->name);


    free_string(obj2->short_descr);


    obj2->short_descr=str_dup(obj->short_descr);


    free_string(obj2->description);


    obj2->description=str_dup(obj->description);


    if (obj2->questmaker != NULL) free_string(obj2->questmaker);


	obj2->questmaker=str_dup(ch->name);


    if (obj->chpoweron != NULL && obj->points >= 50)


    {


    	free_string(obj2->chpoweron);


    	obj2->chpoweron=str_dup(obj->chpoweron);


    }


    if (obj->chpoweroff != NULL && obj->points >= 50)


    {


    	free_string(obj2->chpoweroff);


    	obj2->chpoweroff=str_dup(obj->chpoweroff);


    }


    if (obj->chpoweruse != NULL && obj->points >= 50)


    {


    	free_string(obj2->chpoweruse);


    	obj2->chpoweruse=str_dup(obj->chpoweruse);


    }


    if (obj->victpoweron != NULL && obj->points >= 50)


    {


    	free_string(obj2->victpoweron);


    	obj2->victpoweron=str_dup(obj->victpoweron);


    }


    if (obj->victpoweroff != NULL && obj->points >= 50)


    {


    	free_string(obj2->victpoweroff);


    	obj2->victpoweroff=str_dup(obj->victpoweroff);


    }


    if (obj->victpoweruse != NULL && obj->points >= 50)


    {


    	free_string(obj2->victpoweruse);


    	obj2->victpoweruse=str_dup(obj->victpoweruse);


    }


    if (obj->points >= 50)


    {


	obj2->spectype	 = obj->spectype;


	obj2->specpower	 = obj->specpower;


    }


    obj2->item_type	 = obj->item_type;


    obj2->extra_flags	 = obj->extra_flags;


    obj2->wear_flags	 = obj->wear_flags;


    obj2->weight	 = obj->weight;


    obj2->condition	 = obj->condition;


    obj2->toughness	 = obj->toughness;


    obj2->resistance	 = obj->resistance;


    obj2->quest		 = obj->quest;


    obj2->points	 = obj->points;


    obj2->cost		 = obj->cost;


    obj2->value[0]	 = obj->value[0];


    obj2->value[1]	 = obj->value[1];


    obj2->value[2]	 = obj->value[2];


    obj2->value[3]	 = obj->value[3];


    /*****************************************/


    obj_to_char(obj2,ch);


    if (obj->affected != NULL)


    {


    	for ( paf = obj->affected; paf != NULL; paf = paf->next )


    	{


	    if (affect_free == NULL)


	        paf2 = alloc_perm( sizeof(*paf) );


	    else


	    {


		paf2 = affect_free;


		affect_free = affect_free->next;


	    }


	    paf2->type  	= 0;


	    paf2->duration	= paf->duration;


	    paf2->location	= paf->location;


	    paf2->modifier	= paf->modifier;


	    paf2->bitvector	= 0;


	    paf2->next  	= obj2->affected;


	    obj2->affected	= paf2;


    	}


    }


    act( "$p splits into two identical objects.", ch, obj, NULL, TO_CHAR );


    return;


}





void oset_affect( CHAR_DATA *ch, OBJ_DATA *obj, int value, int affect, bool is_quest )


{


    char buf [MAX_STRING_LENGTH];


    AFFECT_DATA *paf;


    int quest;


    int range;


    int cost;


    int max;





    if (IS_NPC(ch))


    {


	send_to_char("Switch back, smart ass.\n\r", ch);


	return;


    }





    if (value == 0)


    {


	send_to_char("Please enter a positive or negative amount.\n\r", ch);


	return;


    }





    if (!IS_JUDGE(ch) && (obj->questowner == NULL))


    {


	send_to_char("First you must set the owners name on the object.\n\r", ch);


	return;


    }





    if (!IS_JUDGE(ch) && (obj->questmaker == NULL ||


	str_cmp(ch->name,obj->questmaker)) && !is_quest )


    {


	send_to_char("That item has already been oset by someone else.\n\r", ch);


	return;


    }





    if      ( affect == APPLY_STR     ) {range = 3;  cost = 20 ; quest = QUEST_STR;}


    else if ( affect == APPLY_DEX     ) {range = 3;  cost = 20 ; quest = QUEST_DEX;}


    else if ( affect == APPLY_INT     ) {range = 3;  cost = 20 ; quest = QUEST_INT;}


    else if ( affect == APPLY_WIS     ) {range = 3;  cost = 20 ; quest = QUEST_WIS;}


    else if ( affect == APPLY_CON     ) {range = 3;  cost = 20 ; quest = QUEST_CON;}


    else if ( affect == APPLY_HIT     ) {range = 25; cost =  5 ; quest = QUEST_HIT;}


    else if ( affect == APPLY_MANA    ) {range = 25; cost =  5 ; quest = QUEST_MANA;}


    else if ( affect == APPLY_MOVE    ) {range = 25; cost =  5 ; quest = QUEST_MOVE;}


    else if ( affect == APPLY_HITROLL ) {range = 5;  cost = 30 ; quest = QUEST_HITROLL;}


    else if ( affect == APPLY_DAMROLL ) {range = 5;  cost = 30 ; quest = QUEST_DAMROLL;}


    else if ( affect == APPLY_AC      ) {range = 25; cost = 10 ; quest = QUEST_AC;}


    else return;





    if (IS_SET(obj->quest, QUEST_IMPROVED))


	max = 1250 + (ch->race * 20);


    else if ( obj->pIndexData->vnum == OBJ_VNUM_PROTOPLASM )


	{range *= 2; max = 750 + (ch->race * 10);}


    else


	max = 400 + (ch->race * 10);


    if (obj->item_type == ITEM_WEAPON) {max *= 2;range *= 2;}


    if ( !IS_JUDGE(ch) && ((value > 0 && value > range) ||


	(value < 0 && value < (range-range-range))) )


    {


	send_to_char("That is not within the acceptable range...\n\r", ch);


	send_to_char("Str, Dex, Int, Wis, Con... max =   3 each, at  20 quest points per +1 stat.\n\r", ch);


	send_to_char("Hp, Mana, Move............ max =  25 each, at   5 quest point per point.\n\r", ch);


	send_to_char("Hitroll, Damroll.......... max =   5 each, at  30 quest points per point.\n\r", ch);


	send_to_char("Ac........................ max = -25,      at  10 points per point.\n\r", ch);


	send_to_char("\n\rNote: Created items can have upto 2 times the above maximum.\n\r", ch);


	send_to_char("Also: Weapons may have upto 2 (4 for created) times the above maximum.\n\r", ch);


	return;


    }





    if ( quest >= QUEST_HIT && value < 0 ) cost *= (value - (value*2));


    else cost *= value;





    if ( cost < 0 ) cost = 0;





    if (!IS_JUDGE(ch) && IS_SET(obj->quest, quest) )


    {


	send_to_char("That affect has already been set on this object.\n\r", ch);


	return;


    }





    if (!IS_JUDGE(ch) && (obj->points + cost > max))


    {


	sprintf(buf,"You are limited to %d quest points per item.\n\r",max);


	send_to_char(buf, ch);


	return;


    }





    if (is_quest && ch->pcdata->quest < cost)


    {


	sprintf(buf,"That costs %d quest points, while you only have %d.\n\r",cost, ch->pcdata->quest);


	send_to_char(buf, ch);


	return;


    }





    if (!IS_SET(obj->quest, quest) ) SET_BIT(obj->quest,quest);





    if (is_quest) ch->pcdata->quest -= cost;


    obj->points += cost;


    if (obj->questmaker != NULL) free_string(obj->questmaker);


    obj->questmaker = str_dup(ch->name);





    if ( affect_free == NULL )


    {


	paf		= alloc_perm( sizeof(*paf) );


    }


    else


    {


	paf		= affect_free;


	affect_free	= affect_free->next;


    }





    paf->type	= 0;


    paf->duration	= -1;


    paf->location	= affect;


    paf->modifier	= value;


    paf->bitvector	= 0;


    paf->next		= obj->affected;


    obj->affected	= paf;





    /*


    send_to_char("Ok.\n\r",ch);


*/    


return;


}








void do_makepreg( CHAR_DATA *ch, char *argument )


{


    char arg1[MAX_INPUT_LENGTH];


    char arg2[MAX_INPUT_LENGTH];


    char buf[MAX_INPUT_LENGTH];


    CHAR_DATA *victim1;


    CHAR_DATA *victim2;





    argument = one_argument( argument, arg1 );


    argument = one_argument( argument, arg2 );





    if ( arg1[0] == '\0' || arg2[0] == '\0' )


    {


	send_to_char("Syntax: makepreg <female> <male>\n\r",ch);


	return;


    }


    if ( ( victim1 = get_char_room(ch, arg1) ) == NULL )


    {


	send_to_char("They are not here.\n\r",ch);


	return;


    }


    if ( ( victim2 = get_char_room(ch, arg2) ) == NULL )


    {


	send_to_char("They are not here.\n\r",ch);


	return;


    }


    if (IS_NPC(victim1) || IS_NPC(victim2))


    {


	send_to_char("Not on NPC's.\n\r",ch);


	return;


    }


	if ((victim1->sex != SEX_FEMALE && victim2->sex !=SEX_MALE)) {


		send_to_char("No way!\n\r",ch);


		return;}


	else


		{


    if (!str_cmp(victim1->name, victim2->pcdata->marriage) &&


	!str_cmp(victim2->name, victim1->pcdata->marriage))


    {


/*	make_preg(victim1, victim2);	*/


	save_char_obj(victim1);


	save_char_obj(victim2);


	sprintf(buf,"%s and %s are now pregnant!",victim1->name,victim2->name);


	do_info(ch,buf);


	return;


    }


    send_to_char("But they are not yet engaged!\n\r",ch);


    return;}


}










650201551  10733

#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "merc.h"


void load_kingdoms(void) {

	FILE *fp;
	ROOM_INDEX_DATA *room;
	OBJ_INDEX_DATA *obj;
	int i;
	int vnum;

	king_table[0].name = "";
	king_table[0].who_name = "";
	king_table[0].leader_name = "";
	king_table[0].pk = 0;
	king_table[0].pd = 0;
	king_table[0].num = 0;
	king_table[0].recall = 0;
	king_table[0].object = NULL;
	king_table[0].altar = 0;

	if ((fp = fopen("../area/kingdom.dat", "r")) == NULL) {
	log_string("Error: kingdom.dat not found!");
	exit(1);}

	for (i = 1; i <= MAX_KINGDOM; i++) {

	vnum = 90000 + i*100;

	king_table[i].name = fread_string(fp);
	king_table[i].who_name = fread_string(fp);
	king_table[i].leader_name = fread_string(fp);
	king_table[i].pk = fread_number(fp);
	king_table[i].pd = fread_number(fp);
	king_table[i].recall = fread_number(fp);
	king_table[i].altar = fread_number(fp);
	king_table[i].num = i;
/*	obj = get_obj_index(vnum);
	if (obj != NULL)
	king_table[i].object =  create_object(obj,0);
	if (king_table[i].object != NULL && (room = get_room_index(king_table[i].altar)) != NULL)
		obj_to_room(king_table[i].object,room);
*/	}	

	fclose(fp);
	return;
}


void save_kingdoms(void) {

	FILE *fp;
	int i;

	if ((fp = fopen("../area/kingdom.dat","w")) == NULL) {
	log_string("Error writing to kingdom.dat");
	}

	for (i = 1; i <= MAX_KINGDOM; i++) {
	fprintf(fp,"%s~\n", king_table[i].name);
	fprintf(fp,"%s~\n", king_table[i].who_name);
	fprintf(fp,"%s~\n", king_table[i].leader_name);
	fprintf(fp, "%d\n%d\n",king_table[i].pk, king_table[i].pd);
	fprintf(fp, "%d\n%d\n",king_table[i].recall,king_table[i].altar);

	}

	fclose(fp);
	return;
}

void do_clanlist(CHAR_DATA *ch, char *argument) {

	char buf[MAX_STRING_LENGTH];
	int i;

	if (IS_NPC(ch)) return;

	sprintf(buf, "Clan               Leader       PKs     PDs\n\r" );
	send_to_char(buf,ch);
	sprintf(buf, "----               ------       ---     ---\n\r" );
	send_to_char(buf,ch);
	for (i = 1; i <= MAX_KINGDOM; i++) {
	sprintf(buf, "%-18s %-12s %-7d %-7d\n\r", 
	king_table[i].name,
	king_table[i].leader_name,
	king_table[i].pk,
	king_table[i].pd);
	send_to_char(buf,ch);
	}
	send_to_char("\n\r", ch );

	return;
}

void do_induct(CHAR_DATA *ch, char *argument) {

	CHAR_DATA *victim;
	char arg[MAX_STRING_LENGTH];

	argument = one_argument(argument,arg);

	if (IS_NPC(ch)) return;

	if (ch->pcdata->kingdom == 0) {
	send_to_char("You are not in a clan.\n\r", ch );
	return;}

	if (str_cmp(ch->pcdata->switchname,king_table[ch->pcdata->kingdom].leader_name)
	&& !IS_SET(ch->special, SPC_PRINCE)) {
	send_to_char("You cannot induct people.\n\r", ch );
	return;}

	if ((victim = get_char_room(ch, arg)) == NULL) {
	send_to_char("They are not here.\n\r", ch );
	return;}

	if (IS_NPC(victim)) {
	send_to_char("Not on NPCs.\n\r", ch );
	return;}
/*
	if (!IS_SET(victim->newbits, NEW_CLANNABLE)) {
	send_to_char("That person is not CLANNABLE.\n\r", ch );
	return;}
*/
	if (victim->pcdata->kingdom != 0) {
	send_to_char("That person is already clanned.\n\r", ch );
	return;}

	victim->pcdata->kingdom = ch->pcdata->kingdom;
	if (IS_SET(victim->special, SPC_PRINCE)) 
	REMOVE_BIT(victim->special, SPC_PRINCE);
	send_to_char("They are now in your clan.\n\r", ch);
	send_to_char("You are now in a clan.\n\r", victim);
	save_char_obj(victim);
	return;
}

void do_outcast(CHAR_DATA *ch, char *argument) {

	CHAR_DATA *victim;
	char arg[MAX_STRING_LENGTH];
	argument = one_argument(argument, arg);

	if (IS_NPC(ch)) return;

	if (ch->pcdata->kingdom == 0) {
	send_to_char("You are not in a clan.\n\r", ch );
	return;}

	if (str_cmp(ch->pcdata->switchname,king_table[ch->pcdata->kingdom].leader_name)) {
	send_to_char("You are not a clan leader.\n\r", ch );
	return;}

	if ((victim = get_char_world(ch, arg)) == NULL ) {
	send_to_char("They are not here.\n\r", ch );
	return;}

	if (IS_NPC(victim)) {
	send_to_char("Not on NPCs.\n\r", ch );
	return;}

	if (victim->pcdata->kingdom != ch->pcdata->kingdom) {
	send_to_char("They are not in your clan.\n\r", ch );
	return;}

	if (ch == victim) {
	send_to_char("You can't outcast yourself.\n\r", ch );
	return;}

	victim->pcdata->kingdom = 0;
	if (IS_SET(victim->special, SPC_PRINCE))
	REMOVE_BIT(victim->special, SPC_PRINCE);
	send_to_char("You remove them from your clan.\n\r", ch );
	send_to_char("You have been outcasted from your clan!\n\r",victim);	

	return;
}

void do_prince(CHAR_DATA *ch, char *argument) {

	CHAR_DATA *victim;
	char arg[MAX_STRING_LENGTH];

	argument = one_argument(argument, arg);

	if (IS_NPC(ch)) return;

	if (ch->pcdata->kingdom == 0) {
	send_to_char("You are not in a clan.\n\r", ch );
	return;}

	if (str_cmp(ch->pcdata->switchname,king_table[ch->pcdata->kingdom].leader_name)) {
	send_to_char("You are not the leader of your clan.\n\r", ch );
	return;}

	if ((victim = get_char_room(ch, arg)) == NULL) {
	send_to_char("They are not here.\n\r", ch );
	return;}

	if (IS_NPC(victim)) {
	send_to_char("Not on NPCs.\n\r", ch );
	return;}

	if (victim->pcdata->kingdom != ch->pcdata->kingdom) {
	send_to_char("They are not in your clan.\n\r", ch );
	return;}

	if (ch == victim) {
	send_to_char("You can't do that.\n\r", ch );
	return;}

	if (IS_SET(victim->special, SPC_PRINCE)) {
	REMOVE_BIT(victim->special, SPC_PRINCE);
	send_to_char("You are no longer a prince.\n\r", victim);
	send_to_char("They are no longer a prince.\n\r", ch );
	save_char_obj(victim);
	return;}

	SET_BIT(victim->special, SPC_PRINCE);
	send_to_char("You are now a prince!\n\r", victim);
	send_to_char("You make them a prince.\n\r", ch );
	save_char_obj(victim);
	return;
}

void do_clannable(CHAR_DATA *ch, char *argument) {

	if (IS_NPC(ch)) return;

	if (ch->pcdata->kingdom != 0) {
	send_to_char("You already are in a clan.\n\r", ch );
	return;}

	if (IS_SET(ch->newbits, NEW_CLANNABLE)) {
	REMOVE_BIT(ch->newbits, NEW_CLANNABLE);
	send_to_char("You can no longer be clanned.\n\r", ch );
	return;}

	SET_BIT(ch->newbits, NEW_CLANNABLE);
	send_to_char("You can now be clanned.\n\r", ch );

	return;
}

void do_kingdom(CHAR_DATA *ch, char *argument)
{

    char buf[MAX_STRING_LENGTH];
    CHAR_DATA *gch;
   char rankname[9];

    if (IS_NPC(ch)) return;

	if (ch->pcdata->kingdom == 0) {
	send_to_char("You are not in a kingdom.\n\r", ch );
	return;}

	sprintf(buf, "%s's Kingdom of %s:\n\r",
	king_table[ch->pcdata->kingdom].leader_name,
	king_table[ch->pcdata->kingdom].name);

    send_to_char( buf, ch );
    send_to_char("#2[    Name    ] [ Hits ] [ HPmax ] [ Mana ] [ Move ] [ Status ] [  Rank  ]#n\n\r", ch );
    for ( gch = char_list; gch != NULL; gch = gch->next )
    {
	if ( IS_NPC(gch) ) continue;
	if ( gch->pcdata->kingdom != ch->pcdata->kingdom) 
	    continue;
	if (!str_cmp(king_table[ch->pcdata->kingdom].leader_name,gch->pcdata->switchname)) 
	sprintf(rankname,"King");
	else if (IS_SET(gch->special, SPC_PRINCE)) 
	sprintf(rankname, "Prince");
	else
	 sprintf(rankname,"Member");
	    sprintf( buf,
	    "#2[#n%-12s#2] [#n%6d#2] [#n%7d#2] [#n%6d#2] [#n%6d#2] [#n   %-2d   #2] [ #n%-6s #2]#n\n\r",
		gch->pcdata->switchname ,
		gch->hit,gch->max_hit,gch->mana,gch->move,
		gch->race, rankname);
		send_to_char( buf, ch );
    }
    return;
}

void do_krecall(CHAR_DATA *ch, char *argument) {

	CHAR_DATA *victim;
	CHAR_DATA *mount;
	ROOM_INDEX_DATA *location;

	if (IS_NPC(ch)) return;

	if (ch->pcdata->kingdom == 0) {
	send_to_char("Huh?\n\r", ch );
	return;}

	act("$n's body flickers with green energy.",ch,NULL,NULL,TO_ROOM);
	act("Your body flickers with green energy.",ch,NULL,NULL,TO_CHAR);

	if ((location = get_room_index(king_table[ch->pcdata->kingdom].recall)) == NULL) {
	send_to_char("You are completely lost.\n\r", ch );
	return;}

	if (ch->in_room == location) return;

	if (IS_SET(ch->in_room->room_flags, ROOM_NO_RECALL) || IS_AFFECTED(ch, AFF_CURSE)) {
	send_to_char("You are unable to recall.\n\r", ch );
	return;}

	if ((victim = ch->fighting) != NULL) {
	if (number_bits(1) == 0) {
		WAIT_STATE(ch,4);
		send_to_char("You failed!\n\r", ch );
		return;}
	send_to_char("You recall from combat!\n\r", ch );
	stop_fighting(ch,TRUE);
	}

	act("$n dissapears.",ch,NULL,NULL,TO_ROOM);
	char_from_room(ch);
	char_to_room(ch,location);
	act("$n appears in the room.",ch,NULL,NULL,TO_ROOM);
	do_look(ch,"auto");
	if ((mount = ch->mount) == NULL) return;
	char_from_room(mount);
	char_to_room(mount,ch->in_room);
	
	return;
}


bool lost_kpower(CHAR_DATA *ch) {

	ROOM_INDEX_DATA *room;

	if (IS_NPC(ch)) return FALSE;
	
	if (ch->pcdata->kingdom <= 0 || ch->pcdata->kingdom > MAX_KINGDOM) 
		return FALSE;

	if (king_table[ch->pcdata->kingdom].object == NULL)
		return FALSE;

	if ((room = get_room_index(king_table[ch->pcdata->kingdom].altar)) == NULL) 
		return FALSE;

/*	if (king_table[ch->pcdata->kingdom].object->in_room->vnum ==
king_table[ch->pcdata->kingdom].altar) 
		return FALSE;
*/
	return FALSE;
	return TRUE;
}




 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
 *                                                                         *
 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
 *  Chastain, Michael Quan, and Mitchell Tse.                              *
 *                                                                         *
 *  In order to use any part of this Merc Diku Mud, you must comply with   *
 *  both the original Diku license in 'license.doc' as well the Merc       *
 *  license in 'license.txt'.  In particular, you may not remove either of *
 *  these copyright notices.                                               *
 *                                                                         *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 ***************************************************************************/

#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"

/*
 * Local functions.
 */

void    adv_spell_damage        args( ( CHAR_DATA *ch, OBJ_DATA *book, 
				OBJ_DATA *page, char *argument) );
void    adv_spell_affect        args( ( CHAR_DATA *ch, OBJ_DATA *book, 
				OBJ_DATA *page, char *argument) );
void    adv_spell_action        args( ( CHAR_DATA *ch, OBJ_DATA *book, 
				OBJ_DATA *page, char *argument) );


void do_chant( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    OBJ_DATA *book;
    OBJ_DATA *page;
    OBJ_DATA *obj;
    char arg[MAX_INPUT_LENGTH];
    bool victim_target = FALSE;
    bool object_target = FALSE;
    bool global_target = FALSE; /* Target object/victim may be anywhere */
    int spellno = 1;
    int spellcount = 0;
    int spelltype;
    int sn = 0;
    int level;

    one_argument( argument, arg );

    if ( ( book = get_eq_char(ch, WEAR_WIELD) ) == NULL || 
	book->item_type != ITEM_BOOK)
    {
	if ( ( book = get_eq_char(ch, WEAR_HOLD) ) == NULL || 
	    book->item_type != ITEM_BOOK)
	{
	    send_to_char( "First you must hold a spellbook.\n\r", ch );
	    return;
	}
    }
    if (IS_SET(book->value[1], CONT_CLOSED))
    {
	send_to_char( "First you better open the book.\n\r", ch );
	return;
    }
    if (book->value[2] < 1)
    {
	send_to_char( "There are no spells on the index page!\n\r", ch );
	return;
    }
    if ( ( page = get_page( book, book->value[2] ) ) == NULL )
    {
	send_to_char( "The current page seems to have been torn out!\n\r", ch );
	return;
    }

    spellcount = ((page->value[1] * 10000) + (page->value[2] * 10) + 
	page->value[3]);
    act("You chant the arcane words from $p.",ch,book,NULL,TO_CHAR);
    act("$n chants some arcane words from $p.",ch,book,NULL,TO_ROOM);
    if (IS_SET(page->quest, QUEST_MASTER_RUNE))
    {
	ch->spectype = 0;
	if (IS_SET(page->spectype, ADV_FAILED) || 
	    !IS_SET(page->spectype, ADV_FINISHED) || page->points < 1)
	    send_to_char( "The spell failed.\n\r", ch );
	else if (IS_SET(page->spectype, ADV_DAMAGE)) 
	    adv_spell_damage(ch,book,page,argument);
	else if (IS_SET(page->spectype, ADV_AFFECT))
	    adv_spell_affect(ch,book,page,argument);
	else if (IS_SET(page->spectype, ADV_ACTION))
	    adv_spell_action(ch,book,page,argument);
	else send_to_char( "The spell failed.\n\r", ch );
	return;
    }
    switch ( spellcount )
    {
    default:
	send_to_char( "Nothing happens.\n\r", ch );
	return;
    case 10022:
	/* FIRE + DESTRUCTION + TARGETING */
	sn = skill_lookup( "fireball" );
	victim_target = TRUE;
	spellno = 2;
	break;
    case 640322:
	/* LIFE + ENHANCEMENT + TARGETING */
	sn = skill_lookup( "heal" );
	victim_target = TRUE;
	spellno = 2;
	global_target = TRUE;
	break;
    case 1280044:
	/* DEATH + SUMMONING + AREA */
	sn = skill_lookup( "guardian" );
	spellno = 3;
	break;
    case 2565128:
	/* MIND + INFORMATION + OBJECT */
	sn = skill_lookup( "identify" );
	object_target = TRUE;
	global_target = TRUE;
	break;
    case 320322:
	/* LIGHT + ENHANCEMENT + TARGETING */
    case 160642:
	/* DARK + REDUCTION + TARGETING */
	sn = skill_lookup( "cure blindness" );
	global_target = TRUE;
	victim_target = TRUE;
	break;
    case 320642:
	/* LIGHT + REDUCTION + TARGETING */
    case 160322:
	/* DARK + ENHANCEMENT + TARGETING */
	sn = skill_lookup( "blindness" );
	global_target = TRUE;
	victim_target = TRUE;
	break;
    case 640321:
	/* LIFE + ENHANCEMENT + SELF */
	sn = skill_lookup( "heal" );
	spellno = 3;
	break;
    case 5121282:
	/* SPIRIT + CONTROL + TARGETING */
	sn = skill_lookup( "change sex" );
	global_target = TRUE;
	victim_target = TRUE;
	break;
    case 5125122:
	/* SPIRIT + INFORMATION + TARGETING */
	sn = skill_lookup( "know alignment" );
	global_target = TRUE;
	victim_target = TRUE;
	break;

    }
    if ( arg[0] == '\0' && (victim_target == TRUE || object_target == TRUE))
    {
	send_to_char( "Please specify a target.\n\r", ch );
	return;
    }

    if (victim_target && sn > 0)
    {
	if ( !global_target && ( victim = get_char_room( ch, arg ) ) == NULL )
	{
	    send_to_char( "They are not here.\n\r", ch );
	    return;
	}
	else if ( global_target && ( victim = get_char_world( ch, arg ) ) == NULL )
	{
	    send_to_char( "They are not here.\n\r", ch );
	    return;
	}
	if (IS_ITEMAFF(victim, ITEMA_REFLECT))
	{
	    send_to_char( "You are unable to focus your spell on them.\n\r", ch );
	    return;
	}

	if (!IS_NPC(victim) && IS_CLASS( victim, CLASS_DROW ))
	{
	    if (ch == victim )
	    {
		send_to_char("You lower your magical resistance....\n\r", ch);
	    }
	    else if (number_percent ( )  <=  victim->pcdata->stats[DROW_MAGIC])
	    {
	       send_to_char("Your spell does not affect them.\n\r", ch);
	       return;
	    }
	}

	spelltype = (skill_table[sn].target);
	level = ch->spl[spelltype] * 0.25;
	(*skill_table[sn].spell_fun) ( sn, level, ch, victim );
	if (spellno > 1) (*skill_table[sn].spell_fun) ( sn, level, ch, victim );
	if (spellno > 2) (*skill_table[sn].spell_fun) ( sn, level, ch, victim );
	if (!IS_IMMORTAL( ch ))
		WAIT_STATE(ch, skill_table[sn].beats);
    }
    else if (object_target && sn > 0)
    {
	if ( !global_target && ( obj = get_obj_carry( ch, arg ) ) == NULL )
	{
	    send_to_char( "You are not carrying that object.\n\r", ch );
	    return;
	}
	else if ( global_target && ( obj = get_obj_world( ch, arg ) ) == NULL )
	{
	    send_to_char( "You cannot find any object like that.\n\r", ch );
	    return;
	}
	spelltype = (skill_table[sn].target);
	level = ch->spl[spelltype] * 0.25;
	(*skill_table[sn].spell_fun) ( sn, level, ch, obj );
	if (spellno > 1) (*skill_table[sn].spell_fun) ( sn, level, ch, obj );
	if (spellno > 2) (*skill_table[sn].spell_fun) ( sn, level, ch, obj );
	if (!IS_IMMORTAL( ch))  
		WAIT_STATE(ch, skill_table[sn].beats);
    }
    else if (sn > 0)
    {
	spelltype = (skill_table[sn].target);
	if (spelltype == TAR_OBJ_INV)
	{
	    send_to_char( "Nothing happens.\n\r", ch );
	    return;
	}
	level = ch->spl[spelltype] * 0.25;
	(*skill_table[sn].spell_fun) ( sn, level, ch, ch );
	if (spellno > 1) (*skill_table[sn].spell_fun) ( sn, level, ch, ch );
	if (spellno > 2) (*skill_table[sn].spell_fun) ( sn, level, ch, ch );
	if (!IS_IMMORTAL( ch ))
		WAIT_STATE(ch, skill_table[sn].beats);
    }
    else send_to_char( "Nothing happens.\n\r", ch );
    return;
}

OBJ_DATA *get_page( OBJ_DATA *book, int page_num )
{
    OBJ_DATA *page;
    OBJ_DATA *page_next;

    if (page_num < 1) return NULL;
    for ( page = book->contains; page != NULL; page = page_next )
    {
	page_next = page->next_content;
	if (page->value[0] == page_num) return page;
    }
    return NULL;
}

void adv_spell_damage( CHAR_DATA *ch, OBJ_DATA *book, OBJ_DATA *page, char *argument)
{
    char arg [MAX_STRING_LENGTH];
    char buf [MAX_STRING_LENGTH];
    OBJ_DATA *page_next;
    ROOM_INDEX_DATA *old_room;
    char next_par [MAX_INPUT_LENGTH];
    int mana_cost = page->points;
    int min = page->value[1];
    int max = page->value[2];
    int dam;
    int level;
    bool area_affect = FALSE;
    bool victim_target = FALSE;
    bool global_target = FALSE;
    bool next_page = FALSE;
    bool parameter = FALSE;
    bool not_caster = FALSE;
    bool no_players = FALSE;
    bool cast_message = FALSE;
    bool reversed = FALSE;

    if (ch->mana < mana_cost)
    {send_to_char("You have insufficient mana to chant this spell.\n\r",ch);return;}

    if (min < 1 || max < 1)
    {send_to_char("The spell failed.\n\r",ch);return;}

    if (IS_SET(page->spectype, ADV_NEXT_PAGE) &&
	IS_SET(page->spectype, ADV_SPELL_FIRST))
    {
	if (strlen(page->chpoweroff) < 2 || !str_cmp(page->chpoweroff,"(null)"))
	{send_to_char("The spell failed.\n\r",ch);return;}
	if (IS_SET(page->spectype, ADV_PARAMETER))
	{
	    if (!str_cmp(page->chpoweron,"(null)"))
		{send_to_char("The spell failed.\n\r",ch);return;}
	    else strcpy(next_par,page->chpoweron);
	}
	else strcpy(next_par,arg);
	if ( page->specpower < page->value[0] )
	{send_to_char( "The spell failed.\n\r", ch );return;}
	if ( ( page_next = get_page( book, page->specpower ) ) == NULL )
	{send_to_char( "The spell failed.\n\r", ch );return;}
	if (IS_SET(page_next->quest, QUEST_MASTER_RUNE))
	{
	    if      (IS_SET(page_next->spectype, ADV_DAMAGE))
		adv_spell_damage(ch,book,page_next,next_par);
	    else if (IS_SET(page_next->spectype, ADV_AFFECT))
		adv_spell_affect(ch,book,page_next,next_par);
	    else if (IS_SET(page_next->spectype, ADV_ACTION))
		adv_spell_action(ch,book,page_next,next_par);
	    else {send_to_char( "The spell failed.\n\r", ch );return;}
	}
	else {send_to_char( "The spell failed.\n\r", ch );return;}
    }

    one_argument( argument, arg );

    if (strlen(page->victpoweron) > 0 || str_cmp(page->victpoweron,"(null)"))
    {
	if (strlen(page->victpoweroff) > 0 || str_cmp(page->victpoweroff,"(null)"))
	    cast_message = TRUE;
    }

    if (IS_SET(page->spectype, ADV_AREA_AFFECT  )) area_affect   = TRUE;
    if (IS_SET(page->spectype, ADV_VICTIM_TARGET)) victim_target = TRUE;
    if (IS_SET(page->spectype, ADV_GLOBAL_TARGET)) global_target = TRUE;
    if (IS_SET(page->spectype, ADV_NEXT_PAGE    )) next_page     = TRUE;
    if (IS_SET(page->spectype, ADV_PARAMETER    )) parameter     = TRUE;
    if (IS_SET(page->spectype, ADV_NOT_CASTER   )) not_caster    = TRUE;
    if (IS_SET(page->spectype, ADV_NO_PLAYERS   )) no_players    = TRUE;
    if (IS_SET(page->spectype, ADV_REVERSED     )) reversed      = TRUE;

    if (victim_target)
    {
	CHAR_DATA *victim;
	
	if ( !global_target && ( victim = get_char_room( ch, arg ) ) == NULL )
	{
	    send_to_char( "They are not here.\n\r", ch );
	    return;
	}
	else if ( global_target && ( victim = get_char_world( ch, arg ) ) == NULL )
	{
	    send_to_char( "They are not here.\n\r", ch );
	    return;
	}
	if (reversed)
	    level = ch->spl[BLUE_MAGIC];
	else {
/*
	 if (!IS_NPC(victim = get_char_world( ch, arg)) && global_target)
	{  send_to_char("This type of spell is temporarily disabled.\n\r", ch );
		return;}
*/
	    level = ch->spl[RED_MAGIC];}
	if (ch->in_room == victim->in_room)
	    dam = number_range(min,max) + level;
	else
	    dam = number_range(min,max);
	if (ch->spectype < 1000)
	{
	    ch->spectype += dam;
/*          if (!IS_NPC(victim) && IS_SET(victim->act, PLR_VAMPIRE) && 
		IS_VAMPAFF(victim, VAM_FORTITUDE) && dam > 1 && !reversed)
		dam = number_range(1,dam);*/
	    if (IS_ITEMAFF(victim, ITEMA_RESISTANCE) && dam > 1 && !reversed)
		dam = number_range(1,dam);
	    else if (!IS_NPC(victim) && IS_CLASS(victim, CLASS_DEMON) && !reversed &&
		IS_SET(victim->pcdata->powers[DPOWER_FLAGS], DEM_TOUGH) && dam > 1)
		dam = number_range(1,dam);
/*          else if (!IS_NPC(victim) && IS_CLASS(victim, CLASS_WEREWOLF) && 
		victim->power[DISC_WERE_BOAR] > 2 && dam > 1 && !reversed)
		dam *= 0.5;*/
	    if (!IS_NPC(victim) && IS_CLASS(victim,CLASS_DEMON) && victim->in_room != NULL 
		&& victim->in_room->vnum == ROOM_VNUM_HELL && !reversed)
	    { if (dam < 5) dam = 1; else dam *= 0.2; }
	}
	else dam = 0;
	old_room = ch->in_room;
	if (victim->in_room != NULL && victim->in_room != ch->in_room)
	{
	    char_from_room(ch);
	    char_to_room(ch,victim->in_room);
	}
	if (!reversed)
	{
	    if (is_safe(ch,victim))
	    {
		char_from_room(ch);
		char_to_room(ch,old_room);
		return;
	    }
	}
	else if (IS_ITEMAFF(victim, ITEMA_REFLECT))
	{
	    send_to_char( "You are unable to focus your spell on them.\n\r", ch );
	    char_from_room(ch);
	    char_to_room(ch,old_room);
	    return;
	}
	char_from_room(ch);
	char_to_room(ch,old_room);
	if (cast_message)
	{
	    strcpy(buf,page->victpoweron);
	    act2(buf,ch,NULL,victim,TO_CHAR);
	    strcpy(buf,page->victpoweroff);
	    act2(buf,ch,NULL,victim,TO_ROOM);
	}
	if (reversed)
	{
	    victim->hit += dam;
	    if (victim->hit > victim->max_hit) victim->hit = victim->max_hit;
	}
	else
	{
	    adv_damage(ch,victim,dam);
	    sprintf(buf,"Your %s strikes $N incredibly hard!",page->chpoweroff);
	    act2(buf,ch,NULL,victim,TO_CHAR);
	    sprintf(buf,"$n's %s strikes $N incredibly hard!",page->chpoweroff);
	    act2(buf,ch,NULL,victim,TO_NOTVICT);
	    sprintf(buf,"$n's %s strikes you incredibly hard!",page->chpoweroff);
	    act2(buf,ch,NULL,victim,TO_VICT);
	 /*   if (!IS_NPC(victim) && number_percent() <= victim->pcdata->atm)
		act( "$n's spell is unable to penetrate your antimagic shield.", ch, NULL, victim, TO_VICT );
	    else*/
		hurt_person(ch,victim,dam);
	}
	if (!IS_IMMORTAL( ch ))
	{
		WAIT_STATE(ch, 12);
		ch->mana -= mana_cost;
	}
    }
    else if (area_affect)
    {
	CHAR_DATA *vch = ch;
	CHAR_DATA *vch_next;

	if (reversed)
	    level = ch->spl[BLUE_MAGIC];
	else
	    level = ch->spl[RED_MAGIC];
	dam = number_range(min,max) + (level * 0.5);
	if (ch->spectype < 1000)
	{
	    ch->spectype += dam;
	}
	else dam = 0;
	if (IS_SET(ch->in_room->room_flags, ROOM_SAFE) && !reversed)
	{
	    send_to_char("You cannot fight in a safe room.\n\r",ch);
	    return;
	}
	if (cast_message)
	{
	    strcpy(buf,page->victpoweron);
	    act2(buf,ch,NULL,vch,TO_CHAR);
	    strcpy(buf,page->victpoweroff);
	    act2(buf,ch,NULL,vch,TO_ROOM);
	}

	for ( vch = char_list; vch != NULL; vch = vch_next )
	{
	    vch_next    = vch->next;
	    if ( vch->in_room == NULL ) continue;
	    if ( ch == vch && not_caster ) continue;
	    if ( !IS_NPC(vch) && no_players ) continue;
	    if (!reversed)
	    {
		if (is_safe(ch,vch)) continue;
	    }
	    if (IS_ITEMAFF(vch, ITEMA_REFLECT))
	    {
		send_to_char( "You are unable to focus your spell on them.\n\r", ch );
		continue;
	    }
	    if ( vch->in_room == ch->in_room )
	    {
		if (reversed)
		{
		    vch->hit += dam;
		    if (vch->hit > vch->max_hit) vch->hit = vch->max_hit;
		}
		else
		{
		    adv_damage(ch,vch,dam);
		    sprintf(buf,"Your %s strikes $N incredably hard!",page->chpoweroff);
		    act2(buf,ch,NULL,vch,TO_CHAR);
		    sprintf(buf,"$n's %s strikes $N incredably hard!",page->chpoweroff);
		    act2(buf,ch,NULL,vch,TO_NOTVICT);
		    sprintf(buf,"$n's %s strikes you incredably hard!",page->chpoweroff);
		    act2(buf,ch,NULL,vch,TO_VICT);
/*                  if (!IS_NPC(vch) && number_percent() <= vch->pcdata->atm)
			act( "$n's spell is unable to penetrate your antimagic shield.", ch, NULL, vch, TO_VICT );
		    else if (!IS_NPC(vch) && IS_SET(vch->act, PLR_VAMPIRE) && 
			IS_VAMPAFF(vch, VAM_FORTITUDE) && dam > 1)
			hurt_person(ch,vch,number_range(1,dam));*/
		    if (IS_ITEMAFF(vch, ITEMA_RESISTANCE) && dam > 1)
			hurt_person(ch,vch,number_range(1,dam));
/*                  else if (!IS_NPC(vch) && IS_SET(vch->act, PLR_WEREWOLF) && 
			vch->pcdata->disc[TOTEM_BOAR] > 2 && dam > 1)
			hurt_person(ch,vch,(dam*0.5));*/
		    else hurt_person(ch,vch,dam);
		}
		continue;
	    }
	}
	if (!IS_IMMORTAL(ch))
	{
		WAIT_STATE(ch, 12);
		ch->mana -= mana_cost;
	}
    }
    else {send_to_char("The spell failed.\n\r",ch);return;}
    if (IS_SET(page->spectype, ADV_NEXT_PAGE) &&
	!IS_SET(page->spectype, ADV_SPELL_FIRST))
    {
	if (strlen(page->chpoweroff) < 2 || !str_cmp(page->chpoweroff,"(null)"))
	{send_to_char("The spell failed.\n\r",ch);return;}
	if (IS_SET(page->spectype, ADV_PARAMETER))
	{
	    if (!str_cmp(page->chpoweron,"(null)"))
		{send_to_char("The spell failed.\n\r",ch);return;}
	    else strcpy(next_par,page->chpoweron);
	}
	else strcpy(next_par,arg);
	if ( page->specpower < page->value[0] )
	{send_to_char( "The spell failed.\n\r", ch );return;}
	if ( ( page_next = get_page( book, page->specpower ) ) == NULL )
	{send_to_char( "The spell failed.\n\r", ch );return;}
	if (IS_SET(page_next->quest, QUEST_MASTER_RUNE))
	{
	    if      (IS_SET(page_next->spectype, ADV_DAMAGE))
		adv_spell_damage(ch,book,page_next,next_par);
	    else if (IS_SET(page_next->spectype, ADV_AFFECT))
		adv_spell_affect(ch,book,page_next,next_par);
	    else if (IS_SET(page_next->spectype, ADV_ACTION))
		adv_spell_action(ch,book,page_next,next_par);
	    else {send_to_char( "The spell failed.\n\r", ch );return;}
	}
	else {send_to_char( "The spell failed.\n\r", ch );return;}
    }
    return;
}

void adv_spell_affect( CHAR_DATA *ch, OBJ_DATA *book, OBJ_DATA *page, char *argument)
{
    char arg [MAX_STRING_LENGTH];
    char c_m [MAX_INPUT_LENGTH];
    char c_1 [MAX_INPUT_LENGTH];
    char c_2 [MAX_INPUT_LENGTH];
    OBJ_DATA *page_next;
    OBJ_DATA *obj = NULL;
    CHAR_DATA *victim = ch;
    char next_par [MAX_INPUT_LENGTH];
    int mana_cost = page->points;
    int apply_bit = page->value[1];
    int bonuses = page->value[2];
    int affect_bit = page->value[3];
    int sn;
    int level = page->level;
    bool any_affects = FALSE;
    bool area_affect = FALSE;
    bool victim_target = FALSE;
    bool object_target = FALSE;
    bool global_target = FALSE;
    bool next_page = FALSE;
    bool parameter = FALSE;
    bool not_caster = FALSE;
    bool no_players = FALSE;
    bool cast_message = FALSE;
    bool message_one = FALSE;
    bool message_two = FALSE;
    bool is_reversed = FALSE;

    if (ch->mana < mana_cost)
    {send_to_char("You have insufficient mana to chant this spell.\n\r",ch);return;}

    if (IS_SET(page->spectype, ADV_NEXT_PAGE) &&
	IS_SET(page->spectype, ADV_SPELL_FIRST))
    {
	if (strlen(page->chpoweroff) < 2 || !str_cmp(page->chpoweroff,"(null)"))
	{send_to_char("The spell failed.\n\r",ch);return;}
	if (IS_SET(page->spectype, ADV_PARAMETER))
	{
	    if (!str_cmp(page->chpoweron,"(null)"))
		{send_to_char("The spell failed.\n\r",ch);return;}
	    else strcpy(next_par,page->chpoweron);
	}
	else strcpy(next_par,argument);
	if ( page->specpower < page->value[0] )
	{send_to_char( "The spell failed.\n\r", ch );return;}
	if ( ( page_next = get_page( book, page->specpower ) ) == NULL )
	{send_to_char( "The spell failed.\n\r", ch );return;}
	if (IS_SET(page_next->quest, QUEST_MASTER_RUNE))
	{
	    if      (IS_SET(page_next->spectype, ADV_DAMAGE))
		adv_spell_damage(ch,book,page_next,next_par);
	    else if (IS_SET(page_next->spectype, ADV_AFFECT))
		adv_spell_affect(ch,book,page_next,next_par);
	    else if (IS_SET(page_next->spectype, ADV_ACTION))
		adv_spell_action(ch,book,page_next,next_par);
	    else {send_to_char( "The spell failed.\n\r", ch );return;}
	}
	else {send_to_char( "The spell failed.\n\r", ch );return;}
    }

    one_argument( argument, arg );

    if (strlen(page->chpoweroff) > 0 && str_cmp(page->chpoweroff,"(null)"))
	{strcpy(c_m,page->chpoweroff);cast_message = TRUE;}
    if (strlen(page->victpoweron) > 0 && str_cmp(page->victpoweron,"(null)"))
	{strcpy(c_1,page->victpoweron);message_one = TRUE;}
    if (strlen(page->victpoweroff) > 0 && str_cmp(page->victpoweroff,"(null)"))
	{strcpy(c_2,page->victpoweroff);message_two = TRUE;}

    if (IS_SET(page->spectype, ADV_AREA_AFFECT  )) area_affect   = TRUE;
    if (IS_SET(page->spectype, ADV_VICTIM_TARGET)) victim_target = TRUE;
    if (IS_SET(page->spectype, ADV_OBJECT_TARGET)) object_target = TRUE;
    if (IS_SET(page->spectype, ADV_GLOBAL_TARGET)) global_target = TRUE;
    if (IS_SET(page->spectype, ADV_NEXT_PAGE    )) next_page     = TRUE;
    if (IS_SET(page->spectype, ADV_PARAMETER    )) parameter     = TRUE;
    if (IS_SET(page->spectype, ADV_NOT_CASTER   )) not_caster    = TRUE;
    if (IS_SET(page->spectype, ADV_NO_PLAYERS   )) no_players    = TRUE;
    if (IS_SET(page->spectype, ADV_REVERSED     )) 
	{is_reversed = TRUE;bonuses = 0 - bonuses;}

    if (victim_target && !area_affect && !global_target && !object_target)
    {
	if ( ( victim = get_char_room( ch, arg ) ) == NULL )
	{send_to_char("The spell failed.\n\r",ch);return;}
	if (victim->in_room == NULL)
	{send_to_char("The spell failed.\n\r",ch);return;}
    }
    else if (victim_target && area_affect && !global_target && !object_target)
    {
	if ( ( victim = get_char_world( ch, arg ) ) == NULL )
	{send_to_char("The spell failed.\n\r",ch);return;}
	if (victim->in_room == NULL ||
	    victim->in_room->area != ch->in_room->area)
	{send_to_char("The spell failed.\n\r",ch);return;}
    }
    else if (victim_target && global_target && !object_target)
    {
	if ( ( victim = get_char_world( ch, arg ) ) == NULL )
	{send_to_char("The spell failed.\n\r",ch);return;}
	if (victim->in_room == NULL)
	{send_to_char("The spell failed.\n\r",ch);return;}
    }
    else if (object_target && !area_affect && !global_target && !victim_target)
    {
	if ( ( obj = get_obj_carry( ch, arg ) ) == NULL )
	{send_to_char("The spell failed.\n\r",ch);return;}
    }
    else if (object_target && area_affect && !global_target && !victim_target)
    {
	if ( ( obj = get_obj_here( ch, arg ) ) == NULL )
	{send_to_char("The spell failed.\n\r",ch);return;}
    }
    else if (object_target && global_target && !victim_target)
    {
	if ( ( obj = get_obj_world( ch, arg ) ) == NULL )
	{send_to_char("The spell failed.\n\r",ch);return;}
	if (obj->in_room == NULL)
	{send_to_char("The spell failed.\n\r",ch);return;}
    }

    if (page->toughness < PURPLE_MAGIC || page->toughness > YELLOW_MAGIC)
	{send_to_char("The spell failed.\n\r",ch);return;}
    if (page->toughness == PURPLE_MAGIC)
    {
	if ( ( sn = skill_lookup( "purple sorcery" ) ) < 0 )
	{send_to_char("The spell failed.\n\r",ch);return;}
    }
    else if (page->toughness == RED_MAGIC)
    {
	if ( ( sn = skill_lookup( "red sorcery" ) ) < 0 )
	{send_to_char("The spell failed.\n\r",ch);return;}
    }
    else if (page->toughness == BLUE_MAGIC)
    {
	if ( ( sn = skill_lookup( "blue sorcery" ) ) < 0 )
	{send_to_char("The spell failed.\n\r",ch);return;}
    }
    else if (page->toughness == GREEN_MAGIC)
    {
	if ( ( sn = skill_lookup( "green sorcery" ) ) < 0 )
	{send_to_char("The spell failed.\n\r",ch);return;}
    }
    else if (page->toughness == YELLOW_MAGIC)
    {
	if ( ( sn = skill_lookup( "yellow sorcery" ) ) < 0 )
	{send_to_char("The spell failed.\n\r",ch);return;}
    }
    else {send_to_char("The spell failed.\n\r",ch);return;}

    if (!victim_target && victim != ch)
	{send_to_char("The spell failed.\n\r",ch);return;}
    if (not_caster && ch == victim)
	{send_to_char("The spell failed.\n\r",ch);return;}
    else if (no_players && !IS_NPC(victim))
	{send_to_char("The spell failed.\n\r",ch);return;}

    if ( is_affected( victim, sn ) )
    {
	send_to_char("They are already affected by a spell of that colour.\n\r",ch);
	return;
    }

    if ( apply_bit == 0 )
    {
	enhance_stat(sn,level,ch,victim,APPLY_NONE,bonuses,affect_bit);
	affect_bit = 0;
	any_affects = TRUE;
    }
    if ( IS_SET(apply_bit, ADV_STR) )
    {
	enhance_stat(sn,level,ch,victim,APPLY_STR,bonuses * 0.1,affect_bit);
	affect_bit = 0;
	any_affects = TRUE;
    }
    if ( IS_SET(apply_bit, ADV_DEX) )
    {
	enhance_stat(sn,level,ch,victim,APPLY_DEX,bonuses * 0.1,affect_bit);
	affect_bit = 0;
	any_affects = TRUE;
    }
    if ( IS_SET(apply_bit, ADV_INT) )
    {
	enhance_stat(sn,level,ch,victim,APPLY_INT,bonuses * 0.1,affect_bit);
	affect_bit = 0;
	any_affects = TRUE;
    }
    if ( IS_SET(apply_bit, ADV_WIS) )
    {
	enhance_stat(sn,level,ch,victim,APPLY_WIS,bonuses * 0.1,affect_bit);
	affect_bit = 0;
	any_affects = TRUE;
    }
    if ( IS_SET(apply_bit, ADV_CON) )
    {
	enhance_stat(sn,level,ch,victim,APPLY_CON,bonuses * 0.1,affect_bit);
	affect_bit = 0;
	any_affects = TRUE;
    }
    if ( IS_SET(apply_bit, ADV_MANA) )
    {
	enhance_stat(sn,level,ch,victim,APPLY_MANA,bonuses * 5,affect_bit);
	affect_bit = 0;
	any_affects = TRUE;
    }
    if ( IS_SET(apply_bit, ADV_HIT) )
    {
	enhance_stat(sn,level,ch,victim,APPLY_HIT,bonuses * 5,affect_bit);
	affect_bit = 0;
	any_affects = TRUE;
    }
    if ( IS_SET(apply_bit, ADV_MOVE) )
    {
	enhance_stat(sn,level,ch,victim,APPLY_MOVE,bonuses * 5,affect_bit);
	affect_bit = 0;
	any_affects = TRUE;
    }
    if ( IS_SET(apply_bit, ADV_AC) )
    {
	enhance_stat(sn,level,ch,victim,APPLY_AC,0 - (bonuses * 5),affect_bit);
	affect_bit = 0;
	any_affects = TRUE;
    }
    if ( IS_SET(apply_bit, ADV_HITROLL) )
    {
	enhance_stat(sn,level,ch,victim,APPLY_HITROLL,bonuses * 0.5,affect_bit);
	affect_bit = 0;
	any_affects = TRUE;
    }
    if ( IS_SET(apply_bit, ADV_DAMROLL) )
    {
	enhance_stat(sn,level,ch,victim,APPLY_DAMROLL,bonuses * 0.5,affect_bit);
	affect_bit = 0;
	any_affects = TRUE;
    }
    if ( IS_SET(apply_bit, ADV_SAVING_SPELL) )
    {
	enhance_stat(sn,level,ch,victim,APPLY_SAVING_SPELL,bonuses*0.2,affect_bit);
	affect_bit = 0;
	any_affects = TRUE;
    }
    if (!any_affects) {send_to_char("The spell failed.\n\r",ch);return;}

    if (cast_message) act2(c_m,ch,NULL,victim,TO_CHAR);
    if (message_one)  act2(c_1,ch,NULL,victim,TO_VICT);
    if (message_two)  act2(c_2,ch,NULL,victim,TO_NOTVICT);
    if (!IS_IMMORTAL(ch))
    {
	WAIT_STATE(ch,12);
	ch->mana -= mana_cost;
    }

    if (IS_SET(page->spectype, ADV_NEXT_PAGE) &&
	!IS_SET(page->spectype, ADV_SPELL_FIRST))
    {
	if (strlen(page->chpoweroff) < 2 || !str_cmp(page->chpoweroff,"(null)"))
	{send_to_char("The spell failed.\n\r",ch);return;}
	if (IS_SET(page->spectype, ADV_PARAMETER))
	{
	    if (!str_cmp(page->chpoweron,"(null)"))
		{send_to_char("The spell failed.\n\r",ch);return;}
	    else strcpy(next_par,page->chpoweron);
	}
	else strcpy(next_par,argument);
	if ( page->specpower < page->value[0] )
	{send_to_char( "The spell failed.\n\r", ch );return;}
	if ( ( page_next = get_page( book, page->specpower ) ) == NULL )
	{send_to_char( "The spell failed.\n\r", ch );return;}
	if (IS_SET(page_next->quest, QUEST_MASTER_RUNE))
	{
	    if      (IS_SET(page_next->spectype, ADV_DAMAGE))
		adv_spell_damage(ch,book,page_next,next_par);
	    else if (IS_SET(page_next->spectype, ADV_AFFECT))
		adv_spell_affect(ch,book,page_next,next_par);
	    else if (IS_SET(page_next->spectype, ADV_ACTION))
		adv_spell_action(ch,book,page_next,next_par);
	    else {send_to_char( "The spell failed.\n\r", ch );return;}
	}
	else {send_to_char( "The spell failed.\n\r", ch );return;}
    }
    return;
}

void adv_spell_action( CHAR_DATA *ch, OBJ_DATA *book, OBJ_DATA *page, char *argument)
{
    char arg1 [MAX_STRING_LENGTH];
    char arg2 [MAX_STRING_LENGTH];
    char c_m [MAX_INPUT_LENGTH];
    char c_1 [MAX_INPUT_LENGTH];
    char c_2 [MAX_INPUT_LENGTH];
    OBJ_DATA *page_next;
    OBJ_DATA *obj = NULL;
    OBJ_DATA *obj2 = NULL;
    CHAR_DATA *victim = NULL;
    CHAR_DATA *victim2 = NULL;
    ROOM_INDEX_DATA *old_room = ch->in_room;
    char next_par [MAX_INPUT_LENGTH];
    int mana_cost = page->points;
    int action_bit = page->value[1];
    int action_type = page->value[2];
    bool area_affect = FALSE;
    bool victim_target = FALSE;
    bool object_target = FALSE;
    bool second_victim = FALSE;
    bool second_object = FALSE;
    bool global_target = FALSE;
    bool next_page = FALSE;
    bool parameter = FALSE;
    bool not_caster = FALSE;
    bool no_players = FALSE;
    bool cast_message = FALSE;
    bool message_one = FALSE;
    bool message_two = FALSE;
    bool is_reversed = FALSE;

    if (ch->mana < mana_cost)
    {send_to_char("You have insufficient mana to chant this spell.\n\r",ch);return;}

    if (IS_SET(page->spectype, ADV_NEXT_PAGE) &&
	IS_SET(page->spectype, ADV_SPELL_FIRST))
    {
	if (strlen(page->chpoweroff) < 2 || !str_cmp(page->chpoweroff,"(null)"))
	{send_to_char("The spell failed.\n\r",ch);return;}
	if (IS_SET(page->spectype, ADV_PARAMETER))
	{
	    if (!str_cmp(page->chpoweron,"(null)"))
		{send_to_char("The spell failed.\n\r",ch);return;}
	    else strcpy(next_par,page->chpoweron);
	}
	else strcpy(next_par,argument);
	if ( page->specpower < page->value[0] )
	{send_to_char( "The spell failed.\n\r", ch );return;}
	if ( ( page_next = get_page( book, page->specpower ) ) == NULL )
	{send_to_char( "The spell failed.\n\r", ch );return;}
	if (IS_SET(page_next->quest, QUEST_MASTER_RUNE))
	{
	    if      (IS_SET(page_next->spectype, ADV_DAMAGE))
		adv_spell_damage(ch,book,page_next,next_par);
	    else if (IS_SET(page_next->spectype, ADV_AFFECT))
		adv_spell_affect(ch,book,page_next,next_par);
	    else if (IS_SET(page_next->spectype, ADV_ACTION))
		adv_spell_action(ch,book,page_next,next_par);
	    else {send_to_char( "The spell failed.\n\r", ch );return;}
	}
	else {send_to_char( "The spell failed.\n\r", ch );return;}
    }

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if (strlen(page->chpoweroff) > 0 && str_cmp(page->chpoweroff,"(null)"))
	{strcpy(c_m,page->chpoweroff);cast_message = TRUE;}
    if (strlen(page->victpoweron) > 0 && str_cmp(page->victpoweron,"(null)"))
	{strcpy(c_1,page->victpoweron);message_one = TRUE;}
    if (strlen(page->victpoweroff) > 0 && str_cmp(page->victpoweroff,"(null)"))
	{strcpy(c_2,page->victpoweroff);message_two = TRUE;}

    if (IS_SET(page->spectype, ADV_AREA_AFFECT  )) area_affect   = TRUE;
    if (IS_SET(page->spectype, ADV_VICTIM_TARGET)) victim_target = TRUE;
    if (IS_SET(page->spectype, ADV_OBJECT_TARGET)) object_target = TRUE;
    if (IS_SET(page->spectype, ADV_GLOBAL_TARGET)) global_target = TRUE;
    if (IS_SET(page->spectype, ADV_NEXT_PAGE    )) next_page     = TRUE;
    if (IS_SET(page->spectype, ADV_PARAMETER    )) parameter     = TRUE;
    if (IS_SET(page->spectype, ADV_NOT_CASTER   )) not_caster    = TRUE;
    if (IS_SET(page->spectype, ADV_NO_PLAYERS   )) no_players    = TRUE;
    if (IS_SET(page->spectype, ADV_SECOND_VICTIM)) second_victim = TRUE;
    if (IS_SET(page->spectype, ADV_SECOND_OBJECT)) second_object = TRUE;
    if (IS_SET(page->spectype, ADV_REVERSED     )) is_reversed   = TRUE;

    if (victim_target && !area_affect && !global_target && !object_target)
    {
	if ( ( victim = get_char_room( ch, arg1 ) ) == NULL )
	{send_to_char("The spell failed.\n\r",ch);return;}
	if (victim->in_room == NULL)
	{send_to_char("The spell failed.\n\r",ch);return;}
	if (!IS_NPC(victim) && !IS_IMMUNE(victim, IMM_SUMMON))
	{send_to_char("The spell failed.\n\r",ch);return;}
	if (victim == ch)
	{send_to_char("The spell failed.\n\r",ch);return;}
    }
    else if (victim_target && area_affect && !global_target && !object_target)
    {
	if ( ( victim = get_char_world( ch, arg1 ) ) == NULL )
	{send_to_char("The spell failed.\n\r",ch);return;}
	if (victim->in_room == NULL ||
	    victim->in_room->area != ch->in_room->area)
	{send_to_char("The spell failed.\n\r",ch);return;}
	if (!IS_NPC(victim) && !IS_IMMUNE(victim, IMM_SUMMON))
	{send_to_char("The spell failed.\n\r",ch);return;}
	if (victim == ch)
	{send_to_char("The spell failed.\n\r",ch);return;}
    }
    else if (victim_target && global_target && !object_target)
    {
	if ( ( victim = get_char_world( ch, arg1 ) ) == NULL )
	{send_to_char("The spell failed.\n\r",ch);return;}
	if (victim->in_room == NULL)
	{send_to_char("The spell failed.\n\r",ch);return;}
	if (!IS_NPC(victim) && !IS_IMMUNE(victim, IMM_SUMMON))
	{send_to_char("The spell failed.\n\r",ch);return;}
	if (victim == ch)
	{send_to_char("The spell failed.\n\r",ch);return;}
    }
    else if (object_target && !area_affect && !global_target && !victim_target)
    {
	if ( ( obj = get_obj_carry( ch, arg1 ) ) == NULL )
	{send_to_char("The spell failed.\n\r",ch);return;}
    }
    else if (object_target && area_affect && !global_target && !victim_target)
    {
	if ( ( obj = get_obj_here( ch, arg1 ) ) == NULL )
	{send_to_char("The spell failed.\n\r",ch);return;}
    }
    else if (object_target && global_target && !victim_target)
    {
	if ( ( obj = get_obj_world( ch, arg1 ) ) == NULL )
	{send_to_char("The spell failed.\n\r",ch);return;}
	if (obj->in_room == NULL)
	{send_to_char("The spell failed.\n\r",ch);return;}
    }

    if ( arg2[0] == '\0' && (second_victim || second_object) )
    {
	send_to_char("Please specify a target.\n\r",ch);
	return;
    }
    else if (second_victim && victim_target && !area_affect && !global_target && !object_target)
    {
	if ( ( victim2 = get_char_room( ch, arg2 ) ) == NULL )
	{send_to_char("The spell failed.\n\r",ch);return;}
	if (victim2->in_room == NULL)
	{send_to_char("The spell failed.\n\r",ch);return;}
	if (victim == NULL || IS_NPC(victim) || IS_IMMUNE(victim, IMM_SUMMON))
	{send_to_char("The spell failed.\n\r",ch);return;}
	if (!IS_NPC(victim2) && !IS_IMMUNE(victim2, IMM_SUMMON))
	{send_to_char("The spell failed.\n\r",ch);return;}
	if (victim == victim2)
	{send_to_char("The spell failed.\n\r",ch);return;}
    }
    else if (second_victim && victim_target && area_affect && !global_target && !object_target)
    {
	if ( ( victim2 = get_char_world( ch, arg2 ) ) == NULL )
	{send_to_char("The spell failed.\n\r",ch);return;}
	if (victim2->in_room == NULL ||
	    victim2->in_room->area != ch->in_room->area)
	{send_to_char("The spell failed.\n\r",ch);return;}
	if (victim == NULL || IS_NPC(victim) || IS_IMMUNE(victim, IMM_SUMMON))
	{send_to_char("The spell failed.\n\r",ch);return;}
	if (!IS_NPC(victim2) && !IS_IMMUNE(victim2, IMM_SUMMON))
	{send_to_char("The spell failed.\n\r",ch);return;}
	if (victim == victim2)
	{send_to_char("The spell failed.\n\r",ch);return;}
    }
    else if (second_victim && victim_target && global_target && !object_target)
    {
	if ( ( victim2 = get_char_world( ch, arg2 ) ) == NULL )
	{send_to_char("The spell failed.\n\r",ch);return;}
	if (victim2->in_room == NULL)
	{send_to_char("The spell failed.\n\r",ch);return;}
	if (victim == NULL || IS_NPC(victim) || IS_IMMUNE(victim, IMM_SUMMON))
	{send_to_char("The spell failed.\n\r",ch);return;}
	if (!IS_NPC(victim2) && !IS_IMMUNE(victim2, IMM_SUMMON))
	{send_to_char("The spell failed.\n\r",ch);return;}
	if (victim == victim2)
	{send_to_char("The spell failed.\n\r",ch);return;}
    }
    else if (second_object && object_target && !area_affect && !global_target && !victim_target)
    {
	if ( ( obj2 = get_obj_carry( ch, arg2 ) ) == NULL )
	{send_to_char("The spell failed.\n\r",ch);return;}
    }
    else if (second_object && object_target && area_affect && !global_target && !victim_target)
    {
	if ( ( obj2 = get_obj_here( ch, arg2 ) ) == NULL )
	{send_to_char("The spell failed.\n\r",ch);return;}
    }
    else if (second_object && object_target && global_target && !victim_target)
    {
	if ( ( obj2 = get_obj_world( ch, arg2 ) ) == NULL )
	{send_to_char("The spell failed.\n\r",ch);return;}
    }

    if (victim != NULL)
    {
	if (victim->level > ch->spl[PURPLE_MAGIC])
	{
	    send_to_char("The spell failed.\n\r",ch);
	    return;
	}
    }

    if (victim2 != NULL)
    {
	if (victim2->level > ch->spl[PURPLE_MAGIC])
	{
	    send_to_char("The spell failed.\n\r",ch);
	    return;
	}
    }

    switch ( action_bit )
    {
    default:
	send_to_char("The spell failed.\n\r",ch);
	return;
    case ACTION_MOVE:
	if (!victim_target && !second_victim && !object_target && !second_object)
	{
	    if (cast_message) act2(c_m,ch,NULL,NULL,TO_CHAR);
	    if (message_one) act2(c_1,ch,NULL,NULL,TO_ROOM);
	    char_from_room(ch);
	    char_to_room(ch,old_room);
	    if (message_two) act2(c_2,ch,NULL,NULL,TO_ROOM);
	}
	else if ( arg1[0] == '\0' )
	{
	    send_to_char("Please specify a target.\n\r",ch);
	    return;
	}
	else if (victim_target && !second_victim && !object_target && !second_object)
	{
	    if (victim == NULL || victim->in_room == NULL ||
		victim->in_room == ch->in_room)
	    {send_to_char("The spell failed.\n\r",ch);return;}
	    if (is_reversed)
	    {
		if (victim->position == POS_FIGHTING)
		{send_to_char("The spell failed.\n\r",ch);return;}
		if (cast_message) act2(c_m,victim,NULL,NULL,TO_CHAR);
		if (message_one) act2(c_1,victim,NULL,NULL,TO_ROOM);
		char_from_room(victim);
		char_to_room(victim,ch->in_room);
		if (message_two) act2(c_2,victim,NULL,NULL,TO_ROOM);
		do_look(victim,"");
	    }
	    else
	    {
		if (ch->position == POS_FIGHTING)
		{send_to_char("The spell failed.\n\r",ch);return;}
		if (cast_message) act2(c_m,ch,NULL,NULL,TO_CHAR);
		if (message_one) act2(c_1,ch,NULL,NULL,TO_ROOM);
		char_from_room(ch);
		char_to_room(ch,victim->in_room);
		if (message_two) act2(c_2,ch,NULL,NULL,TO_ROOM);
		do_look(ch,"");
	    }
	}
	else if (!victim_target && !second_victim && object_target && !second_object)
	{
	    if (obj == NULL || obj->in_room == NULL ||
		obj->in_room == ch->in_room)
	    {send_to_char("The spell failed.\n\r",ch);return;}
	    if (cast_message) act2(c_m,ch,obj,NULL,TO_CHAR);
	    if (message_one) act2(c_1,ch,obj,NULL,TO_ROOM);
	    if (is_reversed)
	    {
		obj_from_room(obj);
		obj_to_room(obj,ch->in_room);
	    }
	    else
	    {
		char_from_room(ch);
		char_to_room(ch,obj->in_room);
		do_look(ch,"");
	    }
	    if (message_two) act2(c_2,ch,obj,NULL,TO_ROOM);
	}
	else if (victim_target && second_victim && !object_target && !second_object)
	{
	    if (victim == NULL || victim->in_room == NULL)
	    {send_to_char("The spell failed.\n\r",ch);return;}
	    if (victim2 == NULL || victim2->in_room == NULL ||
		victim2->in_room == victim->in_room)
	    {send_to_char("The spell failed.\n\r",ch);return;}
	    if (is_reversed)
	    {
		if (victim2->position == POS_FIGHTING)
		{send_to_char("The spell failed.\n\r",ch);return;}
		if (cast_message) act2(c_m,victim2,NULL,victim,TO_CHAR);
		if (message_one) act2(c_1,victim2,NULL,victim,TO_ROOM);
		char_from_room(victim2);
		char_to_room(victim2,victim->in_room);
		if (message_two) act2(c_2,victim2,NULL,victim,TO_ROOM);
		do_look(victim2,"");
	    }
	    else
	    {
		if (victim->position == POS_FIGHTING)
		{send_to_char("The spell failed.\n\r",ch);return;}
		if (cast_message) act2(c_m,victim,NULL,victim2,TO_CHAR);
		if (message_one) act2(c_1,victim,NULL,victim2,TO_ROOM);
		char_from_room(victim);
		char_to_room(victim,victim2->in_room);
		if (message_two) act2(c_2,victim,NULL,victim2,TO_ROOM);
		do_look(victim,"");
	    }
	}
	else if (victim_target && !second_victim && !object_target && second_object)
	{
	    if (victim == NULL || victim->in_room == NULL)
	    {send_to_char("The spell failed.\n\r",ch);return;}
	    if (obj2 == NULL || obj2->in_room == NULL ||
		obj2->in_room == victim->in_room)
	    {send_to_char("The spell failed.\n\r",ch);return;}
	    if (cast_message) act2(c_m,victim,NULL,NULL,TO_CHAR);
	    if (message_one) act2(c_1,victim,obj2,NULL,TO_ROOM);
	    if (is_reversed)
	    {
		obj_from_room(obj2);
		obj_to_room(obj2,victim->in_room);
	    }
	    else
	    {
		if (victim->position == POS_FIGHTING)
		{send_to_char("The spell failed.\n\r",ch);return;}
		char_from_room(victim);
		char_to_room(victim,obj2->in_room);
		do_look(victim,"");
	    }
	    if (message_two) act2(c_2,victim,obj2,NULL,TO_ROOM);
	}
	else if (!victim_target && !second_victim && object_target && second_object)
	{
	    if (obj == NULL || obj->in_room == NULL)
	    {send_to_char("The spell failed.\n\r",ch);return;}
	    if (obj2 == NULL || obj2->in_room == NULL ||
		obj2->in_room == obj->in_room)
	    {send_to_char("The spell failed.\n\r",ch);return;}
	    if (cast_message) act2(c_m,ch,obj,NULL,TO_CHAR);
	    if (is_reversed)
	    {
		old_room = ch->in_room;
		if (message_one) act2(c_1,ch,obj2,NULL,TO_ROOM);
		obj_from_room(obj2);
		obj_to_room(obj2,obj->in_room);
		char_from_room(ch);
		char_to_room(ch,obj->in_room);
		if (message_two) act2(c_2,ch,obj2,NULL,TO_ROOM);
		char_from_room(ch);
		char_to_room(ch,old_room);
	    }
	    else
	    {
		old_room = ch->in_room;
		if (message_one) act2(c_1,ch,obj,NULL,TO_ROOM);
		obj_from_room(obj);
		obj_to_room(obj,obj2->in_room);
		char_from_room(ch);
		char_to_room(ch,obj2->in_room);
		if (message_two) act2(c_2,ch,obj,NULL,TO_ROOM);
		char_from_room(ch);
		char_to_room(ch,old_room);
	    }
	}
	else if (!victim_target && second_victim && object_target && !second_object)
	{
	    if (victim2 == NULL || victim2->in_room == NULL)
	    {send_to_char("The spell failed.\n\r",ch);return;}
	    if (obj == NULL || obj->in_room == NULL ||
		obj->in_room == victim2->in_room)
	    {send_to_char("The spell failed.\n\r",ch);return;}
	    if (cast_message) act2(c_m,victim2,NULL,NULL,TO_CHAR);
	    if (message_one) act2(c_1,victim,obj2,NULL,TO_ROOM);
	    if (is_reversed)
	    {
		if (victim2->position == POS_FIGHTING)
		{send_to_char("The spell failed.\n\r",ch);return;}
		char_from_room(victim2);
		char_to_room(victim2,obj->in_room);
		do_look(victim2,"");
	    }
	    else
	    {
		obj_from_room(obj);
		obj_to_room(obj,victim2->in_room);
	    }
	    if (message_two) act2(c_2,victim2,obj,NULL,TO_ROOM);
	}
	else {send_to_char("The spell failed.\n\r",ch);return;}
	break;
    case ACTION_MOB:
	if ( action_type < 1)
	{send_to_char("The spell failed.\n\r",ch);return;}
	if (IS_NPC(ch) || ch->pcdata->followers > 4)
	{send_to_char("The spell failed.\n\r",ch);return;}
	if (( victim = create_mobile( get_mob_index( action_type ))) == NULL )
	{send_to_char("The spell failed.\n\r",ch);return;}
	if (cast_message) act2(c_m,ch,NULL,victim,TO_CHAR);
	if (message_one) act2(c_1,ch,NULL,victim,TO_ROOM);
	ch->pcdata->followers++;
	char_to_room( victim, ch->in_room );
	SET_BIT(victim->act, ACT_NOEXP);
	free_string(victim->lord);
	victim->lord = str_dup(ch->name);
	if (victim->level > ch->spl[PURPLE_MAGIC])
	{
	    send_to_char("The spell failed.\n\r",ch);
	    extract_char(victim, TRUE);
	    return;
	}
	break;
    case ACTION_OBJECT:
	if ( action_type < 1)
	{send_to_char("The spell failed.\n\r",ch);return;}
	if (( obj = create_object( get_obj_index( action_type ),0 )) == NULL )
	{send_to_char("The spell failed.\n\r",ch);return;}
	if (cast_message) act2(c_m,ch,obj,NULL,TO_CHAR);
	if (message_one) act2(c_1,ch,obj,NULL,TO_ROOM);
	free_string(obj->questmaker);
	obj->questmaker = str_dup(ch->name);
	obj_to_room( obj, ch->in_room );
	break;
    }
    if (!IS_IMMORTAL( ch ))
    {
	WAIT_STATE(ch,12);
	ch->mana -= mana_cost;
    }

    if (IS_SET(page->spectype, ADV_NEXT_PAGE) &&
	!IS_SET(page->spectype, ADV_SPELL_FIRST))
    {
	if (strlen(page->chpoweroff) < 2 || !str_cmp(page->chpoweroff,"(null)"))
	{send_to_char("The spell failed.\n\r",ch);return;}
	if (IS_SET(page->spectype, ADV_PARAMETER))
	{
	    if (!str_cmp(page->chpoweron,"(null)"))
		{send_to_char("The spell failed.\n\r",ch);return;}
	    else strcpy(next_par,page->chpoweron);
	}
	else strcpy(next_par,argument);
	if ( page->specpower < page->value[0] )
	{send_to_char( "The spell failed.\n\r", ch );return;}
	if ( ( page_next = get_page( book, page->specpower ) ) == NULL )
	{send_to_char( "The spell failed.\n\r", ch );return;}
	if (IS_SET(page_next->quest, QUEST_MASTER_RUNE))
	{
	    if      (IS_SET(page_next->spectype, ADV_DAMAGE))
		adv_spell_damage(ch,book,page_next,next_par);
	    else if (IS_SET(page_next->spectype, ADV_AFFECT))
		adv_spell_affect(ch,book,page_next,next_par);
	    else if (IS_SET(page_next->spectype, ADV_ACTION))
		adv_spell_action(ch,book,page_next,next_par);
	    else {send_to_char( "The spell failed.\n\r", ch );return;}
	}
	else {send_to_char( "The spell failed.\n\r", ch );return;}
    }
    return;
}


void do_mlearn(CHAR_DATA *ch, char *argument) {

	char arg1[MAX_STRING_LENGTH];
	char arg2[MAX_STRING_LENGTH];
	int type = 0;
	int power = 0;
	int cost;
	bool master = TRUE;

	argument = one_argument( argument, arg1);
	argument = one_argument( argument, arg2);

	if (IS_NPC(ch)) return;

	if (!IS_CLASS(ch, CLASS_MAGE)) {
	send_to_char("Huh?\n\r", ch );
	return;}

	if (!str_cmp(arg1,"sigil")) {
	power = MPOWER_SIGILS;
	if (!str_cmp(arg2,"self")) type = SIGIL_SELF;
	else if (!str_cmp(arg2,"targeting")) type = SIGIL_TARGETING;
	else if (!str_cmp(arg2,"area")) type = SIGIL_AREA;
	else if (!str_cmp(arg2,"object")) type = SIGIL_OBJECT;	
	}

	if (!str_cmp(arg1,"rune")) {
	power = MPOWER_RUNES;
	if (!str_cmp(arg2,"mastery")) type = RUNE_MASTER;
	else if (!str_cmp(arg2,"spirit")) type = RUNE_SPIRIT;
	else if (!str_cmp(arg2,"mind")) type = RUNE_MIND;
	else if (!str_cmp(arg2,"life")) type = RUNE_LIFE;
	else if (!str_cmp(arg2,"death")) type = RUNE_DEATH;
	else if (!str_cmp(arg2,"earth")) type = RUNE_EARTH;
	else if (!str_cmp(arg2,"air")) type = RUNE_AIR;
	else if (!str_cmp(arg2,"fire")) type = RUNE_FIRE;
	else if (!str_cmp(arg2,"water")) type = RUNE_WATER;
	else if (!str_cmp(arg2,"dark")) type = RUNE_DARK;
	else if (!str_cmp(arg2,"light")) type = RUNE_LIGHT;
	}

	if (!str_cmp(arg1,"glyph")) {
	power = MPOWER_GLYPHS;
	if (!str_cmp(arg2,"protection")) type = GLYPH_PROTECTION;
	else if (!str_cmp(arg2,"reduction")) type = GLYPH_REDUCTION;
	else if (!str_cmp(arg2,"control")) type = GLYPH_CONTROL;
	else if (!str_cmp(arg2,"destruction")) type = GLYPH_DESTRUCTION;
	else if (!str_cmp(arg2,"transportation")) type = GLYPH_TRANSPORTATION;
	else if (!str_cmp(arg2,"transformation")) type = GLYPH_TRANSFORMATION;
	else if (!str_cmp(arg2,"creation")) type = GLYPH_CREATION;
	else if (!str_cmp(arg2,"information")) type = GLYPH_INFORMATION;
	else if (!str_cmp(arg2,"summoning")) type = GLYPH_SUMMONING;
	else if (!str_cmp(arg2,"enhancement")) type = GLYPH_ENHANCEMENT;
	}

	if (power == 0) {
	send_to_char("Syntax:  mlearn [power] [type]\n\r", ch );
	send_to_char("\n\rtypes:  sigil, glyph, rune\n\r\n\r", ch);
	return;}

	if (power == MPOWER_SIGILS && type == 0) {
	send_to_char("Syntax:  mlearn sigil [type]\n\r\n\r", ch);
	send_to_char("types:  area, object, self, targeting\n\r\n\r", ch);
	return;}

	if (power == MPOWER_GLYPHS && type == 0) {
	send_to_char("Syntax:  mlearn glyph [type]\n\r\n\r", ch);
	send_to_char("types:  creation, destruction, summoning, transformation\n\r", ch);
	send_to_char("        transportation, enhancement, reduction, control\n\r", ch);
	send_to_char("        protection, information\n\r\n\r", ch);
	return;}

	if (power == MPOWER_RUNES && type == 0) {
	send_to_char("Syntax:  mlearn rune [type]\n\r\n\r", ch );
	send_to_char("types:  fire, air, earth, water, dark, light\n\r", ch );
	send_to_char("        life, death, mind, spirit\n\r", ch );
	send_to_char("        MASTERY\n\r\n\r", ch );
	return;}

	if (power == MPOWER_RUNES && type == RUNE_MASTER) {

	if (IS_SET(ch->pcdata->powers[MPOWER_RUNES], RUNE_MASTER)) {
	send_to_char("You already have that.\n\r", ch );
	return;}
	/*
	for (i = 0; i < 5; i++)
	if (ch->spl[i] < 240)
	master = FALSE;
	*/

	if (ch->spl[ch->pcdata->powers[0]] < 240) master = FALSE;	

	if (!master) {
	send_to_char("You must completely master your spell color first.\n\r",ch );
	return;}

	if (ch->exp < 7500000) {
	send_to_char("You need 7500000 experience to learn to make the rune of mastery.\n\r", ch );
	return;}

	SET_BIT(ch->pcdata->powers[power], type);
	ch->exp -= 7500000;
	send_to_char("You learn how to make the rune of mastery.\n\r", ch );
	return;
	}

	if (power == MPOWER_SIGILS) cost = 50;
	else cost = 25;

	if (ch->practice < cost) {
	send_to_char("You do not have enough primal for that.\n\r", ch );
	send_to_char("You need 50 primal for sigils, and 25 for others.\n\r", ch);
	return;}

	SET_BIT(ch->pcdata->powers[power], type);
	ch->practice -= cost;
	send_to_char("You learn a new power.\n\r", ch );

	return;
}



 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
 *                                                                         *
 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
 *  Chastain, Michael Quan, and Mitchell Tse.                              *
 *                                                                         *
 *  In order to use any part of this Merc Diku Mud, you must comply with   *
 *  both the original Diku license in 'license.doc' as well the Merc       *
 *  license in 'license.txt'.  In particular, you may not remove either of *
 *  these copyright notices.                                               *
 *                                                                         *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 ***************************************************************************/

#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"



/*
 * Local functions.
 */
void	say_spell	args( ( CHAR_DATA *ch, int sn ) );
void	improve_spl	args( ( CHAR_DATA *ch, int dtype, int sn ) );




/*
 * Improve ability at a certain spell type.  KaVir.
 */
 

void improve_spl( CHAR_DATA *ch, int dtype, int sn )
{
    char buf[MAX_INPUT_LENGTH];
    char bufskill[MAX_INPUT_LENGTH];
    char buftype[MAX_INPUT_LENGTH];
    int dice1;
    int dice2;

    dice1 = number_percent();
    dice2 = number_percent();



         if (dtype == 0 ) sprintf(buftype,"purple");
    else if (dtype == 1 ) sprintf(buftype,"red");
    else if (dtype == 2 ) sprintf(buftype,"blue");
    else if (dtype == 3 ) sprintf(buftype,"green");
    else if (dtype == 4 ) sprintf(buftype,"yellow");
    else return;

    if (ch->spl[dtype] >= 200 && !IS_CLASS(ch, CLASS_MAGE) &&

	!(IS_CLASS(ch, CLASS_DROW) && IS_SET(ch->special, SPC_DROW_MAG)
&& (dtype == 0 || dtype == 1)) &&

	!(IS_CLASS(ch, CLASS_DROW) && IS_SET(ch->special, SPC_DROW_CLE)
&& (dtype == 2 || dtype == 3))

) return;
    if (ch->spl[dtype] >= 240) return;
    if ((dice1 > ch->spl[dtype] || dice2 > ch->spl[dtype]) || (dice1==100 || dice2==100)) ch->spl[dtype] += 1;
    else return;

         if (ch->spl[dtype] == 1  ) sprintf(bufskill,"an apprentice of");
    else if (ch->spl[dtype] == 26 ) sprintf(bufskill,"a student at");
    else if (ch->spl[dtype] == 51 ) sprintf(bufskill,"a scholar at");
    else if (ch->spl[dtype] == 76 ) sprintf(bufskill,"a magus at");
    else if (ch->spl[dtype] == 101) sprintf(bufskill,"an adept at");
    else if (ch->spl[dtype] == 126) sprintf(bufskill,"a mage at");
    else if (ch->spl[dtype] == 151) sprintf(bufskill,"a warlock at");
    else if (ch->spl[dtype] == 176) sprintf(bufskill,"a master wizard at");
    else if (ch->spl[dtype] == 200) sprintf(bufskill,"a grand sorcerer at");
    else if (ch->spl[dtype] == 240) sprintf(bufskill,"the complete master of");
    else return;
    sprintf(buf,"You are now %s %s magic.\n\r",bufskill,buftype);
    ADD_COLOUR(ch,buf,WHITE);
    send_to_char(buf,ch);
    return;
}

bool is_obj( CHAR_DATA *ch )
{
    OBJ_DATA *obj;

    if ( ( obj = ch->pcdata->chobj ) == NULL )
    {
	send_to_char("Huh?\n\r",ch);
	return FALSE;
    }
    if ( obj->chobj == NULL || obj->chobj != ch )
    {
	send_to_char("Huh?\n\r",ch);
	return FALSE;
    }
    if (!IS_CLASS(ch,CLASS_DEMON) && !IS_SET(ch->special,SPC_CHAMPION))
    {
	send_to_char("Huh?\n\r",ch);
	return FALSE;
    }
    if (!IS_DEMPOWER(ch, DEM_MAGIC))
    {
	send_to_char("You haven't been granted the gift of Magic.\n\r",ch);
	return FALSE;
    }
    return TRUE;
}

/*
 * Lookup a skill by name.
 */
int skill_lookup( const char *name )
{
    int sn;

    for ( sn = 0; sn < MAX_SKILL; sn++ )
    {
	if ( skill_table[sn].name == NULL )
	    break;
	if ( LOWER(name[0]) == LOWER(skill_table[sn].name[0])
	&&   !str_prefix( name, skill_table[sn].name ) )
	    return sn;
    }

    return -1;
}



/*
 * Lookup a skill by slot number.
 * Used for object loading.
 */
int slot_lookup( int slot )
{
    extern bool fBootDb;
    int sn;

    if ( slot <= 0 )
	return -1;

    for ( sn = 0; sn < MAX_SKILL; sn++ )
    {
	if ( slot == skill_table[sn].slot )
	    return sn;
    }

    if ( fBootDb )
    {
	bug( "Slot_lookup: bad slot %d.", slot );
	abort( );
    }

    return -1;
}



/*
 * Utter mystical words for an sn.
 */
void say_spell( CHAR_DATA *ch, int sn )
{
    char buf  [MAX_STRING_LENGTH];
    char buf2 [MAX_STRING_LENGTH];
    char colour [MAX_STRING_LENGTH];
/*  CHAR_DATA *rch; */
    char *pName;
    int iSyl;
    int length;

    struct syl_type
    {
	char *	old;
	char *	new;
    };

    static const struct syl_type syl_table[] =
    {
	{ " ",		" "		},
	{ "ar",		"abra"		},
	{ "au",		"kada"		},
	{ "bless",	"fido"		},
	{ "blind",	"nose"		},
	{ "bur",	"mosa"		},
	{ "cu",		"judi"		},
	{ "de",		"oculo"		},
	{ "en",		"unso"		},
	{ "light",	"dies"		},
	{ "lo",		"hi"		},
	{ "mor",	"zak"		},
	{ "move",	"sido"		},
	{ "ness",	"lacri"		},
	{ "ning",	"illa"		},
	{ "per",	"duda"		},
	{ "ra",		"gru"		},
	{ "re",		"candus"	},
	{ "son",	"sabru"		},
	{ "tect",	"infra"		},
	{ "tri",	"cula"		},
	{ "ven",	"nofo"		},
	{ "a", "c" }, { "b", "b" }, { "c", "q" }, { "d", "e" },
	{ "e", "z" }, { "f", "m" }, { "g", "o" }, { "h", "p" },
	{ "i", "u" }, { "j", "y" }, { "k", "t" }, { "l", "r" },
	{ "m", "w" }, { "n", "i" }, { "o", "a" }, { "p", "s" },
	{ "q", "d" }, { "r", "f" }, { "s", "g" }, { "t", "h" },
	{ "u", "j" }, { "v", "z" }, { "w", "x" }, { "x", "n" },
	{ "y", "l" }, { "z", "k" },
	{ "", "" }
    };

    buf[0]	= '\0';
    for ( pName = skill_table[sn].name; *pName != '\0'; pName += length )
    {
	for ( iSyl = 0; (length = strlen(syl_table[iSyl].old)) != 0; iSyl++ )
	{
	    if ( !str_prefix( syl_table[iSyl].old, pName ) )
	    {
		strcat( buf, syl_table[iSyl].new );
		break;
	    }
	}

	if ( length == 0 )
	    length = 1;
    }

    sprintf( buf2, "$n utters the words, '%s'.", buf );
    sprintf( buf,  "$n utters the words, '%s'.", skill_table[sn].name );
    if ( skill_table[sn].target == 0 )
    {
    	sprintf(colour,"$n's eyes glow bright purple for a moment.");
    	ADD_COLOUR(ch,colour,MAGENTA);
    	act(colour,ch,NULL,NULL,TO_ROOM);
    	sprintf(colour,"Your eyes glow bright purple for a moment.");
    	ADD_COLOUR(ch,colour,MAGENTA);
    	act(colour,ch,NULL,NULL,TO_CHAR);
    }
    else if ( skill_table[sn].target == 1 )
    {
    	sprintf(colour,"$n's eyes glow bright red for a moment.");
    	ADD_COLOUR(ch,colour,L_RED);
    	act(colour,ch,NULL,NULL,TO_ROOM);
    	sprintf(colour,"Your eyes glow bright red for a moment.");
    	ADD_COLOUR(ch,colour,L_RED);
    	act(colour,ch,NULL,NULL,TO_CHAR);
    }
    else if ( skill_table[sn].target == 2 )
    {
    	sprintf(colour,"$n's eyes glow bright blue for a moment.");
    	ADD_COLOUR(ch,colour,L_BLUE);
    	act(colour,ch,NULL,NULL,TO_ROOM);
    	sprintf(colour,"Your eyes glow bright blue for a moment.");
    	ADD_COLOUR(ch,colour,L_BLUE);
    	act(colour,ch,NULL,NULL,TO_CHAR);
    }
    else if ( skill_table[sn].target == 3 )
    {
    	sprintf(colour,"$n's eyes glow bright green for a moment.");
    	ADD_COLOUR(ch,colour,L_GREEN);
    	act(colour,ch,NULL,NULL,TO_ROOM);
    	sprintf(colour,"Your eyes glow bright green for a moment.");
    	ADD_COLOUR(ch,colour,L_GREEN);
    	act(colour,ch,NULL,NULL,TO_CHAR);
    }
    else if ( skill_table[sn].target == 4 )
    {
    	sprintf(colour,"$n's eyes glow bright yellow for a moment.");
    	ADD_COLOUR(ch,colour,YELLOW);
    	act(colour,ch,NULL,NULL,TO_ROOM);
    	sprintf(colour,"Your eyes glow bright yellow for a moment.");
    	ADD_COLOUR(ch,colour,YELLOW);
    	act(colour,ch,NULL,NULL,TO_CHAR);
    }
    return;
}



/*
 * Compute a saving throw.
 * Negative apply's make saving throw better.
 */
bool saves_spell( int level, CHAR_DATA *victim )
{
    int save;
    int tsave;

    if (!IS_NPC(victim))
    {
	tsave = ( victim->spl[0]+victim->spl[1]+victim->spl[2]+
		  victim->spl[3]+victim->spl[4] ) * 0.05;
    	save = 50 + ( tsave - level - victim->saving_throw ) * 5;
    }
    else
    	save = 50 + ( victim->level - level - victim->saving_throw ) * 5;
    save = URANGE( 15, save, 85 );
    return number_percent( ) < save;
}



/*
 * The kludgy global is for spells who want more stuff from command line.
 */
char *target_name;

void do_cast( CHAR_DATA *ch, char *argument )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    OBJ_DATA *obj;
    void *vo;
    int mana;
    int sn;

    /*
     * Switched NPC's can cast spells, but others can't.
     */
    if ( IS_NPC(ch) && ch->desc == NULL )
	return;

    /* Polymorphed players cannot cast spells */
    if ( !IS_NPC(ch) && IS_AFFECTED(ch, AFF_POLYMORPH) && 
	!IS_VAMPAFF(ch,VAM_DISGUISED) && !IS_POLYAFF(ch, POLY_SPIDER)
	&& !IS_SET(ch->flag2, VAMP_OBJMASK) && !IS_CLASS(ch,CLASS_DEMON))
    {
	if ( !is_obj(ch) )
	{
	    send_to_char( "You cannot cast spells in this form.\n\r", ch );
	    return;
	}
    }

    if (IS_CLASS(ch,CLASS_VAMPIRE) && IS_AFFECTED(ch, AFF_PEACE))
    {
	stc("You are unable to cast spells with Majesty on.\n\r",ch);
	return;
    }

    if (form_data[ch->cur_form].can_cast == FALSE && ch->cur_form != 0)
    {
	stc("You cannot cast spells in this form.\n\r",ch);
	return;
    }

    if ( IS_ITEMAFF(ch, ITEMA_REFLECT))
    {
	send_to_char( "You are unable to focus your spell.\n\r", ch );
	return;
    }

    target_name = one_argument( argument, arg1 );
    one_argument( target_name, arg2 );

    if ( arg1[0] == '\0' )
    {
	send_to_char( "Cast which what where?\n\r", ch );
	return;
    }

    if ( ( sn = skill_lookup( arg1 ) ) < 0
    || ( !IS_NPC(ch) && ch->level < skill_table[sn].skill_level) )
    {
	send_to_char( "You can't do that.\n\r", ch );
	return;
    }
  
    if ( ch->position < skill_table[sn].minimum_position )
    {
	if (!IS_NPC(ch) && !IS_CLASS(ch, CLASS_VAMPIRE) &&
	    IS_VAMPAFF(ch, VAM_CELERITY))
	{
	    if ( ch->move < 25 )
	    {
		send_to_char( "You can't concentrate enough.\n\r", ch );
		return;
	    }
	    ch->move = ch->move - 25;
	}
	else
	{
	    if ( ch->move < 50 )
	    {
		send_to_char( "You can't concentrate enough.\n\r", ch );
		return;
	    }
	    ch->move = ch->move - 50;
	}
    }

    mana = IS_NPC(ch) ? 0 : UMAX(
	skill_table[sn].min_mana,
	100 / ( 2 + (ch->level*12) - skill_table[sn].skill_level) );

    if ( !IS_NPC(ch) && IS_SET(ch->special, SPC_WOLFMAN) )
    {
	if (ch->power[DISC_WERE_OWL] < 4) mana *= 2;
    }

    /*
     * Locate targets.
     */
    victim	= NULL;
    obj		= NULL;
    vo		= NULL;
      
    switch ( skill_table[sn].target )
    {
    default:
	bug( "Do_cast: bad target for sn %d.", sn );
	return;

    case TAR_IGNORE:
	break;

    case TAR_CHAR_OFFENSIVE:
	if ( arg2[0] == '\0' )
	{
	    if ( ( victim = ch->fighting ) == NULL )
	    {
		send_to_char( "Cast the spell on whom?\n\r", ch );
		return;
	    }
	}
	else
	{
	    if ( ( victim = get_char_room( ch, arg2 ) ) == NULL )
	    {
		send_to_char( "They aren't here.\n\r", ch );
		return;
	    }
	}

	if ( ch == victim )
	    send_to_char( "Cast this on yourself? Ok...\n\r", ch );

	if ( IS_ITEMAFF(victim, ITEMA_REFLECT))
	{
	    send_to_char( "You are unable to focus your spell upon them.\n\r", ch );
	    return;
	}

	if (!IS_NPC(victim) && (!CAN_PK(ch)||!CAN_PK(victim)) && (ch != victim))
	{
	    send_to_char( "You are unable to affect them.\n\r", ch );
	    return;
	}

        if (!IS_NPC(victim) && IS_CLASS( victim, CLASS_DROW ))
        {
            if (ch == victim )
            {
                send_to_char("You lower your magical resistance....\n\r", ch);
            }
            else if (number_percent ( )  <= victim->pcdata->stats[DROW_MAGIC])
            {
               send_to_char("Your spell does not affect them.\n\r", ch);
               return;
            }  
        }

	if ( !IS_NPC(ch) )
	{
	    if ( IS_AFFECTED(ch, AFF_CHARM) && ch->master == victim )
	    {
		send_to_char( "You can't do that on your own follower.\n\r",
		    ch );
		return;
	    }
	}

	vo = (void *) victim;
	break;

    case TAR_CHAR_DEFENSIVE:
	if ( arg2[0] == '\0' )
	{
	    victim = ch;
	}
	else
	{
	    if ( ( victim = get_char_room( ch, arg2 ) ) == NULL )
	    {
		send_to_char( "They aren't here.\n\r", ch );
		return;
	    }
	}

	if ( IS_ITEMAFF(victim, ITEMA_REFLECT))
	{
	    send_to_char( "You are unable to focus your spell upon them.\n\r", ch );
	    return;
	}

        if (!IS_NPC(victim) && IS_CLASS(victim, CLASS_DROW ))
        {
            if (ch == victim )
            {
                send_to_char("You lower your magical resistance....\n\r", ch);
            }
            else if (number_percent( ) <=victim->pcdata->stats[DROW_MAGIC])
            {
               send_to_char("Your spell does not affect them.\n\r", ch);
               return;
            }  
        }

	vo = (void *) victim;
	break;

    case TAR_CHAR_SELF:
	if ( arg2[0] != '\0' && !is_name( arg2, ch->name ) )
	{
	    send_to_char( "You cannot cast this spell on another.\n\r", ch );
	    return;
	}

	vo = (void *) ch;
	break;

    case TAR_OBJ_INV:
	if ( arg2[0] == '\0' )
	{
	    send_to_char( "What should the spell be cast upon?\n\r", ch );
	    return;
	}

	if ( ( obj = get_obj_carry( ch, arg2 ) ) == NULL )
	{
	    send_to_char( "You are not carrying that.\n\r", ch );
	    return;
	}

	vo = (void *) obj;
	break;
    }
	    
    if ( !IS_NPC(ch) && ch->mana < mana )
    {
	send_to_char( "You don't have enough mana.\n\r", ch );
	return;
    }
      
    if ( str_cmp( skill_table[sn].name, "ventriloquate" ) )
	say_spell( ch, sn );
      
    WAIT_STATE( ch, skill_table[sn].beats );
      
    if ( !IS_NPC(ch) && number_percent( ) > ch->pcdata->learned[sn] )
    {
	send_to_char( "You lost your concentration.\n\r", ch );
	ch->mana -= mana / 2;
	improve_spl(ch,skill_table[sn].target,sn);
    }
    else
    {
	ch->mana -= mana;
	/* Check players ability at spell type for spell power...KaVir */
	if (IS_NPC(ch))
	    (*skill_table[sn].spell_fun) ( sn, ch->level, ch, vo );
	else
	{
	    (*skill_table[sn].spell_fun) ( sn, (ch->spl[skill_table[sn].target]*0.25), ch, vo );
	    improve_spl(ch,skill_table[sn].target,sn);
	}
    }

    if ( skill_table[sn].target == TAR_CHAR_OFFENSIVE
    &&   victim != ch
    &&   victim->master != ch )
    {
	CHAR_DATA *vch;
	CHAR_DATA *vch_next;

	for ( vch = ch->in_room->people; vch; vch = vch_next )
	{
	    vch_next = vch->next_in_room;
	    if ( victim == vch && victim->fighting == NULL )
	    {
		multi_hit( victim, ch, TYPE_UNDEFINED );
		break;
	    }
	}
    }

    return;
}



/*
 * Cast spells at targets using a magical object.
 */
void obj_cast_spell( int sn, int level, CHAR_DATA *ch, CHAR_DATA *victim, OBJ_DATA *obj )
{
    void *vo;

    if ( sn <= 0 )
	return;

	if (IS_NPC(ch)) return;

    if ( sn >= MAX_SKILL || skill_table[sn].spell_fun == 0 )
    {
	bug( "Obj_cast_spell: bad sn %d.", sn );
	return;
    }

    switch ( skill_table[sn].target )
    {
    default:
	bug( "Obj_cast_spell: bad target for sn %d.", sn );
	return;

    case TAR_IGNORE:
	vo = NULL;
	break;

    case TAR_CHAR_OFFENSIVE:
	if ( victim == NULL )
	    victim = ch->fighting;
	if ( victim == NULL )
	{
	    send_to_char( "You can't do that.\n\r", ch );
	    return;
	}
	vo = (void *) victim;
	break;

    case TAR_CHAR_DEFENSIVE:
	if ( victim == NULL )
	    victim = ch;
	vo = (void *) victim;
	break;

    case TAR_CHAR_SELF:
	vo = (void *) ch;
	break;

    case TAR_OBJ_INV:
	if ( obj == NULL )
	{
	    send_to_char( "You can't do that.\n\r", ch );
	    return;
	}
	vo = (void *) obj;
	break;
    }

    target_name = "";
    (*skill_table[sn].spell_fun) ( sn, level, ch, vo );

    if ( skill_table[sn].target == TAR_CHAR_OFFENSIVE
    &&   victim != ch
    &&   victim->master != ch )
    {
	CHAR_DATA *vch;
	CHAR_DATA *vch_next;

	for ( vch = ch->in_room->people; vch; vch = vch_next )
	{
	    vch_next = vch->next_in_room;
	    if ( victim == vch && victim->fighting == NULL )
	    {
		multi_hit( victim, ch, TYPE_UNDEFINED );
		break;
	    }
	}
    }

    return;
}



/*
 * Spell functions.
 */
void spell_acid_blast( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    int dam;
    int hp;

    if (IS_ITEMAFF(victim, ITEMA_ACIDSHIELD)) return;
    dam = dice( level, 6 );
    if ( saves_spell( level, victim ) )
	dam /= 2;
    hp = victim->hit;
    damage( ch, victim, dam, sn );
    if (!IS_NPC(victim) && IS_IMMUNE(victim, IMM_ACID) )
	victim->hit = hp;
    return;
}



void spell_armor( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;

    if ( is_affected( victim, sn ) )
	return;
    af.type      = sn;
    af.duration  = 24;
    af.modifier  = -20;
    af.location  = APPLY_AC;
    af.bitvector = 0;
    affect_to_char( victim, &af );
    act( "$n is shrouded in a suit of translucent glowing armor.", victim, NULL, NULL, TO_ROOM );
    send_to_char( "You are shrouded in a suit of translucent glowing armor.\n\r", victim );
    if ( ch != victim )
	send_to_char( "Ok.\n\r", ch );
    return;
}



void spell_godbless( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;

    if ( is_affected( victim, sn ) ) return;
    af.type      = sn;
    af.duration  = 150;
    af.location  = APPLY_HITROLL;
    af.modifier  = 150;
    af.bitvector = 0;
    affect_to_char( victim, &af );

    af.location  = APPLY_SAVING_SPELL;
    af.modifier  = 0 - 150;
    affect_to_char( victim, &af );

    af.location  = APPLY_DAMROLL;
    af.modifier  = 150;
    affect_to_char( victim, &af );
    act( "$n is filled with God's Blessing.", victim, NULL, NULL, TO_ROOM );
    send_to_char( "You are filled with God's Blessing.\n\r", victim );
    return;
}

void spell_bless( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;

    if ( is_affected( victim, sn ) ) return;
    af.type      = sn;
    af.duration  = 6+level;
    af.location  = APPLY_HITROLL;
    af.modifier  = level / 8;
    af.bitvector = 0;
    affect_to_char( victim, &af );

    af.location  = APPLY_SAVING_SPELL;
    af.modifier  = 0 - level / 8;
    affect_to_char( victim, &af );
    act( "$n is blessed.", victim, NULL, NULL, TO_ROOM );
    send_to_char( "You feel righteous.\n\r", victim );
    if ( ch != victim )
	send_to_char( "Ok.\n\r", ch );
    return;
}



void spell_blindness( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;
    char buf [MAX_INPUT_LENGTH];

    if ( IS_AFFECTED(victim, AFF_BLIND) || saves_spell( level, victim ) )
	return;

    af.type      = sn;
    af.location  = APPLY_HITROLL;
    af.modifier  = -4;
    af.duration  = 1+level;
    af.bitvector = AFF_BLIND;
    affect_to_char( victim, &af );
    send_to_char( "You are blinded!\n\r", victim );
    if (!IS_NPC(victim))
	sprintf(buf,"%s is blinded!\n\r",victim->name);
    else
	sprintf(buf,"%s is blinded!\n\r",victim->short_descr);
    send_to_char(buf,ch);
    return;
}



void spell_burning_hands( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    static const sh_int dam_each[] = 
    {
	 4,
	 6,  8, 10, 12,	14,	17, 20, 23, 26, 29,
	29, 29, 30, 30,	31,	31, 32, 32, 33, 33,
	34, 34, 35, 35,	36,	36, 37, 37, 38, 38,
	39, 39, 40, 40,	41,	41, 42, 42, 43, 43,
	44, 44, 45, 45,	46,	46, 47, 47, 48, 48,
	50, 60, 70, 80,	90,	100,125,150,175,200
    };
    int dam;
    int hp;

    if (IS_ITEMAFF(victim, ITEMA_FIRESHIELD)) return;

    level	= UMIN(level, sizeof(dam_each)/sizeof(dam_each[0]) - 1);
    level	= UMAX(0, level);
    dam		= number_range( dam_each[level] / 2, dam_each[level] * 2 );
    if ( saves_spell( level, victim ) )
	dam /= 2;
    hp = victim->hit;
    if (!IS_NPC(victim) && IS_CLASS(victim, CLASS_VAMPIRE) )
    {
    	damage( ch, victim, (dam*2), sn );
	hp = ((hp - victim->hit)/2) + victim->hit;
    }
    else
    	damage( ch, victim, dam, sn );
    if (!IS_NPC(victim) && IS_IMMUNE(victim, IMM_HEAT) )
	victim->hit = hp;
    return;
}



void spell_call_lightning( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *vch;
    CHAR_DATA *vch_next;
    int dam;
    int hp;

    if ( !IS_OUTSIDE(ch) )
    {
	send_to_char( "You must be out of doors.\n\r", ch );
	return;
    }

    if ( weather_info.sky < SKY_RAINING )
    {
	send_to_char( "You need bad weather.\n\r", ch );
	return;
    }

    dam = dice(level/2, 8);

    send_to_char( "God's lightning strikes your foes!\n\r", ch );
    act( "$n calls God's lightning to strike $s foes!",
	ch, NULL, NULL, TO_ROOM );

    for ( vch = char_list; vch != NULL; vch = vch_next )
    {
	vch_next	= vch->next;
	if ( vch->in_room == NULL )
	    continue;
	if ( vch->in_room == ch->in_room )
	{
	    if ( vch != ch && ( IS_NPC(ch) ? !IS_NPC(vch) : IS_NPC(vch) ) )
	    {
		if (IS_ITEMAFF(vch, ITEMA_SHOCKSHIELD)) continue;
    		if ( saves_spell( level, vch ) )
		    dam /= 2;
    		hp = vch->hit;
    		damage( ch, vch, dam, sn );
    		if (!IS_NPC(vch) && IS_IMMUNE(vch, IMM_LIGHTNING) )
		    vch->hit = hp;
	    }
	    continue;
	}

	if ( vch->in_room->area == ch->in_room->area
	&&   IS_OUTSIDE(vch)
	&&   IS_AWAKE(vch) )
	    send_to_char( "Lightning flashes in the sky.\n\r", vch );
    }
    return;
}




void spell_cause_light( int sn, int level, CHAR_DATA *ch, void *vo )
{
    damage( ch, (CHAR_DATA *) vo, dice(1, 8) + level / 3, sn );
    return;
}



void spell_cause_critical( int sn, int level, CHAR_DATA *ch, void *vo )
{
    damage( ch, (CHAR_DATA *) vo, dice(3, 8) + level - 6, sn );
    return;
}



void spell_cause_serious( int sn, int level, CHAR_DATA *ch, void *vo )
{
    damage( ch, (CHAR_DATA *) vo, dice(2, 8) + level / 2, sn );
    return;
}



void spell_change_sex( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;

    return;
    if ( is_affected( victim, sn ) )
	return;
    af.type      = sn;
    af.duration  = 10 * level;
    af.location  = APPLY_SEX;
    do
    {
	af.modifier  = number_range( 0, 2 ) - victim->sex;
    }
    while ( af.modifier == 0 );
    af.bitvector = 0;
    affect_to_char( victim, &af );
    send_to_char( "You feel different.\n\r", victim );
    if ( ch != victim )
	send_to_char( "Ok.\n\r", ch );
    return;
}



void spell_charm_person( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;

    if ( victim == ch )
    {
	send_to_char( "You like yourself even better!\n\r", ch );
	return;
    }

    if ( !IS_NPC(victim) && IS_IMMUNE(victim, IMM_CHARM) )
    {
	send_to_char( "You failed.\n\r", ch );
	return;
    }

    /* I don't want people charming ghosts and stuff - KaVir */
    if ( IS_NPC(victim) && IS_AFFECTED(victim, AFF_ETHEREAL) )
    {
	send_to_char( "You failed.\n\r", ch );
	return;
    }

    if (IS_IMMORTAL( victim ))
    {
	send_to_char( "You can cast puny mortal magic on immortals!\n\r",ch);
	return;
    }

    if ( IS_AFFECTED(victim, AFF_CHARM)
    ||   IS_AFFECTED(ch, AFF_CHARM)
    ||   level < victim->level
    ||   saves_spell( level, victim ) )
	return;

    if ( victim->master )
	stop_follower( victim );
    add_follower( victim, ch );
    af.type      = sn;
    af.duration  = number_fuzzy( level / 4 );
    af.location  = 0;
    af.modifier  = 0;
    af.bitvector = AFF_CHARM;
    affect_to_char( victim, &af );
    act( "Isn't $n just so nice?", ch, NULL, victim, TO_VICT );
    if ( ch != victim )
	send_to_char( "Ok.\n\r", ch );
    return;
}



void spell_chill_touch( int sn, int level, CHAR_DATA *ch, void *vo )
{
    bool no_dam = FALSE;
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    static const sh_int dam_each[] = 
    {
	 9,
	10, 10, 10, 11, 11,	12, 12, 13, 13, 13,
	14, 14, 14, 15, 15,	15, 16, 16, 16, 17,
	17, 17, 18, 18, 18,	19, 19, 19, 20, 20,
	20, 21, 21, 21, 22,	22, 22, 23, 23, 23,
	24, 24, 24, 25, 25,	25, 26, 26, 26, 27,
	30, 40, 50, 60, 70,	80, 90,100,110,120
    };
    AFFECT_DATA af;
    int dam;
    int hp;

    if (IS_ITEMAFF(victim, ITEMA_ICESHIELD)) return;

    level	= UMIN(level, sizeof(dam_each)/sizeof(dam_each[0]) - 1);
    level	= UMAX(0, level);
    dam		= number_range( dam_each[level] / 2, dam_each[level] * 2 );
    if (!IS_NPC(victim) && IS_IMMUNE(victim, IMM_COLD) ) no_dam = TRUE;
    if ( !no_dam && (!saves_spell( level, victim ) ||
	  IS_NPC(victim) || !IS_CLASS(victim, CLASS_VAMPIRE) ) )
    {
	af.type      = sn;
	af.duration  = 6;
	af.location  = APPLY_STR;
	af.modifier  = -1;
	af.bitvector = 0;
	affect_join( victim, &af );
    }
    else
    {
	dam /= 2;
    }

    hp = victim->hit;
    damage( ch, victim, dam, sn );
    if (no_dam) victim->hit = hp;
    return;
}



void spell_colour_spray( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    static const sh_int dam_each[] = 
    {
	10,
	15, 15, 15, 15, 15,	20, 20, 20, 20, 20,
	30, 35, 40, 45, 50,	55, 55, 55, 56, 57,
	58, 58, 59, 60, 61,	61, 62, 63, 64, 64,
	65, 66, 67, 67, 68,	69, 70, 70, 71, 72,
	73, 73, 74, 75, 76,	76, 77, 78, 79, 79,
	85, 95,110,125,150,	175,200,250,300,350
    };
    int dam;

    level	= UMIN(level, sizeof(dam_each)/sizeof(dam_each[0]) - 1);
    level	= UMAX(0, level);
    dam		= number_range( dam_each[level] / 2,  dam_each[level] * 2 );
    if ( saves_spell( level, victim ) )
	dam /= 2;

    damage( ch, victim, dam, sn );
    return;
}



void spell_continual_light( int sn, int level, CHAR_DATA *ch, void *vo )
{
    OBJ_DATA *light;

    light = create_object( get_obj_index( OBJ_VNUM_LIGHT_BALL ), 0 );
    obj_to_room( light, ch->in_room );
    act( "$n twiddles $s thumbs and $p appears.",   ch, light, NULL, TO_ROOM );
    act( "You twiddle your thumbs and $p appears.", ch, light, NULL, TO_CHAR );
    return;
}



void spell_control_weather( int sn, int level, CHAR_DATA *ch, void *vo )
{
    if ( !str_cmp( target_name, "better" ) )
	weather_info.change += dice( level / 3, 4 );
    else if ( !str_cmp( target_name, "worse" ) )
	weather_info.change -= dice( level / 3, 4 );
    else
	send_to_char ("Do you want it to get better or worse?\n\r", ch );

    send_to_char( "Ok.\n\r", ch );
    return;
}



void spell_create_food( int sn, int level, CHAR_DATA *ch, void *vo )
{
    OBJ_DATA *mushroom;

    mushroom = create_object( get_obj_index( OBJ_VNUM_MUSHROOM ), 0 );
    mushroom->value[0] = 5 + level;
    obj_to_room( mushroom, ch->in_room );
    act( "$p suddenly appears.", ch, mushroom, NULL, TO_ROOM );
    act( "$p suddenly appears.", ch, mushroom, NULL, TO_CHAR );
    return;
}



void spell_create_spring( int sn, int level, CHAR_DATA *ch, void *vo )
{
    OBJ_DATA *spring;

    if (!IS_NPC(ch) && IS_CLASS(ch,CLASS_VAMPIRE))
	return;
    else
    	spring = create_object( get_obj_index( OBJ_VNUM_SPRING ), 0 );
    spring->timer = level;
    obj_to_room( spring, ch->in_room );
    act( "$p flows from the ground.", ch, spring, NULL, TO_ROOM );
    act( "$p flows from the ground.", ch, spring, NULL, TO_CHAR );
    return;
}



void spell_create_water( int sn, int level, CHAR_DATA *ch, void *vo )
{
    OBJ_DATA *obj = (OBJ_DATA *) vo;
    int water;

    if ( obj->item_type != ITEM_DRINK_CON )
    {
	send_to_char( "It is unable to hold water.\n\r", ch );
	return;
    }

    if ( obj->value[2] != LIQ_WATER && obj->value[1] != 0 )
    {
	send_to_char( "It contains some other liquid.\n\r", ch );
	return;
    }

    water = UMIN(
		level * (weather_info.sky >= SKY_RAINING ? 4 : 2),
		obj->value[0] - obj->value[1]
		);
  
    if ( water > 0 )
    {
	obj->value[2] = LIQ_WATER;
	obj->value[1] += water;
	if ( !is_name( "water", obj->name ) )
	{
	    char buf[MAX_STRING_LENGTH];

	    sprintf( buf, "%s water", obj->name );
	    free_string( obj->name );
	    obj->name = str_dup( buf );
	}
	act( "$p is filled.", ch, obj, NULL, TO_CHAR );
    }

    return;
}



void spell_cure_blindness( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    if ( !is_affected( victim, gsn_blindness ) )
	return;
    affect_strip( victim, gsn_blindness );
    send_to_char( "Your vision returns!\n\r", victim );
    if ( ch != victim )
	send_to_char( "Ok.\n\r", ch );
    if (!IS_NPC(ch) && ch != victim) do_humanity(ch,"");
    return;
}



void spell_cure_critical( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    int heal;

    heal = dice(3, 8) + level - 6;
    victim->hit = UMIN( victim->hit + heal, victim->max_hit );
    update_pos( victim );
    send_to_char( "You feel better!\n\r", victim );
    if ( ch != victim )
	send_to_char( "Ok.\n\r", ch );
    if (!IS_NPC(ch) && ch != victim) do_humanity(ch,"");
    return;
}



void spell_cure_light( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    int heal;

    heal = dice(1, 8) + level / 3;
    victim->hit = UMIN( victim->hit + heal, victim->max_hit );
    update_pos( victim );
    send_to_char( "You feel better!\n\r", victim );
    if ( ch != victim )
	send_to_char( "Ok.\n\r", ch );
    if (!IS_NPC(ch) && ch != victim) do_humanity(ch,"");
    return;
}



void spell_cure_poison( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    if ( is_affected( victim, gsn_poison ) )
    {
	affect_strip( victim, gsn_poison );
	act( "$N looks better.", ch, NULL, victim, TO_NOTVICT );
	send_to_char( "A warm feeling runs through your body.\n\r", victim );
	send_to_char( "Ok.\n\r", ch );
    	if (!IS_NPC(ch) && ch != victim) do_humanity(ch,"");
    }
    return;
}



void spell_cure_serious( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    int heal;

    heal = dice(2, 8) + level /2 ;
    victim->hit = UMIN( victim->hit + heal, victim->max_hit );
    update_pos( victim );
    send_to_char( "You feel better!\n\r", victim );
    if ( ch != victim )
	send_to_char( "Ok.\n\r", ch );
    if (!IS_NPC(ch) && ch != victim) do_humanity(ch,"");
    return;
}



void spell_curse( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;

    if ( IS_AFFECTED(victim, AFF_CURSE) || saves_spell( level, victim ) )
	return;
    af.type      = sn;
    af.duration  = 4*level;
    af.location  = APPLY_HITROLL;
    af.modifier  = -1;
    af.bitvector = AFF_CURSE;
    affect_to_char( victim, &af );

    af.location  = APPLY_SAVING_SPELL;
    af.modifier  = 1;
    affect_to_char( victim, &af );

    send_to_char( "You feel unclean.\n\r", victim );
    if ( ch != victim )
	send_to_char( "Ok.\n\r", ch );
    return;
}



void spell_detect_evil( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;

    if ( IS_AFFECTED(victim, AFF_DETECT_EVIL) )
	return;
    af.type      = sn;
    af.duration  = level;
    af.modifier  = 0;
    af.location  = APPLY_NONE;
    af.bitvector = AFF_DETECT_EVIL;
    affect_to_char( victim, &af );
    send_to_char( "Your eyes tingle.\n\r", victim );
    if ( ch != victim )
	send_to_char( "Ok.\n\r", ch );
    return;
}



void spell_detect_hidden( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;

    if ( IS_AFFECTED(victim, AFF_DETECT_HIDDEN) )
	return;
    af.type      = sn;
    af.duration  = level;
    af.location  = APPLY_NONE;
    af.modifier  = 0;
    af.bitvector = AFF_DETECT_HIDDEN;
    affect_to_char( victim, &af );
    send_to_char( "Your awareness improves.\n\r", victim );
    if ( ch != victim )
	send_to_char( "Ok.\n\r", ch );
    return;
}



void spell_detect_invis( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;

    if ( IS_AFFECTED(victim, AFF_DETECT_INVIS) )
	return;
    af.type      = sn;
    af.duration  = level;
    af.modifier  = 0;
    af.location  = APPLY_NONE;
    af.bitvector = AFF_DETECT_INVIS;
    affect_to_char( victim, &af );
    send_to_char( "Your eyes tingle.\n\r", victim );
    if ( ch != victim )
	send_to_char( "Ok.\n\r", ch );
    return;
}



void spell_detect_magic( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;

    if ( IS_AFFECTED(victim, AFF_DETECT_MAGIC) )
	return;
    af.type      = sn;
    af.duration  = level;
    af.modifier  = 0;
    af.location  = APPLY_NONE;
    af.bitvector = AFF_DETECT_MAGIC;
    affect_to_char( victim, &af );
    send_to_char( "Your eyes tingle.\n\r", victim );
    if ( ch != victim )
	send_to_char( "Ok.\n\r", ch );
    return;
}



void spell_detect_poison( int sn, int level, CHAR_DATA *ch, void *vo )
{
    OBJ_DATA *obj = (OBJ_DATA *) vo;

    if ( obj->item_type == ITEM_DRINK_CON || obj->item_type == ITEM_FOOD )
    {
	if ( obj->value[3] != 0 )
	    send_to_char( "You smell poisonous fumes.\n\r", ch );
	else
	    send_to_char( "It looks very delicious.\n\r", ch );
    }
    else
    {
	send_to_char( "It doesn't look poisoned.\n\r", ch );
    }

    return;
}



void spell_dispel_evil( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    int dam;
  
    if ( !IS_NPC(ch) && IS_EVIL(ch) )
	victim = ch;
  
    if ( IS_GOOD(victim) )
    {
	act( "God protects $N.", ch, NULL, victim, TO_ROOM );
	return;
    }

    if ( IS_NEUTRAL(victim) )
    {
	act( "$N does not seem to be affected.", ch, NULL, victim, TO_CHAR );
	return;
    }

    dam = dice( level, 4 );
    if ( saves_spell( level, victim ) )
	dam /= 2;
    damage( ch, victim, dam, sn );
    if (!IS_NPC(ch) && ch != victim) do_humanity(ch,"");
    return;
}



void spell_dispel_magic( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
	bool dark = FALSE;

    if ( victim != ch &&
	(saves_spell( level, victim ) || level < victim->level) )
    {
	send_to_char( "You failed.\n\r", ch );
	return;
    }

    if ( !(victim->affected) && !IS_SET(victim->flag2, AFF_TOTALBLIND))
    {
	send_to_char( "Nothing happens.\n\r", ch );
	return;
    }
/*	if (IS_AFFECTED(victim, AFF_DARKNESS)) dark = TRUE;*/

    while (victim->affected)
	affect_remove(victim,victim->affected);

	if (dark == TRUE) REMOVE_BIT(ch->in_room->room_flags, ROOM_TOTAL_DARKNESS);

    if ( ch == victim )
    {
    	act("You remove all magical affects from yourself.",ch,NULL,NULL,TO_CHAR);
    	act("$n has removed all magical affects from $mself.",ch,NULL,NULL,TO_ROOM);
	if ( IS_SET(victim->flag2, AFF_TOTALBLIND) )
        {
	  REMOVE_BIT(victim->flag2, AFF_TOTALBLIND);
	  stc("The searing blindness leaves your eyes.\n\r",victim);
	}
    }
    else
    {
    	act("You remove all magical affects from $N.",ch,NULL,victim,TO_CHAR);
    	act("$n has removed all magical affects from $N.",ch,NULL,victim,TO_NOTVICT);
    	act("$n has removed all magical affects from you.",ch,NULL,victim,TO_VICT);
	if ( IS_SET(victim->flag2, AFF_TOTALBLIND) )
        {
          REMOVE_BIT(victim->flag2, AFF_TOTALBLIND);
          stc("The searing blindness leaves your eyes.\n\r",victim);
        }
    }

    return;
}



void spell_earthquake( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *vch;
    CHAR_DATA *vch_next;

    send_to_char( "The earth trembles beneath your feet!\n\r", ch );
    act( "$n makes the earth tremble and shiver.", ch, NULL, NULL, TO_ROOM );

    for ( vch = char_list; vch != NULL; vch = vch_next )
    {
	vch_next	= vch->next;
	if ( vch->in_room == NULL || !can_see(ch, vch))
	    continue;
	if ( vch->in_room == ch->in_room )
	{
	    if ( vch != ch && ( IS_NPC(ch) ? !IS_NPC(vch) : IS_NPC(vch) ) )
		damage( ch, vch, level + dice(2, 8), sn );
	    continue;
	}

	if ( vch->in_room->area == ch->in_room->area )
	    send_to_char( "The earth trembles and shivers.\n\r", vch );
    }

    return;
}



void spell_enchant_weapon( int sn, int level, CHAR_DATA *ch, void *vo )
{
    OBJ_DATA *obj = (OBJ_DATA *) vo;
    AFFECT_DATA *paf;

    if ( obj->item_type != ITEM_WEAPON
    ||   IS_SET(obj->quest, QUEST_ENCHANTED)
    ||   IS_SET(obj->quest, QUEST_ARTIFACT)
    ||   obj->chobj != NULL )
    {
	send_to_char("You are unable to enchant this weapon.\n\r",ch);
	return;
    }

    if ( affect_free == NULL )
    {
	paf		= alloc_perm( sizeof(*paf) );
    }
    else
    {
	paf		= affect_free;
	affect_free	= affect_free->next;
    }
/*
    paf->type		= 0;
*/
    paf->type		= sn;
    paf->duration	= -1;
    paf->location	= APPLY_HITROLL;
    paf->modifier	= level / 5;
    paf->bitvector	= 0;
    paf->next		= obj->affected;
    obj->affected	= paf;

    if ( affect_free == NULL )
    {
	paf		= alloc_perm( sizeof(*paf) );
    }
    else
    {
	paf		= affect_free;
	affect_free	= affect_free->next;
    }
/*
    paf->type		= -1;
*/
    paf->type		= sn;
    paf->duration	= -1;
    paf->location	= APPLY_DAMROLL;
    paf->modifier	= level / 10;
    paf->bitvector	= 0;
    paf->next		= obj->affected;
    obj->affected	= paf;

    if ( IS_GOOD(ch) )
    {
	SET_BIT(obj->extra_flags, ITEM_ANTI_EVIL);
	SET_BIT(obj->quest, QUEST_ENCHANTED);
	act( "$p glows blue.", ch, obj, NULL, TO_CHAR );
	act( "$p glows blue.", ch, obj, NULL, TO_ROOM );
    }
    else if ( IS_EVIL(ch) )
    {
	SET_BIT(obj->extra_flags, ITEM_ANTI_GOOD);
	SET_BIT(obj->quest, QUEST_ENCHANTED);
	act( "$p glows red.", ch, obj, NULL, TO_CHAR );
	act( "$p glows red.", ch, obj, NULL, TO_ROOM );
    }
    else
    {
	SET_BIT(obj->extra_flags, ITEM_ANTI_EVIL);
	SET_BIT(obj->extra_flags, ITEM_ANTI_GOOD);
	SET_BIT(obj->quest, QUEST_ENCHANTED);
	act( "$p glows yellow.", ch, obj, NULL, TO_CHAR );
	act( "$p glows yellow.", ch, obj, NULL, TO_ROOM );
    }
    return;
}



/*
 * Drain XP, MANA, HP.
 * Caster gains HP.
 */
void spell_energy_drain( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    int dam;
    int hp;

    if ( saves_spell( level, victim ) )
	return;

    if ( !IS_HERO(ch))
        ch->alignment = UMAX(-1000, ch->alignment - 200);

    if ( victim->level <= 2 )
    {
	dam		 = ch->hit + 1;
    }
    else
    {
	dam		 = dice(1, level);
    	if (IS_NPC(victim) || !IS_IMMUNE(victim, IMM_DRAIN) )
	{
	    victim->mana	/= 2;
	    victim->move	/= 2;
	    ch->hit		+= dam;
	    if (ch->hit > (2*ch->max_hit))
	    	ch->hit = (2 * ch->max_hit);
	}
    }

    hp = victim->hit;
    damage( ch, victim, dam, sn );
    if (!IS_NPC(victim) && IS_IMMUNE(victim, IMM_DRAIN) )
	victim->hit = hp;
    if (!IS_NPC(ch) && ch != victim) do_beastlike(ch,"");

    return;
}



void spell_fireball( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    static const sh_int dam_each[] = 
    {
	 20,
	 20,  20,  20,  20,  20,	 25,  25,  25,  25,  25,
	 30,  30,  30,  30,  30,	 35,  40,  45,  50,  55,
	 60,  65,  70,  75,  80,	 82,  84,  86,  88,  90,
	 92,  94,  96,  98, 100,	102, 104, 106, 108, 110,
	112, 114, 116, 118, 120,	122, 124, 126, 128, 130,
	150, 200, 250, 300, 400,	500, 650, 750, 850,1000
    };
    int dam;
    int hp;

    if (IS_ITEMAFF(victim, ITEMA_FIRESHIELD)) return;

    level	= UMIN(level, sizeof(dam_each)/sizeof(dam_each[0]) - 1);
    level	= UMAX(0, level);
    dam		= number_range( dam_each[level] / 2, dam_each[level] * 2 );
    if ( saves_spell( level, victim ) )
	dam /= 2;
    hp = victim->hit;
    if (!IS_NPC(victim) && IS_CLASS(victim, CLASS_VAMPIRE) )
    {
    	damage( ch, victim, (dam*2), sn );
	hp = ((hp - victim->hit)/2) + victim->hit;
    }
    else
    	damage( ch, victim, dam, sn );
    if (!IS_NPC(victim) && IS_IMMUNE(victim, IMM_HEAT) )
	victim->hit = hp;
    return;
}



void spell_flamestrike( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    int dam;
    int hp;

    if (IS_ITEMAFF(victim, ITEMA_FIRESHIELD)) return;
    dam = dice(6, 8);
    if ( saves_spell( level, victim ) )
	dam /= 2;
    hp = victim->hit;
    if (!IS_NPC(victim) && IS_CLASS(victim, CLASS_VAMPIRE) )
    {
    	damage( ch, victim, (dam*2), sn );
	hp = ((hp - victim->hit)/2) + victim->hit;
    }
    else
    	damage( ch, victim, dam, sn );
    if (!IS_NPC(victim) && IS_IMMUNE(victim, IMM_HEAT) )
	victim->hit = hp;
    return;
}



void spell_faerie_fire( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;

    if ( IS_AFFECTED(victim, AFF_FAERIE_FIRE) )
	return;
    af.type      = sn;
    af.duration  = level;
    af.location  = APPLY_AC;
    af.modifier  = 2 * level;
    af.bitvector = AFF_FAERIE_FIRE;
    affect_to_char( victim, &af );
    send_to_char( "You are surrounded by a pink outline.\n\r", victim );
    act( "$n is surrounded by a pink outline.", victim, NULL, NULL, TO_ROOM );
    return;
}

void spell_tendrils( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;
    char buf[MAX_STRING_LENGTH];
    sprintf(buf,
    "A look of concentration passes over your face.\n\r");
    send_to_char(buf,ch);
    sprintf(buf,
    "A look of concentration passes over %s's face.\n\r",ch->name);
    
    act(buf,ch,NULL,NULL,TO_ROOM);
 
 
    if ( IS_AFFECTED(victim, AFF_TENDRILS) )
    {
        send_to_char( "They are already entangled by tendrils!\n\r", ch );
	return;
    }
 
    if ( is_safe(ch, victim) ) return;
 
    if ( saves_spell( level, victim ) && victim->position >= POS_FIGHTING
)
    {
        send_to_char( "You escape from your enemy's tendrils!\n\r", victim
);
        act("$n escapes the tendrils!",victim,NULL,NULL,TO_ROOM);
	return;
    }
 
    af.type      = sn;
    af.location  = APPLY_AC;
    af.modifier  = 100;
    af.duration  = number_range(2,3);
    af.bitvector = AFF_TENDRILS;
    affect_to_char( victim, &af );
    send_to_char( "You are entrapped by tendrils of darkness!\n\r", victim
);
    act("$n is entrapped by tendrils of darkness",victim,NULL,NULL,TO_ROOM);
    return;
}

void spell_spew( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *vch;
    CHAR_DATA *vch_next;
    int dam;
 
    for ( vch = ch->in_room->people; vch != NULL; vch = vch_next )
    {
	vch_next = vch->next_in_room;
            if (IS_NPC(vch)) dam=250*level;
            if (!IS_NPC(vch)) dam=100*level;
            if (is_safe(ch,vch)==TRUE) break;
            damage( ch, vch, dam, sn );
    }
    return;
}

void spell_infirmity( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;

    if ( IS_AFFECTED(victim, AFF_INFIRMITY) )
{
        act("A look of concentration passes over $n's face.",ch,NULL,NULL,TO_ROOM);
        send_to_char("A look of concentration passes over your face.\n\r",ch);
        send_to_char("They are already weak.\n\r",ch);
   	return;
} 
    af.type      = sn;
    af.duration  = level;
    af.location  = APPLY_DEX;
    af.modifier  = 0 - level;
    af.bitvector = AFF_INFIRMITY;
    affect_to_char( victim, &af );

    af.type      = sn;
    af.duration  = level;
    af.location  = APPLY_STR;
    af.modifier  = 0 - level;
    af.bitvector = AFF_INFIRMITY;
    affect_to_char( victim, &af );

    af.type      = sn;
    af.duration  = level;
    af.location  = APPLY_WIS;
    af.modifier  = 0 - level;
    af.bitvector = AFF_INFIRMITY;
    affect_to_char( victim, &af );

    af.type      = sn;
    af.duration  = level;
    af.location  = APPLY_CON;
    af.modifier  = 0 - level;
    af.bitvector = AFF_INFIRMITY;
    affect_to_char( victim, &af );

    af.type      = sn;
    af.duration  = level;
    af.location  = APPLY_INT;
    af.modifier  = 0 - level;
    af.bitvector = AFF_INFIRMITY;
    affect_to_char( victim, &af );

    af.type      = sn;
    af.duration  = level;
    af.location  = APPLY_DAMROLL;
    af.modifier  = 0 - level;
    af.bitvector = AFF_INFIRMITY;
    affect_to_char( victim, &af );

    af.type      = sn;
    af.duration  = level;
    af.location  = APPLY_HITROLL;
    af.modifier  = 0 - level;
    af.bitvector = AFF_INFIRMITY;
    affect_to_char( victim, &af );
    send_to_char("A look of concentration passes over your face.\n\r",ch);
    act("A look of concentration passes over $n's face.",ch,NULL,NULL,TO_ROOM);
    send_to_char( "You feel weaker.\n\r", victim );
    send_to_char( "You feel slower.\n\r", victim );
    send_to_char( "You feel less healthy.\n\r", victim );
    act( "$n looks weaker.", victim, NULL, NULL, TO_ROOM );
    act( "$n looks slower.", victim, NULL, NULL, TO_ROOM );
    act( "$n looks less healthy.",victim,NULL,NULL, TO_ROOM);
    return;
}



void spell_faerie_fog( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *ich;

    act( "$n conjures a cloud of purple smoke.", ch, NULL, NULL, TO_ROOM );
    send_to_char( "You conjure a cloud of purple smoke.\n\r", ch );

    for ( ich = ch->in_room->people; ich != NULL; ich = ich->next_in_room )
    {/*
	if ( !IS_NPC(ich) && IS_SET(ich->act, PLR_WIZINVIS) )
	    continue;
	*/

	if ( ich == ch || saves_spell( level, ich ) )
	    continue;

	if (IS_CLASS(ich, CLASS_DROW) &&( (ich->pcdata->stats[DROW_MAGIC]  - 5) >= number_percent()))
	continue;

	affect_strip ( ich, gsn_invis			);
	affect_strip ( ich, gsn_mass_invis		);
	affect_strip ( ich, gsn_sneak			);
	REMOVE_BIT   ( ich->affected_by, AFF_HIDE	);
	REMOVE_BIT   ( ich->affected_by, AFF_INVISIBLE	);
	REMOVE_BIT   ( ich->affected_by, AFF_SNEAK	);

	if (IS_CLASS(ich, CLASS_DROW) && IS_SET(ich->newbits, NEW_DARKNESS))
	{
	REMOVE_BIT(ich->newbits, NEW_DARKNESS);
	REMOVE_BIT(ich->in_room->room_flags, ROOM_TOTAL_DARKNESS);
	}

	act( "$n is revealed!", ich, NULL, NULL, TO_ROOM );
	send_to_char( "You are revealed!\n\r", ich );
    }

    return;
}



void spell_fly( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;

    if ( IS_AFFECTED(victim, AFF_FLYING) )
	return;
    af.type      = sn;
    af.duration  = level + 3;
    af.location  = 0;
    af.modifier  = 0;
    af.bitvector = AFF_FLYING;
    affect_to_char( victim, &af );
    send_to_char( "You rise up off the ground.\n\r", victim );
    act( "$n rises up off the ground.", victim, NULL, NULL, TO_ROOM );
    return;
}



void spell_gate( int sn, int level, CHAR_DATA *ch, void *vo )
{
    char_to_room( create_mobile( get_mob_index(MOB_VNUM_VAMPIRE) ),
	ch->in_room );
    return;
}



/*
 * Spell for mega1.are from Glop/Erkenbrand.
 */
void spell_general_purpose( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    int dam;

    dam = number_range( 25, 100 );
    if ( saves_spell( level, victim ) )
	dam /= 2;
    damage( ch, victim, dam, sn );
    return;
}



void spell_giant_strength( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;

    if ( is_affected( victim, sn ) )
	return;
    af.type      = sn;
    af.duration  = level;
    af.location  = APPLY_STR;
    af.modifier  = 1 + (level >= 18) + (level >= 25);
    af.bitvector = 0;
    affect_to_char( victim, &af );
    send_to_char( "You feel stronger.\n\r", victim );
    if ( ch != victim )
	send_to_char( "Ok.\n\r", ch );
    return;
}



void spell_harm( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    int dam;

    dam = UMAX(  20, victim->hit - dice(1,4) );
    if ( saves_spell( level, victim ) )
	dam = UMIN( 50, dam / 4 );
    dam = UMIN( 100, dam );
    damage( ch, victim, dam, sn );
    return;
}



void spell_heal( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    victim->hit = UMIN( victim->hit + 100, victim->max_hit );
    update_pos( victim );
    send_to_char( "A warm feeling fills your body.\n\r", victim );
    if (ch == victim)
	act( "$n heals $mself.", ch, NULL, NULL, TO_ROOM );
    else
	act( "$n heals $N.", ch, NULL, victim, TO_NOTVICT );
    if ( ch != victim )
	send_to_char( "Ok.\n\r", ch );
    if (!IS_NPC(ch) && ch != victim) do_humanity(ch,"");
    return;
}



/*
 * Spell for mega1.are from Glop/Erkenbrand.
 */
void spell_high_explosive( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    int dam;

    dam = number_range( 30, 120 );
    if ( saves_spell( level, victim ) )
	dam /= 2;
    damage( ch, victim, dam, sn );
    return;
}



void spell_identify( int sn, int level, CHAR_DATA *ch, void *vo )
{
    OBJ_DATA *obj = (OBJ_DATA *) vo;
    char buf[MAX_STRING_LENGTH];
    AFFECT_DATA *paf;
    int itemtype;

    act("You examine $p carefully.",ch,obj,NULL,TO_CHAR);
    act("$n examines $p carefully.",ch,obj,NULL,TO_ROOM);

    sprintf( buf,
	"Object '%s' is type %s, extra flags %s.\n\rWeight is %d, value is %d.\n\r",

	obj->name,
	item_type_name( obj ),
	extra_bit_name( obj->extra_flags ),
	obj->weight,
	obj->cost
	);
    send_to_char( buf, ch );

    if (obj->points > 0 && obj->item_type != ITEM_QUEST
	 && obj->item_type != ITEM_PAGE)
    {
	sprintf( buf, "Quest point value is %d.\n\r", obj->points );
	send_to_char( buf, ch );
    }
    if (obj->questmaker != NULL && strlen(obj->questmaker) > 1 &&
	obj->questowner != NULL && strlen(obj->questowner) > 1)
    {
	sprintf( buf, "This object was created by %s, and is owned by %s.\n\r", obj->questmaker,obj->questowner );
	send_to_char( buf, ch );
    }
    else if (obj->questmaker != NULL && strlen(obj->questmaker) > 1)
    {
	sprintf( buf, "This object was created by %s.\n\r", obj->questmaker );
	send_to_char( buf, ch );
    }
    else if (obj->questowner != NULL && strlen(obj->questowner) > 1)
    {
	sprintf( buf, "This object is owned by %s.\n\r", obj->questowner );
	send_to_char( buf, ch );
    }

    if (IS_SET(obj->spectype, SITEM_COPPER))
        send_to_char("This item is forged with copper.\n\r",ch);
    if (IS_SET(obj->spectype, SITEM_IRON))
        send_to_char("This item is forged with iron.\n\r",ch);
    if (IS_SET(obj->spectype, SITEM_STEEL))
        send_to_char("This item is forged with steel.\n\r",ch);
    if (IS_SET(obj->spectype, SITEM_ADAMANTITE))
        send_to_char("This item is forged with adamantite.\n\r",ch);
    if (IS_SET(obj->quest, QUEST_BLOODA))
        send_to_char( "This weapon is dripping with kindred blood.\n\r",ch);
    if (IS_SET(obj->quest, QUEST_ENCHANTED))
	send_to_char( "This item has been enchanted.\n\r", ch );
    if (IS_SET(obj->quest, QUEST_SPELLPROOF))
	send_to_char( "This item is resistant to offensive spells.\n\r", ch );
    if (IS_SET(obj->spectype, SITEM_DEMONIC))
	send_to_char( "This item is crafted from demonsteel.\n\r", ch );
    else if (IS_SET(obj->spectype, SITEM_SILVER))
	send_to_char( "This item is crafted from gleaming silver.\n\r", ch );

    switch ( obj->item_type )
    {
    case ITEM_PILL: 
    case ITEM_SCROLL: 
    case ITEM_POTION:
	sprintf( buf, "Level %d spells of:", obj->value[0] );
	send_to_char( buf, ch );

	if ( obj->value[1] >= 0 && obj->value[1] < MAX_SKILL )
	{
	    send_to_char( " '", ch );
	    send_to_char( skill_table[obj->value[1]].name, ch );
	    send_to_char( "'", ch );
	}

	if ( obj->value[2] >= 0 && obj->value[2] < MAX_SKILL )
	{
	    send_to_char( " '", ch );
	    send_to_char( skill_table[obj->value[2]].name, ch );
	    send_to_char( "'", ch );
	}

	if ( obj->value[3] >= 0 && obj->value[3] < MAX_SKILL )
	{
	    send_to_char( " '", ch );
	    send_to_char( skill_table[obj->value[3]].name, ch );
	    send_to_char( "'", ch );
	}

	send_to_char( ".\n\r", ch );
	break;

    case ITEM_QUEST:
	sprintf( buf, "Quest point value is %d.\n\r", obj->value[0] );
	send_to_char( buf, ch );
	break;

    case ITEM_QUESTCARD:
	sprintf( buf, "Quest completion reward is %d quest points.\n\r", obj->level );
	send_to_char( buf, ch );
	break;

    case ITEM_WAND: 
    case ITEM_STAFF: 
	sprintf( buf, "Has %d(%d) charges of level %d",
	    obj->value[1], obj->value[2], obj->value[0] );
	send_to_char( buf, ch );
      
	if ( obj->value[3] >= 0 && obj->value[3] < MAX_SKILL )
	{
	    send_to_char( " '", ch );
	    send_to_char( skill_table[obj->value[3]].name, ch );
	    send_to_char( "'", ch );
	}

	send_to_char( ".\n\r", ch );
	break;
      
    case ITEM_WEAPON:
	sprintf( buf, "Damage is %d to %d (average %d).\n\r",
	    obj->value[1], obj->value[2],
	    ( obj->value[1] + obj->value[2] ) / 2 );
	send_to_char( buf, ch );

	if (obj->value[0] >= 1000)
	    itemtype = obj->value[0] - ((obj->value[0] / 1000) * 1000);
	else
	    itemtype = obj->value[0];

	if (itemtype > 0)
	{
	    if (obj->level < 10)
		sprintf(buf,"%s is a minor spell weapon.\n\r",capitalize(obj->short_descr));
	    else if (obj->level < 20)
		sprintf(buf,"%s is a lesser spell weapon.\n\r",capitalize(obj->short_descr));
	    else if (obj->level < 30)
		sprintf(buf,"%s is an average spell weapon.\n\r",capitalize(obj->short_descr));
	    else if (obj->level < 40)
		sprintf(buf,"%s is a greater spell weapon.\n\r",capitalize(obj->short_descr));
	    else if (obj->level < 50)
		sprintf(buf,"%s is a major spell weapon.\n\r",capitalize(obj->short_descr));
	    else if (obj->level > 50)
		sprintf(buf,"%s is an ultimate spell weapon.\n\r",capitalize(obj->short_descr));
	    else
		sprintf(buf,"%s is a supreme spell weapon.\n\r",capitalize(obj->short_descr));
	    send_to_char(buf,ch);
	}

	if (itemtype == 1)
	    sprintf (buf, "This weapon is dripping with corrosive acid.\n\r");
	else if (itemtype == 4)
	    sprintf (buf, "This weapon radiates an aura of darkness.\n\r");
	else if (itemtype == 30)
	    sprintf (buf, "This ancient relic is the bane of all evil.\n\r");
	else if (itemtype == 34)
	    sprintf (buf, "This vampiric weapon drinks the souls of its victims.\n\r");
	else if (itemtype == 37)
	    sprintf (buf, "This weapon has been tempered in hellfire.\n\r");
	else if (itemtype == 48)
	    sprintf (buf, "This weapon crackles with sparks of lightning.\n\r");
	else if (itemtype == 53)
	    sprintf (buf, "This weapon is dripping with a dark poison.\n\r");
	else if (itemtype > 0)
	    sprintf (buf, "This weapon has been imbued with the power of %s.\n\r",skill_table[itemtype].name);
	if (itemtype > 0)
	    send_to_char( buf, ch );

	if (obj->value[0] >= 1000)
	    itemtype = obj->value[0] / 1000;
	else
	    break;

	if (itemtype == 4)
	    sprintf (buf, "This weapon radiates an aura of darkness.\n\r");
	else if (itemtype == 27 || itemtype == 2)
	    sprintf (buf, "This weapon allows the wielder to see invisible things.\n\r");
	else if (itemtype == 39 || itemtype == 3)
	    sprintf (buf, "This weapon grants the power of flight.\n\r");
	else if (itemtype == 45 || itemtype == 1)
	    sprintf (buf, "This weapon allows the wielder to see in the dark.\n\r");
	else if (itemtype == 46 || itemtype == 5)
	    sprintf (buf, "This weapon renders the wielder invisible to the human eye.\n\r");
	else if (itemtype == 52 || itemtype == 6)
	    sprintf (buf, "This weapon allows the wielder to walk through solid doors.\n\r");
	else if (itemtype == 54 || itemtype == 7)
	    sprintf (buf, "This holy weapon protects the wielder from evil.\n\r");
	else if (itemtype == 57 || itemtype == 8)
	    sprintf (buf, "This ancient weapon protects the wielder in combat.\n\r");
	else if (itemtype == 9)
	    sprintf (buf, "This crafty weapon allows the wielder to walk in complete silence.\n\r");
	else if (itemtype == 10)
	    sprintf (buf, "This powerful weapon surrounds its wielder with a shield of lightning.\n\r");
	else if (itemtype == 11)
	    sprintf (buf, "This powerful weapon surrounds its wielder with a shield of fire.\n\r");
	else if (itemtype == 12)
	    sprintf (buf, "This powerful weapon surrounds its wielder with a shield of ice.\n\r");
	else if (itemtype == 13)
	    sprintf (buf, "This powerful weapon surrounds its wielder with a shield of acid.\n\r");
	else if (itemtype == 14)
	    sprintf (buf, "This weapon protects its wielder from clan DarkBlade guardians.\n\r");
	else if (itemtype == 15)
	    sprintf (buf, "This ancient weapon surrounds its wielder with a shield of chaos.\n\r");
	else if (itemtype == 16)
	    sprintf (buf, "This ancient weapon regenerates the wounds of its wielder.\n\r");
	else if (itemtype == 17)
	    sprintf (buf, "This ancient weapon allows its wielder to move at supernatural speed.\n\r");
	else if (itemtype == 18)
	    sprintf (buf, "This razor sharp weapon can slice through armour without difficulty.\n\r");
	else if (itemtype == 19)
	    sprintf (buf, "This ancient weapon protects its wearer from player attacks.\n\r");
	else if (itemtype == 20)
	    sprintf (buf, "This ancient weapon surrounds its wielder with a shield of darkness.\n\r");
	else if (itemtype == 21)
	    sprintf (buf, "This ancient weapon grants superior protection to its wielder.\n\r");
	else if (itemtype == 22)
	    sprintf (buf, "This ancient weapon grants its wielder supernatural vision.\n\r");
	else if (itemtype == 23)
	    sprintf (buf, "This ancient weapon makes its wielder fleet-footed.\n\r");
	else if (itemtype == 24)
	    sprintf (buf, "This ancient weapon conceals its wielder from sight.\n\r");
	else if (itemtype == 25)
	    sprintf (buf, "This ancient weapon invokes the power of the beast.\n\r");
	else
	    sprintf (buf, "This item is bugged...please report it.\n\r");
	if (itemtype > 0)
	    send_to_char( buf, ch );
	break;

    case ITEM_ARMOR:
	sprintf( buf, "Armor class is %d.\n\r", obj->value[0] );
	send_to_char( buf, ch );
	if (obj->value[3] < 1)
	    break;
	if (obj->value[3] == 4)
	    sprintf (buf, "This object radiates an aura of darkness.\n\r");
	else if (obj->value[3] == 27 || obj->value[3] == 2)
	    sprintf (buf, "This item allows the wearer to see invisible things.\n\r");
	else if (obj->value[3] == 39 || obj->value[3] == 3)
	    sprintf (buf, "This object grants the power of flight.\n\r");
	else if (obj->value[3] == 45 || obj->value[3] == 1)
	    sprintf (buf, "This item allows the wearer to see in the dark.\n\r");
	else if (obj->value[3] == 46 || obj->value[3] == 5)
	    sprintf (buf, "This object renders the wearer invisible to the human eye.\n\r");
	else if (obj->value[3] == 52 || obj->value[3] == 6)
	    sprintf (buf, "This object allows the wearer to walk through solid doors.\n\r");
	else if (obj->value[3] == 54 || obj->value[3] == 7)
	    sprintf (buf, "This holy relic protects the wearer from evil.\n\r");
	else if (obj->value[3] == 57 || obj->value[3] == 8)
	    sprintf (buf, "This ancient relic protects the wearer in combat.\n\r");
	else if (obj->value[3] == 9)
	    sprintf (buf, "This crafty item allows the wearer to walk in complete silence.\n\r");
	else if (obj->value[3] == 10)
	    sprintf (buf, "This powerful item surrounds its wearer with a shield of lightning.\n\r");
	else if (obj->value[3] == 11)
	    sprintf (buf, "This powerful item surrounds its wearer with a shield of fire.\n\r");
	else if (obj->value[3] == 12)
	    sprintf (buf, "This powerful item surrounds its wearer with a shield of ice.\n\r");
	else if (obj->value[3] == 13)
	    sprintf (buf, "This powerful item surrounds its wearer with a shield of acid.\n\r");
	else if (obj->value[3] == 14)
	    sprintf (buf, "This object protects its wearer from clan DarkBlade guardians.\n\r");
	else if (obj->value[3] == 15)
	    sprintf (buf, "This ancient item surrounds its wearer with a shield of chaos.\n\r");
	else if (obj->value[3] == 16)
	    sprintf (buf, "This ancient item regenerates the wounds of its wearer.\n\r");
	else if (obj->value[3] == 17)
	    sprintf (buf, "This ancient item allows its wearer to move at supernatural speed.\n\r");
	else if (obj->value[3] == 18)
	    sprintf (buf, "This powerful item allows its wearer to shear through armour without difficulty.\n\r");
	else if (obj->value[3] == 19)
	    sprintf (buf, "This powerful item protects its wearer from player attacks.\n\r");
	else if (obj->value[3] == 20)
	    sprintf (buf, "This ancient item surrounds its wearer with a shield of darkness.\n\r");
	else if (obj->value[3] == 21)
	    sprintf (buf, "This ancient item grants superior protection to its wearer.\n\r");
	else if (obj->value[3] == 22)
	    sprintf (buf, "This ancient item grants its wearer supernatural vision.\n\r");
	else if (obj->value[3] == 23)
	    sprintf (buf, "This ancient item makes its wearer fleet-footed.\n\r");
	else if (obj->value[3] == 24)
	    sprintf (buf, "This ancient item conceals its wearer from sight.\n\r");
	else if (obj->value[3] == 25)
	    sprintf (buf, "This ancient item invokes the power of the beast.\n\r");
	else
	    sprintf (buf, "This item is bugged...please report it.\n\r");
	if (obj->value[3] > 0)
	    send_to_char( buf, ch );
	break;
    }

    for ( paf = obj->pIndexData->affected; paf != NULL; paf = paf->next )
    {
	if ( paf->location != APPLY_NONE && paf->modifier != 0 )
	{
	    sprintf( buf, "Affects %s by %d.\n\r",
		affect_loc_name( paf->location ), paf->modifier );
	    send_to_char( buf, ch );
	}
    }

    for ( paf = obj->affected; paf != NULL; paf = paf->next )
    {
	if ( paf->location != APPLY_NONE && paf->modifier != 0 )
	{
	    sprintf( buf, "Affects %s by %d.\n\r",
		affect_loc_name( paf->location ), paf->modifier );
	    send_to_char( buf, ch );
	}
    }

    return;
}



void spell_infravision( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;

    if ( IS_AFFECTED(victim, AFF_INFRARED) )
	return;
    act( "$n's eyes glow red.\n\r", ch, NULL, NULL, TO_ROOM );
    af.type      = sn;
    af.duration  = 2 * level;
    af.location  = APPLY_NONE;
    af.modifier  = 0;
    af.bitvector = AFF_INFRARED;
    affect_to_char( victim, &af );
    send_to_char( "Your eyes glow red.\n\r", victim );
    if ( ch != victim )
	send_to_char( "Ok.\n\r", ch );
    return;
}



void spell_invis( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;

    if ( IS_AFFECTED(victim, AFF_INVISIBLE) )
	return;

    act( "$n fades out of existence.", victim, NULL, NULL, TO_ROOM );
    af.type      = sn;
    af.duration  = 24;
    af.location  = APPLY_NONE;
    af.modifier  = 0;
    af.bitvector = AFF_INVISIBLE;
    affect_to_char( victim, &af );
    send_to_char( "You fade out of existence.\n\r", victim );
    if ( ch != victim )
	send_to_char( "Ok.\n\r", ch );
    return;
}



void spell_know_alignment( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    char *msg;
    int ap;

    ap = victim->alignment;

         if ( ap >  700 ) msg = "$N has an aura as white as the driven snow.";
    else if ( ap >  350 ) msg = "$N is of excellent moral character.";
    else if ( ap >  100 ) msg = "$N is often kind and thoughtful.";
    else if ( ap > -100 ) msg = "$N doesn't have a firm moral commitment.";
    else if ( ap > -350 ) msg = "$N lies to $S friends.";
    else if ( ap > -700 ) msg = "$N's slash DISEMBOWELS you!";
    else msg = "I'd rather just not say anything at all about $N.";

    act( msg, ch, NULL, victim, TO_CHAR );
    return;
}



void spell_lightning_bolt( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    static const sh_int dam_each[] = 
    {
	10,
	15, 15, 15, 20, 20,	25, 25, 25, 25, 28,
	31, 34, 37, 40, 40,	41, 42, 42, 43, 44,
	44, 45, 46, 46, 47,	48, 48, 49, 50, 50,
	51, 52, 52, 53, 54,	54, 55, 56, 56, 57,
	58, 58, 59, 60, 60,	61, 62, 62, 63, 64,
	70, 80, 90,120,150,	200,250,300,350,400
    };
    int dam;
    int hp;

    if (IS_ITEMAFF(victim, ITEMA_SHOCKSHIELD)) return;

    level	= UMIN(level, sizeof(dam_each)/sizeof(dam_each[0]) - 1);
    level	= UMAX(0, level);
    dam		= number_range( dam_each[level] / 2, dam_each[level] * 2 );
    if ( saves_spell( level, victim ) )
	dam /= 2;
    hp = victim->hit;
    damage( ch, victim, dam, sn );
    if (!IS_NPC(victim) && IS_IMMUNE(victim, IMM_LIGHTNING) )
	victim->hit = hp;
    return;
}



void spell_locate_object( int sn, int level, CHAR_DATA *ch, void *vo )
{
    char buf[MAX_STRING_LENGTH];
    OBJ_DATA *obj;
    OBJ_DATA *in_obj;
    bool found;
    int count=0;

    found = FALSE;
    for ( obj = object_list; obj != NULL; obj = obj->next )
    {
	if ( !can_see_obj( ch, obj ) || !is_name( target_name, obj->name ) )
	    continue;

	found = TRUE;

	for ( in_obj = obj; in_obj->in_obj != NULL; in_obj = in_obj->in_obj )
	    ;

	if ( in_obj->carried_by != NULL )
	{
	    sprintf( buf, "%s carried by %s.\n\r",
		obj->short_descr, PERS(in_obj->carried_by, ch) );
	}
	else
	{
	    sprintf( buf, "%s in %s.\n\r",
		obj->short_descr, in_obj->in_room == NULL
		    ? "somewhere" : in_obj->in_room->name );
	}

	buf[0] = UPPER(buf[0]);
	send_to_char( buf, ch );

        if (count > 50 )
            break;
        else
	   count++;


    }

    if ( !found )
	send_to_char( "Nothing like that in hell, earth, or heaven.\n\r", ch );

    return;
}



void spell_magic_missile( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    static const sh_int dam_each[] = 
    {
	 0,
	 3,  3,  4,  4,  5,	 6,  6,  6,  6,  6,
	 7,  7,  7,  7,  7,	 8,  8,  8,  8,  8,
	 9,  9,  9,  9,  9,	10, 10, 10, 10, 10,
	11, 11, 11, 11, 11,	12, 12, 12, 12, 12,
	13, 13, 13, 13, 13,	14, 14, 14, 14, 14,
	15, 20, 25, 30, 35,	40, 45, 55, 65, 75
    };
    int dam;

    level	= UMIN(level, sizeof(dam_each)/sizeof(dam_each[0]) - 1);
    level	= UMAX(0, level);
    dam		= number_range( dam_each[level] / 2, dam_each[level] * 2 );
    if ( saves_spell( level, victim ) )
	dam /= 2;
    damage( ch, victim, dam, sn );
    return;
}



void spell_mass_invis( int sn, int level, CHAR_DATA *ch, void *vo )
{
    AFFECT_DATA af;
    CHAR_DATA *gch;

    for ( gch = ch->in_room->people; gch != NULL; gch = gch->next_in_room )
    {
	if ( !is_same_group( gch, ch ) || IS_AFFECTED(gch, AFF_INVISIBLE) )
	    continue;
	act( "$n slowly fades out of existence.", gch, NULL, NULL, TO_ROOM );
	send_to_char( "You slowly fade out of existence.\n\r", gch );
	af.type      = sn;
	af.duration  = 24;
	af.location  = APPLY_NONE;
	af.modifier  = 0;
	af.bitvector = AFF_INVISIBLE;
	affect_to_char( gch, &af );
    }
    send_to_char( "Ok.\n\r", ch );

    return;
}



void spell_null( int sn, int level, CHAR_DATA *ch, void *vo )
{
    send_to_char( "That's not a spell!\n\r", ch );
    return;
}



void spell_pass_door( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;

    if ( IS_AFFECTED(victim, AFF_PASS_DOOR) )
	return;
    af.type      = sn;
    af.duration  = number_fuzzy( level / 4 );
    af.location  = APPLY_NONE;
    af.modifier  = 0;
    af.bitvector = AFF_PASS_DOOR;
    affect_to_char( victim, &af );
    act( "$n turns translucent.", victim, NULL, NULL, TO_ROOM );
    send_to_char( "You turn translucent.\n\r", victim );
    return;
}



void spell_poison( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;
    char buf [MAX_INPUT_LENGTH];

    /* Ghosts cannot be poisoned - KaVir */
    if ( IS_NPC(victim) && IS_AFFECTED(victim, AFF_ETHEREAL) ) return;
          return;
    if ( !IS_NPC(victim) && IS_CLASS(victim, CLASS_VAMPIRE) &&
	IS_VAMPAFF(victim, VAM_SERPENTIS) ) return;
    else if ( !IS_NPC(victim) && IS_CLASS(victim, CLASS_WEREWOLF) &&
	victim->power[DISC_WERE_SPID] > 2 ) return;
    else if ( !IS_NPC(victim) && IS_CLASS(victim, CLASS_DROW) &&
IS_SET(victim->pcdata->powers[1], DPOWER_DROWPOISON)) return;

    if ( saves_spell( level, victim ) )
	return;
    af.type      = sn;
    af.duration  = level;
    af.location  = APPLY_STR;
    af.modifier  = 0 - number_range(1,3);
    af.bitvector = AFF_POISON;
    affect_join( victim, &af );
    send_to_char( "You feel very sick.\n\r", victim );
    if ( ch == victim ) return;
    if (!IS_NPC(victim))
	sprintf(buf,"%s looks very sick as your poison takes affect.\n\r",victim->name);
    else
	sprintf(buf,"%s looks very sick as your poison takes affect.\n\r",victim->short_descr);
    send_to_char(buf,ch);
    return;
}



void spell_protection( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;

    if ( IS_AFFECTED(victim, AFF_PROTECT) )
	return;
    af.type      = sn;
    af.duration  = 24;
    af.location  = APPLY_NONE;
    af.modifier  = 0;
    af.bitvector = AFF_PROTECT;
    affect_to_char( victim, &af );
    send_to_char( "You feel protected.\n\r", victim );
    if ( ch != victim )
	send_to_char( "Ok.\n\r", ch );
    return;
}



void spell_refresh( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    victim->move = UMIN( victim->move + level, victim->max_move );
    act("$n looks less tired.",victim,NULL,NULL,TO_ROOM);
    send_to_char( "You feel less tired.\n\r", victim );
    if (!IS_NPC(victim) && victim->sex == SEX_MALE && 
	victim->pcdata->stage[0] < 1 && victim->pcdata->stage[2] > 0)
	victim->pcdata->stage[2] = 0;
    return;
}



void spell_remove_curse( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim;
    OBJ_DATA  *obj;
    char       arg [MAX_INPUT_LENGTH];

    one_argument( target_name, arg );

    if ( arg[0] == '\0')
    {
	send_to_char( "Remove curse on what?\n\r", ch );
	return;
    }

    if ( ( victim = get_char_world( ch, target_name ) ) != NULL )
    {
	if ( is_affected( victim, gsn_curse ) )
    	{
	    affect_strip( victim, gsn_curse );
	    send_to_char( "You feel better.\n\r", victim );
	    if ( ch != victim )
		send_to_char( "Ok.\n\r", ch );
	    if (!IS_NPC(ch) && ch != victim) do_humanity(ch,"");
	}
	return;
    }
    if ( ( obj = get_obj_carry( ch, arg ) ) != NULL )
    {
	if ( IS_SET(obj->extra_flags, ITEM_NOREMOVE) )
	{
	    REMOVE_BIT(obj->extra_flags, ITEM_NOREMOVE);
	    act( "$p flickers with energy.", ch, obj, NULL, TO_CHAR );
	}
	else if ( IS_SET(obj->extra_flags, ITEM_NODROP) )
	{
	    REMOVE_BIT(obj->extra_flags, ITEM_NODROP);
	    act( "$p flickers with energy.", ch, obj, NULL, TO_CHAR );
	}
	return;
    }
    send_to_char( "No such creature or object to remove curse on.\n\r", ch );
    return;
}



void spell_sanctuary( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;

    if ( IS_AFFECTED(victim, AFF_SANCTUARY) )
	return;
    af.type      = sn;
    af.duration  = number_fuzzy( level / 4 );
    af.location  = APPLY_NONE;
    af.modifier  = 0;
    af.bitvector = AFF_SANCTUARY;
    affect_to_char( victim, &af );
    act( "$n is surrounded in a white aura.", victim, NULL, NULL, TO_ROOM );
    send_to_char( "You are surrounded by a white aura!\n\r", victim );
    return;
}



void spell_shield( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;

    if ( is_affected( victim, sn ) )
	return;
    af.type      = sn;
    af.duration  = 8 + level;
    af.location  = APPLY_AC;
    af.modifier  = -20;
    af.bitvector = 0;
    affect_to_char( victim, &af );
    act( "$n is surrounded by a force shield.", victim, NULL, NULL, TO_ROOM );
    send_to_char( "You are surrounded by a force shield.\n\r", victim );
    return;
}



void spell_shocking_grasp( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    static const int dam_each[] = 
    {
	10,
	10, 10, 15, 15, 15,	20, 20, 25, 29, 33,
	36, 39, 39, 39, 40,	40, 41, 41, 42, 42,
	43, 43, 44, 44, 45,	45, 46, 46, 47, 47,
	48, 48, 49, 49, 50,	50, 51, 51, 52, 52,
	53, 53, 54, 54, 55,	55, 56, 56, 57, 57,
	60, 70, 85,100,125,	150,175,200,225,300
    };
    int dam;
    int hp;

    if (IS_ITEMAFF(victim, ITEMA_SHOCKSHIELD)) return;

    level	= UMIN(level, sizeof(dam_each)/sizeof(dam_each[0]) - 1);
    level	= UMAX(0, level);
    dam		= number_range( dam_each[level] / 2, dam_each[level] * 2 );
    if ( saves_spell( level, victim ) )
	dam /= 2;
    hp = victim->hit;
    damage( ch, victim, dam, sn );
    if (!IS_NPC(victim) && IS_IMMUNE(victim, IMM_LIGHTNING) )
	victim->hit = hp;
    return;
}



void spell_sleep( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;
  
    if ( IS_AFFECTED(victim, AFF_SLEEP)
    ||   level < victim->level
    || ( !IS_NPC(victim) && IS_IMMUNE(victim, IMM_SLEEP) )
    || (  IS_NPC(victim) && IS_AFFECTED(victim, AFF_ETHEREAL) )
    ||   saves_spell( level, victim ) )
	return;

    af.type      = sn;
    af.duration  = 4 + level;
    af.location  = APPLY_NONE;
    af.modifier  = 0;
    af.bitvector = AFF_SLEEP;
    affect_join( victim, &af );

    if ( IS_AWAKE(victim) )
    {
	send_to_char( "You feel very sleepy ..... zzzzzz.\n\r", victim );
	act( "$n goes to sleep.", victim, NULL, NULL, TO_ROOM );
	victim->position = POS_SLEEPING;
    }

    return;
}



void spell_stone_skin( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;

    if ( is_affected( ch, sn ) )
	return;
    af.type      = sn;
    af.duration  = level;
    af.location  = APPLY_AC;
    af.modifier  = -40;
    af.bitvector = 0;
    affect_to_char( victim, &af );
    act( "$n's skin turns to stone.", victim, NULL, NULL, TO_ROOM );
    send_to_char( "Your skin turns to stone.\n\r", victim );
    return;
}



void spell_summon( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim;
    CHAR_DATA *mount;

    if ( ( victim = get_char_world( ch, target_name ) ) == NULL
    ||   victim == ch
    ||   victim->in_room == NULL
    ||   IS_SET(victim->in_room->room_flags, ROOM_SAFE)
    ||   IS_SET(victim->in_room->room_flags, ROOM_PRIVATE)
    ||   IS_SET(victim->in_room->room_flags, ROOM_SOLITARY)
    ||   IS_SET(victim->in_room->room_flags, ROOM_NO_RECALL)
    ||   victim->level >= level + 3
    ||   victim->fighting != NULL
    ||   victim->in_room->area != ch->in_room->area
    ||   (!IS_NPC(victim) && !IS_IMMUNE(victim, IMM_SUMMON) )
    ||   (IS_NPC(victim) && IS_AFFECTED(victim, AFF_ETHEREAL) )
    ||   (IS_NPC(victim) && saves_spell( level, victim ) ) )
    {
	send_to_char( "You failed.\n\r", ch );
	return;
    }

    act( "$n disappears suddenly.", victim, NULL, NULL, TO_ROOM );
    char_from_room( victim );
    char_to_room( victim, ch->in_room );
    act( "$n arrives suddenly.", victim, NULL, NULL, TO_ROOM );
    act( "$N has summoned you!", victim, NULL, ch,   TO_CHAR );
    do_look( victim, "auto" );
    if ( (mount = victim->mount) == NULL ) return;
    char_from_room( mount );
    char_to_room( mount, get_room_index(victim->in_room->vnum) );
    do_look( mount, "auto" );
    return;
}



void spell_teleport( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    CHAR_DATA *mount;
    ROOM_INDEX_DATA *pRoomIndex;
    int to_room;

    if ( victim->in_room == NULL
    ||   IS_SET(victim->in_room->room_flags, ROOM_NO_RECALL)
    ||   IS_SET(victim->in_room->room_flags, ROOM_SAFE)
    ||   IS_SET(victim->in_room->room_flags, ROOM_NO_TELEPORT)
    || ( !IS_NPC(ch) && victim->fighting != NULL )
    || ( !IS_NPC(victim) && !IS_IMMUNE(victim, IMM_SUMMON) )
    || ( victim != ch
    && ( saves_spell( level, victim ) || saves_spell( level, victim ) ) ) )
    {
	send_to_char( "You failed.\n\r", ch );
	return;
    }

    for ( ; ; )
    {
	to_room = number_range( 0, 65535 );
	pRoomIndex = get_room_index( to_room );
	if ( pRoomIndex != NULL )
	if ( !IS_SET(pRoomIndex->room_flags, ROOM_PRIVATE)
	&&   !IS_SET(pRoomIndex->room_flags, ROOM_SOLITARY)
	&&   !IS_SET(pRoomIndex->room_flags, ROOM_NO_TELEPORT)
	&&   to_room != 30008 && to_room != 30002 )
	    break;
    }

    act( "$n slowly fades out of existence.", victim, NULL, NULL, TO_ROOM );
    char_from_room( victim );
    char_to_room( victim, pRoomIndex );
    act( "$n slowly fades into existence.", victim, NULL, NULL, TO_ROOM );
    do_look( victim, "auto" );
    if ( (mount = ch->mount) == NULL ) return;
    char_from_room( mount );
    char_to_room( mount, ch->in_room );
    do_look( mount, "auto" );
    return;
}



void spell_ventriloquate( int sn, int level, CHAR_DATA *ch, void *vo )
{
    char buf1[MAX_STRING_LENGTH];
    char buf2[MAX_STRING_LENGTH];
    char speaker[MAX_INPUT_LENGTH];
    CHAR_DATA *vch;

    target_name = one_argument( target_name, speaker );

    sprintf( buf1, "%s says '%s'.\n\r",              speaker, target_name );
    sprintf( buf2, "Someone makes %s say '%s'.\n\r", speaker, target_name );
    buf1[0] = UPPER(buf1[0]);

    for ( vch = ch->in_room->people; vch != NULL; vch = vch->next_in_room )
    {
	if ( !is_name( speaker, vch->name ) )
	    send_to_char( saves_spell( level, vch ) ? buf2 : buf1, vch );
    }

    return;
}



void spell_weaken( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;

    if ( is_affected( victim, sn ) || saves_spell( level, victim ) )
	return;
    af.type      = sn;
    af.duration  = level / 2;
    af.location  = APPLY_STR;
    af.modifier  = -2;
    af.bitvector = 0;
    affect_to_char( victim, &af );
    send_to_char( "You feel weaker.\n\r", victim );
    if ( ch != victim )
	send_to_char( "Ok.\n\r", ch );
    return;
}



/*
 * This is for muds that _want_ scrolls of recall.
 * Ick.
 */
void spell_word_of_recall( int sn, int level, CHAR_DATA *ch, void *vo )
{
    do_recall( (CHAR_DATA *) vo, "" );
    return;
}



/*
 * NPC spells.
 */
void spell_acid_breath( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    OBJ_DATA *obj_lose;
    OBJ_DATA *obj_next;
    int dam;
    int hpch;
    int hp;

    if (IS_ITEMAFF(victim, ITEMA_ACIDSHIELD)) return;

    if ( number_percent( ) < 2 * level && !saves_spell( level, victim ) )
    {
	for ( obj_lose = ch->carrying; obj_lose != NULL; obj_lose = obj_next )
	{
	    int iWear;

	    obj_next = obj_lose->next_content;

	    if ( number_bits( 2 ) != 0 )
		continue;

	    if (IS_SET(obj_lose->quest,QUEST_SPELLPROOF)) continue;
	    switch ( obj_lose->item_type )
	    {
	    case ITEM_ARMOR:
		if ( obj_lose->value[0] > 0 )
		{
		    act( "$p is pitted and etched!",
			victim, obj_lose, NULL, TO_CHAR );
		    if ( ( iWear = obj_lose->wear_loc ) != WEAR_NONE )
			victim->armor -= apply_ac( obj_lose, iWear );
		    obj_lose->value[0] -= 1;
		    obj_lose->cost      = 0;
		    if ( iWear != WEAR_NONE )
			victim->armor += apply_ac( obj_lose, iWear );
		}
		break;

	    case ITEM_CONTAINER:
		act( "$p fumes and dissolves!",
		    victim, obj_lose, NULL, TO_CHAR );
		extract_obj( obj_lose );
		break;
	    }
	}
    }

    hpch = UMAX( 10, ch->hit );
    dam  = number_range( hpch/16+1, hpch/8 );
    if ( saves_spell( level, victim ) )
	dam /= 2;
    hp = victim->hit;
    damage( ch, victim, dam, sn );
    if (!IS_NPC(victim) && IS_IMMUNE(victim, IMM_ACID) )
	victim->hit = hp;
    return;
}



void spell_fire_breath( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    OBJ_DATA *obj_lose;
    OBJ_DATA *obj_next;
    int dam;
    int hpch;
    int hp;

    if (IS_ITEMAFF(victim, ITEMA_FIRESHIELD)) return;

    if ( number_percent( ) < 2 * level && !saves_spell( level, victim ) )
    {
	for ( obj_lose = victim->carrying; obj_lose != NULL;
	obj_lose = obj_next )
	{
	    char *msg;

	    obj_next = obj_lose->next_content;
	    if ( number_bits( 2 ) != 0 )
		continue;

	    if (IS_SET(obj_lose->quest,QUEST_SPELLPROOF)) continue;
	    switch ( obj_lose->item_type )
	    {
	    	default:             continue;
	    	case ITEM_CONTAINER: msg = "$p ignites and burns!";   break;
	    	case ITEM_POTION:    msg = "$p bubbles and boils!";   break;
	    	case ITEM_SCROLL:    msg = "$p crackles and burns!";  break;
	    	case ITEM_STAFF:     msg = "$p smokes and chars!";    break;
	    	case ITEM_WAND:      msg = "$p sparks and sputters!"; break;
	   	case ITEM_FOOD:      msg = "$p blackens and crisps!"; break;
	    	case ITEM_PILL:      msg = "$p melts and drips!";     break;
	    }

	    act( msg, victim, obj_lose, NULL, TO_CHAR );
	    extract_obj( obj_lose );
	}
    }

    hpch = UMAX( 10, ch->hit );
    dam  = number_range( hpch/16+1, hpch/8 );
    if ( saves_spell( level, victim ) )
	dam /= 2;
    hp = victim->hit;
    if (!IS_NPC(victim) && IS_CLASS(victim, CLASS_VAMPIRE) )
    {
    	damage( ch, victim, (dam*2), sn );
	hp = ((hp - victim->hit)/2) + victim->hit;
    }
    else
    	damage( ch, victim, dam, sn );
    if (!IS_NPC(victim) && IS_IMMUNE(victim, IMM_HEAT) )
	victim->hit = hp;
    return;
}



void spell_frost_breath( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    OBJ_DATA *obj_lose;
    OBJ_DATA *obj_next;
    int dam;
    int hpch;
    int hp;

    if (IS_ITEMAFF(victim, ITEMA_ICESHIELD)) return;

    if ( number_percent( ) < 2 * level && !saves_spell( level, victim ) )
    {
	for ( obj_lose = victim->carrying; obj_lose != NULL;
	obj_lose = obj_next )
	{
	    char *msg;

	    obj_next = obj_lose->next_content;
	    if ( number_bits( 2 ) != 0 )
		continue;

	    if (IS_SET(obj_lose->quest,QUEST_SPELLPROOF)) continue;
	    switch ( obj_lose->item_type )
	    {
	    	default:            continue;
	    	case ITEM_CONTAINER:
	    	case ITEM_DRINK_CON:
	    	case ITEM_POTION:   msg = "$p freezes and shatters!"; break;
	    }

	    act( msg, victim, obj_lose, NULL, TO_CHAR );
	    extract_obj( obj_lose );
	}
    }

    hpch = UMAX( 10, ch->hit );
    dam  = number_range( hpch/16+1, hpch/8 );
    if ( saves_spell( level, victim ) )
	dam /= 2;
    if (!IS_NPC(victim) && IS_CLASS(victim, CLASS_VAMPIRE) )
	dam /= 2;
    hp = victim->hit;
    damage( ch, victim, dam, sn );
    if (!IS_NPC(victim) && IS_IMMUNE(victim, IMM_COLD) )
	victim->hit = hp;
    return;
}



void spell_gas_breath( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *vch;
    CHAR_DATA *vch_next;
    int dam;
    int hpch;
    int chhp;

    for ( vch = ch->in_room->people; vch != NULL; vch = vch_next )
    {
	vch_next = vch->next_in_room;
	if (can_see(ch, vch)) 
	if ( IS_NPC(ch) ? !IS_NPC(vch) : IS_NPC(vch) )
	{
	    hpch = UMAX( 10, ch->hit );
	    dam  = number_range( hpch/16+1, hpch/8 );
	    if ( saves_spell( level, vch ) )
		dam /= 2;
	    chhp = vch->hit;
	    damage( ch, vch, dam, sn );
	    if (!IS_NPC(vch) && IS_CLASS(vch, CLASS_VAMPIRE) )
		vch->hit = chhp;
	}
    }
    return;
}



void spell_lightning_breath( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    int dam;
    int hpch;
    int hp;

    if (IS_ITEMAFF(victim, ITEMA_SHOCKSHIELD)) return;

    hpch = UMAX( 10, ch->hit );
    dam = number_range( hpch/16+1, hpch/8 );
    if ( saves_spell( level, victim ) )
	dam /= 2;
    hp = victim->hit;
    damage( ch, victim, dam, sn );
    if (!IS_NPC(victim) && IS_IMMUNE(victim, IMM_LIGHTNING) )
	victim->hit = hp;
    return;
}

/* Extra spells written by KaVir. */

void spell_guardian( int sn, int level, CHAR_DATA *ch, void *vo )
{
    char buf [MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    AFFECT_DATA af;

    if (ch->pcdata->followers > 4)
    {
	send_to_char("Nothing happens.\n\r",ch);
	return;
    }
    ch->pcdata->followers++;

    victim=create_mobile( get_mob_index( MOB_VNUM_GUARDIAN ) );
    victim->level = level;
    victim->hit = 100*level;
    victim->max_hit = 100*level;
    victim->hitroll = level;
    victim->damroll = level;
    victim->armor = 100 - (level*7);

    strcpy(buf,"Come forth, creature of darkness, and do my bidding!");
    do_say( ch, buf );

    send_to_char( "A demon bursts from the ground and bows before you.\n\r",ch );
    act( "$N bursts from the ground and bows before $n.", ch, NULL, victim, TO_ROOM );

    char_to_room( victim, ch->in_room );


    add_follower( victim, ch );
    af.type      = sn;
    af.duration  = 666;
    af.location  = APPLY_NONE;
    af.modifier  = 0;
    af.bitvector = AFF_CHARM;
    affect_to_char( victim, &af );
    return;
}

void spell_soulblade( int sn, int level, CHAR_DATA *ch, void *vo )
{
    OBJ_DATA    *obj = (OBJ_DATA *) vo;
    char buf     [MAX_STRING_LENGTH];
    char wpnname [MAX_INPUT_LENGTH];
    int weapontype = 3;

    obj = create_object( get_obj_index( OBJ_VNUM_SOULBLADE ), 0 );

    if (ch->wpn[1]  > ch->wpn[weapontype])
	{weapontype = 1;strcpy(wpnname,"blade");}
    if (ch->wpn[2]  > ch->wpn[weapontype])
	{weapontype = 2;strcpy(wpnname,"blade");}
    if (ch->wpn[4]  > ch->wpn[weapontype])
	{weapontype = 4;strcpy(wpnname,"whip");}
    if (ch->wpn[5]  > ch->wpn[weapontype])
	{weapontype = 5;strcpy(wpnname,"claw");}
    if (ch->wpn[6]  > ch->wpn[weapontype])
	{weapontype = 6;strcpy(wpnname,"blaster");}
    if (ch->wpn[7]  > ch->wpn[weapontype])
	{weapontype = 7;strcpy(wpnname,"mace");}
    if (ch->wpn[8]  > ch->wpn[weapontype])
	{weapontype = 8;strcpy(wpnname,"mace");}
    if (ch->wpn[9]  > ch->wpn[weapontype])
	{weapontype = 9;strcpy(wpnname,"grepper");}
    if (ch->wpn[10] > ch->wpn[weapontype])
	{weapontype = 10;strcpy(wpnname,"biter");}
    if (ch->wpn[11] > ch->wpn[weapontype])
	{weapontype = 11;strcpy(wpnname,"blade");}
    if (ch->wpn[12] > ch->wpn[weapontype])
	{weapontype = 12;strcpy(wpnname,"sucker");}
    if (weapontype == 3) strcpy(wpnname,"blade");
    /* First we name the weapon */
    free_string(obj->name);
    sprintf(buf,"%s soul %s",ch->name,wpnname);
    obj->name=str_dup(buf);
    free_string(obj->short_descr);
    if (IS_NPC(ch)) sprintf(buf,"%s's soul %s",ch->short_descr,wpnname);
    else sprintf(buf,"%s's soul %s",ch->pcdata->switchname,wpnname);
    buf[0] = UPPER(buf[0]);
    obj->short_descr=str_dup(buf);
    free_string(obj->description);
    if (IS_NPC(ch)) sprintf(buf,"%s's soul %s is lying here.",ch->short_descr,wpnname);
    else sprintf(buf,"%s's soul %s is lying here.",ch->name,wpnname);
    buf[0] = UPPER(buf[0]);
    obj->description=str_dup(buf);

    if (IS_NPC(ch)) obj->level = ch->level;
    else if (ch->spl[2] > 4) obj->level = ch->spl[2]/4;
    else obj->level = 1;
    if (obj->level > 60) obj->level = 60;
    obj->value[0] = 13034;
    obj->value[1] = 10;
    obj->value[2] = 20;
    obj->value[3] = weapontype;
    if (obj->questmaker != NULL) free_string(obj->questmaker);
    obj->questmaker = str_dup(ch->name);
    if (!IS_NPC(ch))
    {
	if (obj->questowner != NULL) free_string(obj->questowner);
	obj->questowner = str_dup(ch->pcdata->switchname);
    }
    obj_to_char(obj,ch);
    act("$p fades into existance in your hand.", ch, obj, NULL, TO_CHAR);
    act("$p fades into existance in $n's hand.", ch, obj, NULL, TO_ROOM);
    return;
}

void spell_mana( int sn, int level, CHAR_DATA *ch, void *vo)
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    if (!IS_NPC(ch) && !IS_CLASS(ch, CLASS_VAMPIRE) &&
	IS_VAMPAFF(ch, VAM_CELERITY))
    {
	if ( ch->move < 25 )
	{
	    send_to_char( "You are too exhausted to do that.\n\r", ch );
	    return;
	}
	ch->move = ch->move - 25;
    }
    else
    {
	if ( ch->move < 50 )
	{
	    send_to_char( "You are too exhausted to do that.\n\r", ch );
	    return;
	}
	ch->move = ch->move - 50;
    }
    victim->mana = UMIN( victim->mana + level + 10, victim->max_mana);
    update_pos(ch);
    update_pos(victim);
    if (ch == victim)
    {
        send_to_char("You draw in energy from your surrounding area.\n\r",
                ch);
        act("$n draws in energy from $s surrounding area.", ch, NULL, NULL,
                TO_ROOM);
        return;
    }
    act("You draw in energy from around you and channel it into $N.",
            ch, NULL, victim, TO_CHAR);
    act("$n draws in energy and channels it into $N.",
            ch, NULL, victim, TO_NOTVICT);
    act("$n draws in energy and channels it into you.",
            ch, NULL, victim, TO_VICT);
    if (!IS_NPC(ch) && ch != victim) do_humanity(ch,"");
    return;
}

void spell_frenzy( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA  *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;
    

    if ( is_affected( victim, sn )) return;
    af.type      = sn;
    af.duration  = 1 + level / 10;
    af.location  = APPLY_HITROLL;
    af.modifier  = level / 5;
    af.bitvector = 0;
    affect_to_char( victim, &af );

    af.location  = APPLY_DAMROLL;
    af.modifier  = level / 5;
    affect_to_char( victim, &af );

    af.location  = APPLY_AC;
    af.modifier  = level / 2;
    affect_to_char( victim, &af );
    if ( ch != victim )
        send_to_char( "Ok.\n\r", ch );
    act( "$n is consumed with rage.", victim, NULL, NULL, TO_ROOM );
    send_to_char( "You are consumed with rage!\n\r", victim );
    if (!IS_NPC(victim)) do_beastlike(victim,"");
    return;
}

void spell_darkblessing( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA  *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;

    if ( is_affected( victim, sn ) ) return;

    af.type      = sn;
    af.duration  = level / 2;
    af.location  = APPLY_HITROLL;
    af.modifier  = 1 + level / 14;
    af.bitvector = 0;
    affect_to_char( victim, &af );
    af.location  = APPLY_DAMROLL;
    af.modifier  = 1 + level / 14;
    affect_to_char( victim, &af );

    if ( ch != victim )
        send_to_char( "Ok.\n\r", ch );
    act( "$n looks wicked.", victim, NULL, NULL, TO_ROOM );
    send_to_char( "You feel wicked.\n\r", victim );
    return;
}

void spell_portal( int sn, int level, CHAR_DATA *ch, void *vo)
{
    CHAR_DATA *victim;
    OBJ_DATA  *obj;
    char       arg [MAX_INPUT_LENGTH];
    int        duration;

    one_argument( target_name, arg );

    if ( arg[0] == '\0')
    {
	send_to_char( "Who do you wish to create a portal to?\n\r", ch );
	return;
    }

    victim = get_char_world( ch, arg );

    if ( ( victim = get_char_world( ch, target_name ) ) == NULL
    ||   victim == ch
    ||   victim->in_room == NULL
    ||   IS_NPC(ch)
    ||   IS_NPC(victim)
    ||   (!IS_NPC(victim) && !IS_IMMUNE(victim, IMM_SUMMON) )
    ||   IS_SET(ch->in_room->room_flags, ROOM_PRIVATE)
    ||   IS_SET(ch->in_room->room_flags, ROOM_SOLITARY)
    ||   IS_SET(ch->in_room->room_flags, ROOM_NO_RECALL)
    ||   IS_SET(victim->in_room->room_flags, ROOM_PRIVATE)
    ||   IS_SET(victim->in_room->room_flags, ROOM_SOLITARY)
    ||   IS_SET(victim->in_room->room_flags, ROOM_NO_RECALL)
    ||   victim->in_room->vnum == ch->in_room->vnum)
    {
	send_to_char( "You failed.\n\r", ch );
	return;
    }

    duration = number_range(2,3);

    obj = create_object( get_obj_index( OBJ_VNUM_PORTAL ), 0 );
    obj->value[0] = victim->in_room->vnum;
    obj->value[3] = ch->in_room->vnum;
    obj->timer = duration;
    if (IS_AFFECTED(ch,AFF_SHADOWPLANE))
	obj->extra_flags = ITEM_SHADOWPLANE;
    obj_to_room( obj, ch->in_room );

    obj = create_object( get_obj_index( OBJ_VNUM_PORTAL ), 0 );
    obj->value[0] = ch->in_room->vnum;
    obj->value[3] = victim->in_room->vnum;
    obj->timer = duration;
    if (IS_AFFECTED(victim,AFF_SHADOWPLANE))
	obj->extra_flags = ITEM_SHADOWPLANE;
    obj_to_room( obj, victim->in_room );

    act( "$p appears in front of $n.", ch, obj, NULL, TO_ROOM );
    act( "$p appears in front of you.", ch, obj, NULL, TO_CHAR );
    act( "$p appears in front of $n.", victim, obj, NULL, TO_ROOM );
    act( "$p appears in front of you.", ch, obj, victim, TO_VICT );
    return;
}

/* This spell is designed for potions */
void spell_energyflux( int sn, int level, CHAR_DATA *ch, void *vo)
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;

    victim->mana = UMIN( victim->mana + 50, victim->max_mana);
    update_pos(victim);
    send_to_char("You feel mana channel into your body.\n\r",victim);
    return;
}

void spell_voodoo( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    OBJ_DATA  *obj;
    char       buf [MAX_INPUT_LENGTH];
    char       arg [MAX_INPUT_LENGTH];
    char     part1 [MAX_INPUT_LENGTH];
    char     part2 [MAX_INPUT_LENGTH];
    int       worn;

    one_argument( target_name, arg );

    victim = get_char_world( ch, arg );

    if (ch->practice < 5)
    {
	send_to_char( "It costs 5 points of primal energy to create a voodoo doll.\n\r", ch );
	return;
    }

    if ( ( victim = get_char_world( ch, target_name ) ) == NULL )
    {
	send_to_char( "Nobody by that name is playing.\n\r", ch );
	return;
    }

    if ( ( obj = get_eq_char( ch, WEAR_WIELD ) ) == NULL )
    {
    	if ( ( obj = get_eq_char( ch, WEAR_HOLD ) ) == NULL )
	{
	    send_to_char( "You are not holding any body parts.\n\r", ch );
	    return;
	}
	else worn = WEAR_HOLD;
    }
    else worn = WEAR_WIELD;

    if ( IS_NPC(victim) )
    {
	send_to_char( "Not on NPC's.\n\r", ch );
	return;
    }

    if      (obj->value[2] == 12) sprintf(part1,"head %s",victim->name);
    else if (obj->value[2] == 13) sprintf(part1,"heart %s",victim->name);
    else if (obj->value[2] == 14) sprintf(part1,"arm %s",victim->name);
    else if (obj->value[2] == 15) sprintf(part1,"leg %s",victim->name);
    else if (obj->value[2] == 30004) sprintf(part1,"entrails %s",victim->name);
    else if (obj->value[2] == 30005) sprintf(part1,"brain %s",victim->name);
    else if (obj->value[2] == 30006) sprintf(part1,"eye eyeball %s",victim->name);
    else if (obj->value[2] == 30012) sprintf(part1,"face %s",victim->name);
    else if (obj->value[2] == 30013) sprintf(part1,"windpipe %s",victim->name);
    else if (obj->value[2] == 30014) sprintf(part1,"cracked head %s",victim->name);
    else if (obj->value[2] == 30025) sprintf(part1,"ear %s",victim->name);
    else if (obj->value[2] == 30026) sprintf(part1,"nose %s",victim->name);
    else if (obj->value[2] == 30027) sprintf(part1,"tooth %s",victim->name);
    else if (obj->value[2] == 30028) sprintf(part1,"tongue %s",victim->name);
    else if (obj->value[2] == 30029) sprintf(part1,"hand %s",victim->name);
    else if (obj->value[2] == 30030) sprintf(part1,"foot %s",victim->name);
    else if (obj->value[2] == 30031) sprintf(part1,"thumb %s",victim->name);
    else if (obj->value[2] == 30032) sprintf(part1,"index finger %s",victim->name);
    else if (obj->value[2] == 30033) sprintf(part1,"middle finger %s",victim->name);
    else if (obj->value[2] == 30034) sprintf(part1,"ring finger %s",victim->name);
    else if (obj->value[2] == 30035) sprintf(part1,"little finger %s",victim->name);
    else if (obj->value[2] == 30036) sprintf(part1,"toe %s",victim->name);
    else
    {
	sprintf(buf,"%s isn't a part of %s!\n\r",obj->name,victim->name);
	send_to_char( buf, ch );
	return;
    }

    sprintf(part2,obj->name);

    if ( str_cmp(part1,part2) )
    {
	sprintf(buf,"But you are holding %s, not %s!\n\r",obj->short_descr,victim->name);
	send_to_char( buf, ch );
	return;
    }

    act("$p vanishes from your hand in a puff of smoke.", ch, obj, NULL, TO_CHAR);
    act("$p vanishes from $n's hand in a puff of smoke.", ch, obj, NULL, TO_ROOM);
    obj_from_char(obj);
    extract_obj(obj);

    obj = create_object( get_obj_index( OBJ_VNUM_VOODOO_DOLL ), 0 );

    sprintf(buf,"%s voodoo doll",victim->name);
    free_string(obj->name);
    obj->name=str_dup(buf);

    sprintf(buf,"a voodoo doll of %s",victim->name);
    free_string(obj->short_descr);
    obj->short_descr=str_dup(buf);

    sprintf(buf,"A voodoo doll of %s lies here.",victim->name);
    free_string(obj->description);
    obj->description=str_dup(buf);

    obj_to_char(obj,ch);
    equip_char(ch,obj,worn);

    act("$p appears in your hand.", ch, obj, NULL, TO_CHAR);
    act("$p appears in $n's hand.", ch, obj, NULL, TO_ROOM);

    ch->practice -= 5;

    return;
}

void spell_transport( int sn, int level, CHAR_DATA *ch, void *vo )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;
    CHAR_DATA *victim;

    target_name = one_argument( target_name, arg1 );
    target_name = one_argument( target_name, arg2 );

    if ( arg1[0] == '\0' )
    {
        send_to_char( "Transport which object?\n\r", ch );
        return;
    }

    if ( arg2[0] == '\0' )
    {
        send_to_char( "Transport who whom?\n\r", ch );
        return;
    }
    if ( ( victim = get_char_world( ch, arg2 ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( ( obj = get_obj_carry( ch, arg1 ) ) == NULL )
    {
	send_to_char( "You are not carrying that item.\n\r", ch );
	return;
    }

	if (IS_SET(obj->quest, QUEST_ARTIFACT)) {
	send_to_char("You can't transport that.\n\r", ch );
	return;}

	if (obj->item_type == ITEM_KINGDOM_POWER) {
	send_to_char("You can't transport that.\n\r", ch );
	return;}

    if (!IS_NPC(victim) && !IS_IMMUNE(victim, IMM_TRANSPORT))
    {
	send_to_char( "You are unable to transport anything to them.\n\r", ch );
	return;
    }

    act("$p vanishes from your hands in an swirl of smoke.",ch,obj,NULL,TO_CHAR);
    act("$p vanishes from $n's hands in a swirl of smoke.",ch,obj,NULL,TO_ROOM);
    obj_from_char(obj);
    obj_to_char(obj,victim);
    act("$p appears in your hands in an swirl of smoke.",victim,obj,NULL,TO_CHAR);
    act("$p appears in $n's hands in an swirl of smoke.",victim,obj,NULL,TO_ROOM);
    do_autosave(ch,"");
    do_autosave(victim,"");
    return;
}

void spell_regenerate( int sn, int level, CHAR_DATA *ch, void *vo )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;
    CHAR_DATA *victim;
    int teeth = 0;

    target_name = one_argument( target_name, arg1 );
    target_name = one_argument( target_name, arg2 );

    if ( arg1[0] == '\0' )
    {
        send_to_char( "Which body part?\n\r", ch );
        return;
    }

    if ( arg2[0] == '\0' )
    {
        send_to_char( "Regenerate which person?\n\r", ch );
        return;
    }
    if ( ( victim = get_char_room( ch, arg2 ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if (victim->loc_hp[6] > 0)
    {
	send_to_char( "You cannot regenerate someone who is still bleeding.\n\r", ch );
	return;
    }

    if ( ( obj = get_obj_carry( ch, arg1 ) ) == NULL )
    {
	send_to_char( "You are not carrying that item.\n\r", ch );
	return;
    }

    if (IS_HEAD(victim,LOST_TOOTH_1  )) teeth += 1;
    if (IS_HEAD(victim,LOST_TOOTH_2  )) teeth += 2;
    if (IS_HEAD(victim,LOST_TOOTH_4  )) teeth += 4;
    if (IS_HEAD(victim,LOST_TOOTH_8  )) teeth += 8;
    if (IS_HEAD(victim,LOST_TOOTH_16 )) teeth += 16;

    if (obj->pIndexData->vnum == OBJ_VNUM_SLICED_ARM)
    {
	if (!IS_ARM_L(victim,LOST_ARM) && !IS_ARM_R(victim,LOST_ARM))
	    {send_to_char("They don't need an arm.\n\r",ch); return;}
	if (IS_ARM_L(victim,LOST_ARM))
	    REMOVE_BIT(victim->loc_hp[LOC_ARM_L],LOST_ARM);
	else if (IS_ARM_R(victim,LOST_ARM))
	    REMOVE_BIT(victim->loc_hp[LOC_ARM_R],LOST_ARM);
	act("You press $p onto the stump of $N's shoulder.",ch,obj,victim,TO_CHAR);
	act("$n presses $p onto the stump of $N's shoulder.",ch,obj,victim,TO_NOTVICT);
	act("$n presses $p onto the stump of your shoulder.",ch,obj,victim,TO_VICT);
	extract_obj(obj);
	return;
    }
    else if (obj->pIndexData->vnum == OBJ_VNUM_SLICED_LEG)
    {
	if (!IS_LEG_L(victim,LOST_LEG) && !IS_LEG_R(victim,LOST_LEG))
	    {send_to_char("They don't need a leg.\n\r",ch); return;}
	if (IS_LEG_L(victim,LOST_LEG))
	    REMOVE_BIT(victim->loc_hp[LOC_LEG_L],LOST_LEG);
	else if (IS_LEG_R(victim,LOST_LEG))
	    REMOVE_BIT(victim->loc_hp[LOC_LEG_R],LOST_LEG);
	act("You press $p onto the stump of $N's hip.",ch,obj,victim,TO_CHAR);
	act("$n presses $p onto the stump of $N's hip.",ch,obj,victim,TO_NOTVICT);
	act("$n presses $p onto the stump of your hip.",ch,obj,victim,TO_VICT);
	extract_obj(obj);
	return;
    }
    else if (obj->pIndexData->vnum == OBJ_VNUM_SQUIDGY_EYEBALL)
    {
	if (!IS_HEAD(victim,LOST_EYE_L) && !IS_HEAD(victim,LOST_EYE_R))
	    {send_to_char("They don't need an eye.\n\r",ch); return;}
	if (IS_HEAD(victim,LOST_EYE_L))
	    REMOVE_BIT(victim->loc_hp[LOC_HEAD],LOST_EYE_L);
	else if (IS_HEAD(victim,LOST_EYE_R))
	    REMOVE_BIT(victim->loc_hp[LOC_HEAD],LOST_EYE_R);
	act("You press $p into $N's empty eye socket.",ch,obj,victim,TO_CHAR);
	act("$n presses $p into $N's empty eye socket.",ch,obj,victim,TO_NOTVICT);
	act("$n presses $p into your empty eye socket.",ch,obj,victim,TO_VICT);
	extract_obj(obj);
	return;
    }
    else if (obj->pIndexData->vnum == OBJ_VNUM_SLICED_EAR)
    {
	if (!IS_HEAD(victim,LOST_EAR_L) && !IS_HEAD(victim,LOST_EAR_R))
	    {send_to_char("They don't need an ear.\n\r",ch); return;}
	if (IS_HEAD(victim,LOST_EAR_L))
	    REMOVE_BIT(victim->loc_hp[LOC_HEAD],LOST_EAR_L);
	else if (IS_HEAD(victim,LOST_EAR_R))
	    REMOVE_BIT(victim->loc_hp[LOC_HEAD],LOST_EAR_R);
	act("You press $p onto the side of $N's head.",ch,obj,victim,TO_CHAR);
	act("$n presses $p onto the side of $N's head.",ch,obj,victim,TO_NOTVICT);
	act("$n presses $p onto the side of your head.",ch,obj,victim,TO_VICT);
	extract_obj(obj);
	return;
    }
    else if (obj->pIndexData->vnum == OBJ_VNUM_SLICED_NOSE)
    {
	if (!IS_HEAD(victim,LOST_NOSE))
	    {send_to_char("They don't need a nose.\n\r",ch); return;}
	REMOVE_BIT(victim->loc_hp[LOC_HEAD],LOST_NOSE);
	act("You press $p onto the front of $N's face.",ch,obj,victim,TO_CHAR);
	act("$n presses $p onto the front of $N's face.",ch,obj,victim,TO_NOTVICT);
	act("$n presses $p onto the front of your face.",ch,obj,victim,TO_VICT);
	extract_obj(obj);
	return;
    }
    else if (obj->pIndexData->vnum == OBJ_VNUM_SEVERED_HAND)
    {
	if (!IS_ARM_L(victim,LOST_ARM) && IS_ARM_L(victim,LOST_HAND))
	    REMOVE_BIT(victim->loc_hp[LOC_ARM_L],LOST_HAND);
	else if (!IS_ARM_R(victim,LOST_ARM) && IS_ARM_R(victim,LOST_HAND))
	    REMOVE_BIT(victim->loc_hp[LOC_ARM_R],LOST_HAND);
	else
	{
	    send_to_char("They don't need a hand.\n\r",ch);
	    return;
	}
	act("You press $p onto the stump of $N's wrist.",ch,obj,victim,TO_CHAR);
	act("$n presses $p onto the stump of $N's wrist.",ch,obj,victim,TO_NOTVICT);
	act("$n presses $p onto the stump of your wrist.",ch,obj,victim,TO_VICT);
	extract_obj(obj);
	return;
    }
    else if (obj->pIndexData->vnum == OBJ_VNUM_SEVERED_FOOT)
    {
	if (!IS_LEG_L(victim,LOST_LEG) && IS_LEG_L(victim,LOST_FOOT))
	    REMOVE_BIT(victim->loc_hp[LOC_LEG_L],LOST_FOOT);
	else if (!IS_LEG_R(victim,LOST_LEG) && IS_LEG_R(victim,LOST_FOOT))
	    REMOVE_BIT(victim->loc_hp[LOC_LEG_R],LOST_FOOT);
	else
	{
	    send_to_char("They don't need a foot.\n\r",ch);
	    return;
	}
	act("You press $p onto the stump of $N's ankle.",ch,obj,victim,TO_CHAR);
	act("$n presses $p onto the stump of $N's ankle.",ch,obj,victim,TO_NOTVICT);
	act("$n presses $p onto the stump of your ankle.",ch,obj,victim,TO_VICT);
	extract_obj(obj);
	return;
    }
    else if (obj->pIndexData->vnum == OBJ_VNUM_SEVERED_THUMB)
    {
	if (!IS_ARM_L(victim,LOST_ARM) && !IS_ARM_L(victim,LOST_HAND)
		&& IS_ARM_L(victim,LOST_THUMB))
	    REMOVE_BIT(victim->loc_hp[LOC_ARM_L],LOST_THUMB);
	else if (!IS_ARM_R(victim,LOST_ARM) && !IS_ARM_R(victim,LOST_HAND)
		&& IS_ARM_R(victim,LOST_THUMB))
	    REMOVE_BIT(victim->loc_hp[LOC_ARM_R],LOST_THUMB);
	else
	{
	    send_to_char("They don't need a thumb.\n\r",ch);
	    return;
	}
	act("You press $p onto $N's hand.",ch,obj,victim,TO_CHAR);
	act("$n presses $p onto $N's hand.",ch,obj,victim,TO_NOTVICT);
	act("$n presses $p onto your hand.",ch,obj,victim,TO_VICT);
	extract_obj(obj);
	return;
    }
    else if (obj->pIndexData->vnum == OBJ_VNUM_SEVERED_INDEX)
    {
	if (!IS_ARM_L(victim,LOST_ARM) && !IS_ARM_L(victim,LOST_HAND)
		&& IS_ARM_L(victim,LOST_FINGER_I))
	    REMOVE_BIT(victim->loc_hp[LOC_ARM_L],LOST_FINGER_I);
	else if (!IS_ARM_R(victim,LOST_ARM) && !IS_ARM_R(victim,LOST_HAND)
		&& IS_ARM_R(victim,LOST_FINGER_I))
	    REMOVE_BIT(victim->loc_hp[LOC_ARM_R],LOST_FINGER_I);
	else
	{
	    send_to_char("They don't need an index finger.\n\r",ch);
	    return;
	}
	act("You press $p onto $N's hand.",ch,obj,victim,TO_CHAR);
	act("$n presses $p onto $N's hand.",ch,obj,victim,TO_NOTVICT);
	act("$n presses $p onto your hand.",ch,obj,victim,TO_VICT);
	extract_obj(obj);
	return;
    }
    else if (obj->pIndexData->vnum == OBJ_VNUM_SEVERED_MIDDLE)
    {
	if (!IS_ARM_L(victim,LOST_ARM) && !IS_ARM_L(victim,LOST_HAND)
		&& IS_ARM_L(victim,LOST_FINGER_M))
	    REMOVE_BIT(victim->loc_hp[LOC_ARM_L],LOST_FINGER_M);
	else if (!IS_ARM_R(victim,LOST_ARM) && !IS_ARM_R(victim,LOST_HAND)
		&& IS_ARM_R(victim,LOST_FINGER_M))
	    REMOVE_BIT(victim->loc_hp[LOC_ARM_R],LOST_FINGER_M);
	else
	{
	    send_to_char("They don't need a middle finger.\n\r",ch);
	    return;
	}
	act("You press $p onto $N's hand.",ch,obj,victim,TO_CHAR);
	act("$n presses $p onto $N's hand.",ch,obj,victim,TO_NOTVICT);
	act("$n presses $p onto your hand.",ch,obj,victim,TO_VICT);
	extract_obj(obj);
	return;
    }
    else if (obj->pIndexData->vnum == OBJ_VNUM_SEVERED_RING)
    {
	if (!IS_ARM_L(victim,LOST_ARM) && !IS_ARM_L(victim,LOST_HAND)
		&& IS_ARM_L(victim,LOST_FINGER_R))
	    REMOVE_BIT(victim->loc_hp[LOC_ARM_L],LOST_FINGER_R);
	else if (!IS_ARM_R(victim,LOST_ARM) && !IS_ARM_R(victim,LOST_HAND)
		&& IS_ARM_R(victim,LOST_FINGER_R))
	    REMOVE_BIT(victim->loc_hp[LOC_ARM_R],LOST_FINGER_R);
	else
	{
	    send_to_char("They don't need a ring finger.\n\r",ch);
	    return;
	}
	act("You press $p onto $N's hand.",ch,obj,victim,TO_CHAR);
	act("$n presses $p onto $N's hand.",ch,obj,victim,TO_NOTVICT);
	act("$n presses $p onto your hand.",ch,obj,victim,TO_VICT);
	extract_obj(obj);
	return;
    }
    else if (obj->pIndexData->vnum == OBJ_VNUM_SEVERED_LITTLE)
    {
	if (!IS_ARM_L(victim,LOST_ARM) && !IS_ARM_L(victim,LOST_HAND)
		&& IS_ARM_L(victim,LOST_FINGER_L))
	    REMOVE_BIT(victim->loc_hp[LOC_ARM_L],LOST_FINGER_L);
	else if (!IS_ARM_R(victim,LOST_ARM) && !IS_ARM_R(victim,LOST_HAND)
		&& IS_ARM_R(victim,LOST_FINGER_L))
	    REMOVE_BIT(victim->loc_hp[LOC_ARM_R],LOST_FINGER_L);
	else
	{
	    send_to_char("They don't need a little finger.\n\r",ch);
	    return;
	}
	act("You press $p onto $N's hand.",ch,obj,victim,TO_CHAR);
	act("$n presses $p onto $N's hand.",ch,obj,victim,TO_NOTVICT);
	act("$n presses $p onto your hand.",ch,obj,victim,TO_VICT);
	extract_obj(obj);
	return;
    }
    else if (teeth > 0)
    {
    	if (IS_HEAD(victim,LOST_TOOTH_1 ))
	    REMOVE_BIT(victim->loc_hp[LOC_HEAD],LOST_TOOTH_1);
    	if (IS_HEAD(victim,LOST_TOOTH_2 ))
	    REMOVE_BIT(victim->loc_hp[LOC_HEAD],LOST_TOOTH_2);
    	if (IS_HEAD(victim,LOST_TOOTH_4 ))
	    REMOVE_BIT(victim->loc_hp[LOC_HEAD],LOST_TOOTH_4);
    	if (IS_HEAD(victim,LOST_TOOTH_8 ))
	    REMOVE_BIT(victim->loc_hp[LOC_HEAD],LOST_TOOTH_8);
    	if (IS_HEAD(victim,LOST_TOOTH_16))
	    REMOVE_BIT(victim->loc_hp[LOC_HEAD],LOST_TOOTH_16);
	teeth -= 1;
	if (teeth >= 16) {teeth -= 16;
	    SET_BIT(victim->loc_hp[LOC_HEAD],LOST_TOOTH_16);}
	if (teeth >= 8 ) {teeth -= 8;
	    SET_BIT(victim->loc_hp[LOC_HEAD],LOST_TOOTH_8);}
	if (teeth >= 4 ) {teeth -= 4;
	    SET_BIT(victim->loc_hp[LOC_HEAD],LOST_TOOTH_4);}
	if (teeth >= 2 ) {teeth -= 2;
	    SET_BIT(victim->loc_hp[LOC_HEAD],LOST_TOOTH_2);}
	if (teeth >= 1 ) {teeth -= 1;
	    SET_BIT(victim->loc_hp[LOC_HEAD],LOST_TOOTH_1);}
	act("You press $p into $N's mouth.",ch,obj,victim,TO_CHAR);
	act("$n presses $p into $N's mouth.",ch,obj,victim,TO_NOTVICT);
	act("$n presses $p into your mouth.",ch,obj,victim,TO_VICT);
	extract_obj(obj);
    }
    else
    {
	act("There is nowhere to stick $p on $N.",ch,obj,victim,TO_CHAR);
	return;
    }
    return;
}

void spell_clot( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    if (IS_BLEEDING(victim,BLEEDING_HEAD))
    {
	act("$n's head stops bleeding.",victim,NULL,NULL,TO_ROOM);
	act("Your head stops bleeding.",victim,NULL,NULL,TO_CHAR);
	REMOVE_BIT(victim->loc_hp[6],BLEEDING_HEAD);
    }
    else if (IS_BLEEDING(victim,BLEEDING_THROAT))
    {
	act("$n's throat stops bleeding.",victim,NULL,NULL,TO_ROOM);
	act("Your throat stops bleeding.",victim,NULL,NULL,TO_CHAR);
	REMOVE_BIT(victim->loc_hp[6],BLEEDING_THROAT);
    }
    else if (IS_BLEEDING(victim,BLEEDING_ARM_L))
    {
	act("The stump of $n's left arm stops bleeding.",victim,NULL,NULL,TO_ROOM);
	act("The stump of your left arm stops bleeding.",victim,NULL,NULL,TO_CHAR);
	REMOVE_BIT(victim->loc_hp[6],BLEEDING_ARM_L);
    }
    else if (IS_BLEEDING(victim,BLEEDING_ARM_R))
    {
	act("The stump of $n's right arm stops bleeding.",victim,NULL,NULL,TO_ROOM);
	act("The stump of your right arm stops bleeding.",victim,NULL,NULL,TO_CHAR);
	REMOVE_BIT(victim->loc_hp[6],BLEEDING_ARM_R);
    }
    else if (IS_BLEEDING(victim,BLEEDING_LEG_L))
    {
	act("The stump of $n's left leg stops bleeding.",victim,NULL,NULL,TO_ROOM);
	act("The stump of your left leg stops bleeding.",victim,NULL,NULL,TO_CHAR);
	REMOVE_BIT(victim->loc_hp[6],BLEEDING_LEG_L);
    }
    else if (IS_BLEEDING(victim,BLEEDING_LEG_R))
    {
	act("The stump of $n's right leg stops bleeding.",victim,NULL,NULL,TO_ROOM);
	act("The stump of your right leg stops bleeding.",victim,NULL,NULL,TO_CHAR);
	REMOVE_BIT(victim->loc_hp[6],BLEEDING_LEG_R);
    }
    else if (IS_BLEEDING(victim,BLEEDING_HAND_L))
    {
	act("The stump of $n's left wrist stops bleeding.",victim,NULL,NULL,TO_ROOM);
	act("The stump of your left wrist stops bleeding.",victim,NULL,NULL,TO_CHAR);
	REMOVE_BIT(victim->loc_hp[6],BLEEDING_HAND_L);
    }
    else if (IS_BLEEDING(victim,BLEEDING_HAND_R))
    {
	act("The stump of $n's right wrist stops bleeding.",victim,NULL,NULL,TO_ROOM);
	act("The stump of your right wrist stops bleeding.",victim,NULL,NULL,TO_CHAR);
	REMOVE_BIT(victim->loc_hp[6],BLEEDING_HAND_R);
    }
    else if (IS_BLEEDING(victim,BLEEDING_FOOT_L))
    {
	act("The stump of $n's left ankle stops bleeding.",victim,NULL,NULL,TO_ROOM);
	act("The stump of your left ankle stops bleeding.",victim,NULL,NULL,TO_CHAR);
	REMOVE_BIT(victim->loc_hp[6],BLEEDING_FOOT_L);
    }
    else if (IS_BLEEDING(victim,BLEEDING_FOOT_R))
    {
	act("The stump of $n's right ankle stops bleeding.",victim,NULL,NULL,TO_ROOM);
	act("The stump of your right ankle stops bleeding.",victim,NULL,NULL,TO_CHAR);
	REMOVE_BIT(victim->loc_hp[6],BLEEDING_FOOT_R);
    }
    else send_to_char("They have no wounds to clot.\n\r",ch);
    if (!IS_NPC(ch) && ch != victim) do_humanity(ch,"");
    return;
}

void spell_mend( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    int ribs = 0;

    if (IS_BODY(victim,BROKEN_RIBS_1 )) ribs += 1;
    if (IS_BODY(victim,BROKEN_RIBS_2 )) ribs += 2;
    if (IS_BODY(victim,BROKEN_RIBS_4 )) ribs += 4;
    if (IS_BODY(victim,BROKEN_RIBS_8 )) ribs += 8;
    if (IS_BODY(victim,BROKEN_RIBS_16)) ribs += 16;

    if (ribs > 0)
    {
    	if (IS_BODY(victim,BROKEN_RIBS_1 ))
	    REMOVE_BIT(victim->loc_hp[1],BROKEN_RIBS_1);
    	if (IS_BODY(victim,BROKEN_RIBS_2 ))
	    REMOVE_BIT(victim->loc_hp[1],BROKEN_RIBS_2);
	if (IS_BODY(victim,BROKEN_RIBS_4 ))
	    REMOVE_BIT(victim->loc_hp[1],BROKEN_RIBS_4);
	if (IS_BODY(victim,BROKEN_RIBS_8 ))
	    REMOVE_BIT(victim->loc_hp[1],BROKEN_RIBS_8);
	if (IS_BODY(victim,BROKEN_RIBS_16))
	    REMOVE_BIT(victim->loc_hp[1],BROKEN_RIBS_16);
	ribs -= 1;
	if (ribs >= 16) {ribs -= 16;
	    SET_BIT(victim->loc_hp[1],BROKEN_RIBS_16);}
	if (ribs >= 8 ) {ribs -= 8;
	    SET_BIT(victim->loc_hp[1],BROKEN_RIBS_8);}
	if (ribs >= 4 ) {ribs -= 4;
	    SET_BIT(victim->loc_hp[1],BROKEN_RIBS_4);}
	if (ribs >= 2 ) {ribs -= 2;
	    SET_BIT(victim->loc_hp[1],BROKEN_RIBS_2);}
	if (ribs >= 1 ) {ribs -= 1;
	    SET_BIT(victim->loc_hp[1],BROKEN_RIBS_1);}
	act("One of $n's ribs snap back into place.",victim,NULL,NULL,TO_ROOM);
	act("One of your ribs snap back into place.",victim,NULL,NULL,TO_CHAR);
    }
    else if (IS_HEAD(victim,BROKEN_NOSE) && !IS_HEAD(victim,LOST_NOSE))
    {
	act("$n's nose snaps back into place.",victim,NULL,NULL,TO_ROOM);
	act("Your nose snaps back into place.",victim,NULL,NULL,TO_CHAR);
	REMOVE_BIT(victim->loc_hp[LOC_HEAD],BROKEN_NOSE);
    }
    else if (IS_HEAD(victim,BROKEN_JAW))
    {
	act("$n's jaw snaps back into place.",victim,NULL,NULL,TO_ROOM);
	act("Your jaw snaps back into place.",victim,NULL,NULL,TO_CHAR);
	REMOVE_BIT(victim->loc_hp[LOC_HEAD],BROKEN_JAW);
    }
    else if (IS_HEAD(victim,BROKEN_SKULL))
    {
	act("$n's skull knits itself back together.",victim,NULL,NULL,TO_ROOM);
	act("Your skull knits itself back together.",victim,NULL,NULL,TO_CHAR);
	REMOVE_BIT(victim->loc_hp[LOC_HEAD],BROKEN_SKULL);
    }
    else if (IS_BODY(victim,BROKEN_SPINE))
    {
	act("$n's spine knits itself back together.",victim,NULL,NULL,TO_ROOM);
	act("Your spine knits itself back together.",victim,NULL,NULL,TO_CHAR);
	REMOVE_BIT(victim->loc_hp[LOC_BODY],BROKEN_SPINE);
    }
    else if (IS_BODY(victim,BROKEN_NECK))
    {
	act("$n's neck snaps back into place.",victim,NULL,NULL,TO_ROOM);
	act("Your neck snaps back into place.",victim,NULL,NULL,TO_CHAR);
	REMOVE_BIT(victim->loc_hp[LOC_BODY],BROKEN_NECK);
    }
    else if (IS_ARM_L(victim,BROKEN_ARM) && !IS_ARM_L(victim,LOST_ARM))
    {
	act("$n's left arm snaps back into place.",victim,NULL,NULL,TO_ROOM);
	act("Your left arm snaps back into place.",victim,NULL,NULL,TO_CHAR);
	REMOVE_BIT(victim->loc_hp[LOC_ARM_L],BROKEN_ARM);
    }
    else if (IS_ARM_R(victim,BROKEN_ARM) && !IS_ARM_R(victim,LOST_ARM))
    {
	act("$n's right arm snaps back into place.",victim,NULL,NULL,TO_ROOM);
	act("Your right arm snaps back into place.",victim,NULL,NULL,TO_CHAR);
	REMOVE_BIT(victim->loc_hp[LOC_ARM_R],BROKEN_ARM);
    }
    else if (IS_LEG_L(victim,BROKEN_LEG) && !IS_LEG_L(victim,LOST_LEG))
    {
	act("$n's left leg snaps back into place.",victim,NULL,NULL,TO_ROOM);
	act("Your left leg snaps back into place.",victim,NULL,NULL,TO_CHAR);
	REMOVE_BIT(victim->loc_hp[LOC_LEG_L],BROKEN_LEG);
    }
    else if (IS_LEG_R(victim,BROKEN_LEG) && !IS_LEG_R(victim,LOST_LEG))
    {
	act("$n's right leg snaps back into place.",victim,NULL,NULL,TO_ROOM);
	act("Your right leg snaps back into place.",victim,NULL,NULL,TO_CHAR);
	REMOVE_BIT(victim->loc_hp[LOC_LEG_R],BROKEN_LEG);
    }
    else if (IS_ARM_L(victim,BROKEN_THUMB) && !IS_ARM_L(victim,LOST_ARM)
	&& !IS_ARM_L(victim,LOST_HAND) && !IS_ARM_L(victim,LOST_THUMB))
    {
	act("$n's left thumb snaps back into place.",victim,NULL,NULL,TO_ROOM);
	act("Your left thumb snaps back into place.",victim,NULL,NULL,TO_CHAR);
	REMOVE_BIT(victim->loc_hp[LOC_ARM_L],BROKEN_THUMB);
    }
    else if (IS_ARM_L(victim,BROKEN_FINGER_I) && !IS_ARM_L(victim,LOST_ARM)
	&& !IS_ARM_L(victim,LOST_HAND) && !IS_ARM_L(victim,LOST_FINGER_I))
    {
	act("$n's left index finger snaps back into place.",victim,NULL,NULL,TO_ROOM);
	act("Your left index finger snaps back into place.",victim,NULL,NULL,TO_CHAR);
	REMOVE_BIT(victim->loc_hp[LOC_ARM_L],BROKEN_FINGER_I);
    }
    else if (IS_ARM_L(victim,BROKEN_FINGER_M) && !IS_ARM_L(victim,LOST_ARM)
	&& !IS_ARM_L(victim,LOST_HAND) && !IS_ARM_L(victim,LOST_FINGER_M))
    {
	act("$n's left middle finger snaps back into place.",victim,NULL,NULL,TO_ROOM);
	act("Your left middle finger snaps back into place.",victim,NULL,NULL,TO_CHAR);
	REMOVE_BIT(victim->loc_hp[LOC_ARM_L],BROKEN_FINGER_M);
    }
    else if (IS_ARM_L(victim,BROKEN_FINGER_R) && !IS_ARM_L(victim,LOST_ARM)
	&& !IS_ARM_L(victim,LOST_HAND) && !IS_ARM_L(victim,LOST_FINGER_R))
    {
	act("$n's left ring finger snaps back into place.",victim,NULL,NULL,TO_ROOM);
	act("Your left ring finger snaps back into place.",victim,NULL,NULL,TO_CHAR);
	REMOVE_BIT(victim->loc_hp[LOC_ARM_L],BROKEN_FINGER_R);
    }
    else if (IS_ARM_L(victim,BROKEN_FINGER_L) && !IS_ARM_L(victim,LOST_ARM)
	&& !IS_ARM_L(victim,LOST_HAND) && !IS_ARM_L(victim,LOST_FINGER_L))
    {
	act("$n's left little finger snaps back into place.",victim,NULL,NULL,TO_ROOM);
	act("Your left little finger snaps back into place.",victim,NULL,NULL,TO_CHAR);
	REMOVE_BIT(victim->loc_hp[LOC_ARM_L],BROKEN_FINGER_L);
    }
    else if (IS_ARM_R(victim,BROKEN_THUMB) && !IS_ARM_R(victim,LOST_ARM)
	&& !IS_ARM_R(victim,LOST_HAND) && !IS_ARM_R(victim,LOST_THUMB))
    {
	act("$n's right thumb snaps back into place.",victim,NULL,NULL,TO_ROOM);
	act("Your right thumb snaps back into place.",victim,NULL,NULL,TO_CHAR);
	REMOVE_BIT(victim->loc_hp[LOC_ARM_R],BROKEN_THUMB);
    }
    else if (IS_ARM_R(victim,BROKEN_FINGER_I) && !IS_ARM_R(victim,LOST_ARM)
	&& !IS_ARM_R(victim,LOST_HAND) && !IS_ARM_R(victim,LOST_FINGER_I))
    {
	act("$n's right index finger snaps back into place.",victim,NULL,NULL,TO_ROOM);
	act("Your right index finger snaps back into place.",victim,NULL,NULL,TO_CHAR);
	REMOVE_BIT(victim->loc_hp[LOC_ARM_R],BROKEN_FINGER_I);
    }
    else if (IS_ARM_R(victim,BROKEN_FINGER_M) && !IS_ARM_R(victim,LOST_ARM)
	&& !IS_ARM_R(victim,LOST_HAND) && !IS_ARM_R(victim,LOST_FINGER_M))
    {
	act("$n's right middle finger snaps back into place.",victim,NULL,NULL,TO_ROOM);
	act("Your right middle finger snaps back into place.",victim,NULL,NULL,TO_CHAR);
	REMOVE_BIT(victim->loc_hp[LOC_ARM_R],BROKEN_FINGER_M);
    }
    else if (IS_ARM_R(victim,BROKEN_FINGER_R) && !IS_ARM_R(victim,LOST_ARM)
	&& !IS_ARM_R(victim,LOST_HAND) && !IS_ARM_R(victim,LOST_FINGER_R))
    {
	act("$n's right ring finger snaps back into place.",victim,NULL,NULL,TO_ROOM);
	act("Your right ring finger snaps back into place.",victim,NULL,NULL,TO_CHAR);
	REMOVE_BIT(victim->loc_hp[LOC_ARM_R],BROKEN_FINGER_R);
    }
    else if (IS_ARM_R(victim,BROKEN_FINGER_L) && !IS_ARM_R(victim,LOST_ARM)
	&& !IS_ARM_R(victim,LOST_HAND) && !IS_ARM_R(victim,LOST_FINGER_L))
    {
	act("$n's right little finger snaps back into place.",victim,NULL,NULL,TO_ROOM);
	act("Your right little finger snaps back into place.",victim,NULL,NULL,TO_CHAR);
	REMOVE_BIT(victim->loc_hp[LOC_ARM_R],BROKEN_FINGER_L);
    }
    else if (IS_BODY(victim,CUT_THROAT))
    {
    	if (IS_SET(victim->loc_hp[6], BLEEDING_THROAT))
    	{
	    send_to_char( "But their throat is still bleeding!\n\r", ch );
	    return;
    	}
	act("The wound in $n's throat closes up.",victim,NULL,NULL,TO_ROOM);
	act("The wound in your throat closes up.",victim,NULL,NULL,TO_CHAR);
	REMOVE_BIT(victim->loc_hp[LOC_BODY],CUT_THROAT);
    }
    else send_to_char("They have no bones to mend.\n\r",ch);
    if (!IS_NPC(ch) && ch != victim) do_humanity(ch,"");
    return;
}

void spell_quest( int sn, int level, CHAR_DATA *ch, void *vo )
{
    OBJ_INDEX_DATA *pObjIndex;
    OBJ_DATA *obj;

    if (ch->practice < 1)
    {
	send_to_char( "It costs at least 1 point of primal energy to create a quest card.\n\r", ch );
	return;
    }

    if ( (pObjIndex = get_obj_index( OBJ_VNUM_QUESTCARD )) == NULL)
    {
	send_to_char("Missing object, please inform KaVir.\n\r",ch);
	return;
    }
    if (ch->in_room == NULL) return;
    obj = create_object(pObjIndex, 0);
    obj_to_char(obj, ch);
    quest_object(ch,obj);
    if (ch->practice >= 50) {ch->practice -= 50; obj->level = 50;}
    else {obj->level = ch->practice; ch->practice = 0;}
    act("$p fades into existance in your hands.",ch,obj,NULL,TO_CHAR);
    act("$p fades into existance in $n's hands.",ch,obj,NULL,TO_ROOM);
    if (obj->questmaker != NULL) free_string(obj->questmaker);
    obj->questmaker = str_dup(ch->name);
    if (obj->questowner != NULL) free_string(obj->questowner);
    obj->questowner = str_dup(ch->name);
    return;
}

void spell_minor_creation( int sn, int level, CHAR_DATA *ch, void *vo )
{
    OBJ_DATA *obj;
    char arg[MAX_INPUT_LENGTH];
    char buf[MAX_INPUT_LENGTH];
    char itemkind[10];
    int itemtype;

    target_name = one_argument( target_name, arg );

    if      (!str_cmp(arg,"potion")) {itemtype = ITEM_POTION;sprintf(itemkind,"potion");}
    else if (!str_cmp(arg,"scroll")) {itemtype = ITEM_SCROLL;sprintf(itemkind,"scroll");}
    else if (!str_cmp(arg,"wand"  )) {itemtype = ITEM_WAND;sprintf(itemkind,"wand");}
    else if (!str_cmp(arg,"staff" )) {itemtype = ITEM_STAFF;sprintf(itemkind,"staff");}
    else if (!str_cmp(arg,"pill"  )) {itemtype = ITEM_PILL;sprintf(itemkind,"pill");}
    else
    {
	send_to_char( "Item can be one of: Potion, Scroll, Wand, Staff or Pill.\n\r", ch );
	return;
    }
    obj = create_object( get_obj_index( OBJ_VNUM_PROTOPLASM ), 0 );
    obj->item_type = itemtype;

    sprintf(buf,"%s %s",ch->name,itemkind);
    free_string(obj->name);
    obj->name=str_dup(buf);
    sprintf(buf,"%s's %s",ch->name, itemkind);
    free_string(obj->short_descr);
    obj->short_descr=str_dup(buf);
    sprintf(buf,"%s's %s lies here.",ch->name,itemkind);
    free_string(obj->description);
    obj->description=str_dup(buf);

    obj->weight = 10;

    if (obj->questmaker != NULL) free_string(obj->questmaker);
    obj->questmaker=str_dup(ch->name);

    obj_to_char( obj, ch );
    act( "$p suddenly appears in your hands.", ch, obj, NULL, TO_CHAR );
    act( "$p suddenly appears in $n's hands.", ch, obj, NULL, TO_ROOM );
    return;
}

void spell_brew( int sn, int level, CHAR_DATA *ch, void *vo )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    char buf[MAX_INPUT_LENGTH];
    char col[10];
    OBJ_DATA *obj;

    target_name = one_argument( target_name, arg1 );
    target_name = one_argument( target_name, arg2 );

    if (IS_NPC(ch)) return;
    if ( arg1[0] == '\0' || arg2[0] == '\0' )
    {
        send_to_char( "What spell do you wish to brew, and on what?\n\r", ch );
        return;
    }

    if ( ( sn = skill_lookup( arg2 ) ) < 0
    || ( !IS_NPC(ch) && ch->level < skill_table[sn].skill_level) )
    {
	send_to_char( "You can't do that.\n\r", ch );
	return;
    }

    if ( ch->pcdata->learned[sn] < 100 )
    {
	send_to_char( "You are not adept at that spell.\n\r", ch );
	return;
    }

    if ( ( obj = get_obj_carry( ch, arg1 ) ) == NULL )
    {
	send_to_char( "You are not carrying that.\n\r", ch );
	return;
    }

    if ( obj->item_type != ITEM_POTION )
    {
	send_to_char( "That is not a potion.\n\r", ch );
	return;
    }

    if ( obj->value[0] != 0 || obj->value[1] != 0 ||
    	 obj->value[2] != 0 || obj->value[3] != 0 )
    {
	send_to_char( "You need an empty potion bottle.\n\r", ch );
	return;
    }
    if      ( skill_table[sn].target == 0 )
    	{obj->value[0] = ch->spl[0]/4;sprintf(col,"purple");}
    else if ( skill_table[sn].target == 1 )
    	{obj->value[0] = ch->spl[1]/4;sprintf(col,"red");}
    else if ( skill_table[sn].target == 2 )
    	{obj->value[0] = ch->spl[2]/4;sprintf(col,"blue");}
    else if ( skill_table[sn].target == 3 )
    	{obj->value[0] = ch->spl[3]/4;sprintf(col,"green");}
    else if ( skill_table[sn].target == 4 )
    	{obj->value[0] = ch->spl[4]/4;sprintf(col,"yellow");}
    else
    {
	send_to_char( "Oh dear...big bug...please inform KaVir.\n\r", ch );
	return;
    }
    obj->value[1] = sn;
    if (obj->value[0] >= 25) obj->value[2] = sn; else obj->value[2] = -1;
    if (obj->value[0] >= 50) obj->value[3] = sn; else obj->value[3] = -1;
    free_string(obj->name);
    sprintf(buf,"%s potion %s %s",ch->name,col,skill_table[sn].name);
    obj->name=str_dup(buf);
    free_string(obj->short_descr);
    sprintf(buf,"%s's %s potion of %s",ch->name,col,skill_table[sn].name);
    obj->short_descr=str_dup(buf);
    free_string(obj->description);
    sprintf(buf,"A %s potion is lying here.",col);
    obj->description=str_dup(buf);
    act("You brew $p.",ch,obj,NULL,TO_CHAR);
    act("$n brews $p.",ch,obj,NULL,TO_ROOM);
    return;
}

void spell_scribe( int sn, int level, CHAR_DATA *ch, void *vo )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    char buf[MAX_INPUT_LENGTH];
    char col[10];
    OBJ_DATA *obj;

    target_name = one_argument( target_name, arg1 );
    target_name = one_argument( target_name, arg2 );

    if (IS_NPC(ch)) return;
    if ( arg1[0] == '\0' || arg2[0] == '\0' )
    {
        send_to_char( "What spell do you wish to scribe, and on what?\n\r", ch );
        return;
    }

    if ( ( sn = skill_lookup( arg2 ) ) < 0
    || ( !IS_NPC(ch) && ch->level < skill_table[sn].skill_level) )
    {
	send_to_char( "You can't do that.\n\r", ch );
	return;
    }

    if ( ch->pcdata->learned[sn] < 100 )
    {
	send_to_char( "You are not adept at that spell.\n\r", ch );
	return;
    }

    if ( ( obj = get_obj_carry( ch, arg1 ) ) == NULL )
    {
	send_to_char( "You are not carrying that.\n\r", ch );
	return;
    }

    if ( obj->item_type != ITEM_SCROLL )
    {
	send_to_char( "That is not a scroll.\n\r", ch );
	return;
    }

    if ( obj->value[0] != 0 || obj->value[1] != 0 ||
    	 obj->value[2] != 0 || obj->value[3] != 0 )
    {
	send_to_char( "You need an empty scroll parchment.\n\r", ch );
	return;
    }
    if      ( skill_table[sn].target == 0 )
    	{obj->value[0] = ch->spl[0]/4;sprintf(col,"purple");}
    else if ( skill_table[sn].target == 1 )
    	{obj->value[0] = ch->spl[1]/4;sprintf(col,"red");}
    else if ( skill_table[sn].target == 2 )
    	{obj->value[0] = ch->spl[2]/4;sprintf(col,"blue");}
    else if ( skill_table[sn].target == 3 )
    	{obj->value[0] = ch->spl[3]/4;sprintf(col,"green");}
    else if ( skill_table[sn].target == 4 )
    	{obj->value[0] = ch->spl[4]/4;sprintf(col,"yellow");}
    else
    {
	send_to_char( "Oh dear...big bug...please inform KaVir.\n\r", ch );
	return;
    }
    obj->value[1] = sn;
    if (obj->value[0] >= 25) obj->value[2] = sn; else obj->value[2] = -1;
    if (obj->value[0] >= 50) obj->value[3] = sn; else obj->value[3] = -1;
    free_string(obj->name);
    sprintf(buf,"%s scroll %s %s",ch->name,col,skill_table[sn].name);
    obj->name=str_dup(buf);
    free_string(obj->short_descr);
    sprintf(buf,"%s's %s scroll of %s",ch->name,col,skill_table[sn].name);
    obj->short_descr=str_dup(buf);
    free_string(obj->description);
    sprintf(buf,"A %s scroll is lying here.",col);
    obj->description=str_dup(buf);
    act("You scribe $p.",ch,obj,NULL,TO_CHAR);
    act("$n scribes $p.",ch,obj,NULL,TO_ROOM);
    return;
}

void spell_carve( int sn, int level, CHAR_DATA *ch, void *vo )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    char buf[MAX_INPUT_LENGTH];
    char col[10];
    OBJ_DATA *obj;

    target_name = one_argument( target_name, arg1 );
    target_name = one_argument( target_name, arg2 );

    if (IS_NPC(ch)) return;
    if ( arg1[0] == '\0' || arg2[0] == '\0' )
    {
        send_to_char( "What spell do you wish to carve, and on what?\n\r", ch );
        return;
    }

    if ( ( sn = skill_lookup( arg2 ) ) < 0
    || ( !IS_NPC(ch) && ch->level < skill_table[sn].skill_level) )
    {
	send_to_char( "You can't do that.\n\r", ch );
	return;
    }

    if ( ch->pcdata->learned[sn] < 100 )
    {
	send_to_char( "You are not adept at that spell.\n\r", ch );
	return;
    }

    if ( ( obj = get_obj_carry( ch, arg1 ) ) == NULL )
    {
	send_to_char( "You are not carrying that.\n\r", ch );
	return;
    }

    if ( obj->item_type != ITEM_WAND )
    {
	send_to_char( "That is not a wand.\n\r", ch );
	return;
    }

    if ( obj->value[0] != 0 || obj->value[1] != 0 ||
    	 obj->value[2] != 0 || obj->value[3] != 0 )
    {
	send_to_char( "You need an unenchanted wand.\n\r", ch );
	return;
    }
    if      ( skill_table[sn].target == 0 )
    	{obj->value[0] = ch->spl[0]/4;sprintf(col,"purple");}
    else if ( skill_table[sn].target == 1 )
    	{obj->value[0] = ch->spl[1]/4;sprintf(col,"red");}
    else if ( skill_table[sn].target == 2 )
    	{obj->value[0] = ch->spl[2]/4;sprintf(col,"blue");}
    else if ( skill_table[sn].target == 3 )
    	{obj->value[0] = ch->spl[3]/4;sprintf(col,"green");}
    else if ( skill_table[sn].target == 4 )
    	{obj->value[0] = ch->spl[4]/4;sprintf(col,"yellow");}
    else
    {
	send_to_char( "Oh dear...big bug...please inform KaVir.\n\r", ch );
	return;
    }
    obj->value[1] = (obj->value[0] / 5) + 1;
    obj->value[2] = (obj->value[0] / 5) + 1;
    obj->value[3] = sn;
    free_string(obj->name);
    sprintf(buf,"%s wand %s %s",ch->name,col,skill_table[sn].name);
    obj->name=str_dup(buf);
    free_string(obj->short_descr);
    sprintf(buf,"%s's %s wand of %s",ch->name,col,skill_table[sn].name);
    obj->short_descr=str_dup(buf);
    free_string(obj->description);
    sprintf(buf,"A %s wand is lying here.",col);
    obj->description=str_dup(buf);
    obj->wear_flags = ITEM_TAKE + ITEM_HOLD;
    act("You carve $p.",ch,obj,NULL,TO_CHAR);
    act("$n carves $p.",ch,obj,NULL,TO_ROOM);
    return;
}

void spell_engrave( int sn, int level, CHAR_DATA *ch, void *vo )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    char buf[MAX_INPUT_LENGTH];
    char col[10];
    OBJ_DATA *obj;

    target_name = one_argument( target_name, arg1 );
    target_name = one_argument( target_name, arg2 );

    if (IS_NPC(ch)) return;
    if ( arg1[0] == '\0' || arg2[0] == '\0' )
    {
        send_to_char( "What spell do you wish to engrave, and on what?\n\r", ch );
        return;
    }

    if ( ( sn = skill_lookup( arg2 ) ) < 0
    || ( !IS_NPC(ch) && ch->level < skill_table[sn].skill_level ) )
    {
	send_to_char( "You can't do that.\n\r", ch );
	return;
    }

    if ( ch->pcdata->learned[sn] < 100 )
    {
	send_to_char( "You are not adept at that spell.\n\r", ch );
	return;
    }

    if ( ( obj = get_obj_carry( ch, arg1 ) ) == NULL )
    {
	send_to_char( "You are not carrying that.\n\r", ch );
	return;
    }

    if ( obj->item_type != ITEM_STAFF )
    {
	send_to_char( "That is not a staff.\n\r", ch );
	return;
    }

    if ( obj->value[0] != 0 || obj->value[1] != 0 ||
    	 obj->value[2] != 0 || obj->value[3] != 0 )
    {
	send_to_char( "You need an unenchanted staff.\n\r", ch );
	return;
    }
    if      ( skill_table[sn].target == 0 )
    	{obj->value[0] = (ch->spl[0]+1)/4;sprintf(col,"purple");}
    else if ( skill_table[sn].target == 1 )
    	{obj->value[0] = (ch->spl[1]+1)/4;sprintf(col,"red");}
    else if ( skill_table[sn].target == 2 )
    	{obj->value[0] = (ch->spl[2]+1)/4;sprintf(col,"blue");}
    else if ( skill_table[sn].target == 3 )
    	{obj->value[0] = (ch->spl[3]+1)/4;sprintf(col,"green");}
    else if ( skill_table[sn].target == 4 )
    	{obj->value[0] = (ch->spl[4]+1)/4;sprintf(col,"yellow");}
    else
    {
	send_to_char( "Oh dear...big bug...please inform KaVir.\n\r", ch );
	return;
    }
    obj->value[1] = (obj->value[0] / 10) + 1;
    obj->value[2] = (obj->value[0] / 10) + 1;
    obj->value[3] = sn;
    free_string(obj->name);
    sprintf(buf,"%s staff %s %s",ch->name,col,skill_table[sn].name);
    obj->name=str_dup(buf);
    free_string(obj->short_descr);
    sprintf(buf,"%s's %s staff of %s",ch->name,col,skill_table[sn].name);
    obj->short_descr=str_dup(buf);
    free_string(obj->description);
    sprintf(buf,"A %s staff is lying here.",col);
    obj->description=str_dup(buf);
    obj->wear_flags = ITEM_TAKE + ITEM_HOLD;
    act("You engrave $p.",ch,obj,NULL,TO_CHAR);
    act("$n engraves $p.",ch,obj,NULL,TO_ROOM);
    return;
}

void spell_bake( int sn, int level, CHAR_DATA *ch, void *vo )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    char buf[MAX_INPUT_LENGTH];
    char col[10];
    OBJ_DATA *obj;

    target_name = one_argument( target_name, arg1 );
    target_name = one_argument( target_name, arg2 );

    if (IS_NPC(ch)) return;
    if ( arg1[0] == '\0' || arg2[0] == '\0' )
    {
        send_to_char( "What spell do you wish to bake, and on what?\n\r", ch );
        return;
    }

    if ( ( sn = skill_lookup( arg2 ) ) < 0
    || ( !IS_NPC(ch) && ch->level < skill_table[sn].skill_level ) )
    {
	send_to_char( "You can't do that.\n\r", ch );
	return;
    }

    if ( ch->pcdata->learned[sn] < 100 )
    {
	send_to_char( "You are not adept at that spell.\n\r", ch );
	return;
    }

    if ( ( obj = get_obj_carry( ch, arg1 ) ) == NULL )
    {
	send_to_char( "You are not carrying that.\n\r", ch );
	return;
    }

    if ( obj->item_type != ITEM_PILL )
    {
	send_to_char( "That is not a pill.\n\r", ch );
	return;
    }

    if ( obj->value[0] != 0 || obj->value[1] != 0 ||
    	 obj->value[2] != 0 || obj->value[3] != 0 )
    {
	send_to_char( "You need an unused pill.\n\r", ch );
	return;
    }
    if      ( skill_table[sn].target == 0 )
    	{obj->value[0] = ch->spl[0]/4;sprintf(col,"purple");}
    else if ( skill_table[sn].target == 1 )
    	{obj->value[0] = ch->spl[1]/4;sprintf(col,"red");}
    else if ( skill_table[sn].target == 2 )
    	{obj->value[0] = ch->spl[2]/4;sprintf(col,"blue");}
    else if ( skill_table[sn].target == 3 )
    	{obj->value[0] = ch->spl[3]/4;sprintf(col,"green");}
    else if ( skill_table[sn].target == 4 )
    	{obj->value[0] = ch->spl[4]/4;sprintf(col,"yellow");}
    else
    {
	send_to_char( "Oh dear...big bug...please inform KaVir.\n\r", ch );
	return;
    }
    obj->value[1] = sn;
    if (obj->value[0] >= 25) obj->value[2] = sn; else obj->value[2] = -1;
    if (obj->value[0] >= 50) obj->value[3] = sn; else obj->value[3] = -1;
    free_string(obj->name);
    sprintf(buf,"%s pill %s %s",ch->name,col,skill_table[sn].name);
    obj->name=str_dup(buf);
    free_string(obj->short_descr);
    sprintf(buf,"%s's %s pill of %s",ch->name,col,skill_table[sn].name);
    obj->short_descr=str_dup(buf);
    free_string(obj->description);
    sprintf(buf,"A %s pill is lying here.",col);
    obj->description=str_dup(buf);
    act("You bake $p.",ch,obj,NULL,TO_CHAR);
    act("$n bakes $p.",ch,obj,NULL,TO_ROOM);
    return;
}

void spell_mount( int sn, int level, CHAR_DATA *ch, void *vo )
{
    char buf[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;

    if (IS_NPC(ch)) return;

    if (ch->pcdata->followers > 4)
    {
	send_to_char("Nothing happens.\n\r",ch);
	return;
    }
    ch->pcdata->followers++;

    if (IS_CLASS(ch, CLASS_DEMON))
    {
	victim=create_mobile( get_mob_index( 30000 ) );
	victim->level = level*2;
	victim->armor = 0 - (10*level);
	victim->hitroll = level*2;
	victim->damroll = level*2;
	victim->hit = 250*level;
	victim->max_hit = 250*level;
	free_string(victim->lord);
	victim->lord = str_dup(ch->name);
	SET_BIT(victim->act, ACT_NOEXP);
	SET_BIT(victim->act, ACT_MOUNT);
	char_to_room( victim, ch->in_room );
	act( "$N fades into existance.", ch, NULL, victim, TO_CHAR );
	act( "$N fades into existance.", ch, NULL, victim, TO_ROOM );
	return;
    }
	else if (IS_CLASS(ch, CLASS_DROW)) {
        victim=create_mobile( get_mob_index( 26001 ) );
        victim->level = level*2;
        victim->armor = 0 - (10*level);
        victim->hitroll = level*2;
        victim->damroll = level*2;
        victim->hit = 250*level;
        victim->max_hit = 250*level;
        free_string(victim->lord);
        victim->lord = str_dup(ch->name);
	SET_BIT(victim->act, ACT_NOEXP);
	SET_BIT(victim->act, ACT_MOUNT);
        char_to_room( victim, ch->in_room );
        act( "$N fades into existance.", ch, NULL, victim, TO_CHAR );
        act( "$N fades into existance.", ch, NULL, victim, TO_ROOM );
        return;
}
    victim=create_mobile( get_mob_index( MOB_VNUM_MOUNT ) );
    victim->level = level;
    victim->armor = 0 - (2*level);
    victim->hitroll = level;
    victim->damroll = level;
    victim->hit = 100*level;
    victim->max_hit = 100*level;
    free_string(victim->lord);
    victim->lord = str_dup(ch->name);
    SET_BIT(victim->affected_by,AFF_FLYING);
    SET_BIT(victim->act, ACT_NOEXP);
    if (IS_GOOD(ch))
    {
	free_string(victim->name);
	victim->name = str_dup("mount white horse pegasus");
	sprintf(buf,"%s's white pegasus",ch->name);
	free_string(victim->short_descr);
	victim->short_descr = str_dup(buf);
	free_string(victim->long_descr);
	victim->long_descr = str_dup("A beautiful white pegasus stands here.\n\r");
    }
    else if (IS_NEUTRAL(ch))
    {
	free_string(victim->name);
	victim->name = str_dup("mount griffin");
	sprintf(buf,"%s's griffin",ch->name);
	free_string(victim->short_descr);
	victim->short_descr = str_dup(buf);
	free_string(victim->long_descr);
	victim->long_descr = str_dup("A vicious looking griffin stands here.\n\r");
    }
    else
    {
	free_string(victim->name);
	victim->name = str_dup("mount black horse nightmare");
	sprintf(buf,"%s's black nightmare",ch->name);
	free_string(victim->short_descr);
	victim->short_descr = str_dup(buf);
	free_string(victim->long_descr);
	victim->long_descr = str_dup("A large black demonic horse stands here.\n\r");
    }
    char_to_room( victim, ch->in_room );
    act( "$N fades into existance.", ch, NULL, victim, TO_CHAR );
    act( "$N fades into existance.", ch, NULL, victim, TO_ROOM );
    return;
}


/* 
 * Old march mount spell 

void spell_mount( int sn, int level, CHAR_DATA *ch, void *vo )
{
    char buf[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;

    if (IS_NPC(ch)) return;
    victim=create_mobile( get_mob_index( MOB_VNUM_MOUNT ) );
    victim->level = level;
    victim->armor = 0 - (2*(level+1));
    victim->hitroll = level;
    victim->damroll = level;
    victim->hit = 100*level;
    victim->max_hit = 100*level;
    SET_BIT(victim->affected_by,AFF_FLYING);
    if (
    if (IS_GOOD(ch))
    {
	free_string(victim->name);
	victim->name = str_dup("mount white horse pegasus");
	sprintf(buf,"%s's white pegasus",ch->name);
	free_string(victim->short_descr);
	victim->short_descr = str_dup(buf);
	free_string(victim->long_descr);
	victim->long_descr = str_dup("A beautiful white pegasus stands here.\n\r");
    }
    else if (IS_NEUTRAL(ch))
    {
	free_string(victim->name);
	victim->name = str_dup("mount griffin");
	sprintf(buf,"%s's griffin",ch->name);
	free_string(victim->short_descr);
	victim->short_descr = str_dup(buf);
	free_string(victim->long_descr);
	victim->long_descr = str_dup("A vicious looking griffin stands here.\n\r");
    }
    else
    {
	free_string(victim->name);
	victim->name = str_dup("mount black horse nightmare");
	sprintf(buf,"%s's black nightmare",ch->name);
	free_string(victim->short_descr);
	victim->short_descr = str_dup(buf);
	free_string(victim->long_descr);
	victim->long_descr = str_dup("A large black demonic horse stands here.\n\r");
    }
    act( "$N fades into existance.", ch, NULL, victim, TO_CHAR );
    act( "$N fades into existance.", ch, NULL, victim, TO_ROOM );
    char_to_room( victim, ch->in_room );
    return;
}
*/

void spell_scan( int sn, int level, CHAR_DATA *ch, void *vo )
{
    OBJ_DATA *obj;
    OBJ_DATA *obj_next;
    bool found = FALSE;

    for ( obj = ch->carrying; obj != NULL; obj = obj_next )
    {
	obj_next = obj->next_content;
	if ( obj->condition < 100 && can_see_obj( ch, obj ) )
	{
	    found = TRUE;
	    act("$p needs repairing.",ch,obj,NULL,TO_CHAR);
	}
    }
    if ( !found )
    {
	send_to_char( "None of your equipment needs repairing.\n\r", ch );
	return;
    }
    return;
}

void spell_repair( int sn, int level, CHAR_DATA *ch, void *vo )
{
    OBJ_DATA *obj;
    OBJ_DATA *obj_next;
    bool found = FALSE;

    for ( obj = ch->carrying; obj != NULL; obj = obj_next )
    {
	obj_next = obj->next_content;
	if ( obj->condition < 100 && can_see_obj( ch, obj ) )
	{
	    found = TRUE;
	    obj->condition = 100;
	    act("$p magically repairs itself.",ch,obj,NULL,TO_CHAR);
	    act("$p magically repairs itself.",ch,obj,NULL,TO_ROOM);
	}
    }
    if ( !found )
    {
	send_to_char( "None of your equipment needs repairing.\n\r", ch );
	return;
    }
    return;
}

void spell_spellproof( int sn, int level, CHAR_DATA *ch, void *vo )
{
    OBJ_DATA *obj = (OBJ_DATA *) vo;

    if ( obj->chobj != NULL )
    {
	send_to_char("Your spell has no affect.\n\r",ch);
	return;
    }

    if ( IS_SET(obj->quest, QUEST_SPELLPROOF) )
    {
	send_to_char( "That item is already resistance to spells.\n\r", ch );
	return;
    }

    SET_BIT(obj->quest, QUEST_SPELLPROOF);
    act("$p shimmers for a moment.",ch,obj,NULL,TO_CHAR);
    act("$p shimmers for a moment.",ch,obj,NULL,TO_ROOM);
    return;
}

void spell_preserve( int sn, int level, CHAR_DATA *ch, void *vo )
{
    OBJ_DATA *obj = (OBJ_DATA *) vo;

    if (IS_SET(obj->quest, QUEST_CLONED))
{
send_to_char("You cant preserve cloned items.",ch);
return;
}

    if ( obj->timer < 1 )
    {
	send_to_char( "That item doesn't require preserving.\n\r", ch );
	return;
    }
    if ( obj->chobj != NULL )
    {
	send_to_char( "You cannot preserve that.\n\r", ch );
	return;
    }

    obj->timer = -1;
    act("$p shimmers for a moment.",ch,obj,NULL,TO_CHAR);
    act("$p shimmers for a moment.",ch,obj,NULL,TO_ROOM);
    return;
}

void spell_major_creation( int sn, int level, CHAR_DATA *ch, void *vo )
{
    OBJ_DATA *obj;
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    char buf[MAX_INPUT_LENGTH];
    char itemkind[10];
    int itemtype;
    int itempower = 0;
    int vn = 0;

    target_name = one_argument( target_name, arg1 );
    target_name = one_argument( target_name, arg2 );

    if (IS_NPC(ch)) return;
    if (arg1[0] == '\0')
    {
	send_to_char( "Item can be one of: Rune, Glyph, Sigil, Book, Page or Pen.\n\r", ch );
	return;
    }

/*
The Rune is the foundation/source of the spell.
The Glyphs form the focus/purpose of the spell.
The Sigils form the affects of the spell.
*/

    if (!str_cmp(arg1,"rune"  ))
    {
	if (arg2[0] == '\0')
	{send_to_char("You know of no such Rune.\n\r",ch);return;}
	itemtype = ITEM_SYMBOL;
	vn = 1;
	sprintf(itemkind,"rune");
	if      (!str_cmp(arg2,"fire"   )) itempower = 1;
	else if (!str_cmp(arg2,"air"    )) itempower = 2;
	else if (!str_cmp(arg2,"earth"  )) itempower = 4;
	else if (!str_cmp(arg2,"water"  )) itempower = 8;
	else if (!str_cmp(arg2,"dark"   )) itempower = 16;
	else if (!str_cmp(arg2,"light"  )) itempower = 32;
	else if (!str_cmp(arg2,"life"   )) itempower = 64;
	else if (!str_cmp(arg2,"death"  )) itempower = 128;
	else if (!str_cmp(arg2,"mind"   )) itempower = 256;
	else if (!str_cmp(arg2,"spirit" )) itempower = 512;
	else if (!str_cmp(arg2,"mastery")) itempower = 1024;
	else
	{send_to_char("You know of no such Rune.\n\r",ch);return;}
	if (!IS_SET(ch->pcdata->powers[MPOWER_RUNES], itempower))
	{send_to_char("You know of no such Rune.\n\r",ch);return;}
    }
    else if (!str_cmp(arg1,"glyph" ))
    {
	if (arg2[0] == '\0')
	{send_to_char("You know of no such Glyph.\n\r",ch);return;}
	itemtype = ITEM_SYMBOL;
	vn = 2;
	sprintf(itemkind,"glyph");
	if      (!str_cmp(arg2,"creation"      )) itempower = 1;
	else if (!str_cmp(arg2,"destruction"   )) itempower = 2;
	else if (!str_cmp(arg2,"summoning"     )) itempower = 4;
	else if (!str_cmp(arg2,"transformation")) itempower = 8;
	else if (!str_cmp(arg2,"transportation")) itempower = 16;
	else if (!str_cmp(arg2,"enhancement"   )) itempower = 32;
	else if (!str_cmp(arg2,"reduction"     )) itempower = 64;
	else if (!str_cmp(arg2,"control"       )) itempower = 128;
	else if (!str_cmp(arg2,"protection"    )) itempower = 256;
	else if (!str_cmp(arg2,"information"   )) itempower = 512;
	else
	{send_to_char("You know of no such Glyph.\n\r",ch);return;}
	if (!IS_SET(ch->pcdata->powers[MPOWER_GLYPHS], itempower))
	{send_to_char("You know of no such Glyph.\n\r",ch);return;}
    }
    else if (!str_cmp(arg1,"sigil" ))
    {
	if (arg2[0] == '\0')
	{send_to_char("You know of no such Sigil.\n\r",ch);return;}
	itemtype = ITEM_SYMBOL;
	vn = 3;
	sprintf(itemkind,"sigil");
	if      (!str_cmp(arg2,"self"     )) itempower = 1;
	else if (!str_cmp(arg2,"targeting")) itempower = 2;
	else if (!str_cmp(arg2,"area"     )) itempower = 4;
	else if (!str_cmp(arg2,"object"   )) itempower = 8;
	else
	{send_to_char("You know of no such Sigil.\n\r",ch);return;}
	if (!IS_SET(ch->pcdata->powers[MPOWER_SIGILS], itempower))
	{send_to_char("You know of no such Sigil.\n\r",ch);return;}
    }
    else if (!str_cmp(arg1,"book"  )) {itemtype = ITEM_BOOK;sprintf(itemkind,"book");}
    else if (!str_cmp(arg1,"page"  )) {itemtype = ITEM_PAGE;sprintf(itemkind,"page");}
    else if (!str_cmp(arg1,"pen"   )) {itemtype = ITEM_TOOL;sprintf(itemkind,"pen");}
    else
    {
	send_to_char( "Item can be one of: Rune, Glyph, Sigil, Book, Page or Pen.\n\r", ch );
	return;
    }
    obj = create_object( get_obj_index( OBJ_VNUM_PROTOPLASM ), 0 );
    obj->item_type = itemtype;

    if (itemtype == ITEM_SYMBOL)
    {
	sprintf(buf,"%s %s",itemkind,arg2);
	obj->value[vn] = itempower;
    }
    else sprintf(buf,"%s",itemkind);
    if (itemtype == ITEM_TOOL)
    {
	obj->value[0] = TOOL_PEN;
	obj->weight = 1;
	obj->wear_flags = ITEM_TAKE + ITEM_HOLD;
    }
    else if (itemtype == ITEM_BOOK)
    {obj->weight = 50;obj->wear_flags = ITEM_TAKE + ITEM_HOLD;}
    free_string(obj->name);
    obj->name=str_dup(buf);
    if (itemtype == ITEM_SYMBOL) sprintf(buf,"a %s of %s",itemkind,arg2);
    else sprintf(buf,"a %s",itemkind);
    free_string(obj->short_descr);
    obj->short_descr=str_dup(buf);
    sprintf(buf,"A %s lies here.",itemkind);
    free_string(obj->description);
    obj->description=str_dup(buf);

    if (obj->questmaker != NULL) free_string(obj->questmaker);
    obj->questmaker=str_dup(ch->name);

    obj_to_char( obj, ch );
    act( "$p suddenly appears in your hands.", ch, obj, NULL, TO_CHAR );
    act( "$p suddenly appears in $n's hands.", ch, obj, NULL, TO_ROOM );
    return;
}

void spell_copy( int sn, int level, CHAR_DATA *ch, void *vo )
{
    OBJ_DATA *rune;
    OBJ_DATA *page;
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];

    target_name = one_argument( target_name, arg1 );
    target_name = one_argument( target_name, arg2 );

    if (IS_NPC(ch)) return;

    if ( arg1[0] == '\0' || arg2[0] == '\0' )
    {send_to_char("Syntax is: cast 'copy' <rune> <page>.\n\r",ch);return;}
    if ( ( rune = get_obj_carry( ch, arg1 ) ) == NULL )
    {send_to_char("You are not carrying that rune.\n\r",ch);return;}
    if ( rune->item_type != ITEM_SYMBOL )
    {send_to_char("That item isn't a rune.\n\r",ch);return;}
    if ( ( page = get_obj_carry( ch, arg2 ) ) == NULL )
    {send_to_char("You are not carrying that page.\n\r",ch);return;}
    if ( page->item_type != ITEM_PAGE )
    {send_to_char("That item isn't a page.\n\r",ch);return;}

    if ( rune->value[1] > 0 && !IS_SET( ch->pcdata->powers[MPOWER_RUNES],rune->value[1]) )
    {send_to_char("You don't understand how that rune works.\n\r",ch);return;}
    if ( rune->value[2] > 0 && !IS_SET( ch->pcdata->powers[MPOWER_GLYPHS],rune->value[2]) )
    {send_to_char("You don't understand how that glyph works.\n\r",ch);return;}
    if ( rune->value[3] > 0 && !IS_SET( ch->pcdata->powers[MPOWER_SIGILS],rune->value[3]) )
    {send_to_char("You don't understand how that sigil works.\n\r",ch);return;}

    if (rune->value[1] == RUNE_MASTER)
    {
	if ( IS_SET(page->quest, QUEST_MASTER_RUNE) )
	{
	    send_to_char( "There is already a master rune draw on this page.\n\r", ch );
	    return;
	}
	else if (page->value[0] + page->value[1] + page->value[2] + 
	    page->value[3] > 0)
	{
	    send_to_char( "There is already a spell on this page.\n\r", ch );
	    return;
	}
	else
	{
	    act("You copy $p rune onto $P.",ch,rune,page,TO_CHAR);
	    act("$n copies $p rune onto $P.",ch,rune,page,TO_ROOM);
	    SET_BIT(page->quest, QUEST_MASTER_RUNE);
	}
	return;
    }
    else if ( IS_SET(page->quest, QUEST_MASTER_RUNE) )
    {
	send_to_char( "There is already a master rune draw on this page.\n\r", ch );
	return;
    }
    else if (rune->value[1] > 0 && !IS_SET(page->value[1], rune->value[1]))
	page->value[1] += rune->value[1];
    else if (rune->value[1] > 0)
	{send_to_char("That rune has already been copied onto the page.\n\r",ch);return;}
    else if (rune->value[2] > 0 && !IS_SET(page->value[2], rune->value[2]))
	page->value[2] += rune->value[2];
    else if (rune->value[2] > 0)
	{send_to_char("That glyph has already been copied onto the page.\n\r",ch);return;}
    else if (rune->value[3] > 0 && !IS_SET(page->value[3], rune->value[3]))
	page->value[3] += rune->value[3];
    else if (rune->value[3] > 0)
	{send_to_char("That sigil has already been copied onto the page.\n\r",ch);return;}

    act("You copy $p onto $P.",ch,rune,page,TO_CHAR);
    act("$n copies $p onto $P.",ch,rune,page,TO_ROOM);
    return;
}

void spell_insert_page( int sn, int level, CHAR_DATA *ch, void *vo )
{
    OBJ_DATA *page;
    OBJ_DATA *book;
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];

    target_name = one_argument( target_name, arg1 );
    target_name = one_argument( target_name, arg2 );

    if ( arg1[0] == '\0' || arg2[0] == '\0' )
    {send_to_char("Syntax is: cast 'insert page' <page> <book>.\n\r",ch);return;}
    if ( ( page = get_obj_carry( ch, arg1 ) ) == NULL )
    {send_to_char("You are not carrying that page.\n\r",ch);return;}
    if ( page->item_type != ITEM_PAGE )
    {send_to_char("That item isn't a page.\n\r",ch);return;}
    if ( ( book = get_obj_carry( ch, arg2 ) ) == NULL )
    {send_to_char("You are not carrying that book.\n\r",ch);return;}
    if ( book->item_type != ITEM_BOOK )
    {send_to_char("That item isn't a book.\n\r",ch);return;}
    if ( IS_SET(book->value[1], CONT_CLOSED) )
    {send_to_char("First you need to open it!\n\r",ch);return;}

    obj_from_char(page);
    obj_to_obj(page,book);
    book->value[3] += 1;
    book->value[2] = book->value[3];
    page->value[0] = book->value[3];
    page->specpower = book->value[3]+1;

    act("You insert $p into $P.",ch,page,book,TO_CHAR);
    act("$n inserts $p into $P.",ch,page,book,TO_ROOM);
    return;
}

void spell_remove_page( int sn, int level, CHAR_DATA *ch, void *vo )
{
    char arg1[MAX_INPUT_LENGTH];
    OBJ_DATA *page;
    OBJ_DATA *book;
    OBJ_DATA *page_next;
    int count = 0;

    target_name = one_argument( target_name, arg1 );

    if ( arg1[0] == '\0' )
    {send_to_char("Syntax is: cast 'remove page' <book>.\n\r",ch);return;}
    if ( ( book = get_obj_carry( ch, arg1 ) ) == NULL )
    {send_to_char("You are not carrying that book.\n\r",ch);return;}
    if ( book->item_type != ITEM_BOOK )
    {send_to_char("That item isn't a book.\n\r",ch);return;}
    if ( IS_SET(book->value[1], CONT_CLOSED) )
    {send_to_char("First you need to open it!\n\r",ch);return;}
    if ( book->value[2] == 0 )
    {send_to_char("You cannot remove the index page!\n\r",ch);return;}

    if ( ( page = get_page(book, book->value[2]) ) == NULL )
    {
	send_to_char("The page seems to have been torn out.\n\r",ch);
	return;
    }

    obj_from_obj(page);
    obj_to_char(page,ch);
    page->value[0] = 0;

    act("You remove $p from $P.",ch,page,book,TO_CHAR);
    act("$n removes $p from $P.",ch,page,book,TO_ROOM);

    for ( page = book->contains; page != NULL; page = page_next )
    {
	page_next = page->next_content;
	count += 1;
	page->value[0] = count;
    }
    book->value[3] = count;

    if (book->value[2] > book->value[3]) book->value[2] = book->value[3];

    return;
}

void enhance_stat( int sn, int level, CHAR_DATA *ch, CHAR_DATA *victim, int apply_bit, int bonuses, int affect_bit )
{
    AFFECT_DATA af;

    if ( IS_ITEMAFF(victim, ITEMA_REFLECT))
    {
	send_to_char( "You are unable to focus your spell.\n\r", ch );
	return;
    }

    if (IS_SET(affect_bit, AFF_WEBBED) && IS_AFFECTED(victim, AFF_WEBBED))
	affect_bit -= AFF_WEBBED;
    else if (IS_SET(affect_bit, AFF_WEBBED) && is_safe(ch,victim))
	affect_bit -= AFF_WEBBED;
    if (IS_SET(affect_bit, AFF_TENDRILS) && IS_AFFECTED(victim,AFF_TENDRILS))
        affect_bit -= AFF_TENDRILS;
    else if (IS_SET(affect_bit, AFF_TENDRILS) && is_safe(ch,victim))
        affect_bit -= AFF_TENDRILS; 
    if (IS_SET(affect_bit, AFF_CHARM) && !IS_AFFECTED(victim, AFF_CHARM))
    {
	if (victim->level <= 50 && (IS_NPC(victim) || !IS_IMMUNE(victim, IMM_CHARM)))
	{
	    if ( victim->master )
	        stop_follower( victim );
            add_follower( victim, ch );
	}
	else
	{
	    send_to_char("The spell failed.\n\r",ch);
	    return;
	}
    }

    af.type      = sn;
    af.duration  = level;
    af.location  = apply_bit;
    af.modifier  = bonuses;
    af.bitvector = affect_bit;
    affect_to_char( victim, &af );

    return;
}

void spell_chaos_blast( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    int dam;

    if (IS_ITEMAFF(victim, ITEMA_CHAOSSHIELD)) return;
    dam = dice( level, 8 );
    if ( saves_spell( level, victim ) ) dam *= 0.5;
    damage( ch, victim, dam, sn );
    return;
}
/*
void spell_make_bag( int sn, int level, CHAR_DATA *ch,void *vo)
{
   static char *headers[]  =  { "corpse of the ", "corpse of The ",
                                "corpse of an ", "corpse of An ",
                                "corpse of a ", "corpse of A ",
                                "corpse of " };
  OBJ_DATA *obj = (OBJ_DATA *) vo;
  char buf[MAX_STRING_LENGTH];
  int i;
  
  if ( obj->item_type != ITEM_CORPSE_NPC && obj->item_type !=ITEM_CORPSE_PC)
  return;

  for (i = 0; i < 7; i++)
    {
    int len = strlen(headers[i]);
    if ( memcmp(obj->short_descr, headers[i], len) == 0)
        {
         sprintf( buf, "bag %s", obj->short_descr+len );
         free_string( obj->name );
         obj->name = str_dup(buf);
         sprintf( buf, "A bag of fine %s hide catches your eye. ",
                 obj->short_descr+len );
         free_string( obj->description );
         obj->description = str_dup( buf );
         sprintf(buf, "bag made from %s hide", obj->short_descr+len);
         free_string( obj->short_descr );
         obj->short_descr = str_dup( buf );

         break;
    }
}
obj->item_type = ITEM_CONTAINER;
obj->wear_flags = ITEM_HOLD|ITEM_TAKE;
obj->timer = 0;
obj->weight = 5;
obj->level = 1;
obj->cost = 100;
obj->value[0] = 200;
obj->value[1] = 1;
obj->value[2] = -1;
obj->pIndexData = get_obj_index( 3373 );

act( "Everyone is jealous of your new $p.", ch, obj, NULL, TO_CHAR );
act( "You are jealous of $n's new $p.", ch, obj, NULL, TO_ROOM );

send_to_char( "Ok.\n\r", ch );
return;

}
*/
void spell_resistance( int sn, int level, CHAR_DATA *ch, void *vo )
{
    OBJ_DATA *obj = (OBJ_DATA *) vo;

    if ( obj->chobj != NULL )
    {
	send_to_char("Your spell has no affect.\n\r",ch);
	return;
    }
    if ( IS_SET(obj->quest, QUEST_ARTIFACT) )
    {
	send_to_char( "Not on artifacts.\n\r", ch );
	return;
    }
    if ( obj->resistance <= 10 )
    {
	send_to_char( "You cannot make that item any more resistant.\n\r", ch );
	return;
    }
    obj->resistance = 10;
    act("$p sparkles for a moment.",ch,obj,NULL,TO_CHAR);
    act("$p sparkles for a moment.",ch,obj,NULL,TO_ROOM);
    return;
}

void spell_drowfire( int sn, int level, CHAR_DATA *ch, void *vo) {
	CHAR_DATA *victim = (CHAR_DATA *) vo;
	AFFECT_DATA af1;
	AFFECT_DATA af2;
	AFFECT_DATA af3;

	act("You chant some arcane words on $N.",ch,NULL,victim,TO_CHAR);
	act("$n chants some arcane words on $N.",ch,NULL,victim,TO_NOTVICT);
	act("$n chants some arcane words on you.",ch,NULL,victim,TO_VICT);

	if (IS_AFFECTED(victim, AFF_DROWFIRE)) {
		send_to_char("They are already affected by drowfire.\n\r",ch);
		return;}
	if (is_safe(ch, victim)) return;

	af1.type	= sn;
	af1.location	= APPLY_AC;
	af1.modifier	= 200;
	af1.duration	= 2;
	af1.bitvector	= AFF_DROWFIRE;
	affect_to_char(victim, &af1);

	af2.type	= sn;
	af2.location	= APPLY_STR;
	af2.modifier	= -2;
	af2.duration	= 2;
	af2.bitvector	= AFF_CURSE;
	affect_to_char(victim, &af2);

	af3.type	= sn;
	af3.location	= APPLY_HITROLL;
	af3.modifier	= -10;
	af3.duration	= 2;
	af3.bitvector	= AFF_BLIND;
	affect_to_char(victim, &af3);

	send_to_char("You are engulfed in drowfire!\n\r", victim);
	act("$n is engulfed in drowfire!",victim,NULL,NULL,TO_ROOM);
	return;
}


void spell_web( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;

    act("You point your finger at $N and a web flies from your hand!",ch,NULL,victim,TO_CHAR);
    act("$n points $s finger at $N and a web flies from $s hand!",ch,NULL,victim,TO_NOTVICT);
    act("$n points $s finger at you and a web flies from $s hand!",ch,NULL,victim,TO_VICT);

    if ( IS_AFFECTED(victim, AFF_WEBBED) )
    {
	send_to_char( "But they are already webbed!\n\r", ch );
	return;
    }

    if ( is_safe(ch, victim) ) return;

    if ( saves_spell( level, victim ) && victim->position >= POS_FIGHTING )
    {
	send_to_char( "You dodge the web!\n\r", victim );
	act("$n dodges the web!",victim,NULL,NULL,TO_ROOM);
	return;
    }

    af.type      = sn;
    af.location  = APPLY_AC;
    af.modifier  = 200;
    af.duration  = number_range(1,2);
    af.bitvector = AFF_WEBBED;
    affect_to_char( victim, &af );
    send_to_char( "You are coated in a sticky web!\n\r", victim );
    act("$n is coated in a sticky web!",victim,NULL,NULL,TO_ROOM);
    return;
}

void spell_polymorph( int sn, int level, CHAR_DATA *ch, void *vo )
{
    AFFECT_DATA af;
    char buf [MAX_INPUT_LENGTH];

    if (IS_AFFECTED(ch, AFF_POLYMORPH))
    {
	send_to_char("You cannot polymorph from this form.\n\r",ch);
	return;
    }
    if ( ch->position == POS_FIGHTING || is_affected( ch, sn ) )
	return;

    if ( !str_cmp( target_name, "frog" ) )
    {
	if (!IS_NPC(ch) && ch->stance[0] != -1) do_stance(ch,"");
	if (ch->mounted == IS_RIDING) do_dismount(ch,"");
	act("$n polymorphs into a frog!",ch,NULL,NULL,TO_ROOM);
	send_to_char("You polymorph into a frog!\n\r",ch);
	clear_stats(ch);
	af.type      = sn;
	af.duration  = number_range(3,5);
	af.location  = APPLY_POLY;
	af.modifier  = POLY_FROG;
	af.bitvector = AFF_POLYMORPH;
	affect_to_char( ch, &af );
	sprintf(buf,"%s the frog",ch->name);
	free_string(ch->morph);
	ch->morph = str_dup(buf);
	return;
    }
    else if ( !str_cmp( target_name, "fish" ) )
    {
	if (!IS_NPC(ch) && ch->stance[0] != -1) do_stance(ch,"");
	if (ch->mounted == IS_RIDING) do_dismount(ch,"");
	act("$n polymorphs into a fish!",ch,NULL,NULL,TO_ROOM);
	send_to_char("You polymorph into a fish!\n\r",ch);
	clear_stats(ch);
	af.type      = sn;
	af.duration  = number_range(3,5);
	af.location  = APPLY_POLY;
	af.modifier  = POLY_FISH;
	af.bitvector = AFF_POLYMORPH;
	affect_to_char( ch, &af );
	sprintf(buf,"%s the fish",ch->name);
	free_string(ch->morph);
	ch->morph = str_dup(buf);
	return;
    }
    else if ( !str_cmp( target_name, "raven" ) )
    {
	if (!IS_NPC(ch) && ch->stance[0] != -1) do_stance(ch,"");
	if (ch->mounted == IS_RIDING) do_dismount(ch,"");
	act("$n polymorphs into a raven!",ch,NULL,NULL,TO_ROOM);
	send_to_char("You polymorph into a raven!\n\r",ch);
	clear_stats(ch);
	af.type      = sn;
	af.duration  = number_range(3,5);
	af.location  = APPLY_AC;
	af.modifier  = -150;
	if (IS_AFFECTED(ch, AFF_FLYING)) af.bitvector = AFF_POLYMORPH;
	else af.bitvector = AFF_POLYMORPH + AFF_FLYING;
	affect_to_char( ch, &af );
	af.location  = APPLY_POLY;
	af.modifier  = POLY_RAVEN;
	affect_to_char( ch, &af );
	sprintf(buf,"%s the raven",ch->name);
	free_string(ch->morph);
	ch->morph = str_dup(buf);
	return;
    }
    send_to_char( "You can polymorph into a frog, a fish, or an raven.\n\r", ch );
    return;
}
/*
void spell_contraception( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;

    if ( IS_AFFECTED(victim, AFF_CONTRACEPTION) )
	return;
    if (victim->sex != SEX_FEMALE) return;
    af.type      = sn;
    af.duration  = 24;
    af.location  = APPLY_NONE;
    af.modifier  = 0;
    af.bitvector = AFF_CONTRACEPTION;
    affect_to_char( victim, &af );
    return;
}
*/
void spell_find_familiar( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim;
    CHAR_DATA *familiar;

/* kavirpoint 
	send_to_char( "This spell has been temporarily disabled.\n\r", ch );
	return;
*/
    if ( target_name[0] == '\0' )
    {
	send_to_char( "Your familiar can be a frog, a raven, a cat or a dog.\n\r", ch );
	return;
    }

    if ( ( familiar = ch->pcdata->familiar ) != NULL ) 
    {
	send_to_char( "But you already have a familiar!\n\r", ch );
	return;
    }

    if ( !str_cmp( target_name, "frog" ) )
    {
	victim = create_mobile( get_mob_index( MOB_VNUM_FROG ) );
	if (victim == NULL)
	{send_to_char("Error - please inform KaVir.\n\r",ch); return;}
    }
    else if ( !str_cmp( target_name, "raven" ) )
    {
	victim = create_mobile( get_mob_index( MOB_VNUM_RAVEN ) );
	if (victim == NULL)
	{send_to_char("Error - please inform KaVir.\n\r",ch); return;}
    }
    else if ( !str_cmp( target_name, "cat" ) )
    {
	victim = create_mobile( get_mob_index( MOB_VNUM_CAT ) );
	if (victim == NULL)
	{send_to_char("Error - please inform KaVir.\n\r",ch); return;}
    }
    else if ( !str_cmp( target_name, "dog" ) )
    {
	victim = create_mobile( get_mob_index( MOB_VNUM_DOG ) );
	if (victim == NULL)
	{send_to_char("Error - please inform KaVir.\n\r",ch); return;}
    }
    else if ( !str_cmp( target_name, "wraith" ) && IS_CLASS(ch, CLASS_MAGE))
    {
	victim = create_mobile( get_mob_index( MOB_VNUM_WRAITH ) );
	if (victim == NULL)
	{send_to_char("Error - Inform Zaphonite.\n\r",ch); return;}
	victim->level = (level * 10);
	victim->hit = (level * 250);
	victim->max_hit = (level * 250);
	victim->max_mana = (level * 250);
	victim->mana = victim->max_mana;
	victim->max_move = (level * 250);
	victim->move = victim->max_move;
	victim->hitroll = (level * 5);
	victim->damroll = (level * 5);
	victim->armor = 100 - (level * 250);
    }
    else 
    {
	send_to_char( "Your familiar can be a frog, a raven, a cat or a dog.\n\r", ch );
	return;
    }

    act( "You make a few gestures and $N appears in a swirl of smoke.", ch, NULL, victim, TO_CHAR );
    act( "$n makes a few gestures and $N appears in a swirl of smoke.", ch, NULL, victim, TO_ROOM );
    char_to_room( victim, ch->in_room );

    ch->pcdata->familiar = victim;
    victim->wizard = ch;
    return;
}

void spell_improve( int sn, int level, CHAR_DATA *ch, void *vo )
{
    OBJ_DATA *obj = (OBJ_DATA *) vo;

    if ( IS_SET(obj->quest, QUEST_ARTIFACT) )
    {
	send_to_char( "Not on artifacts.\n\r", ch );
	return;
    }
    if ( obj->pIndexData->vnum != OBJ_VNUM_PROTOPLASM )
    {
	send_to_char( "You cannot enhance this object.\n\r", ch );
	return;
    }
    if (IS_SET(obj->quest, QUEST_IMPROVED))
    {
	send_to_char( "This item has already been improved.\n\r", ch );
	return;
    }
    else if ( obj->points < 750 && obj->item_type != ITEM_WEAPON )
    {
	send_to_char( "The object must be worth at least 750 quest points.\n\r", ch );
	return;
    }
    else if ( obj->points < 1500 && obj->item_type == ITEM_WEAPON )
    {
	send_to_char( "The object must be worth at least 1500 quest points.\n\r", ch );
	return;
    }
    REMOVE_BIT(obj->quest, QUEST_STR);
    REMOVE_BIT(obj->quest, QUEST_DEX);
    REMOVE_BIT(obj->quest, QUEST_INT);
    REMOVE_BIT(obj->quest, QUEST_WIS);
    REMOVE_BIT(obj->quest, QUEST_CON);
    REMOVE_BIT(obj->quest, QUEST_HITROLL);
    REMOVE_BIT(obj->quest, QUEST_DAMROLL);
    REMOVE_BIT(obj->quest, QUEST_HIT);
    REMOVE_BIT(obj->quest, QUEST_MANA);
    REMOVE_BIT(obj->quest, QUEST_MOVE);
    REMOVE_BIT(obj->quest, QUEST_AC);
    SET_BIT(obj->quest, QUEST_IMPROVED);
    act("$p flickers for a moment.",ch,obj,NULL,TO_CHAR);
    act("$p flickers for a moment.",ch,obj,NULL,TO_ROOM);
    return;
}



*****************************************
 *  File: mem.c                                                            *
 *                                                                         *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 *                                                                         *
 *  This code was freely distributed with the The Isles 1.1 source code,   *
 *  and has been used here for OLC - OLC would not be what it is without   *
 *  all the previous coders who released their source code.                *
 *                                                                         *
 ***************************************************************************/



#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"


/*
 * Globals
 */
extern          int                     top_reset;
extern          int                     top_area;
extern          int                     top_exit;
extern          int                     top_ed;
extern          int                     top_room;

AREA_DATA		*	area_free;
EXTRA_DESCR_DATA	*	extra_descr_free;
EXIT_DATA		*	exit_free;
ROOM_INDEX_DATA		*	room_index_free;
OBJ_INDEX_DATA		*	obj_index_free;
SHOP_DATA		*	shop_free;
MOB_INDEX_DATA		*	mob_index_free;
RESET_DATA		*	reset_free;
HELP_DATA		*	help_free;

HELP_DATA		*	help_last;



/*****************************************************************************
 Name:		new_reset_data
 Purpose:	Creates and clears a reset structure.
 ****************************************************************************/
RESET_DATA *new_reset_data( void )
{
    RESET_DATA *pReset;

    if ( !reset_free )
    {
	pReset		= alloc_perm( sizeof(*pReset) );
	top_reset++;
    }
    else
    {
	pReset		= reset_free;
	reset_free	= reset_free->next;
    }

    pReset->next	= NULL;
    pReset->command	= 'X';
    pReset->arg1	= 0;
    pReset->arg2	= 0;
    pReset->arg3	= 0;

    return pReset;
}



/*****************************************************************************
 Name:		free_reset_data
 Purpose:	Clears and deletes a reset structure.
 ****************************************************************************/
void free_reset_data( RESET_DATA *pReset )
{
    pReset->next            = reset_free;
    reset_free              = pReset;
    return;
}



/*****************************************************************************
 Name:		new_area
 Purpose:	Creates and clears a new area structure.
 ****************************************************************************/
AREA_DATA *new_area( void )
{
    AREA_DATA *pArea;
    char buf[MAX_INPUT_LENGTH];

    if ( !area_free )
    {
	pArea		= alloc_perm( sizeof(*pArea) );
	top_area++;
    }
    else
    {
	pArea		= area_free;
	area_free	= area_free->next;
    }

    pArea->next		= NULL;
    pArea->name		= str_dup( "New area" );
    pArea->recall	= ROOM_VNUM_TEMPLE;
    pArea->area_flags	= AREA_ADDED;
    pArea->security	= 1;
    pArea->builders	= str_dup( "None" );
    pArea->lvnum	= 0;
    pArea->uvnum	= 0;
    pArea->age		= 0;
    pArea->nplayer	= 0;
    pArea->vnum		= top_area-1;		/* OLC 1.1b */
    sprintf( buf, "area%d.are", pArea->vnum );
    pArea->filename	= str_dup( buf );

    return pArea;
}



/*****************************************************************************
 Name:		free_area
 Purpose:	Clears and deletes an area structure.
 ****************************************************************************/
void free_area( AREA_DATA *pArea )
{
    free_string( pArea->name );
    free_string( pArea->filename );
    free_string( pArea->builders );

    pArea->next		=   area_free->next;
    area_free		=   pArea;
    return;
}



EXIT_DATA *new_exit( void )
{
    EXIT_DATA *pExit;

    if ( !exit_free )
    {
        pExit           =   alloc_perm( sizeof(*pExit) );
        top_exit++;
    }
    else
    {
        pExit           =   exit_free;
        exit_free       =   exit_free->next;
    }

    pExit->to_room      =   NULL;
    pExit->next         =   NULL;
    pExit->vnum         =   0;
    pExit->exit_info    =   0;
    pExit->key          =   0;
    pExit->keyword      =   &str_empty[0];;
    pExit->description  =   &str_empty[0];;
    pExit->rs_flags     =   0;

    return pExit;
}



void free_exit( EXIT_DATA *pExit )
{
    free_string( pExit->keyword );
    free_string( pExit->description );

    pExit->next         =   exit_free;
    exit_free           =   pExit;
    return;
}



EXTRA_DESCR_DATA *new_extra_descr( void )
{
    EXTRA_DESCR_DATA *pExtra;

    if ( !extra_descr_free )
    {
        pExtra              =   alloc_perm( sizeof(*pExtra) );
        top_ed++;
    }
    else
    {
        pExtra              =   extra_descr_free;
        extra_descr_free    =   extra_descr_free->next;
    }

    pExtra->keyword         =   NULL;
    pExtra->description     =   NULL;
    pExtra->next            =   NULL;

    return pExtra;
}



void free_extra_descr( EXTRA_DESCR_DATA *pExtra )
{
    free_string( pExtra->keyword );
    free_string( pExtra->description );

    pExtra->next        =   extra_descr_free;
    extra_descr_free    =   pExtra;
    return;
}



ROOM_INDEX_DATA *new_room_index( void )
{
    ROOM_INDEX_DATA *pRoom;
    int door;

    if ( !room_index_free )
    {
        pRoom           =   alloc_perm( sizeof(*pRoom) );
        top_room++;
    }
    else
    {
        pRoom           =   room_index_free;
        room_index_free =   room_index_free->next;
    }

    pRoom->next             =   NULL;
    pRoom->people           =   NULL;
    pRoom->contents         =   NULL;
    pRoom->extra_descr      =   NULL;
    pRoom->area             =   NULL;

    for ( door=0; door < MAX_DIR; door++ )
        pRoom->exit[door]   =   NULL;

    pRoom->name             =   &str_empty[0];
    pRoom->description      =   &str_empty[0];
    pRoom->vnum             =   0;
    pRoom->room_flags       =   0;
    pRoom->light            =   0;
    pRoom->sector_type      =   0;

    return pRoom;
}



void free_room_index( ROOM_INDEX_DATA *pRoom )
{
    int door;
    EXTRA_DESCR_DATA *pExtra;
    RESET_DATA *pReset;

    free_string( pRoom->name );
    free_string( pRoom->description );

    for ( door = 0; door < MAX_DIR; door++ )
    {
        if ( pRoom->exit[door] )
            free_exit( pRoom->exit[door] );
    }

    for ( pExtra = pRoom->extra_descr; pExtra; pExtra = pExtra->next )
    {
        free_extra_descr( pExtra );
    }

    for ( pReset = pRoom->reset_first; pReset; pReset = pReset->next )
    {
        free_reset_data( pReset );
    }

    pRoom->next     =   room_index_free;
    room_index_free =   pRoom;
    return;
}



AFFECT_DATA *new_affect( void )
{
    AFFECT_DATA *pAf;

    if ( !affect_free )
    {
        pAf             =   alloc_perm( sizeof(*pAf) );
        top_affect++;
    }
    else
    {
        pAf             =   affect_free;
        affect_free     =   affect_free->next;
    }

    pAf->next       =   NULL;
    pAf->location   =   0;
    pAf->modifier   =   0;
    pAf->type       =   0;
    pAf->duration   =   0;
    pAf->bitvector  =   0;

    return pAf;
}



void free_affect( AFFECT_DATA* pAf )
{
    pAf->next           = affect_free;
    affect_free         = pAf;
    return;
}



SHOP_DATA *new_shop( void )
{
    SHOP_DATA *pShop;
    int buy;

    if ( !shop_free )
    {
        pShop           =   alloc_perm( sizeof(*pShop) );
        top_shop++;
    }
    else
    {
        pShop           =   shop_free;
        shop_free       =   shop_free->next;
    }

    pShop->next         =   NULL;
    pShop->keeper       =   0;

    for ( buy=0; buy<MAX_TRADE; buy++ )
        pShop->buy_type[buy]    =   0;

    pShop->profit_buy   =   100;
    pShop->profit_sell  =   100;
    pShop->open_hour    =   0;
    pShop->close_hour   =   23;

    return pShop;
}



void free_shop( SHOP_DATA *pShop )
{
    pShop->next = shop_free;
    shop_free   = pShop;
    return;
}



OBJ_INDEX_DATA *new_obj_index( void )
{
    OBJ_INDEX_DATA *pObj;
    int value;

    if ( !obj_index_free )
    {
        pObj           =   alloc_perm( sizeof(*pObj) );
        top_obj_index++;
    }
    else
    {
        pObj            =   obj_index_free;
        obj_index_free  =   obj_index_free->next;
    }

    pObj->next          =   NULL;
    pObj->extra_descr   =   NULL;
    pObj->affected      =   NULL;
    pObj->area          =   NULL;
    pObj->name          =   str_dup( "no name" );
    pObj->short_descr   =   str_dup( "(no short description)" );
    pObj->description   =   str_dup( "(no description)" );
    pObj->vnum          =   0;
    pObj->item_type     =   ITEM_TRASH;
    pObj->extra_flags   =   0;
    pObj->wear_flags    =   0;
    pObj->count         =   0;
    pObj->weight        =   0;
    pObj->cost          =   0;
    for ( value=0; value<4; value++ )
        pObj->value[value]  =   0;

    return pObj;
}



void free_obj_index( OBJ_INDEX_DATA *pObj )
{
    EXTRA_DESCR_DATA *pExtra;
    AFFECT_DATA *pAf;

    free_string( pObj->name );
    free_string( pObj->short_descr );
    free_string( pObj->description );

    for ( pAf = pObj->affected; pAf; pAf = pAf->next )
    {
        free_affect( pAf );
    }

    for ( pExtra = pObj->extra_descr; pExtra; pExtra = pExtra->next )
    {
        free_extra_descr( pExtra );
    }
    
    pObj->next              = obj_index_free;
    obj_index_free          = pObj;
    return;
}



MOB_INDEX_DATA *new_mob_index( void )
{
    MOB_INDEX_DATA *pMob;

    if ( !mob_index_free )
    {
        pMob           =   alloc_perm( sizeof(*pMob) );
        top_mob_index++;
    }
    else
    {
        pMob            =   mob_index_free;
        mob_index_free  =   mob_index_free->next;
    }

    pMob->next          =   NULL;
    pMob->spec_fun      =   NULL;
    pMob->pShop         =   NULL;
    pMob->area          =   NULL;
    pMob->player_name   =   str_dup( "no name" );
    pMob->short_descr   =   str_dup( "(no short description)" );
    pMob->long_descr    =   str_dup( "(no long description)\n\r" );
    pMob->description   =   &str_empty[0];
    pMob->vnum          =   0;
    pMob->count         =   0;
    pMob->killed        =   0;
    pMob->sex           =   0;
    pMob->level         =   0;
    pMob->act           =   ACT_IS_NPC;
    pMob->affected_by   =   0;
    pMob->alignment     =   0;
    pMob->hitroll	=   0;
    pMob->ac	        =   0;
    pMob->hitnodice	=   0;
    pMob->hitsizedice	=   0;
    pMob->hitplus	=   0;
    pMob->damnodice	=   0;
    pMob->damsizedice	=   0;
    pMob->damplus	=   0;
    pMob->gold          =   0;

    return pMob;
}



void free_mob_index( MOB_INDEX_DATA *pMob )
{
    free_string( pMob->player_name );
    free_string( pMob->short_descr );
    free_string( pMob->long_descr );
    free_string( pMob->description );

    free_shop( pMob->pShop );

    pMob->next              = mob_index_free;
    mob_index_free          = pMob;
    return;
}



rwi3
ned(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"
#include "player.h"





void do_guide( CHAR_DATA *ch, char *argument )


{


    CHAR_DATA *victim;


    int ch_age = years_old(ch);


    char      arg [MAX_INPUT_LENGTH];





    argument = one_argument( argument, arg );





    if (IS_NPC(ch)) return;





    if (!IS_CLASS(ch, CLASS_MONK) )


    {


	send_to_char("Huh?\n\r",ch);


	return;


    }





    if ( arg[0] == '\0' )


    {


	send_to_char( "Guide whom?\n\r", ch );


	return;


    }





    if ( ch_age < 50 )


    {


       send_to_char("They must be 50 to become a monk!\n\r", ch);


       return;


    }


    


    if ( ( victim = get_char_room( ch, arg ) ) == NULL )


    {


	send_to_char( "They aren't here.\n\r", ch );


	return;


    }





    if ( IS_NPC(victim) )


    {


	send_to_char( "Not on NPC's.\n\r", ch );


	return;


    }





    if ( IS_IMMORTAL(victim) )


    {


	send_to_char( "Not on Immortals's.\n\r", ch );


	return;


    }





    if ( ch == victim )


    {


	send_to_char( "You cannot guide yourself.\n\r", ch );


	return;


    }





    if (IS_CLASS(victim, CLASS_MONK))


    {


	send_to_char( "They are already guided.\n\r", ch );


	return;


    }





    if ( victim->level != LEVEL_AVATAR && !IS_IMMORTAL(victim) )


    {


	send_to_char( "You can only guide avatars.\n\r", ch );


	return;


    }





    if (IS_CLASS(victim, CLASS_VAMPIRE) ||


IS_SET(victim->pcdata->stats[UNI_AFF], VAM_MORTAL))


    {


	send_to_char( "You are unable to guide vampires!\n\r", ch );


	return;


    }





    if (IS_CLASS(victim, CLASS_WEREWOLF))


    {


	send_to_char( "You are unable to guide werewolves!\n\r", ch );


	return;


    }





    if (IS_CLASS(victim, CLASS_DEMON) || IS_SET(victim->special,


SPC_CHAMPION))


    {


	send_to_char( "You are unable to guide demons!\n\r", ch );


	return;


    }








    if (IS_CLASS(victim, CLASS_HIGHLANDER))


    {


	send_to_char( "You are unable to guide highlanders.\n\r", ch );


	return;


    }


    


/*


    if (IS_CLASS(victim, CLASS_PALADIN))


    {


    send_to_char( "You are unable to guide paladins.\n\r", ch);


    return;


    }





	if (IS_CLASS(victim, CLASS_NINJA))


	{


	send_to_char( "You are unable to guide ninjas.\n\r", ch);


	return;


	}


	


*/


	if (IS_CLASS(victim, CLASS_DROW))


	{


	send_to_char( "You are unable to guide drow.\n\r", ch);


	return;


	}


	


	





    if (!IS_IMMUNE(victim,IMM_VAMPIRE))


    {


	send_to_char( "You cannot guide an unwilling person.\n\r", ch );


	return;


    }





    if (ch->exp < 50000)


    {


	send_to_char("You cannot afford the 50000 exp required to guide


them.\n\r",ch);


	return;


    }





    if (victim->exp < 50000)


    {


	send_to_char("They cannot afford the 50000 exp required to be


guided from you.\n\r",ch);


	return;


    }





    ch->exp -= 50000;


    victim->exp -= 50000;





    act("You guide $N in the ways of god.", ch, NULL, victim, TO_CHAR);


    act("$n guide $N in the ways of god.", ch, NULL, victim, TO_NOTVICT);


    act("$n guide you in the way of god.", ch, NULL, victim, TO_VICT);


    victim->level = LEVEL_ARCHMAGE;


    if (victim->trust > 3)


    victim->trust = victim->trust;


    else


    victim->trust = LEVEL_AVATAR;


    send_to_char( "You are now a monk.\n\r", victim );


    free_string(victim->lord);


    victim->lord = str_dup(ch->name);


    victim->class    = CLASS_MONK;


    save_char_obj(ch);


    save_char_obj(victim);


    return;


}





void do_mantra( CHAR_DATA *ch, char *argument )


{


    char arg1[MAX_INPUT_LENGTH];


    char arg2[MAX_INPUT_LENGTH];


    char buf[MAX_STRING_LENGTH];





    argument = one_argument( argument, arg1 );


    argument = one_argument( argument, arg2 );





    if (IS_NPC(ch)) return;





    if (!IS_CLASS(ch, CLASS_MONK))


    {


	send_to_char("Huh?\n\r",ch);


	return;


    }





    if (arg1[0] == '\0' && arg2[0] == '\0')


    {


	sprintf(buf,"Mantras Learned (%d).\n\r", ch->pcdata->powers[PMONK]);


	send_to_char(buf,ch);


	send_to_char("Powers you have:\n\r", ch);


	  if ( ch->pcdata->powers[PMONK] < 1 )


	   send_to_char("You have no knowledge of any Mantras.\n\r", ch);


	  if ( ch->pcdata->powers[PMONK] >= 1 )


	   send_to_char("Eyes of God.\n\r", ch);


	  if ( ch->pcdata->powers[PMONK] >= 2 )


	   send_to_char("Shield/Read Aura/Scry\n\r", ch);


	  if ( ch->pcdata->powers[PMONK] >= 3 )


	   send_to_char("Sacred Invisibility\n\r", ch);


	  if ( ch->pcdata->powers[PMONK] >= 4 )


	   send_to_char("Heart of the Oak\n\r", ch);


	  if ( ch->pcdata->powers[PMONK] >= 5 )


	   send_to_char("Adamantium Hands\n\r", ch);


	  if ( ch->pcdata->powers[PMONK] >= 6 )


	   send_to_char("Skin of Steel\n\r", ch);


	  if ( ch->pcdata->powers[PMONK] >= 7 )


	   send_to_char("The Almighty Favor\n\r", ch);


	  if ( ch->pcdata->powers[PMONK] >= 8 )


	   send_to_char("Dark Blaze\n\r", ch);


	  if ( ch->pcdata->powers[PMONK] >= 9 )


	   send_to_char("Celestial Path\n\r", ch);


	  if ( ch->pcdata->powers[PMONK] >= 10 )


	   send_to_char("Prayer of the Ages\n\r", ch);


	  if ( ch->pcdata->powers[PMONK] >= 11 )


	   send_to_char("Cloak of Life\n\r", ch);


	  if ( ch->pcdata->powers[PMONK] >= 12 )


	   send_to_char("Gods Heal.\n\r", ch);
	   
	   if ( ch->pcdata->powers[PMONK] >= 13 )


	   send_to_char("Gods Hold.\n\r", ch);
	   
	   if ( ch->pcdata->powers[PMONK] >= 14 )


	   send_to_char("Will Be In Soon\n\r", ch);
	   
	   if ( ch->pcdata->powers[PMONK] >= 15 )


	   send_to_char("You have completed your Mantra training.\n\r", ch);


	return;


    }





	if (arg2[0] == '\0')


    {


	if (!str_cmp(arg1,"power"))


	{


	  if ( ch->pcdata->powers[PMONK] < 1 )


	   send_to_char("You have no knowledge of any Mantras.\n\r", ch);


	  if ( ch->pcdata->powers[PMONK] >= 1 )


	   send_to_char("Eyes of God.\n\r", ch);


	  if ( ch->pcdata->powers[PMONK] >= 2 )


	   send_to_char("Shield/Read Aura/Scry\n\r", ch);


	  if ( ch->pcdata->powers[PMONK] >= 3 )


	   send_to_char("Sacred Invisibility\n\r", ch);


	  if ( ch->pcdata->powers[PMONK] >= 4 )


	   send_to_char("Heart of the Oak\n\r", ch);


	  if ( ch->pcdata->powers[PMONK] >= 5 )


	   send_to_char("Adamantium Hands\n\r", ch);


	  if ( ch->pcdata->powers[PMONK] >= 6 )


	   send_to_char("Skin of Steel\n\r", ch);


	  if ( ch->pcdata->powers[PMONK] >= 7 )


	   send_to_char("The Almighty Favor\n\r", ch);


	  if ( ch->pcdata->powers[PMONK] >= 8 )


	   send_to_char("Dark Blaze\n\r", ch);


	  if ( ch->pcdata->powers[PMONK] >= 9 )


	   send_to_char("Celestial Path\n\r", ch);


	  if ( ch->pcdata->powers[PMONK] >= 10 )


	   send_to_char("Prayer of the Ages\n\r", ch);


	  if ( ch->pcdata->powers[PMONK] >= 11 )


	   send_to_char("Cloak of Life\n\r", ch);


	  if ( ch->pcdata->powers[PMONK] >= 12 )


	   send_to_char("Gods Heal.\n\r", ch);
	   
	   if ( ch->pcdata->powers[PMONK] >= 13 )


	   send_to_char("Gods Hold.\n\r", ch);
	   
	   if ( ch->pcdata->powers[PMONK] >= 14 )


	   send_to_char("Will Be In Soon.\n\r", ch);
	   
	   if ( ch->pcdata->powers[PMONK] >= 15 )


	   send_to_char("You have learned all the mantras.\n\r", ch);


	  return;


	}


	sprintf(buf,"Mantras Learned (%d).\n\r",


ch->pcdata->powers[PMONK]);


	send_to_char(buf,ch);


	return;


    }


    if (!str_cmp(arg2,"improve"))


    {


	int improve;


	int cost;


	int max;





	if (!str_cmp(arg1,"power"   )) 


	{


	improve = PMONK;   


	max=14;

	}


	else


	{


	    send_to_char("________________________________\n\r",ch);


	    send_to_char("|                               |\n\r",ch);


	    send_to_char("|             Mantras           |\n\r",ch);


	    send_to_char("|_______________________________|\n\r",ch);


	    send_to_char("| 1.        Eye of God          |\n\r",ch);


	    send_to_char("| 2.   Shield/Read Aura/Scry    |\n\r",ch);


	    send_to_char("| 3.    Sacred Invisibility     |\n\r",ch);


	    send_to_char("| 4.     Adamantium Hands       |\n\r",ch);


	    send_to_char("| 5.       Flaming Hands        |\n\r",ch);


	    send_to_char("| 6.       Skin of Steel        |\n\r",ch);


	    send_to_char("| 7.    The Almighty's Favor    |\n\r",ch);


	    send_to_char("| 8.        Dark Blaze          |\n\r",ch);


	    send_to_char("| 9.      Celestial Path        |\n\r",ch);


	    send_to_char("| 10.   Pray of the Ages        |\n\r",ch);


	    send_to_char("| 11.     Cloak of Life         |\n\r",ch);


	    send_to_char("|_______________________________|\n\r",ch);


	    return;


	}							


	cost = (ch->pcdata->powers[improve]+1) * 10;


	arg1[0] = UPPER(arg1[0]);


	if ( ch->pcdata->powers[improve] >= max )


	{


	    sprintf(buf,"You have already gained all the known Mantras.\n\r");


	    send_to_char(buf,ch);


	    return;


	}


	if ( cost > ch->practice )


	{


	    sprintf(buf,"It costs you %d primal learn the Mantra.\n\r",


cost);


	    send_to_char(buf,ch);


	    return;


	}


	ch->pcdata->powers[improve] += 1;


	ch->practice -= cost;


	sprintf(buf,"You learn a Mantra.\n\r");


	send_to_char(buf,ch);


    }


    else send_to_char("To learn a Mantra, type: Mantra power improve.\n\r",ch);


	return;


}





void do_cloak( CHAR_DATA *ch, char *argument )


{


	if ( IS_NPC(ch) )


     return;





    if (!IS_CLASS(ch, CLASS_MONK))


    {


	  send_to_char("Huh?\n\r",ch);


	  return;


    }





    if (ch->pcdata->powers[PMONK] < 11 )


    {


	  send_to_char("You do not have the mantra of the Cloak of Life.\n\r",ch);


	  return;


    }





    if (ch->move < 1000)


    {


	 send_to_char("You do not have enough vitality to do that.\n\r",ch);


	 return;


    }





    if (IS_SET(ch->newbits, NEW_MONKCLOAK))


    {


       REMOVE_BIT(ch->newbits, NEW_MONKCLOAK);


       send_to_char("You are no longer protected by the Almighty's cloak.\n\r",ch);


       act("$n is no longer protected by the Almighty's cloak of life.\n\r",ch,NULL,NULL,TO_ROOM);


       return;


    }


    if (!IS_SET(ch->newbits,NEW_MONKCLOAK))


    {


       SET_BIT(ch->newbits, NEW_MONKCLOAK);


	 send_to_char("You are protected by the Almighty's cloak.\n\r",ch);


	 act("$n is protected by the Almighty's cloak of life.\n\r",ch,NULL,NULL,TO_ROOM);


	 ch->move = ch->move - 1000;


	 return;


    }





}





void do_prayofages( CHAR_DATA *ch, char *argument )


{


    char      arg [MAX_INPUT_LENGTH];


    CHAR_DATA *victim;





    argument = one_argument( argument, arg );





    if (IS_NPC(ch)) return;





    if (IS_CLASS(ch, CLASS_MONK))


    {


	if (ch->pcdata->powers[PMONK] < 10)


	{


	    send_to_char("You haven't gotten the Pray of Ages mantra.\n\r",ch);


	    return;


	}


    }


    else


    {


	send_to_char("Huh?\n\r",ch);


	return;


    }





    if (arg[0] == '\0')


    {


	send_to_char("Who do you wish to be teleported to?\n\r",ch);


	return;


    }





    if ( ( victim = get_char_world( ch, arg ) ) == NULL )


    {


	send_to_char( "Nobody by that name.\n\r", ch );


	return;


    }





    if ( IS_NPC(victim) )


    {


	send_to_char( "Not on NPC's.\n\r", ch );


	return;


    }


    if ( victim == ch ) 


    {


		send_to_char( "Nothing happens.\n\r", ch);


		return; 


    }





    if ( victim->level != LEVEL_AVATAR && !IS_CLASS(victim, CLASS_MONK))


    {


	send_to_char( "Nothing happens.\n\r", ch );


	return;


    }





    if (victim->in_room == NULL)


    {


	send_to_char( "Nothing happens.\n\r", ch );


	return;


    }





    if ( victim->position != POS_STANDING )


    {


	send_to_char( "You are unable to focus on their location.\n\r", ch );


	return;


    }





    send_to_char("You pray to god and vanish in a flash of light.\n\r",ch);


    act("$n utters a prayer to god and vanishes in a flash of light.",ch,NULL,NULL,TO_ROOM);


    char_from_room(ch);


    char_to_room(ch,victim->in_room);


    do_look(ch,"");


    send_to_char("You emerge from a portal in the sky.\n\r",ch);


    act("$n appears from a portal in the sky.",ch,NULL,NULL,TO_ROOM);


    return;


}





void do_sacredinvis( CHAR_DATA *ch, char *argument)


{


    if ( IS_NPC(ch) )


     return;





    if (!IS_CLASS(ch, CLASS_MONK))


    {


	  send_to_char("Huh?\n\r",ch);


	  return;


    }





    if (ch->pcdata->powers[PMONK] < 3)


    {


	  send_to_char("You do not have the mantra of Sacred Invisibility.\n\r",ch);


	  return;


    }





        if ( IS_SET(ch->affected_by, AFF_HIDE) )


    {


	REMOVE_BIT(ch->affected_by, AFF_HIDE);


	send_to_char( "You emerge from your cloak of invisibility.\n\r", ch );


	act("$n slowly emerges from a cloak of holy invisibility.",ch,NULL,NULL,TO_ROOM);


    }


    else


    {
	if (ch->move < 500) {
	send_to_char("You do not have enough movement to do this.\n\r", ch );
	return;}



	send_to_char( "You slowly fade into a cloak of invisibility.\n\r", ch );


	act("$n slowly fades into a cloak of holy invisibility..",ch,NULL,NULL,TO_ROOM);


	SET_BIT(ch->affected_by, AFF_HIDE);


	ch->move -= 500;
    }


    return;


}








void do_flaminghands( CHAR_DATA *ch, char *argument)


{


    if ( IS_NPC(ch) )


     return;





    if (!IS_CLASS(ch, CLASS_MONK))


    {


	  send_to_char("Huh?\n\r",ch);


	  return;


    }





    if (ch->pcdata->powers[PMONK] <5)


    {


	  send_to_char("You do not have the mantra of Flaming Hands.\n\r",ch);


	  return;


    }





    if (IS_SET(ch->newbits, NEW_MONKFLAME))


    {


	  REMOVE_BIT(ch->newbits, NEW_MONKFLAME);


        send_to_char("Your hands are no longer engulfed by flames.\n\r",ch);


	  act("$n's hands are no longer engulfed by flames.\n\r",ch,NULL,NULL,TO_ROOM);


	  return;


    }


    if (!IS_SET(ch->newbits, NEW_MONKFLAME))


    {


	  SET_BIT(ch->newbits, NEW_MONKFLAME);


	  send_to_char("Your hands are engulfed by flames!\n\r",ch);


	  act("$n's hands are engulfed by flames!\n\r",ch,NULL,NULL,TO_ROOM);


	  return;


    }


}





void do_adamantium( CHAR_DATA *ch, char *argument)
{
     if ( IS_NPC(ch) )
     return;

    if (!IS_CLASS(ch, CLASS_MONK))
    {
	  send_to_char("Huh?\n\r",ch);
	  return;
    }

    if (ch->monkab[BODY] < 1)
    {
	  send_to_char("You have not learned this ability yet.\n\r",ch);
	  return;
    }

    if (IS_SET(ch->newbits, NEW_MONKADAM))
    {
	  REMOVE_BIT(ch->newbits, NEW_MONKADAM);
        send_to_char("Your hands resume their normal toughness.\n\r",ch);
	  act("$n's hands resume their normal toughness.\n\r",ch,NULL,NULL,TO_ROOM);
	  return;
    }

    if (!IS_SET(ch->newbits, NEW_MONKADAM))
    {
	  SET_BIT(ch->newbits, NEW_MONKADAM);
	  send_to_char("Your hands turn as hard as adamantium!\n\r",ch);
	  act("$n's hands turn as hard as adamantium!\n\r",ch,NULL,NULL,TO_ROOM);
	  return;
    }
}



void do_celestial( CHAR_DATA *ch, char *argument)
{
    CHAR_DATA *victim;
    char buf[MAX_STRING_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    argument = one_argument(argument, arg);

    if ( IS_NPC(ch) )
	return;

    if (!IS_CLASS(ch, CLASS_MONK))
	{
         send_to_char("Huh?\n\r",ch);
	   return;
	}

    if (ch->monkab[SPIRIT] < 4)
	{
	   send_to_char("You must obtain level 4 in Spirit to use Celestial Path.\n\r",ch);
	   return;
	}

    if (ch->move < 250)
	{
	    stc("You do not have enough vitality to do that!\n\r",ch);
	    return;
	}

    if ( arg[0] == '\0' )
    {
	send_to_char( "Open a celestial path to who?\n\r", ch );
	return;
    }

    if ( ( victim = get_char_world( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }
 
	if  (!IS_NPC(victim) && !IS_IMMUNE(victim, IMM_SUMMON) )
	{
	send_to_char("There summon is off!\n\r",ch);
	return;
}
   
 if (ch == victim)
    {
        send_to_char("But you're already at yourself!\n\r",ch);
	  return;
    }

    if (victim->in_room->vnum == ch->in_room->vnum)
    {
	  send_to_char("But you're already there!\n\r",ch);
        return;
    }

    char_from_room(ch);
    char_to_room(ch,victim->in_room);
    if (IS_NPC(victim))
    {
    sprintf(buf,"You concentrate and open a Celestial path to %s!\n\r",victim->short_descr);
    send_to_char(buf, ch);
    }

    if (!IS_NPC(victim))
    {
    sprintf(buf,"You concentrate and open a Celestial path to %s!\n\r",victim->name);
    send_to_char(buf, ch);
    }
    act("$n appears before you through a Celestial portal!\n\r",ch,NULL,NULL,TO_ROOM);
    do_look(ch, "auto");
    ch->move = ch->move - 250;
    return;
}





void do_godseye( CHAR_DATA *ch, char *argument )


{


    if ( IS_NPC(ch) )


	return;


  


  	if ( !IS_CLASS(ch, CLASS_MONK) )


  	{


  	send_to_char("Huh?\n\r", ch);


  	return;


  	}


  	


  	if ( ch->pcdata->powers[PMONK] < 1 )


  	{


  	  send_to_char("You have not learned the Eyes of God Mantra.\n\r", ch);


  	  return;


  	}


  


    if ( IS_SET(ch->act, PLR_HOLYLIGHT) )


    {


	REMOVE_BIT(ch->act, PLR_HOLYLIGHT);


	send_to_char( "Your view shimmers into mortal vision.\n\r", ch );


    }


    else


    {


	send_to_char( "God answers your prayers and gives you his vision.\n\r", ch );


	SET_BIT(ch->act, PLR_HOLYLIGHT);


    }


    return;


}





void do_steelskin( CHAR_DATA *ch, char *argument )


{


    if ( IS_NPC(ch) )


	return;


  


  	if (!IS_CLASS(ch, CLASS_MONK) )


  	{


  	send_to_char("Huh?\n\r", ch);


  	return;


  	}


  	


  	if ( ch->pcdata->powers[PMONK] < 6 )


  	{


  	  send_to_char("You have not learned the Steel of Skin Mantra.\n\r", ch);


  	  return;


  	}





/* Remove steel shield in handler.c */


  


    if ( IS_SET(ch->newbits, NEW_MONKSKIN) )


    {


	REMOVE_BIT( ch->newbits, NEW_MONKSKIN );


	send_to_char( "Your steel shield disappears.\n\r", ch );


    }


    else


    {


	send_to_char( "You are surrounded by a steel shield\n\r", ch );


	SET_BIT(ch->newbits, NEW_MONKSKIN);


    }


    return;


}





/* Monk Targeting in ninja.c */





void do_godsbless( CHAR_DATA *ch, char *argument )


{





    int sn;


    int level;


    int spelltype;





    if ( IS_NPC(ch) )


	return;


  


  	if (!IS_CLASS(ch, CLASS_MONK))


  	{


  	send_to_char("Huh?\n\r", ch);


  	return;


  	}


  	


  	if ( IS_CLASS(ch, CLASS_MONK) && ch->pcdata->powers[PMONK] < 7 )


  	{


  	send_to_char("You have not learned the Almighty Favor Mantra.\n\r", ch);


  	return;


  	}


  	


  	if (ch->mana < 1000) 


  	{


	send_to_char("You don't have enough mana.\n\r", ch );


	return;


	}


	


    if ( ( sn = skill_lookup( "godbless" ) ) < 0 ) return;


    spelltype = skill_table[sn].target;


    level = 500;


    (*skill_table[sn].spell_fun) ( sn, level, ch, ch );


    WAIT_STATE( ch, 12 );


	ch->mana = ch->mana - 3000;


    return;


}





void do_godsfavor( CHAR_DATA *ch, char *argument )


{


	


	if ( IS_NPC(ch) )


	return; 





   if (!IS_CLASS(ch, CLASS_MONK))


      {


	send_to_char("Huh?\n\r",ch);


	return;


	}





   if ( IS_CLASS(ch, CLASS_MONK) && ch->pcdata->powers[PMONK] < 8 )


  	{


  	send_to_char("You have not learned the Almighty's Favor Mantra.\n\r", ch);


  	return;


  	}





   if (ch->move < 1500)


	{


	send_to_char("You do not have the vitality to do that!\n\r",ch);


	return;


	}


 if (!IS_SET(ch->newbits, NEW_MONKFAVOR))


   {


     SET_BIT(ch->newbits, NEW_MONKFAVOR);


     send_to_char("God smiles upon you and you feel strengthened.\n\r",ch);


     act("$n is blessed by the Almighty.",ch,NULL,NULL,TO_ROOM);


     ch->move = ch->move - 1500;


     WAIT_STATE(ch, 4);


     return;


   }


 if (IS_SET(ch->newbits, NEW_MONKFAVOR))


   {


     REMOVE_BIT(ch->newbits, NEW_MONKFAVOR);


     send_to_char("You feel weaker as The Almighty's favor leaves you.\n\r",ch);


     act("$n no longer looks so holy.",ch,NULL,NULL,TO_ROOM);


     return;


   }


}













/*
void do_darkblaze( CHAR_DATA *ch, char *argument )


{



	CHAR_DATA *och;


	


    if ( IS_NPC(ch) )


	return;


  


  	if (!IS_CLASS(ch, CLASS_MONK) )


  	{


  	send_to_char("Huh?\n\r", ch);


  	return;


  	}


  	


  	if ( IS_CLASS(ch, CLASS_MONK) && ch->pcdata->powers[PMONK] > 8 )


  	{


  	send_to_char("You have not learned the Dark Blaze Mantra.\n\r", ch);


  	return;


  	}


  	


  	if (ch->move < 1000) 


  	{


	send_to_char("You don't have enough moves.\n\r", ch );


	return;


	}


	


	if ((och->in_room == ch->in_room))


	{


		act("$n prays to God and a flash of light blinds you.", ch , argument , och, TO_VICT);


		SET_BIT(och->flag3, AFF_TOTALBLIND);



		continue;


	} 


	ch->move = ch->move - 1000;


    return;


} 
*/
void do_godsheal( CHAR_DATA *ch, char *argument )
{
    if (IS_NPC(ch))
	return;

     if ( IS_CLASS(ch, CLASS_MONK) && ch->pcdata->powers[PMONK] < 12 )

    {
	send_to_char("You need to obtain heal to use heal.\n\r",ch);
	return;
    }

    if (ch->mana < 300)
    {
	send_to_char("You don't have enough energy to use heal.\n\r",ch);
	return;
    }

    if (ch->fighting != NULL)
    {
	send_to_char("You are surrounded in a glowing halo of energy.\n\r",ch);
	act("$n is surrounded by a glowing halo, and looks very relaxed.\n\r",ch,NULL,NULL,TO_ROOM);
        ch->hit += 150;
        ch->mana -= 400;
	WAIT_STATE(ch,12);
	return;
    }

    if (ch->fighting == NULL)
    {
	send_to_char("You feel a mighty force lay his hands on you.\n\r",ch);
	act("$n is surrounded by a glowing halo, and looks very relaxed.\n\r",ch,NULL,NULL,TO_ROOM);
	ch->hit += 500;
	ch->mana -= 400;
	WAIT_STATE(ch,8);
	return;
    }
  }


void do_ghold( CHAR_DATA *ch,char *argument )
{
  if (IS_NPC(ch)) return;
  
  if (!IS_CLASS(ch,CLASS_MONK))
  {
  send_to_char("Huh?\n\r",ch);
  return;
  }
   if ( IS_CLASS(ch, CLASS_MONK) && ch->pcdata->powers[PMONK] < 13 )

    {
  send_to_char("You need Mantra 13 to use gods hold.\n\r",ch);
  return;
  }
  if (!IS_SET(ch->newbits, NEW_JAWLOCK))
  {
  send_to_char("God joins you at your side to hold your foe.\n\r",ch);
  SET_BIT(ch->newbits, NEW_JAWLOCK);
  return;
  }
  else if (IS_SET(ch->newbits, NEW_JAWLOCK))
  { 
  send_to_char("God leaves your side.\n\r",ch);
  REMOVE_BIT(ch->newbits,NEW_JAWLOCK);
  return;
  }
}



#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"
#include "player.h" 
#include "monk.h"

int     dambonus        args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dam, int stance ) );


int find_dam( CHAR_DATA *ch, CHAR_DATA *victim, int dam, bool foot )
{
   OBJ_DATA *boots; 
   int stance;

    dam += char_damroll(ch);

    if (dam == 0) dam = 1;

    if ( !IS_AWAKE(victim) )
	dam *= 2;

    if ( !IS_NPC(ch) && IS_CLASS(ch, CLASS_VAMPIRE) &&
        ch->power[DISC_VAMP_POTE] > 0)
        dam *= (ch->power[DISC_VAMP_POTE] * .4);

    else if (ch->power[DISC_DAEM_ATTA] > 0)
	dam *= ch->power[DISC_DAEM_ATTA] * .5;


  if ( !IS_NPC(ch) && IS_CLASS(ch, CLASS_MONK) )
  {
    if (ch->chi[CURRENT] > 0 && ch->chi[CURRENT] < 3)
        dam *= 1.2;
    if (ch->chi[CURRENT] > 2)
	dam *= ( ch->chi[CURRENT] / 2 );
  }

    if ( !IS_NPC(victim) && IS_CLASS(victim, CLASS_WEREWOLF) )
    {
	if (IS_SET(victim->special, SPC_WOLFMAN)) dam *= 0.3;
	if (victim->power[DISC_WERE_BOAR] > 2 ) dam *= 0.3;
      if ( foot == TRUE )
      {
	  if ( ( boots = get_eq_char( ch, WEAR_FEET ) ) != NULL 
	      && IS_SET(boots->spectype, SITEM_SILVER)) dam *= 2;
	}
	if ( foot == FALSE )
	{
	  if ( ( boots = get_eq_char( ch, WEAR_HANDS ) ) != NULL 
	      && IS_SET(boots->spectype, SITEM_SILVER)) dam *= 2;
	}
    }

    if ( !IS_NPC(ch) && IS_CLASS(ch, CLASS_WEREWOLF))
    {
	if (ch->power[DISC_WERE_LUNA] > 6)
	{
	   if (weather_info.sunlight == SUN_DARK)
            dam *= 1.6;
	}
    }    

    /* Vampires should be tougher at night and weaker during the day. */
    if ( !IS_NPC(ch) && IS_CLASS(ch, CLASS_VAMPIRE) )
    {
	if (weather_info.sunlight == SUN_LIGHT && dam > 1)
	    dam /= 1.5;
	else if (weather_info.sunlight == SUN_DARK)
	    dam *= 1.5;
    }

    if ( !IS_NPC(ch) ) dam = dam + (dam * ((ch->wpn[0]+1) / 100));

    if ( !IS_NPC(ch) )
    {
	stance = ch->stance[0];
	if ( IS_STANCE(ch, STANCE_NORMAL) ) dam *= 1.25;
	else dam = dambonus(ch,victim,dam,stance);
    }

    if ( dam > 1400 )
      dam = number_range( 1340, 1420 );

    if ( dam <= 0 )
	dam = 2;

    return dam;

}

void do_deathtouch( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char arg[MAX_INPUT_LENGTH];

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if ( !IS_CLASS(ch, CLASS_MONK) )
    {
	stc("Huh?\n\r",ch);
	return;
    }

    if ( ch->monkab[SPIRIT] < 4 )
    {
	stc("You need to obtain level 4 spirit to use Death touch.\n\r",ch);
	return;
    }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char("They are not here.\n\r", ch);
	return;
    }
    
    if (is_safe(ch,victim) ) return;

    if ( victim == ch )
    {
	stc("That doesn't seem like a good idea.\n\r",ch);
	return;
    }

    WAIT_STATE(ch, 12);
    act("You place your hands on $N's head and channel negative energy into $m.",ch,NULL,victim,TO_CHAR);
    act("$n places $s hands on your head, and you scream in utter pain.",ch,NULL,victim,TO_VICT);
    act("$n places $s hands on $N's head and $N screams in pain.",ch,NULL,victim,TO_ROOM);
    SET_BIT(victim->monkstuff, MONK_DEATH);
    return;
}

void do_healingtouch( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char arg[MAX_INPUT_LENGTH];

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if ( !IS_CLASS(ch, CLASS_MONK) )
    {
	stc("Huh?\n\r",ch);
	return;
    }

    if ( ch->monkab[SPIRIT] < 3 )
    {
	stc("You need to obtain level 3 spirit to use Healing touch.\n\r",ch);
	return;
    }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char("They are not here.\n\r", ch);
	return;
    }

    WAIT_STATE(ch, 12);
    if ( victim == ch )
    {
	stc("You focus your energy, and magical sparks leap out of your body.\n\r",ch);
	act("$n concentrates, and magical sparks leap out of $s body.",ch,NULL,NULL,TO_ROOM);
	SET_BIT(ch->monkstuff, MONK_HEAL);
        return;
    }

    act("You place your hands on $N's head and focus your energy on $M.",ch,NULL,victim,TO_CHAR);
    act("$n places $s hands on your head and you feel warmer.",ch,NULL,victim,TO_VICT);
    act("$n places $s hands on $N's head and concentrates.",ch,NULL,victim,TO_ROOM);
    SET_BIT(victim->monkstuff, MONK_HEAL);
    return;

}


void do_spiritpower( CHAR_DATA *ch, char *argument )
{

    if (IS_NPC(ch)) return;

    if ( !IS_CLASS(ch, CLASS_MONK) || ch->monkab[BODY] < 3 )
    {
	stc("Huh?\n\r",ch);
	return;
    }

    if ( IS_SET(ch->newbits, NEW_POWER) )
    {
	stc("Your spiritual power fades.\n\r",ch);
	ch->damroll -= 200;
	ch->hitroll -= 200;
	REMOVE_BIT(ch->newbits, NEW_POWER);
	return;
    }

    if ( ch->move < 100 )
    {
	stc("You are too exhausted.\n\r",ch);
	return;
    }

    SET_BIT(ch->newbits, NEW_POWER);
    ch->damroll += 200;
    ch->hitroll += 200;
    ch->move -= 25;
    stc("Your body pulses with spiritual energy.\n\r",ch);
    return;

 return;

}
    
void do_relax( CHAR_DATA *ch, char *argument )
{
    if (IS_NPC(ch) ) return;

    if ( !IS_CLASS(ch, CLASS_MONK) )
    {
	stc("Huh?\n\r",ch);
	return;
    }

    if ( ch->chi[CURRENT] < 1 )
    {
	stc("You are already totally relaxed.\n\r",ch);
	return;
    }

    if ( ch->position == POS_FIGHTING )
    {
	stc("You cannot relax your ch'i while fighting!\n\r",ch);
	return;
    }

    ch->chi[CURRENT]--;
    WAIT_STATE(ch, 12);
    stc("You breathe deeply and relax your focus.\n\r",ch);
    act("$n looks more relaxed.",ch,NULL,NULL,TO_ROOM);
    return;
}

void do_chi( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];

    if (IS_NPC(ch) ) return;

    if (!IS_CLASS(ch, CLASS_MONK) )
    {
	stc("Huh?\n\r",ch);
	return;
    }

    if ( ch->fighting == NULL )
    {
	stc("You must be fighting to focus your ch'i.\n\r",ch);
	return;
    }

    if ( ch->chi[CURRENT] >= ch->chi[MAXIMUM] )
    {
	if (ch->chi[MAXIMUM] == 0)
	  stc("You have not gained any control of your ch'i.\n\r",ch);
	else
	{
	  sprintf(buf,"You cannot focus your ch'i past a level of %d.",ch->chi[MAXIMUM]);
	  stc(buf,ch);
	}
	return;
    }

    if ( ch->move < 500 + ((ch->chi[CURRENT]+1) * 20) )
    {
	stc("You are too exhausted.\n\r",ch);
	return;
    }

    if ( ch->chi[CURRENT] == 0 )
    {
      stc("Your body flickers with energy.\n\r",ch);
      act("$n's body flickers with energy.",ch,NULL,NULL,TO_ROOM);
    }
    if ( ch->chi[CURRENT] == 1 )
    {
	stc("Your body pulses with energy.\n\r",ch);
	act("$n's body pulses with energy.",ch,NULL,NULL,TO_ROOM);
    }
    if ( ch->chi[CURRENT] == 2 )
    {
	stc("Your body glows with blue energy.\n\r",ch);
	act("$n's body glows with blue energy.",ch,NULL,NULL,TO_ROOM);
    }
    if ( ch->chi[CURRENT] == 3 )
    {
	stc("Your body glows bright red.\n\r",ch);
	act("$n's body glows bright red.",ch,NULL,NULL,TO_ROOM);
    }
    if ( ch->chi[CURRENT] == 4 )
    {
	stc("Your body flashes with power.\n\r",ch);
	act("$n's body flashes with power.",ch,NULL,NULL,TO_ROOM);
    }
    if ( ch->chi[CURRENT] == 5 )
    {
	stc("Your body emits sparks of energy as you fully focus your ch'i.\n\r",ch);
	act("$n's body emits sparks of energy.",ch,NULL,NULL,TO_ROOM);
    }
    WAIT_STATE(ch, 12);
    ch->chi[CURRENT]++;
    ch->move -= ((ch->chi[CURRENT] * 20));
    return;

}

void do_shinkick( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    bool foot = TRUE;
    int dam;
	
	if (IS_NPC(ch)) return;
    if (!IS_CLASS(ch,CLASS_MONK))
    {
    send_to_char("Huh?\n\r",ch);
    return;
    }

    if ( ( victim = ch->fighting ) == NULL )
    {
	send_to_char( "You aren't fighting anyone.\n\r", ch );
	return;
    }
    /*WAIT_STATE( ch, skill_table[gsn_shinkick].beats );
    */
    WAIT_STATE(ch, 12);
    dam = number_range(1,6);

    dam = find_dam( ch, victim, dam, foot );   

    if ( ch->monkcrap == 0 )
    {
	stc("Your aura glows light blue for a moment.\n\r",ch);
	act("$n's aura glows a light blue for a moment.",ch,NULL,victim,TO_VICT);
	SET_BIT(ch->monkcrap, COMB_SHIN);
    }
    else if ( ch->monkcrap > 0 )
    {
	stc("Your aura fades away.\n\r",ch);
	act("$n's aura fades away.",ch,NULL,victim,TO_VICT);
        ch->monkcrap = 0;
    }

    act("You deliver a powerful blow to $N's shin.",ch,NULL,victim,TO_CHAR);
    act("$n delivers a powerful blow to your shin.",ch,NULL,victim,TO_VICT);
    act("$n delivers a powerful blow to $N's shin.",ch,NULL,victim,TO_NOTVICT);
    damage( ch, victim, dam, gsn_shinkick );
    if ( number_range(1, (7 - ch->chi[CURRENT]) ) == 1 )
      victim->position = POS_STUNNED;
    return;
}

void do_palmstrike( CHAR_DATA *ch, char *argument )
{
    char arg [MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    int dam;
    bool foot = FALSE;

    one_argument(argument,arg);

    if ( IS_NPC(ch) ) return;
    if (!IS_CLASS(ch,CLASS_MONK))
    {
    send_to_char("Huh?\n\r",ch);
    return;
    }
    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "You aren't fighting anyone.\n\r", ch );
	return;
    }

    if ( ch == victim )
    {
	send_to_char( "You cannot palm strike yourself!\n\r", ch );
	return;
    }

    if (is_safe(ch,victim)) return;

    if ( victim->position < POS_FIGHTING )
    {
	send_to_char( "You can only palm strike someone who is standing.\n\r", ch );
	return;
    }

    act("You slam your palm into $N's chest.",ch,NULL,victim,TO_CHAR);
    act("$n slams $s palm into your chest.",ch,NULL,victim,TO_VICT);
    act("$n slams $s palm into $N's chest.",ch,NULL,victim,TO_NOTVICT);
    /*
    WAIT_STATE( ch, skill_table[gsn_palmstrike].beats );
*/    
	WAIT_STATE(ch, 11);
	dam = number_range(1,4);

    find_dam( ch, victim, dam, foot );
    dam /= 2;

    damage(ch, victim, dam, gsn_palmstrike);
    if (victim == NULL || victim->position == POS_DEAD || dam < 1) return;
    if (victim->position == POS_FIGHTING) stop_fighting(victim,TRUE);
    act("You fall to the ground stunned!",victim,NULL,NULL,TO_CHAR);
    act("$n falls to the ground stunned!",victim,NULL,NULL,TO_ROOM);
    victim->position = POS_STUNNED;
    return;
}

void do_knee( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    bool foot = TRUE;
    int dam;

    if ( !IS_FS(ch, TECH_KNEE) )
    {
	stc("You haven't learned that technique.\n\r",ch);
	return;
    }

    if ( ( victim = ch->fighting ) == NULL )
    {
	send_to_char( "You aren't fighting anyone.\n\r", ch );
	return;
    }

    /*WAIT_STATE( ch, skill_table[gsn_knee].beats );
    */
    WAIT_STATE(ch, 11);
    dam = number_range(1,6);

    dam = find_dam( ch, victim, dam, foot );   

    if ( IS_SET(ch->monkcrap, COMB_SHIN) && !IS_SET(ch->monkcrap, COMB_KNEE ) )
    {
	stc("Your aura glows dark blue.\n\r",ch);
	act("$n's aura glows dark blue.",ch,NULL,victim,TO_VICT);
        SET_BIT(ch->monkcrap, COMB_KNEE);
    }
    else if ( ch->monkcrap > 0 )
    {
	stc("Your aura slowly fades away.\n\r",ch);
	act("$n's aura slowly fades away.\n\r",ch,NULL,victim,TO_VICT);
        ch->monkcrap = 0;
    }

    act("You leap up and slam your knee into $N's chin.",ch,NULL,victim,TO_CHAR);
    act("$n leaps up and slams $s knee into your chin.",ch,NULL,victim,TO_VICT);
    act("$n leaps up and slams $s knee into $N's chin.",ch,NULL,victim,TO_NOTVICT);
    damage( ch, victim, dam, gsn_knee );
    return;
}

void do_reverse( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    bool foot = TRUE;
    int dam;
    int move = 0;

    if ( !IS_FS(ch, TECH_SWEEP) )
    {
        stc("You haven't learned that technique.\n\r",ch);
        return;
    }

    if ( ( victim = ch->fighting ) == NULL )
    {
        send_to_char( "You aren't fighting anyone.\n\r", ch );
        return;
    }

    WAIT_STATE( ch, skill_table[gsn_monksweep].beats );

    if ( ch->monkcrap == 0 )
    {
	stc("Your aura glows a light blue for a moment.\n\r",ch);
	SET_BIT(ch->monkcrap, COMB_REV1);
    }

    else if ( IS_SET(ch->monkcrap, COMB_REV1) && IS_SET(ch->monkcrap, COMB_SWEEP) )
    {
      act("You spin around and kick $N viciously in the head.",ch,NULL,victim,TO_CHAR);
      act("You place your hands on $N's head.",ch,NULL,victim,TO_CHAR);
      act("You feel revitalized.",ch,NULL,victim,TO_CHAR);
      act("$n's choyoken **- PULVERISES -** you!",ch,NULL,victim,TO_VICT);
      act("$n's choyoken **- PULVERISES -** $N!",ch,NULL,victim,TO_NOTVICT);
      move = (victim->move / 4);
      victim->move -= move;
      ch->move += move;
      ch->monkcrap = 0;
      return;
    }

    dam = number_range(1,4);

    dam = find_dam( ch, victim, dam, foot );

    act("You crouch down and sweep $N's legs out from under $M.",ch,NULL,victim,TO_CHAR);
    act("$n crouches down and sweeps your legs out from under you",ch,NULL,victim,TO_VICT);
    act("$n crouches down and sweeps $N's legs out from under $M",ch,NULL,victim,TO_NOTVICT);
    damage( ch, victim, dam, gsn_monksweep );
    return;
}

void do_sweep( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    bool foot = TRUE;
    int dam;

    if ( !IS_FS(ch, TECH_SWEEP) )
    {
        stc("You haven't learned that technique.\n\r",ch);
        return;
    }  

    if ( ( victim = ch->fighting ) == NULL )
    {
	send_to_char( "You aren't fighting anyone.\n\r", ch );
	return;
    }

    /*WAIT_STATE( ch, skill_table[gsn_monksweep].beats );
*/      WAIT_STATE(ch, 11);
	dam = number_range(1,4);

    dam = find_dam( ch, victim, dam, foot );

    act("You crouch down and sweep $N's legs out from under $M.",ch,NULL,victim,TO_CHAR);
    act("$n crouches down and sweeps your legs out from under you",ch,NULL,victim,TO_VICT);
    act("$n crouches down and sweeps $N's legs out from under $M",ch,NULL,victim,TO_NOTVICT);
    damage( ch, victim, dam, gsn_monksweep );
    return;
}

void do_elbow( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    bool foot = FALSE;
    int dam;

    if ( !IS_FS(ch, TECH_ELBOW) )
    {
	stc("You haven't learned that technique.\n\r",ch);
	return;
    }

    if ( ( victim = ch->fighting ) == NULL )
    {
	send_to_char( "You aren't fighting anyone.\n\r", ch );
	return;
    }

    /*WAIT_STATE( ch, skill_table[gsn_elbow].beats );
  */
    WAIT_STATE(ch, 11);
    dam = number_range(1,6);

    dam = find_dam( ch, victim, dam, foot );   

    act("You ram your elbow into $N's face.",ch,NULL,victim,TO_CHAR);
    act("$n rams $s elbow into your face.",ch,NULL,victim,TO_VICT);
    act("$n rams $s elbow into $N's face.",ch,NULL,victim,TO_NOTVICT);
    damage( ch, victim, dam, gsn_elbow );
    return;
}


void do_thrustkick( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    bool foot = TRUE;
    int dam;

    if ( !IS_FS(ch, TECH_THRUST) )
    {
        stc("You haven't learned that technique.\n\r",ch);
        return;
    } 

    if ( ( victim = ch->fighting ) == NULL )
    {
	send_to_char( "You aren't fighting anyone.\n\r", ch );
	return;
    }

    /*WAIT_STATE( ch, skill_table[gsn_thrustkick].beats );
*/    
	WAIT_STATE(ch, 11);
	dam = number_range(1,5);

    dam = find_dam( ch, victim, dam, foot );   

    if ( ch->monkcrap == 0 && !IS_SET(ch->monkcrap, COMB_THRUST1) )
    {
	stc("Your aura glows dark blue for a moment.\n\r",ch);
	act("$n's aura glows dark blue for a moment.",ch,NULL,victim,TO_VICT);
	act("$n's aura glows dark blue for a moment.",ch,NULL,victim,TO_NOTVICT);
	SET_BIT(ch->monkcrap, COMB_THRUST1);
    }
    else if ( IS_SET(ch->monkcrap, COMB_THRUST1) && !IS_SET(ch->monkcrap,COMB_THRUST2) )
    {
	stc("Your aura flashes bright blue.\n\r",ch);
	act("$n's aura flashes bright blue.",ch,NULL,victim,TO_VICT);
	act("$n's aura flashes bright blue.",ch,NULL,victim,TO_NOTVICT);
	SET_BIT(ch->monkcrap, COMB_THRUST2);
    }
    else if ( ch->monkcrap != 0 )
    {
	stc("Your aura fades.\n\r",ch);
	act("$n's aura fades.",ch,NULL,victim,TO_VICT);
	act("$n's aura fades.",ch,NULL,victim,TO_NOTVICT);
	ch->monkcrap = 0;
    }

    act("You deliver a thrust kick to $N's chest.",ch,NULL,victim,TO_CHAR);
    act("$n delivers a powerful thrust kick to your chest.",ch,NULL,victim,TO_VICT);
    act("$n delivers a powerful thrust kick to $N's chest.",ch,NULL,victim,TO_NOTVICT);
    damage( ch, victim, dam, gsn_thrustkick );
    return;
}

void do_spinkick( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    bool foot = TRUE;
    int dam;

    if ( !IS_FS(ch, TECH_SPIN) )
    {
        stc("You haven't learned that technique.\n\r",ch);
        return;
    } 

    if ( ( victim = ch->fighting ) == NULL )
    {
	send_to_char( "You aren't fighting anyone.\n\r", ch );
	return;
    }

    /*WAIT_STATE( ch, skill_table[gsn_spinkick].beats );
*/    
	WAIT_STATE(ch, 11);
	dam = number_range(1,4);

    dam = find_dam( ch, victim, dam, foot );   

    if ( IS_COMB(ch, COMB_THRUST1) && IS_COMB(ch, COMB_THRUST2) )
    {
	act("Your aura pulsates and channels energy into your attack.",ch,NULL,NULL,TO_CHAR);
	act("$n's aura pulsates and channels energy into $s attack.",ch,NULL,victim,TO_VICT);
	act("$n's aura pulsates and channels energy into $s attack.",ch,NULL,victim,TO_NOTVICT);
	ch->monkcrap = 0;
	dam /= 1.2;
	damage( ch, victim, dam, gsn_lightningkick );
    if ( ch->chi[CURRENT] > 1 )
    {
	dam /= 1.2;
	damage( ch, victim, dam, gsn_lightningkick );
    }
    if ( ch->chi[CURRENT] > 2 )
    {
	dam /= 1.2;
        damage( ch, victim, dam, gsn_lightningkick );
    }
    if ( ch->chi[CURRENT] > 3 )
    {
        dam /= 1.2;
        damage( ch, victim, dam, gsn_lightningkick );
    }
    if ( ch->chi[CURRENT] > 4 )
    {
	dam /= 1.2;
        damage( ch, victim, dam, gsn_lightningkick );
    }
    if ( ch->chi[CURRENT] > 5 )
    {
        dam /= 1.2;
        damage( ch, victim, dam, gsn_lightningkick );
    }
	return;
    }
    else if ( IS_SET(ch->monkcrap, COMB_SHIN) && IS_SET(ch->monkcrap, COMB_KNEE ) )
    {
	CHAR_DATA *vch;
	CHAR_DATA *vch_next;
	CHAR_DATA *mount;
	int number_hit = 0;

	ch->monkcrap = 0;
	stc("You spin around and around, going berserk.\n\r",ch);
	act("$n body speeds up, and $e spins around rapidly.",ch,NULL,victim,TO_ROOM);	
	for ( vch = char_list; vch != NULL; vch = vch_next )
    	{
		vch_next	= vch->next;
		if (number_hit > (ch->chi[CURRENT] + 1)) continue;
		if ( vch->in_room == NULL )
		    continue;
		if ( !IS_NPC(vch) && vch->pcdata->chobj != NULL )
		    continue;
		if ( ch == vch )
		    continue;
		if ( vch->in_room == ch->in_room )
		{
		    if ( ( mount = ch->mount ) != NULL ) {if ( mount == vch ) continue;}
		    if (can_see(ch,vch))
		    {
			one_hit( ch, vch, gsn_tornadokick, 0 );
	                          number_hit++;
		    }
		}
	    }
       return;
    }

    act("You spin around and deliver a blow to $N's head.",ch,NULL,victim,TO_CHAR);
    act("$n spins around and delivers a blow to your head.",ch,NULL,victim,TO_VICT);
    act("$n spins around and delivers a devastating blow to $N's head.",ch,NULL,victim,TO_NOTVICT);
    damage( ch, victim, dam, gsn_spinkick );
    return;
}

void do_backfist( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    bool foot = FALSE;
    int dam;

    if ( !IS_FS(ch, TECH_BACK) )
    {
        stc("You haven't learned that technique.\n\r",ch);
        return;
    } 

    if ( ( victim = ch->fighting ) == NULL )
    {
	send_to_char( "You aren't fighting anyone.\n\r", ch );
	return;
    }

    /*WAIT_STATE( ch, skill_table[gsn_backfist].beats );
*/    
	WAIT_STATE(ch, 11);
	dam = number_range(1,5);

    dam = find_dam( ch, victim, dam, foot );   

    act("You spin around and slam $N's jaw with your fist.",ch,NULL,victim,TO_CHAR);
    act("$n spins around and slams you in the jaw with $s fist.",ch,NULL,victim,TO_VICT);
    act("$n spins around and slams $N in the jaw with $s fist.",ch,NULL,victim,TO_NOTVICT);
    damage( ch, victim, dam, gsn_backfist );
    return;
}


void do_learn( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    char arg1[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    char lin[MAX_STRING_LENGTH];
    int inpart = 0;
    int cost = 50000;

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch, CLASS_MONK))
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }


sprintf(lin,"===========================================================================\n\r");

    if ( arg[0] == '\0' )
    {
      stc(" Syntax: Learn <fight|techniques|abilities|chi> <power|chi>\n\r",ch);
      stc("=============================|Fight Styles|==============================\n\r",ch);
	sprintf(buf,"       Trip     [%s] Kick      [%s] Bash     [%s] Elbow    [%s] Knee     [%s]   \n\r",
            IS_FS(ch, FS_TRIP) ? "*" : " ",
       	    IS_FS(ch, FS_KICK) ? "*" : " ",
            IS_FS(ch, FS_BASH) ? "*" : " ",
            IS_FS(ch, FS_ELBOW) ? "*" : " ", 
            IS_FS(ch, FS_KNEE) ? "*" : " ");
	stc(buf,ch);
	sprintf(buf,"       Disarm   [%s] Bite      [%s] Dirt     [%s] Grapple  [%s] Punch    [%s]   \n\r",
		IS_FS(ch, FS_DISARM) ? "*" : " ",
		IS_FS(ch, FS_BITE) ? "*" : " ",
		IS_FS(ch, FS_DIRT) ? "*" : " ",
		IS_FS(ch, FS_GRAPPLE) ? "*" : " ",
		IS_FS(ch, FS_PUNCH) ? "*" : " ");
	stc(buf,ch);
	sprintf(buf,"       Rip      [%s] Stamp     [%s] Backfist [%s] Jumpkick [%s] Spinkick [%s]   \n\r",
		IS_FS(ch, FS_RIP) ? "*" : " ",
		IS_FS(ch, FS_STAMP) ? "*" : " ",
		IS_FS(ch, FS_BACKFIST) ? "*" : " ",
		IS_FS(ch, FS_JUMPKICK) ? "*" : " ",
		IS_FS(ch, FS_SPINKICK) ? "*" : " ");
	stc(buf,ch);
	sprintf(buf,"       Sweep    [%s] Charge    [%s] Hurl     [%s] Gouge    [%s] Headbutt [%s]   \n\r",
		IS_FS(ch, FS_SWEEP) ? "*" : " ",
		IS_FS(ch, FS_CHARGE) ? "*" : " ",
		IS_FS(ch, FS_HURL) ? "*" : " ",
		IS_FS(ch, FS_GOUGE) ? "*" : " ",
		IS_FS(ch, FS_HEADBUTT) ? "*" : " ");
	stc(buf,ch);
	stc("===========================================================================\n\r",ch);
	stc("                                   Techniques                                  \n\r",ch);
	stc(lin,ch);
	sprintf(buf,"    Thrust Kick [%s]   Spin Kick   [%s]   Backfist    [%s]   Palm Strike [%s]   \n\r",
	  IS_FS(ch, TECH_THRUST) ? "*" : " ",
	  IS_FS(ch, TECH_SPIN)   ? "*" : " ",
	  IS_FS(ch, TECH_BACK)   ? "*" : " ",
	  IS_FS(ch, TECH_PALM)   ? "*" : " ");
	stc(buf,ch);
	sprintf(buf,"    Elbow       [%s]   Sweep       [%s]   Shin Kick   [%s]   Knee        [%s]   \n\r",
	  IS_FS(ch, TECH_ELBOW)  ? "*" : " ",
          IS_FS(ch, TECH_SWEEP)  ? "*" : " ",
          IS_FS(ch, TECH_SHIN)   ? "*" : " ",
          IS_FS(ch, TECH_KNEE)   ? "*" : " ");
	stc(buf,ch);
	stc(lin,ch);
	stc("                                   Abilities                                   \n\r",ch);
	stc(lin,ch);
	sprintf(buf,"                 Awareness [%s%s%s%s]               Body     [%s%s%s%s]\n\r",
	  ch->monkab[AWARE] > 0 ? "*" : " ",
	  ch->monkab[AWARE] > 1 ? "*" : " ",
	  ch->monkab[AWARE] > 2 ? "*" : " ",
	  ch->monkab[AWARE] > 3 ? "*" : " ",
	  ch->monkab[BODY]  > 0 ? "*" : " ",
          ch->monkab[BODY]  > 1 ? "*" : " ",
          ch->monkab[BODY]  > 2 ? "*" : " ",
          ch->monkab[BODY]  > 3 ? "*" : " ");
	stc(buf, ch);
	sprintf(buf,"		  Combat   [%s%s%s%s]              Spirit    [%s%s%s%s]\n\r",
	  ch->monkab[COMBAT] > 0 ? "*" : " ",
          ch->monkab[COMBAT] > 1 ? "*" : " ",
          ch->monkab[COMBAT] > 2 ? "*" : " ",
          ch->monkab[COMBAT] > 3 ? "*" : " ",
	  ch->monkab[SPIRIT] > 0 ? "*" : " ",
          ch->monkab[SPIRIT] > 1 ? "*" : " ",
          ch->monkab[SPIRIT] > 2 ? "*" : " ",
          ch->monkab[SPIRIT] > 3 ? "*" : " ");
	stc(buf, ch);
	stc(lin,ch);
	stc("                                      Chi\n\r",ch);
	stc(lin,ch);
	sprintf(buf,"                 You have attained a level %d mastery of your Ch'i.\n\r",ch->chi[MAXIMUM]);
        stc(buf,ch);
    if ( ch->chi[CURRENT] > 0 )
    {
	sprintf(buf,"                     Your ch'i is currently active at level %d\n\r",ch->chi[CURRENT]);
	stc(buf,ch);
    }
    else
	stc(" 	 	    You are currently not focusing your ch'i\n\r",ch);
	stc(lin,ch);
	return;
    }
    
  if ( !str_cmp(arg1, "fight" ) )
  {
    if (!str_cmp(arg,"trip")) 
	inpart = FS_TRIP;
    else if (!str_cmp(arg,"kick")) 
	inpart = FS_KICK;
    else if (!str_cmp(arg,"bash")) 
	inpart = FS_BASH;
    else if (!str_cmp(arg,"elbow")) 
	inpart = FS_ELBOW;
    else if (!str_cmp(arg,"knee")) 
	inpart = FS_KNEE;
    else if (!str_cmp(arg,"headbutt")) 
	inpart = FS_HEADBUTT;
    else if (!str_cmp(arg,"disarm")) 
	inpart = FS_DISARM;
    else if (!str_cmp(arg,"bite")) 
	inpart = FS_BITE;
    else if (!str_cmp(arg,"dirt")) 
	inpart = FS_DIRT;
    else if (!str_cmp(arg,"grapple")) 
	inpart = FS_GRAPPLE;
    else if (!str_cmp(arg,"punch"))
	inpart = FS_PUNCH;
    else if (!str_cmp(arg,"gouge")) 
	inpart = FS_GOUGE;
    else if (!str_cmp(arg,"rip")) 
	inpart = FS_RIP;
    else if (!str_cmp(arg,"stamp")) 
	inpart = FS_STAMP;
    else if (!str_cmp(arg,"backfist")) 
	inpart = FS_BACKFIST;
    else if (!str_cmp(arg,"jumpkick"))
	inpart = FS_JUMPKICK;
    else if (!str_cmp(arg,"spinkick"))
      inpart = FS_SPINKICK;
    else if (!str_cmp(arg,"hurl")) 
	inpart = FS_HURL;
    else if (!str_cmp(arg,"sweep"))
	inpart = FS_SWEEP;
    else if (!str_cmp(arg,"charge"))
	inpart = FS_CHARGE;
    else
    {
      do_learn(ch,"");
      return;
    }
  }
  else if ( !strcmp(arg1, "techniques") )
  {
    if (!str_cmp(arg,"knee")) 
	{inpart = TECH_KNEE; cost = 200000;}
    else if (!str_cmp(arg,"spin")) 
	{inpart = TECH_SPIN; cost = 200000;}
    else if (!str_cmp(arg,"backfist")) 
	{inpart = TECH_BACK; cost = 200000;}
    else if (!str_cmp(arg,"elbow")) 
	{inpart = TECH_ELBOW; cost = 200000;}
    else if (!str_cmp(arg,"palm")) 
	{inpart = TECH_PALM; cost = 200000;}
    else if (!str_cmp(arg,"shin")) 
	{inpart = TECH_SHIN; cost = 200000;}
    else if (!str_cmp(arg,"sweep")) 
	{inpart = TECH_SWEEP; cost = 200000;}
    else if (!str_cmp(arg, "thrust"))
	{inpart = TECH_THRUST; cost = 200000;}
    else
    {
      do_learn(ch,"");
      return;
    }
  }    
  else if ( !str_cmp(arg1, "abilities" ) )
  {
         if ( !str_cmp( arg, "body" ) )
	{ inpart = BODY; cost = 500000; }
    else if ( !str_cmp( arg, "combat" ) )
	{ inpart = COMBAT; cost = 500000; }
    else if ( !str_cmp( arg, "spirit" ) )
	{ inpart = SPIRIT; cost = 500000; }
    else if ( !str_cmp( arg, "awareness" ) )
	{ inpart = AWARE; cost = 500000; }
    else
    {
      do_learn(ch,"");
      return;
    }
  }
  else if ( !str_cmp(arg1, "chi" ) )
  {
	inpart = MAXIMUM;
	cost = (ch->chi[inpart]+1) * 1000000;
  }
  else 
  {
    do_learn(ch,"");
    return;
  }

    if ( !str_cmp(arg1, "abilities" ) )
    {
	if (ch->monkab[inpart] >= 4)
	{
	  stc("You have already learned all you can in this ability.\n\r",ch);
	  return;
	}
    
        if ( ch->exp < cost )
        {
          send_to_char("You do not have enough experience to learn that power.\n\r",ch);
          return;
        }

        ch->monkab[inpart]++;
        ch->exp -= cost;
        send_to_char("Ok.\n\r",ch);
        save_char_obj(ch);
        return; 
    }
	    
    else if ( !str_cmp( arg1, "chi" ) )
    {
	if ( ch->chi[MAXIMUM] >= 6 )
	{
	  stc("You have already mastered your ch'i.\n\r",ch);
	  return;
	}

        if ( ch->exp < cost)
	{
	  sprintf(buf,"You need %d experience to gain the next level of mastery of your ch'i.",cost);
	  return;
	}

        ch->exp -= cost;
	ch->chi[MAXIMUM]++;
	save_char_obj(ch);
	stc("You gain more control over your ch'i.\n\r",ch);
	return;
    }
    else
    {
    if (IS_FS(ch, inpart))
    {
	send_to_char("You have already got that power.\n\r",ch);
	return;
    }
    if ( ch->exp < cost )
    {
	send_to_char("You do not have enough experience to learn that power.\n\r",ch);
	return;
    }

    SET_BIT(ch->monkstuff, inpart);
    ch->exp -= cost;
    send_to_char("Ok.\n\r",ch);
    save_char_obj(ch);
    return;
  }
}




#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"
#include "player.h"
#include "monk.h"

void do_blinding( CHAR_DATA *ch, char *argument )
{
  CHAR_DATA *victim;
  char arg[MAX_INPUT_LENGTH];

  argument = one_argument( argument, arg );
 
  if ( IS_NPC(ch)) return;

  if ( !IS_CLASS(ch, CLASS_MONK))
  {
    stc("Huh?\n\r",ch);
    return;
  }

  if ( ch->monkab[SPIRIT] < 1 )
  {
    stc("Your spirit is far too weak.\n\r",ch);
    stc("You need a level one mastery of the Spirit to use Blinding Agony.\n\r",ch);
    return;
  }

  if ( arg[0] == '\0' )
  {
    stc("Who do you wish to use Blinding Agony on?\n\r",ch);
    return;
  }

  if ( ch->move < 200 )
  {
    stc("You are far too exhausted to use Blinding Agony.\n\r",ch);
    stc("Try getting 200 movement points.\n\r",ch);
    return;
  }

  if ( ( victim = get_char_room( ch, arg ) ) == NULL )
  {
    stc("They are not here.\n\r",ch);
    return;
  }

  if ( is_safe(ch,victim) ) return;

  if ( IS_SET(victim->flag2, AFF_TOTALBLIND) )
  {
    act("You hurl a ball of blinding light at $N.",ch,NULL,victim,TO_CHAR);
    act("$n hurls a ball of blinding light at you.",ch,NULL,victim,TO_VICT); 
    act("$n hurls a ball of blinding light at $N.",ch,NULL,victim,TO_ROOM);
    stc("Nothing happens.\n\r",ch);
    ch->move -= 100;
    return;
  }

  else
  {
    act("You hurl a ball of blinding light at $N.",ch,NULL,victim,TO_CHAR);
    act("$n hurls a ball of blinding light at you.",ch,NULL,victim,TO_VICT);
    act("$n hurls a ball of blinding light at $N.",ch,NULL,victim,TO_ROOM);
    SET_BIT(victim->flag2, AFF_TOTALBLIND);
    ch->move -= 200;
    stc("The searing heat of the ball blinds you.\n\r",victim);
    return;
  }

 return;

}



*****************************************
 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
 *                                                                         *
 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
 *  Chastain, Michael Quan, and Mitchell Tse.                              *
 *                                                                         *
 *  In order to use any part of this Merc Diku Mud, you must comply with   *
 *  both the original Diku license in 'license.doc' as well the Merc       *
 *  license in 'license.txt'.  In particular, you may not remove either of *
 *  these copyright notices.                                               *
 *                                                                         *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 ***************************************************************************/

#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"
#include "player.h"

void do_principles( CHAR_DATA *ch, char *argument )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch, CLASS_NINJA))
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }

    if (arg1[0] == '\0' && arg2[0] == '\0')
    {
	sprintf(buf,"Principles: Sora (%d), Chikyu (%d), Ningenno (%d).\n\r",
	ch->pcdata->powers[NPOWER_SORA], ch->pcdata->powers[NPOWER_CHIKYU],
	ch->pcdata->powers[NPOWER_NINGENNO]);
	send_to_char(buf,ch);
	return;
    }
    if (arg2[0] == '\0')
    {
	if (!str_cmp(arg1,"sora"))
	{
	    send_to_char("Sora - The finding, observing, and locating principle.\n\r\n\r",ch);
	    if (ch->pcdata->powers[NPOWER_SORA] < 1) 
		send_to_char("You have none of the Sora principles.\n\r",ch);
	    if (ch->pcdata->powers[NPOWER_SORA] > 0) 
		send_to_char("Mitsukeru -Locate- The scrying power to find enemies.\n\r",ch);
	    if (ch->pcdata->powers[NPOWER_SORA] > 1) 
		send_to_char("Koryou -Consider- The read aura power, learn about your enemies.\n\r",ch);
	    if (ch->pcdata->powers[NPOWER_SORA] > 2) 
		send_to_char("Kakusu -Hidden- Enhanced Hide.  Only other ninjas can see you.\n\r",ch);
	    if (ch->pcdata->powers[NPOWER_SORA] > 3) 
		send_to_char("Uro-Uro -Silent Walk- You leave no footprints behind.\n\r",ch);
		if (ch->pcdata->powers[NPOWER_SORA] > 4)
		send_to_char("Kanzuite -Aware- The truesight power.\n\r", ch);
		if (ch->pcdata->powers[NPOWER_SORA] > 5)
		send_to_char("Bomuzite -Sleep Gas- By mixing an potion, you can put everyone in a room to sleep.\n\r", ch);
	    return;
	}
	else if (!str_cmp(arg1,"chikyu"))
	{
	    send_to_char("Chikyu - Preperation for battle.\n\r\n\r",ch);
	    if (ch->pcdata->powers[NPOWER_CHIKYU] < 1) 
		send_to_char("You have none of the Chikyu principles.\n\r",ch);
	    if (ch->pcdata->powers[NPOWER_CHIKYU] > 0) 
		send_to_char("Tsuyoku -Strength- Toughness.\n\r",ch);
	    if (ch->pcdata->powers[NPOWER_CHIKYU] > 1) 
		send_to_char("Songai -Damage- Enhanced damage.\n\r",ch);
	    if (ch->pcdata->powers[NPOWER_CHIKYU] > 2) 
		send_to_char("Isogu -Haste- Adds two extra attacks.\n\r",ch);
	    if (ch->pcdata->powers[NPOWER_CHIKYU] > 3) 
		send_to_char("Tsuiseki -Hunt- Fast hunting.\n\r",ch);
		if (ch->pcdata->powers[NPOWER_CHIKYU] > 4)
		send_to_char("Sakeru -Sonic Speed- Dodge more attacks.\n\r", ch);
	    if (ch->pcdata->powers[NPOWER_CHIKYU] > 5)
		send_to_char("HaraKiri -Blood Power- Hurt yourself to gain  power.\n\r", ch );
	    return;
	}
	else if (!str_cmp(arg1,"ningenno"))
	{
	    send_to_char("Ningenno - The battle, attacking and getting away.\n\r\n\r",ch);
	    if (ch->pcdata->powers[NPOWER_NINGENNO] < 1) 
		send_to_char("You have none of the Ningenno principles.\n\r",ch);
	    if (ch->pcdata->powers[NPOWER_NINGENNO] > 0) 
		send_to_char("Tsume -Claw- IronClaw always worn on wrist to aid in hand-to-hand.\n\r",ch);
	    if (ch->pcdata->powers[NPOWER_NINGENNO] > 1) 
		send_to_char("Hakunetsu -First Strike- You get super backstabs.\n\r",ch);
	    if (ch->pcdata->powers[NPOWER_NINGENNO] > 2) 
		send_to_char("Mienaku -Vanish- Never fail flee.\n\r",ch);
	    if (ch->pcdata->powers[NPOWER_NINGENNO] > 3) 
		send_to_char("Shiroken -Throwing Star- Added attack per round, like headbutt for demons.\n\r",ch);
		if (ch->pcdata->powers[NPOWER_NINGENNO] > 4)
		send_to_char("Dokuyaku -Poison- Adds poisons to the Shiroken\n\r", ch);
	if (ch->pcdata->powers[NPOWER_NINGENNO] > 5)
	send_to_char("Circle - circle behind your opponent and hit him during battle\n\r", ch );

	    return;
	}
	sprintf(buf,"Principles: Sora (%d), Chikyu (%d), Ningenno (%d).\n\r",
	ch->pcdata->powers[NPOWER_SORA], ch->pcdata->powers[NPOWER_CHIKYU],
	ch->pcdata->powers[NPOWER_NINGENNO]);
	send_to_char(buf,ch);
	return;
    }
    if (!str_cmp(arg2,"improve"))
    {
	int improve;
	int cost;
	int max;

	     if (!str_cmp(arg1,"sora"   )) {improve = NPOWER_SORA;   max=6;}
	else if (!str_cmp(arg1,"chikyu"   )) {improve = NPOWER_CHIKYU;   max=6;}
	else if (!str_cmp(arg1,"ningenno"   )) {improve = NPOWER_NINGENNO; max=6;}
	else
	{
	    send_to_char("Principles: Sora, Chikyu, Ningenno.\n\r",ch);
	    return;
	}							
	cost = (ch->pcdata->powers[improve]+1) * 10;
	arg1[0] = UPPER(arg1[0]);
	if ( ch->pcdata->powers[improve] >= max )
	{
	    sprintf(buf,"You have already gained all the powers of the %s principle.\n\r", arg1);
	    send_to_char(buf,ch);
	    return;
	}
	if ( cost > ch->practice )
	{
	    sprintf(buf,"It costs you %d primal to improve your %s principle.\n\r", cost, arg1);
	    send_to_char(buf,ch);
	    return;
	}
	ch->pcdata->powers[improve] += 1;
	ch->practice -= cost;
	sprintf(buf,"You improve your ability in the %s principle.\n\r", arg1);
	send_to_char(buf,ch);
    }
    else send_to_char("To improve a principle, type: Principle <principle type> improve.\n\r",ch);
	return;
}

void do_michi(  CHAR_DATA *ch, char *argument  )
{
    if (IS_NPC(ch)) return;
	
	if (!IS_CLASS(ch, CLASS_NINJA) )
	{
		send_to_char("Huh?\n\r", ch);
		return;
	}

  if ( IS_CLASS(ch, CLASS_NINJA) )
  {
	
	if ( ch->rage >= 50 )
	{
	    send_to_char("But you are already in the state of Michi.\n\r",ch);
	    return;
	}
	if ( ch->move < 1000 )
	{
		send_to_char("But you don't have enough move to perform the michi.\n\r", ch);
		return;
	} 
	
	send_to_char("You are gifted positive energy while performing the michi.\n\r",ch);
	act("$n is gifted positives energy while performing the michi.",ch,NULL,NULL,TO_ROOM);
	ch->rage += 200;
	ch->move -= 1000; 
	WAIT_STATE(ch,12);
	return;
  }
	else
    send_to_char("But you are already in the state of Michi.\n\r",ch);
    return;
}

void do_discipline( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char      arg [MAX_INPUT_LENGTH];

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;
	
	if (!IS_CLASS(ch, CLASS_NINJA) )
	{
		send_to_char("Huh?\n\r", ch);
		return;
	}
    
    if ( arg[0] == '\0' )
    {
	send_to_char( "Discipline whom?\n\r", ch );
	return;
    }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( IS_NPC(victim) )
    {
	send_to_char( "Not on NPC's.\n\r", ch );
	return;
    }

    if ( IS_IMMORTAL(victim) )
    {
	send_to_char( "Not on Immortals's.\n\r", ch );
	return;
    }

    if ( ch == victim )
    {
	send_to_char( "You cannot discipline yourself.\n\r", ch );
	return;
    }

    if (IS_CLASS(victim, CLASS_NINJA))
    {
	send_to_char( "They are already disciplined.\n\r", ch );
	return;
    }

    if ( victim->level != LEVEL_AVATAR && !IS_IMMORTAL(victim) )
    {
	send_to_char( "You can only teach avatars.\n\r", ch );
	return;
    }

	if (victim->class != 0) {
	send_to_char("They already have a profession.\n\r", ch );
	return;}
    if (!IS_IMMUNE(victim,IMM_VAMPIRE))
    {
	send_to_char( "You cannot discipline an unwilling person.\n\r", ch );
	return;
    }

    if (ch->exp < 100000)
    {
	send_to_char("You cannot afford the 100000 exp required to discipline them.\n\r",ch);
	return;
    }

    if (victim->exp < 100000)
    {
	send_to_char("They cannot afford the 100000 exp required to be disciplined from you.\n\r",ch);
	return;
    }

    ch->exp -= 100000;
    victim->exp -= 100000;

    act("You teach $N the ways of the ninja.", ch, NULL, victim, TO_CHAR);
    act("$n teaches $N the ways of the ninja.", ch, NULL, victim, TO_NOTVICT);
    act("$n teaches you the way of the ninja.", ch, NULL, victim, TO_VICT);
    victim->class    = CLASS_NINJA;
    send_to_char( "You are now a ninja.\n\r", victim );
    free_string(victim->lord);
    victim->lord = str_dup(ch->name);
    victim->generation = ch->generation + 1;
    save_char_obj(ch);
    save_char_obj(victim);
    return;
}

void do_kakusu( CHAR_DATA *ch, char *argument )
{
    if (IS_NPC(ch)) return;
	
	if (!IS_CLASS(ch, CLASS_NINJA) )
	{
		send_to_char("Huh?\n\r", ch);
		return;
	}
	
	if (IS_CLASS(ch, CLASS_NINJA) && ch->pcdata->powers[NPOWER_SORA] < 3 )
	{
	  send_to_char("You have not learned the Sora principle to 3.\n\r", ch);
	  return;
	}
	
	if (ch->move < 500)
	{
		send_to_char("You don't have 500 move to activate your power.\n\r", ch);
		return;
	} 

    if ( IS_AFFECTED(ch, AFF_HIDE) )
    {
	REMOVE_BIT(ch->affected_by, AFF_HIDE);
	act( "$n appears from the shadows.", ch, NULL, NULL, TO_ROOM );
	send_to_char( "You appear from the shadows.\n\r", ch );
    }
    else
    {
	act( "$n disappears into the shadows.", ch, NULL, NULL, TO_ROOM );
	send_to_char( "You disappear into the shadows.\n\r", ch );
	SET_BIT(ch->affected_by, AFF_HIDE);
    }
    return;
}

void do_kanzuite( CHAR_DATA *ch, char *argument )
{
    if (IS_NPC(ch)) return;
	
	if (!IS_CLASS(ch, CLASS_NINJA) )
	{
		send_to_char("Huh?\n\r", ch);
		return;
	}
	
    if (IS_CLASS(ch, CLASS_NINJA) && ch->pcdata->powers[NPOWER_SORA] < 5 )
	{
	  send_to_char("You have not learned the Sora principle to 5.\n\r", ch);
	  return;
	}
	
	else if (ch->move < 500)
	{
		send_to_char("You don't have 500 move to increase your awareness.\n\r", ch);
		return;
	} 

    if ( IS_SET(ch->act, PLR_HOLYLIGHT) )
    {
	REMOVE_BIT(ch->act, PLR_HOLYLIGHT);
	send_to_char( "You're senses return to normal.\n\r", ch );
    }
    else
    {
	SET_BIT(ch->act, PLR_HOLYLIGHT);
	send_to_char( "You're senses increase into incredible proportions.\n\r", ch );
	ch->move -= 500; 
    }

    return;
}

void do_mienaku( CHAR_DATA *ch, char *argument )
{
    ROOM_INDEX_DATA *was_in;
    ROOM_INDEX_DATA *now_in;
    CHAR_DATA *victim;
    int attempt;


	if (IS_CLASS(ch, CLASS_NINJA) && ch->pcdata->powers[NPOWER_NINGENNO] < 3 )
	{
	send_to_char("You have not learned the Ningenno principle to 3.\n\r", ch);
	return;
	}
	else if (!IS_CLASS(ch, CLASS_NINJA) )
	{
	send_to_char("Huh?\n\r", ch);
	return;
	}
	
	if ( IS_NPC(ch) ) return;

    if ( ( victim = ch->fighting ) == NULL )
    {
	if ( ch->position == POS_FIGHTING )
	    ch->position = POS_STANDING;
	send_to_char( "You aren't fighting anyone.\n\r", ch );
	return;
    }
	if (ch->move < 200)
	{
	send_to_char("You don't have enough movement points to flee.\n\r", ch);
	return;
	} 
    if (IS_AFFECTED(ch, AFF_WEBBED))
    {
	send_to_char("You are unable to move with all this sticky webbing on.\n\r",ch);
	return;
    }
  
    was_in = ch->in_room;
    
{
	EXIT_DATA *pexit;
	int door;

	send_to_char("You move to vanish from combat!\n\r", ch );

for ( attempt =  0; attempt < 6; attempt++ ) 
	{
	door = number_door( );
	if ( ( pexit = was_in->exit[door] ) == 0
	||   pexit->to_room == NULL
	||   IS_SET(pexit->exit_info, EX_CLOSED)
	|| ( IS_NPC(ch)
	&&   IS_SET(pexit->to_room->room_flags, ROOM_NO_MOB) ) )
	      continue;


	move_char( ch, door );
	if ( ( now_in = ch->in_room ) == was_in )
	      continue;

/* Use escape instead of flee so people know it's the ninja power */
	ch->in_room = was_in;
	act( "$n has escaped!", ch, NULL, NULL, TO_ROOM );
	ch->in_room = now_in;
	
	if ( !IS_NPC(ch) )
	    send_to_char( "You escape from combat!\n\r", ch ); 

/*	if (victim->in_room == ch->in_room)
    {
    	SET_BIT(victim->extra,BLINDFOLDED);
    	act("You start to move at super speeds and blind $N.",ch,NULL,victim,TO_CHAR);
    	act("$n starts to move at super speeds and blinds $N.",ch,NULL,victim,TO_ROOM);
    	act("$n starts to move at super speeds and blinds you.",ch,NULL,victim,TO_VICT);
    	
    	return;
    }
  */  
    ch->move -= 200;
	stop_fighting( ch, TRUE );
	return;
   }
   
}
    return;
}

void do_bomuzite( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char      arg1 [MAX_INPUT_LENGTH];
    argument = one_argument( argument, arg1 );
        
    if (IS_NPC(ch)) return;
	
	if (!IS_CLASS(ch, CLASS_NINJA))
	{
		send_to_char("Huh?\n\r", ch);
		return;
	}
	else if ( ch->pcdata->powers[NPOWER_SORA] < 6 )
	{
	    send_to_char("You have not learned the Sora principle to 6.\n\r", ch);
	    return;
	}
	
    if ( arg1[0] == '\0' )
    {
	send_to_char( "Bomb who?\n\r", ch );
	return;
    }

    if ( ( victim = get_char_room( ch, arg1 ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( ch == victim )
    {
	send_to_char( "Not on yourself!\n\r", ch );
	return;
    }
	
    if ( ch->position == POS_FIGHTING )
    {
	send_to_char( "Not while fighting!\n\r", ch );
	return;
    }
    
	if (ch->move < 500)
	{
	send_to_char("You don't have enough movement points.\n\r", ch);
	return;
	}     
	  
    if ( victim->in_room == ch->in_room )
	{
	act("You toss your bomb onto the floor and put $N to sleep.",ch,NULL,victim,TO_CHAR);
	act("$n tosses a bomb onto the floor.  You feel sleepy.",ch,NULL,victim,TO_VICT);
	victim->position = POS_SLEEPING;
	ch->move -= 500;
	WAIT_STATE(ch, 24);
	return;
	}
	
	return;
}


void do_tsume(CHAR_DATA *ch, char *argument) {

		if (IS_NPC(ch)) return;

	if (!IS_CLASS(ch, CLASS_NINJA) || ch->pcdata->powers[NPOWER_NINGENNO] < 1) {
	send_to_char("Huh?\n\r", ch );
	return;}

	if (IS_VAMPAFF(ch, VAM_CLAWS)) {

	send_to_char("You remove the IronClaws from your wrists.\n\r", ch );
	REMOVE_BIT(ch->pcdata->stats[UNI_AFF], VAM_CLAWS);
	return;}

	send_to_char("You attach IronClaws to your wrists.\n\r", ch );
	SET_BIT(ch->pcdata->stats[UNI_AFF], VAM_CLAWS);

	return;
}

void do_hara_kiri(CHAR_DATA *ch, char *argument) {

	

	if (IS_NPC(ch)) return;

	if (!IS_CLASS(ch, CLASS_NINJA) || ch->pcdata->powers[NPOWER_CHIKYU] < 6) {
	send_to_char("Huh?\n\r", ch );
	return;}

	if (ch->pcdata->powers[HARA_KIRI] > 0) {
	send_to_char("You are already experiencing the power of HaraKiri.\n\r", ch );
	return;}

	if (ch->hit < ch->max_hit/10) {
	send_to_char("You are hurt too badly already.\n\r", ch );
	return;}

	ch->pcdata->powers[HARA_KIRI] = ch->hit/500;
	if (ch->pcdata->powers[HARA_KIRI] < 5)
	ch->pcdata->powers[HARA_KIRI] = 5;	
	ch->hit = 1;
	ch->mana = 1;
	ch->move = 1;
	send_to_char("You cut your finger and bleed profusely.\n\r", ch );
	act("$n cuts his finger and obtains the power of HaraKiri",ch,NULL,NULL,TO_ROOM);
	return;
}


10413

 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *


 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *


 *                                                                         *


 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *


 *  Chastain, Michael Quan, and Mitchell Tse.                              *


 *                                                                         *


 *  In order to use any part of this Merc Diku Mud, you must comply with   *


 *  both the original Diku license in 'license.doc' as well the Merc       *


 *  license in 'license.txt'.  In particular, you may not remove either of *


 *  these copyright notices.                                               *


 *                                                                         *


 *  Much time and thought has gone into this software and you are          *


 *  benefitting.  We hope that you share your changes too.  What goes      *


 *  around, comes around.                                                  *


 ***************************************************************************/





#if defined(macintosh)


#include <types.h>


#else


#include <sys/types.h>


#endif


#include <ctype.h>


#include <stdio.h>


#include <stdlib.h>


#include <string.h>


#include <time.h>


#include "merc.h"


#include "build.h"      





OBJ_INDEX_DATA *        obj_index_hash          [MAX_KEY_HASH];


int                     top_obj_index;








void oedit_create_object(CHAR_DATA *ch, char *argument) 


{


     OBJ_INDEX_DATA *pObjIndex; 





     int  vnum=0;


     int iHash;    


     char vnum_store[MAX_INPUT_LENGTH];


     


     argument = one_argument( argument, vnum_store ); 





     if ((is_number(vnum_store))==FALSE)


     {


        send_to_char("Syntax : oedit create <vnum>\n\r", ch);


        return;


     };


 


     vnum = atoi( vnum_store ); 





     if ( ( pObjIndex = get_obj_index( vnum ) ) != NULL )   


     {


        send_to_char( "Error : An item with that vnum already exists.\n\r", ch );


        return;


     };                           





     pObjIndex                       = alloc_perm( sizeof(*pObjIndex) );


     pObjIndex->vnum                 = vnum;


     pObjIndex->name                 = str_dup("ball of prot-plasm");


     pObjIndex->short_descr          = str_dup("ball of prot-plasm");


     pObjIndex->description          = str_dup("ball of prot-plasm.");


     /* Action description            default setting;*/





     pObjIndex->short_descr[0]       = LOWER(pObjIndex->short_descr[0]);


     pObjIndex->description[0]       = UPPER(pObjIndex->description[0]);





     pObjIndex->item_type            = ITEM_TRASH;  


     pObjIndex->extra_flags          = 0;


     pObjIndex->wear_flags           = -1;


     pObjIndex->value[0]             = 0;


     pObjIndex->value[1]             = 0;


     pObjIndex->value[2]             = 0;


     pObjIndex->value[3]             = 0;


     pObjIndex->weight               = 1;


     pObjIndex->cost                 = 1;   /* Unused */      





    iHash                   = vnum % MAX_KEY_HASH;


    pObjIndex->next         = obj_index_hash[iHash];


    obj_index_hash[iHash]   = pObjIndex;


    top_obj_index++;                         





    ch->builder_mode   = MODE_OEDIT;


    ch->builder_vnum   = vnum;  


    oedit_load(ch, vnum);


    send_to_char("Object Editor Mode Started.\n\rObject Created.\n\r", ch);


    return;


};





void oedit_show( CHAR_DATA *ch, char *argument )


{


    char buf[MAX_STRING_LENGTH];


    char arg[MAX_INPUT_LENGTH];


    AFFECT_DATA *paf;


    OBJ_DATA *obj;


    OBJ_INDEX_DATA *pObjIndex;  





    one_argument( argument, arg );





    if ( ch->builder_mode == MODE_OEDIT && arg[0] == '\0' )


    {


        if ( ( pObjIndex = get_obj_index( ch->builder_vnum ) ) == NULL )


        {


          send_to_char( "OEDIT: No object has that vnum.\n\r", ch );


          return;


        }


        if ( ( obj = get_obj_vnum( ch, pObjIndex->vnum ) ) == NULL )


        {  


          send_to_char( "OEDIT: that item is currently not load in the game.\n\r", ch );


          return;


        }


    }


    else


    {


       if (arg[0] == '\0' )


       {


          send_to_char( "Show which object?\n\r", ch );


          return;


       }


       if ( is_number( arg) == TRUE )


       {


           if ( ( obj = get_obj_vnum( ch, atoi( arg ) ) ) == NULL )


           {


              send_to_char( "Nothing like that in hell, earth, or heaven.\n\r", ch );


              return;


           }


       }


       else


       {


           if ( ( obj = get_obj_world( ch, arg ) ) == NULL )


           {


              send_to_char( "Nothing like that in hell, earth, or heaven.\n\r", ch );


              return;


           }


       }    


    }





    sprintf( buf, "Name: %s.\n\r",obj->name );


    send_to_char( buf, ch );





    sprintf( buf, "Vnum: %d.  Type: %s.\n\r", obj->pIndexData->vnum,


                                              item_type_name( obj ) );


    send_to_char( buf, ch );





    sprintf( buf, "Short description: %s.\n\rLong description: %s\n\r",


        obj->short_descr, obj->description );


    send_to_char( buf, ch );





    sprintf( buf, "Wear bits: %d.  Extra bits: %s.\n\r",


        obj->wear_flags, extra_bit_name( obj->extra_flags ) );


    send_to_char( buf, ch );





    sprintf( buf, "Number: %d/%d.  Weight: %d/%d.\n\r",


        1,           get_obj_number( obj ),


        obj->weight, get_obj_weight( obj ) );


    send_to_char( buf, ch );        





    sprintf( buf, "Cost: %d.  Timer: %d.  Level: %d.\n\r",


        obj->cost, obj->timer, obj->level );


    send_to_char( buf, ch );





    sprintf( buf,


        "In room: %d.  In object: %s.  Carried by: %s.  Wear_loc: %d.\n\r",


        obj->in_room    == NULL    ?        0 : obj->in_room->vnum,


        obj->in_obj     == NULL    ? "(none)" : obj->in_obj->short_descr,


        obj->carried_by == NULL    ? "(none)" : obj->carried_by->name, 


        obj->wear_loc );


    send_to_char( buf, ch );





    sprintf( buf, "Values: %d %d %d %d.\n\r",


        obj->value[0], obj->value[1], obj->value[2], obj->value[3] );


    send_to_char( buf, ch );





    if ( obj->extra_descr != NULL || obj->pIndexData->extra_descr != NULL )


    {


        EXTRA_DESCR_DATA *ed;                  





        send_to_char( "Extra description keywords: '", ch );





        for ( ed = obj->extra_descr; ed != NULL; ed = ed->next )


        {


            send_to_char( ed->keyword, ch );


            if ( ed->next != NULL )


                send_to_char( " ", ch );


        }





        for ( ed = obj->pIndexData->extra_descr; ed != NULL; ed = ed->next )


        {


            send_to_char( ed->keyword, ch );


            if ( ed->next != NULL )


                send_to_char( " ", ch );


        }





        send_to_char( "'.\n\r", ch );


    }





    for ( paf = obj->affected; paf != NULL; paf = paf->next )


    {


        sprintf( buf, "Affects %s by %d.\n\r",


            affect_loc_name( paf->location ), paf->modifier );


        send_to_char( buf, ch );


    }





    for ( paf = obj->pIndexData->affected; paf != NULL; paf = paf->next )


    {


        sprintf( buf, "Affects %s by %d.\n\r",   


            affect_loc_name( paf->location ), paf->modifier );


        send_to_char( buf, ch );


    }





    return;                    


}





void oedit_load( CHAR_DATA *ch, int argument )


{


   OBJ_INDEX_DATA *pObjIndex;


   OBJ_DATA *obj;





    if ( ( pObjIndex = get_obj_index( argument ) ) == NULL )   


    {


        send_to_char("OEDIT : ERROR it is not possible to create this item. \n\r",ch);


        return;


    }





    obj = create_object( pObjIndex, 1 ); /* chage this to the mortal level :) */


    if ( CAN_WEAR(obj, ITEM_TAKE) )


    {


        obj_to_char( obj, ch );


    }                  


    else


    {


        obj_to_room( obj, ch->in_room );


        act( "$n has created $p!", ch, obj, NULL, TO_ROOM );


    }


    return;


};





void oedit_load_object( CHAR_DATA *ch, char *argument )


{


    char arg[MAX_INPUT_LENGTH];


    OBJ_INDEX_DATA *pObjIndex; 


    int vnum;





    argument = one_argument( argument, arg ); 





    if (!is_number(arg))


    {


       send_to_char("Syntax : oedit load <vnum>\n\r", ch);


       return;


    };





    vnum = atoi( arg );





    if ( ( pObjIndex = get_obj_index( vnum ) ) == NULL )


    {


      send_to_char( "OEDIT : No object with that vnum exists.\n\r", ch); 


      return;


    };           





    oedit_load(ch, vnum);


    send_to_char("Object Loaded.\n\r", ch);


    return;


};





void oedit_weight( CHAR_DATA *ch, char *argument )


{


   char arg1 [MAX_INPUT_LENGTH];


   int  value;


   OBJ_DATA *obj; 


   OBJ_INDEX_DATA *pObjIndex;  





   argument = one_argument( argument, arg1 );


   value    = atoi( arg1 );





   if ( ch->builder_mode != MODE_OEDIT )


   {


      send_to_char("OEDIT: But you are not editing an object?\n\r", ch);


      return;


   }


   if ( is_number( arg1 ) )


   {


      if ( ( pObjIndex = get_obj_index( ch->builder_vnum ) ) == NULL )


      {


        send_to_char( "OEDIT: No object has that vnum.\n\r", ch );


        return;


      }


      if ( ( obj = get_obj_vnum( ch, ch->builder_vnum/* pObjIndex->vnum */ ) ) == NULL )


      {  


        send_to_char( "OEDIT: that item is currently not load in the game.\n\r", ch );


        return;


      }


      obj->weight       = value;


      pObjIndex->weight = value;


      send_to_char("Weight Changed.\n\r", ch);


      return;


   }


   else


   {


      send_to_char("Syntax : oedit weight <value>\n\r", ch);


      return;


   }   


   return;


};





void oedit_timmer( CHAR_DATA *ch, char *argument )


{


   char arg1 [MAX_INPUT_LENGTH];


   int  value;


   OBJ_DATA *obj; 


   OBJ_INDEX_DATA *pObjIndex;  





   argument = one_argument( argument, arg1 );


   value    = atoi( arg1 );





   if ( ch->builder_mode != MODE_OEDIT )


   {


      send_to_char("OEDIT: But you are not editing an object?\n\r", ch);


      return;


   }


   if ( is_number( arg1 ) )


   {


      if ( ( pObjIndex = get_obj_index( ch->builder_vnum ) ) == NULL )


      {


        send_to_char( "OEDIT: No object has that vnum.\n\r", ch );


        return;


      }


      if ( ( obj = get_obj_vnum( ch, pObjIndex->vnum ) ) == NULL )


      {  


        send_to_char( "OEDIT: that item is currently not load in the game.\n\r", ch );


        return;


      }


      obj->timer        = value;


      pObjIndex->count  = value;


      send_to_char("Timmer Changed.\n\r", ch);


      return;


   }


   else


   {


      send_to_char("Syntax : oedit timmer <value>\n\r", ch);


      return;


   }   


   return;


};





void oedit_select( CHAR_DATA *ch, char *argument )


{


    char arg[MAX_INPUT_LENGTH];


    OBJ_DATA *obj;





    one_argument( argument, arg );





     if (arg[0] == '\0' )


     {


        send_to_char( "OEDIT: Edit which object?\n\r", ch );


        return;


     }





     if ( is_number( arg ) )


     {


         if ( ( obj = get_obj_vnum( ch, atoi( arg ) ) ) == NULL )


         {


            send_to_char( "Nothing like that in hell, earth, or heaven.\n\r", ch);


            return;


         }


     }


     else


     { 


        if ( ( obj = get_obj_world( ch, arg ) ) == NULL )


        {


            send_to_char( "OEDIT: That object is not currently in the game.\n\r", ch);


            return;


        }


     }


     ch->builder_mode = MODE_OEDIT;


     ch->builder_vnum=  atoi( arg );


     send_to_char("Object Editor Mode Started.\n\rObject Selected.\n\r", ch);


     return;


}





void oedit_affects( CHAR_DATA *ch, char *argument )


{


   char arg1[MAX_INPUT_LENGTH];


   char arg2[MAX_INPUT_LENGTH];


   char buf[MAX_INPUT_LENGTH];


   OBJ_DATA *obj;


   OBJ_INDEX_DATA *pObjIndex; 





    one_argument( argument, arg1 );


    one_argument( argument, arg2 );





    if ( ch->builder_mode != MODE_OEDIT || arg2[0] == '\0' )


    {


         send_to_char( "OEDIT: But you are not editing an object ?\n\r", ch );


         return;


    }





    if ( ( pObjIndex = get_obj_index( ch->builder_vnum ) ) == NULL )


    {


         send_to_char( "OEDIT: No object has that vnum.\n\r", ch );


         return;


    }


    if ( ( obj = get_obj_vnum( ch, pObjIndex->vnum ) ) == NULL )


    {


         send_to_char( "OEDIT: that item is currently not load in the game.\n\r", ch);


         return;                     


    }





    if (arg1[0] == '\0' )


    {


        send_to_char( "Syntax: oedit affect <field> <value>\n\r", ch );


        send_to_char( "Where Field Is :\n\r", ch );


        send_to_char( "str dex wis con int mana move ac hitroll damroll\n\r", ch );


        send_to_char( "closeable closed locked pickproof\n\r", ch );


        return;               


    }


  


     if ( !str_cmp( arg1 , "str" ) )


     {


         if (!is_number( arg2 )) /* logic statement wrong ??? */


         {


              AFFECT_DATA *paf;





              for ( paf = obj->affected; paf != NULL; paf = paf->next )


              {


                 send_to_char("Object affects: - \n\r", ch);


                 sprintf(buf, "type : %d\n\r", paf->type);


                 send_to_char(buf, ch);


                 sprintf(buf, "duration : %d\n\r", paf->duration);


                 send_to_char(buf, ch);


                 sprintf(buf, "location : %d\n\r", paf->location);


                 send_to_char(buf, ch);


                 sprintf(buf, "modifier : %d\n\r", paf->modifier);


                 send_to_char(buf, ch);


                 return;


              }


/*              paf                     = alloc_perm( sizeof(*paf) );


              paf->type               = -1;


              paf->duration           = -1;


              paf->location           = ;


              paf->modifier           = ;


              paf->bitvector          = 0;


              paf->next               = pObjIndex->affected;


              pObjIndex->affected     = paf;*/


         }


         else


         {


            send_to_char( "Syntax: oedit affect str <value>\n\r", ch );


            return;


         }


     }


     return;


}





/*


 * Return ascii name of extra flags vector.


 


char *extra_bit_name( int extra_flags )


{


    static char buf[512];





    buf[0] = '\0';


    if ( extra_flags & ITEM_GLOW         ) strcat( buf, " glow"         );


    if ( extra_flags & ITEM_HUM          ) strcat( buf, " hum"          );


    if ( extra_flags & ITEM_DARK         ) strcat( buf, " dark"         );


    if ( extra_flags & ITEM_LOCK         ) strcat( buf, " lock"         );


    if ( extra_flags & ITEM_EVIL         ) strcat( buf, " evil"         );   


    if ( extra_flags & ITEM_INVIS        ) strcat( buf, " invis"        );


    if ( extra_flags & ITEM_MAGIC        ) strcat( buf, " magic"        );


    if ( extra_flags & ITEM_NODROP       ) strcat( buf, " nodrop"       );


    if ( extra_flags & ITEM_BLESS        ) strcat( buf, " bless"        );


    if ( extra_flags & ITEM_ANTI_GOOD    ) strcat( buf, " anti-good"    );


    if ( extra_flags & ITEM_ANTI_EVIL    ) strcat( buf, " anti-evil"    );


    if ( extra_flags & ITEM_ANTI_NEUTRAL ) strcat( buf, " anti-neutral" );


    if ( extra_flags & ITEM_NOREMOVE     ) strcat( buf, " noremove"     );


    if ( extra_flags & ITEM_INVENTORY    ) strcat( buf, " inventory"    );


    return ( buf[0] != '\0' ) ? buf+1 : "none"; 


}


*/






 *  File: olc.c                                                            *
 *                                                                         *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 *                                                                         *
 *  This code was freely distributed with the The Isles 1.1 source code,   *
 *  and has been used here for OLC - OLC would not be what it is without   *
 *  all the previous coders who released their source code.                *
 *                                                                         *
 ***************************************************************************/



#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"
#include "olc.h"



/*
 * Local functions.
 */
AREA_DATA *get_area_data	args( ( int vnum ) );


/* Executed from comm.c.  Minimizes compiling when changes are made. */
bool run_olc_editor( DESCRIPTOR_DATA *d )
{
    switch ( d->editor )
    {
    case ED_HELP:
	hedit( d->character, d->incomm );
	break;
    case ED_AREA:
	aedit( d->character, d->incomm );
	break;
    case ED_ROOM:
	redit( d->character, d->incomm );
	break;
    case ED_OBJECT:
	oedit( d->character, d->incomm );
	break;
    case ED_MOBILE:
	medit( d->character, d->incomm );
	break;
    default:
	return FALSE;
    }
    return TRUE;
}



char *olc_ed_name( CHAR_DATA *ch )
{
    static char buf[10];
    
    buf[0] = '\0';
    switch (ch->desc->editor)
    {
    case ED_HELP:
	sprintf( buf, "HEdit" );
	break;
    case ED_AREA:
	sprintf( buf, "AEdit" );
	break;
    case ED_ROOM:
	sprintf( buf, "REdit" );
	break;
    case ED_OBJECT:
	sprintf( buf, "OEdit" );
	break;
    case ED_MOBILE:
	sprintf( buf, "MEdit" );
	break;
    default:
	sprintf( buf, " " );
	break;
    }
    return buf;
}



char *olc_ed_vnum( CHAR_DATA *ch )
{
    AREA_DATA *pArea;
    ROOM_INDEX_DATA *pRoom;
    OBJ_INDEX_DATA *pObj;
    MOB_INDEX_DATA *pMob;
    static char buf[10];
	
    buf[0] = '\0';
    switch ( ch->desc->editor )
    {
    case ED_AREA:
	pArea = (AREA_DATA *)ch->desc->pEdit;
	sprintf( buf, "%d", pArea ? pArea->vnum : 0 );
	break;
    case ED_ROOM:
	pRoom = ch->in_room;
	sprintf( buf, "%d", pRoom ? pRoom->vnum : 0 );
	break;
    case ED_OBJECT:
	pObj = (OBJ_INDEX_DATA *)ch->desc->pEdit;
	sprintf( buf, "%d", pObj ? pObj->vnum : 0 );
	break;
    case ED_MOBILE:
	pMob = (MOB_INDEX_DATA *)ch->desc->pEdit;
	sprintf( buf, "%d", pMob ? pMob->vnum : 0 );
	break;
    default:
	sprintf( buf, " " );
	break;
    }

    return buf;
}



/*****************************************************************************
 Name:		show_olc_cmds
 Purpose:	Format up the commands from given table.
 Called by:	show_commands(olc_act.c).
 ****************************************************************************/
void show_olc_cmds( CHAR_DATA *ch, const struct olc_cmd_type *olc_table )
{
    char buf  [ MAX_STRING_LENGTH ];
    int  cmd;
    int  col;
 
    col = 0;
    for (cmd = 0; olc_table[cmd].name[0] != '\0'; cmd++)
    {
	sprintf( buf, "%-15.15s", olc_table[cmd].name );
	send_to_char(buf,ch);
	if ( ++col % 5 == 0 )
	    send_to_char( "\n\r" ,ch);
    }
 
    if ( col % 5 != 0 )
	send_to_char("\n\r",ch );

    return;
}



/*****************************************************************************
 Name:		show_commands
 Purpose:	Display all olc commands.
 Called by:	olc interpreters.
 ****************************************************************************/
bool show_commands( CHAR_DATA *ch, char *argument )
{
    switch (ch->desc->editor)
    {
   	case ED_HELP:
	    show_olc_cmds( ch, hedit_table );
	    break;
	case ED_AREA:
	    show_olc_cmds( ch, aedit_table );
	    break;
	case ED_ROOM:
	    show_olc_cmds( ch, redit_table );
	    break;
	case ED_OBJECT:
	    show_olc_cmds( ch, oedit_table );
	    break;
	case ED_MOBILE:
	    show_olc_cmds( ch, medit_table );
	    break;
    }

    return FALSE;
}



/*****************************************************************************
 *                           Interpreter Tables.                             *
 *****************************************************************************/

const struct olc_cmd_type hedit_table[]=
{
	{  "commands", show_commands },
	{  "create", hedit_create    },
	{  "?", show_help  },
    {  "level", hedit_level },
	{  "text", hedit_text },
	{  "index", hedit_index },
	{  "change", hedit_change },
	{  "keyword", hedit_keyword },
	{  "delete", hedit_delete },
	{  NULL,  0, }
};


const struct olc_cmd_type aedit_table[] =
{
/*  {   command		function		}, */

    {   "age",		aedit_age		},
    {   "builders",	aedit_builder		},
    {   "commands",	show_commands		},
    {   "create",	aedit_create		},
    {   "filename",	aedit_file		},
    {   "name",		aedit_name		},
    {   "recall",	aedit_recall		},
    {	"reset",	aedit_reset		},
    {   "security",	aedit_security		},
    {	"show",		aedit_show		},
    {   "vnum",		aedit_vnum		},
    {   "lvnum",	aedit_lvnum		},
    {   "uvnum",	aedit_uvnum		},

    {   "?",		show_help		},
    {   "version",	show_version		},

    {	"",		0,			}
};



const struct olc_cmd_type redit_table[] =
{
/*  {   command		function		}, */

    {   "commands",	show_commands		},
    {   "create",	redit_create		},
    {   "desc",		redit_desc		},
    {   "ed",		redit_ed		},
    {   "format",	redit_format		},
    {   "name",		redit_name		},
    {	"show",		redit_show		},

    {   "north",	redit_north		},
    {   "south",	redit_south		},
    {   "east",		redit_east		},
    {   "west",		redit_west		},
    {   "up",		redit_up		},
    {   "down",		redit_down		},
    {   "walk",		redit_move		},

    /* New reset commands. */
    {	"mreset",	redit_mreset		},
    {	"oreset",	redit_oreset		},
    {	"mlist",	redit_mlist		},
    {	"olist",	redit_olist		},
    {	"mshow",	redit_mshow		},
    {	"oshow",	redit_oshow		},

    {   "?",		show_help		},
    {   "version",	show_version		},

    {	"",		0,			}
};



const struct olc_cmd_type oedit_table[] =
{
/*  {   command		function		}, */

    {   "addaffect",	oedit_addaffect		},
    {   "commands",	show_commands		},
    {   "cost",		oedit_cost		},
    {   "create",	oedit_create		},
    {   "delaffect",	oedit_delaffect		},
    {   "ed",		oedit_ed		},
    {   "long",		oedit_long		},
    {   "name",		oedit_name		},
    {   "short",	oedit_short		},
    {	"show",		oedit_show		},
    {   "v0",		oedit_value0		},
    {   "v1",		oedit_value1		},
    {   "v2",		oedit_value2		},
    {   "v3",		oedit_value3		},
    {   "weight",	oedit_weight		},

    {   "?",		show_help		},
    {   "version",	show_version		},

    {	"",		0,			}
};



const struct olc_cmd_type medit_table[] =
{
/*  {   command		function		}, */

    {   "alignment",	medit_align		},
    {   "commands",	show_commands		},
    {   "create",	medit_create		},
    {   "desc",		medit_desc		},
    {   "level",	medit_level		},
    {   "long",		medit_long		},
    {   "name",		medit_name		},
    {   "shop",		medit_shop		},
    {   "short",	medit_short		},
    {	"show",		medit_show		},
    {   "spec",		medit_spec		},

    {   "?",		show_help		},
    {   "version",	show_version		},

    {	"",		0,			}
};
/*****************************************************************************
 *                          End Interpreter Tables.                          *
 *****************************************************************************/



/*****************************************************************************
 Name:		get_area_data
 Purpose:	Returns pointer to area with given vnum.
 Called by:	do_aedit(olc.c).
 ****************************************************************************/
AREA_DATA *get_area_data( int vnum )
{
    AREA_DATA *pArea;

    for (pArea = area_first; pArea; pArea = pArea->next )
    {
        if (pArea->vnum == vnum)
            return pArea;
    }

    return 0;
}



/*****************************************************************************
 Name:		edit_done
 Purpose:	Resets builder information on completion.
 Called by:	aedit, redit, oedit, medit(olc.c)
 ****************************************************************************/
bool edit_done( CHAR_DATA *ch )
{
    ch->desc->pEdit = NULL;
    ch->desc->editor = 0;
    return FALSE;
}



/*****************************************************************************
 *                              Interpreters.                                *
 *****************************************************************************/


/* Area Interpreter, called by do_aedit. */
void aedit( CHAR_DATA *ch, char *argument )
{
    AREA_DATA *pArea;
    char command[MAX_INPUT_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    int  cmd;
    int  value;

    EDIT_AREA(ch, pArea);
    smash_tilde( argument );
    strcpy( arg, argument );
    argument = one_argument( argument, command );

    if ( !IS_BUILDER( ch, pArea ) ) 
	send_to_char( "AEdit:  Insufficient security to modify area.\n\r", ch );

    if ( command[0] == '\0' )
    {
	aedit_show( ch, argument );
	return;
    }

    if ( !str_cmp(command, "done") )
    {
	edit_done( ch );
	return;
    }

    if ( !IS_BUILDER( ch, pArea ) )
    {
	interpret( ch, arg );
	return;
    }

    /* Search Table and Dispatch Command. */
    for ( cmd = 0; *aedit_table[cmd].name; cmd++ )
    {
	if ( !str_prefix( command, aedit_table[cmd].name ) )
	{
	    if ( (*aedit_table[cmd].olc_fun) ( ch, argument ) )
		SET_BIT( pArea->area_flags, AREA_CHANGED );
	    return;
	}
    }

    /* Take care of flags. */
    if ( ( value = flag_value( area_flags, arg ) ) != NO_FLAG )
    {
	TOGGLE_BIT(pArea->area_flags, value);

	send_to_char( "Flag toggled.\n\r", ch );
	return;
    }

    /* Default to Standard Interpreter. */
    interpret( ch, arg );
    return;
}



/* Room Interpreter, called by do_redit. */
void redit( CHAR_DATA *ch, char *argument )
{
    ROOM_INDEX_DATA *pRoom;
    AREA_DATA *pArea;
    char arg[MAX_STRING_LENGTH];
    char command[MAX_INPUT_LENGTH];
    int  cmd;
    int  value;

    EDIT_ROOM(ch, pRoom);
    pArea = pRoom->area;

    smash_tilde( argument );
    strcpy( arg, argument );
    argument = one_argument( argument, command );

    if ( !IS_BUILDER( ch, pArea ) ) 
        send_to_char( "REdit:  Insufficient security to modify room.\n\r", ch );

    if ( command[0] == '\0' )
    {
	redit_show( ch, argument );
	return;
    }

    if ( !str_cmp(command, "done") )
    {
	edit_done( ch );
	return;
    }

    if ( !IS_BUILDER( ch, pArea ) )
    {
        interpret( ch, arg );
        return;
    }

    /* Search Table and Dispatch Command. */
    for ( cmd = 0; *redit_table[cmd].name; cmd++ )
    {
	if ( !str_prefix( command, redit_table[cmd].name ) )
	{
	    if ( (*redit_table[cmd].olc_fun) ( ch, argument ) )
		SET_BIT( pArea->area_flags, AREA_CHANGED );
	    return;
	}
    }

    /* Take care of flags. */
    if ( ( value = flag_value( room_flags, arg ) ) != NO_FLAG )
    {
        TOGGLE_BIT(pRoom->room_flags, value);

        SET_BIT( pArea->area_flags, AREA_CHANGED );
        send_to_char( "Room flag toggled.\n\r", ch );
        return;
    }

    if ( ( value = flag_value( sector_flags, arg ) ) != NO_FLAG )
    {
        pRoom->sector_type  = value;

        SET_BIT( pArea->area_flags, AREA_CHANGED );
        send_to_char( "Sector type set.\n\r", ch );
        return;
    }

    /* Default to Standard Interpreter. */
    interpret( ch, arg );
    return;
}



/* Object Interpreter, called by do_oedit. */
void oedit( CHAR_DATA *ch, char *argument )
{
    AREA_DATA *pArea;
    OBJ_INDEX_DATA *pObj;
    char arg[MAX_STRING_LENGTH];
    char command[MAX_INPUT_LENGTH];
    int  cmd;
    int  value;

    smash_tilde( argument );
    strcpy( arg, argument );
    argument = one_argument( argument, command );

    EDIT_OBJ(ch, pObj);
    pArea = pObj->area;

    if ( !IS_BUILDER( ch, pArea ) ) 
	send_to_char( "OEdit: Insufficient security to modify area.\n\r", ch );

    if ( command[0] == '\0' )
    {
	oedit_show( ch, argument );
	return;
    }

    if ( !str_cmp(command, "done") )
    {
	edit_done( ch );
	return;
    }

    if ( !IS_BUILDER( ch, pArea ) )
    {
	interpret( ch, arg );
	return;
    }

    /* Search Table and Dispatch Command. */
    for ( cmd = 0; *oedit_table[cmd].name; cmd++ )
    {
	if ( !str_prefix( command, oedit_table[cmd].name ) )
	{
	    if ( (*oedit_table[cmd].olc_fun) ( ch, argument ) )
		SET_BIT( pArea->area_flags, AREA_CHANGED );
	    return;
	}
    }

    /* Take care of flags. */
    if ( ( value = flag_value( type_flags, arg ) ) != NO_FLAG )
    {
        pObj->item_type = value;

        SET_BIT( pArea->area_flags, AREA_CHANGED );
        send_to_char( "Type set.\n\r", ch);

        /*
         * Clear the values.
         */
        pObj->value[0] = 0;
        pObj->value[1] = 0;
        pObj->value[2] = 0;
        pObj->value[3] = 0;

        return;
    }

    if ( ( value = flag_value( extra_flags, arg ) ) != NO_FLAG )
    {
        TOGGLE_BIT(pObj->extra_flags, value);

        SET_BIT( pArea->area_flags, AREA_CHANGED );
        send_to_char( "Extra flag toggled.\n\r", ch);
        return;
    }

    if ( ( value = flag_value( wear_flags, arg ) ) != NO_FLAG )
    {
        TOGGLE_BIT(pObj->wear_flags, value);

        SET_BIT( pArea->area_flags, AREA_CHANGED );
        send_to_char( "Wear flag toggled.\n\r", ch);
        return;
    }

    /* Default to Standard Interpreter. */
    interpret( ch, arg );
    return;
}



/* Mobile Interpreter, called by do_medit. */
void medit( CHAR_DATA *ch, char *argument )
{
    AREA_DATA *pArea;
    MOB_INDEX_DATA *pMob;
    char command[MAX_INPUT_LENGTH];
    char arg[MAX_STRING_LENGTH];
    int  cmd;
    int  value;

    smash_tilde( argument );
    strcpy( arg, argument );
    argument = one_argument( argument, command );

    EDIT_MOB(ch, pMob);
    pArea = pMob->area;

    if ( !IS_BUILDER( ch, pArea ) ) 
	send_to_char( "MEdit: Insufficient security to modify area.\n\r", ch );

    if ( command[0] == '\0' )
    {
        medit_show( ch, argument );
        return;
    }

    if ( !str_cmp(command, "done") )
    {
	edit_done( ch );
	return;
    }

    if ( !IS_BUILDER( ch, pArea ) )
    {
	interpret( ch, arg );
	return;
    }

    /* Search Table and Dispatch Command. */
    for ( cmd = 0; *medit_table[cmd].name; cmd++ )
    {
	if ( !str_prefix( command, medit_table[cmd].name ) )
	{
	    if ( (*medit_table[cmd].olc_fun) ( ch, argument ) )
		SET_BIT( pArea->area_flags, AREA_CHANGED );
	    return;
	}
    }

    /* Take care of flags. */
    if ( ( value = flag_value( sex_flags, arg ) ) != NO_FLAG )
    {
        pMob->sex = value;

        SET_BIT( pArea->area_flags, AREA_CHANGED );
        send_to_char( "Sex set.\n\r", ch);
        return;
    }


    if ( ( value = flag_value( act_flags, arg ) ) != NO_FLAG )
    {
        TOGGLE_BIT(pMob->act, value);

        SET_BIT( pArea->area_flags, AREA_CHANGED );
        send_to_char( "Act flag toggled.\n\r", ch);
        return;
    }


    if ( ( value = flag_value( affect_flags, arg ) ) != NO_FLAG )
    {
        TOGGLE_BIT(pMob->affected_by, value);

        SET_BIT( pArea->area_flags, AREA_CHANGED );
        send_to_char( "Affect flag toggled.\n\r", ch);
        return;
    }

    /* Default to Standard Interpreter. */
    interpret( ch, arg );
    return;
}



void do_aedit( CHAR_DATA *ch, char *argument )
{
    AREA_DATA *pArea;
    char command[MAX_INPUT_LENGTH];

    argument = one_argument( argument, command );
    pArea = ch->in_room->area;

	if (!IS_BUILDER(ch, pArea)) {
	send_to_char("Huh?\n\r", ch );
	return;}

    if ( command[0] == 'r' && !str_prefix( command, "reset" ) )
    {
	if ( ch->desc->editor == ED_AREA )
	    reset_area( (AREA_DATA *)ch->desc->pEdit );
	else
	    reset_area( pArea );
	send_to_char( "Area reset.\n\r", ch );
	return;
    }

    if ( command[0] == 'c' && !str_prefix( command, "create" ) )
    {
	if ( aedit_create( ch, argument ) )
	{
	    ch->desc->editor = ED_AREA;
	    pArea = (AREA_DATA *)ch->desc->pEdit;
	    SET_BIT( pArea->area_flags, AREA_CHANGED );
	    aedit_show( ch, "" );
	}
	return;
    }

    if ( is_number( command ) )
    {
	if ( !( pArea = get_area_data( atol(command) ) ) )
	{
	    send_to_char( "No such area vnum exists.\n\r", ch );
	    return;
	}
    }

    /*
     * Builder defaults to editing current area.
     */
    ch->desc->pEdit = (void *)pArea;
    ch->desc->editor = ED_AREA;
    aedit_show( ch, "" );
    return;
}



/* Entry point for editing room_index_data. */
void do_redit( CHAR_DATA *ch, char *argument )
{
    ROOM_INDEX_DATA *pRoom;
    char command[MAX_INPUT_LENGTH];

    argument = one_argument( argument, command );
    pRoom = ch->in_room;

	if (!IS_BUILDER(ch, pRoom->area)) {
	send_to_char("Huh?\n\r", ch);
	return;}

    if ( command[0] == 'r' && !str_prefix( command, "reset" ) )
    {
	reset_room( pRoom );
	send_to_char( "Room reset.\n\r", ch );
	return;
    }

    if ( command[0] == 'c' && !str_prefix( command, "create" ) )
    {
	if ( redit_create( ch, argument ) )
	{
	    char_from_room( ch );
	    char_to_room( ch, ch->desc->pEdit );
	    SET_BIT( pRoom->area->area_flags, AREA_CHANGED );
    	}
    }

    /*
     * Builder defaults to editing current room.
     */
    ch->desc->editor = ED_ROOM;
    redit_show( ch, "" );
    return;
}



/* Entry point for editing obj_index_data. */
void do_oedit( CHAR_DATA *ch, char *argument )
{
    OBJ_INDEX_DATA *pObj;
    AREA_DATA *pArea;
    char command[MAX_INPUT_LENGTH];

    argument = one_argument( argument, command );


	if (is_number(command)) {
	pObj = get_obj_index(atol(command));
	if (!pObj) {send_to_char("Invalid vnum\n\r", ch );return;}
	if (!IS_BUILDER(ch, pObj->area)) {
	send_to_char("Huh?\n\r", ch );
	return;}
	}

	if (command[0] == 'c' && !str_prefix(command,"create")) {
	    pArea = get_vnum_area( atol( argument ) );
	if (!pArea) {
	send_to_char("No area with that vnum exists.\n\r", ch);
	return;}
	if (!IS_BUILDER(ch, pArea)) {
	send_to_char("Huh?\n\r", ch );
	return;}
	}

    if ( is_number( command ) )
    {
	if ( !pObj )
	{
	    send_to_char( "OEdit:  That vnum does not exist.\n\r", ch );
	    return;
	}

	ch->desc->pEdit = (void *)pObj;
	ch->desc->editor = ED_OBJECT;
	oedit_show( ch, "" );
	return;
    }

    if ( command[0] == 'c' && !str_prefix( command, "create" ) )
    {
        if ( oedit_create( ch, argument ) )
	{
	    SET_BIT( pArea->area_flags, AREA_CHANGED );
	    ch->desc->editor = ED_OBJECT;
	    oedit_show( ch, "" );
	}
	return;
    }

    send_to_char( "OEdit:  There is no default object to edit.\n\r", ch );
    return;
}



/* Entry point for editing mob_index_data. */
void do_medit( CHAR_DATA *ch, char *argument )
{
    MOB_INDEX_DATA *pMob;
    AREA_DATA *pArea;
    char command[MAX_INPUT_LENGTH];

    argument = one_argument( argument, command );

	if (is_number(command)) {
	pMob = get_mob_index(atol(command));
	if (!pMob) {send_to_char("Invalid vnum\n\r", ch );return;}
	if (!IS_BUILDER(ch, pMob->area)) {
	send_to_char("Huh?\n\r", ch );
	return;}
	}

	if (command[0] == 'c' && !str_prefix(command,"create")) {
	    pArea = get_vnum_area( atol( argument ) );
	if (!IS_BUILDER(ch, pArea)) {
	send_to_char("Huh?\n\r", ch );
	return;}
	}

    if ( is_number( command ) )
    {
	if ( !pMob)
	{
	    send_to_char( "MEdit:  That vnum does not exist.\n\r", ch );
	    return;
	}

	ch->desc->pEdit = (void *)pMob;
	ch->desc->editor = ED_MOBILE;
	medit_show( ch, "" );
	return;
    }

    if ( command[0] == 'c' && !str_prefix( command, "create" ) )
    {
	if ( medit_create( ch, argument ) )
	{
	    SET_BIT( pArea->area_flags, AREA_CHANGED );
	    ch->desc->editor = ED_MOBILE;
	    medit_show( ch, "" );
	}
	return;
    }

    send_to_char( "MEdit:  There is no default mobile to edit.\n\r", ch );
    return;
}



void display_resets( CHAR_DATA *ch )
{
    ROOM_INDEX_DATA	*pRoom;
    RESET_DATA		*pReset;
    MOB_INDEX_DATA	*pMob = NULL;
    char 		buf   [ MAX_STRING_LENGTH ];
    char 		final [ MAX_STRING_LENGTH ];
    int 		iReset = 0;

    EDIT_ROOM(ch, pRoom);
    final[0]  = '\0';
    
    send_to_char ( 
  " No.  Loads    Description       Location         Vnum    Max  Description"
  "\n\r"
  "==== ======== ============= =================== ======== ===== ==========="
  "\n\r", ch );

    for ( pReset = pRoom->reset_first; pReset; pReset = pReset->next )
    {
	OBJ_INDEX_DATA  *pObj;
	MOB_INDEX_DATA  *pMobIndex;
	OBJ_INDEX_DATA  *pObjIndex;
	OBJ_INDEX_DATA  *pObjToIndex;
	ROOM_INDEX_DATA *pRoomIndex;

	buf[0] = '\0';
	sprintf(buf, "[%2d] ", ++iReset );
	send_to_char(buf,ch);

	switch ( pReset->command )
	{
	default:
	    sprintf( buf, "Bad reset command: %c.", pReset->command );
		send_to_char(buf,ch);
	    break;

	case 'M':
	    if ( !( pMobIndex = get_mob_index( pReset->arg1 ) ) )
	    {
                sprintf( buf, "Load Mobile - Bad Mob %d\n\r", pReset->arg1 );
		send_to_char(buf,ch);
                continue;
	    }

	    if ( !( pRoomIndex = get_room_index( pReset->arg3 ) ) )
	    {
                sprintf( buf, "Load Mobile - Bad Room %d\n\r", pReset->arg3 );
		send_to_char(buf,ch);
                continue;
	    }

            pMob = pMobIndex;
            sprintf( buf, "M[%5d] %-13.13s in room             R[%5d] [%3d] %-15.15s\n\r",
                       pReset->arg1, pMob->short_descr, pReset->arg3,
                       pReset->arg2, pRoomIndex->name );
		send_to_char(buf,ch);

	    /*
	     * Check for pet shop.
	     * -------------------
	     *
	    {
		ROOM_INDEX_DATA *pRoomIndexPrev;

		pRoomIndexPrev = get_room_index( pRoomIndex->vnum - 1 );
		if ( pRoomIndexPrev
		    && IS_SET( pRoomIndexPrev->room_flags, ROOM_PET_SHOP ) )
                    final[5] = 'P';
	    }*/

	    break;

	case 'O':
	    if ( !( pObjIndex = get_obj_index( pReset->arg1 ) ) )
	    {
                sprintf( buf, "Load Object - Bad Object %d\n\r",
		    pReset->arg1 );
		send_to_char(buf,ch);
                continue;
	    }

            pObj       = pObjIndex;

	    if ( !( pRoomIndex = get_room_index( pReset->arg3 ) ) )
	    {
                sprintf( buf, "Load Object - Bad Room %d\n\r", pReset->arg3 );
		send_to_char(buf,ch);
                continue;
	    }

            sprintf( buf, "O[%5d] %-13.13s in room             "
                          "R[%5d]       %-15.15s\n\r",
                          pReset->arg1, pObj->short_descr,
                          pReset->arg3, pRoomIndex->name );
		send_to_char(buf,ch);

	    break;

	case 'P':
	    if ( !( pObjIndex = get_obj_index( pReset->arg1 ) ) )
	    {
                sprintf( buf, "Put Object - Bad Object %d\n\r",
                    pReset->arg1 );
		send_to_char(buf,ch);
                continue;
	    }

            pObj       = pObjIndex;

	    if ( !( pObjToIndex = get_obj_index( pReset->arg3 ) ) )
	    {
                sprintf( buf, "Put Object - Bad To Object %d\n\r",
                    pReset->arg3 );
		send_to_char(buf,ch);
                continue;
	    }

	    sprintf( buf,
		"O[%5d] %-13.13s inside              O[%5d]       %-15.15s\n\r",
		pReset->arg1,
		pObj->short_descr,
		pReset->arg3,
		pObjToIndex->short_descr );
		send_to_char(buf,ch);
	    break;

	case 'G':
	case 'E':
	    if ( !( pObjIndex = get_obj_index( pReset->arg1 ) ) )
	    {
                sprintf( buf, "Give/Equip Object - Bad Object %d\n\r",
                    pReset->arg1 );
		send_to_char(buf,ch);
                continue;
	    }

            pObj       = pObjIndex;

	    if ( !pMob )
	    {
                sprintf( buf, "Give/Equip Object - No Previous Mobile\n\r" );
		send_to_char(buf,ch);
                break;
	    }

	    if ( pMob->pShop )
	    {
	    sprintf( buf,
		"O[%5d] %-13.13s in the inventory of S[%5d]       %-15.15s\n\r",
		pReset->arg1,
		pObj->short_descr,                           
		pMob->vnum,
		pMob->short_descr  );
	    }
	    else
	    sprintf( buf,
		"O[%5d] %-13.13s %-19.19s M[%5d]       %-15.15s\n\r",
		pReset->arg1,
		pObj->short_descr,
		(pReset->command == 'G') ?
		    flag_string( wear_loc_strings, WEAR_NONE )
		  : flag_string( wear_loc_strings, pReset->arg3 ),
		  pMob->vnum,
		  pMob->short_descr );

		send_to_char(buf,ch);

	    break;

	/*
	 * Doors are set in rs_flags don't need to be displayed.
	 * If you want to display them then uncomment the new_reset
	 * line in the case 'D' in load_resets in db.c and here.
	 *
	case 'D':
	    pRoomIndex = get_room_index( pReset->arg1 );
	    sprintf( buf, "R[%5d] %s door of %-19.19s reset to %s\n\r",
		pReset->arg1,
		capitalize( dir_name[ pReset->arg2 ] ),
		pRoomIndex->name,
		flag_string( door_resets, pReset->arg3 ) );
		send_to_char(buf,ch);

	    break;
	 *
	 * End Doors Comment.
	 */
	case 'R':
	    if ( !( pRoomIndex = get_room_index( pReset->arg1 ) ) )
	    {
		sprintf( buf, "Randomize Exits - Bad Room %d\n\r",
		    pReset->arg1 );
		send_to_char(buf,ch);
		continue;
	    }

	    sprintf( buf, "R[%5d] Exits are randomized in %s\n\r",
		pReset->arg1, pRoomIndex->name );
		send_to_char(buf,ch);

	    break;
	}
    }

    return;
}



/*****************************************************************************
 Name:		add_reset
 Purpose:	Inserts a new reset in the given index slot.
 Called by:	do_resets(olc.c).
 ****************************************************************************/
void add_reset( ROOM_INDEX_DATA *room, RESET_DATA *pReset, int index )
{
    RESET_DATA *reset;
    int iReset = 0;

    if ( !room->reset_first )
    {
	room->reset_first	= pReset;
	room->reset_last	= pReset;
	pReset->next		= NULL;
	return;
    }

    index--;

    if ( index == 0 )	/* First slot (1) selected. */
    {
	pReset->next = room->reset_first;
	room->reset_first = pReset;
	return;
    }

    /*
     * If negative slot( <= 0 selected) then this will find the last.
     */
    for ( reset = room->reset_first; reset->next; reset = reset->next )
    {
	if ( ++iReset == index )
	    break;
    }

    pReset->next	= reset->next;
    reset->next		= pReset;
    if ( !pReset->next )
	room->reset_last = pReset;
    return;
}



void do_resets( CHAR_DATA *ch, char *argument )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    char arg3[MAX_INPUT_LENGTH];
    char arg4[MAX_INPUT_LENGTH];
    char arg5[MAX_INPUT_LENGTH];
    RESET_DATA *pReset = NULL;

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );
    argument = one_argument( argument, arg3 );
    argument = one_argument( argument, arg4 );
    argument = one_argument( argument, arg5 );

    /*
     * Display resets in current room.
     * -------------------------------
     */
    if ( !IS_BUILDER( ch, ch->in_room->area ) )
    {
	send_to_char("Huh?\n\r", ch);
	return;
    }

    if ( arg1[0] == '\0' )
    {
	if ( ch->in_room->reset_first )
	{
	    send_to_char(
		"Resets: M = mobile, R = room, O = object, "
		"P = pet, S = shopkeeper\n\r", ch );
	    display_resets( ch );
	}
	else
	    send_to_char( "No resets in this room.\n\r", ch );
    }


    /*
     * Take index number and search for commands.
     * ------------------------------------------
     */
    if ( is_number( arg1 ) )
    {
	ROOM_INDEX_DATA *pRoom = ch->in_room;

	/*
	 * Delete a reset.
	 * ---------------
	 */
	if ( !str_cmp( arg2, "delete" ) )
	{
	    int insert_loc = atol( arg1 );

	    if ( !ch->in_room->reset_first )
	    {
		send_to_char( "No resets in this area.\n\r", ch );
		return;
	    }

	    if ( insert_loc-1 <= 0 )
	    {
		pReset = pRoom->reset_first;
		pRoom->reset_first = pRoom->reset_first->next;
		if ( !pRoom->reset_first )
		    pRoom->reset_last = NULL;
	    }
	    else
	    {
		int iReset = 0;
		RESET_DATA *prev = NULL;

		for ( pReset = pRoom->reset_first;
		  pReset;
		  pReset = pReset->next )
		{
		    if ( ++iReset == insert_loc )
			break;
		    prev = pReset;
		}

		if ( !pReset )
		{
		    send_to_char( "Reset not found.\n\r", ch );
		    return;
		}

		if ( prev )
		    prev->next = prev->next->next;
		else
		    pRoom->reset_first = pRoom->reset_first->next;

		for ( pRoom->reset_last = pRoom->reset_first;
		  pRoom->reset_last->next;
		  pRoom->reset_last = pRoom->reset_last->next );
	    }

	    free_reset_data( pReset );
	    send_to_char( "Reset deleted.\n\r", ch );
	}
	else
	/*
	 * Add a reset.
	 * ------------
	 */
	if ( (!str_cmp( arg2, "mob" ) && is_number( arg3 ))
	  || (!str_cmp( arg2, "obj" ) && is_number( arg3 )) )
	{
	    /*
	     * Check for Mobile reset.
	     * -----------------------
	     */
	    if ( !str_cmp( arg2, "mob" ) )
	    {
		pReset = new_reset_data();
		pReset->command = 'M';
		pReset->arg1    = atol( arg3 );
		pReset->arg2    = is_number( arg4 ) ? atol( arg4 ) : 1; /* Max # */
		pReset->arg3    = ch->in_room->vnum;
	    }
	    else
	    /*
	     * Check for Object reset.
	     * -----------------------
	     */
	    if ( !str_cmp( arg2, "obj" ) )
	    {
		pReset = new_reset_data();
		pReset->arg1    = atol( arg3 );
		/*
		 * Inside another object.
		 * ----------------------
		 */
		if ( !str_prefix( arg4, "inside" ) )
		{
		    pReset->command = 'P';
		    pReset->arg2    = 0;
		    pReset->arg3    = is_number( arg5 ) ? atol( arg5 ) : 1;
		}
		else
		/*
		 * Inside the room.
		 * ----------------
		 */
		if ( !str_cmp( arg4, "room" ) )
		{
		    pReset = new_reset_data();
		    pReset->command = 'O';
		    pReset->arg2     = 0;
		    pReset->arg3     = ch->in_room->vnum;
		}
		else
		/*
		 * Into a Mobile's inventory.
		 * --------------------------
		 */
		{
		    if ( flag_value( wear_loc_flags, arg4 ) == NO_FLAG )
		    {
			send_to_char( "Resets: '? wear-loc'\n\r", ch );
			return;
		    }
		if (get_obj_index(atol(arg3)) == NULL) {
		send_to_char("That vnum does not exist.\n\r",  ch);
		return;}

		    pReset = new_reset_data();
		    pReset->arg1 = atol(arg3);
		    pReset->arg3 = flag_value( wear_loc_flags, arg4 );
		    if ( pReset->arg2 == WEAR_NONE )
			pReset->command = 'G';
		    else
			pReset->command = 'E';
		}
	    }

	    add_reset( ch->in_room, pReset, atol( arg1 ) );
	    send_to_char( "Reset added.\n\r", ch );
	}
	else
	{
	send_to_char( "Syntax: RESET <number> OBJ <vnum> <wear_loc>\n\r", ch );
	send_to_char( "        RESET <number> OBJ <vnum> in <vnum>\n\r", ch );
	send_to_char( "        RESET <number> OBJ <vnum> room\n\r", ch );
	send_to_char( "        RESET <number> MOB <vnum> [<max #>]\n\r", ch );
	send_to_char( "        RESET <number> DELETE\n\r", ch );
	}
    }

    return;
}



/*****************************************************************************
 Name:		do_alist
 Purpose:	Normal command to list areas and display area information.
 Called by:	interpreter(interp.c)
 ****************************************************************************/
void do_alist( CHAR_DATA *ch, char *argument )
{
    char buf    [ MAX_STRING_LENGTH ];
    AREA_DATA *pArea;

	if (IS_NPC(ch)) return;

	if (ch->pcdata->security < 2) {
	send_to_char("Huh?\n\r", ch);
	return;}

    sprintf( buf, "[%3s] [%-27s] (%-5s-%5s) [%-10s] %3s [%-10s]\n\r",
       "Num", "Area Name", "lvnum", "uvnum", "Filename", "Sec", "Builders" );
	send_to_char(buf,ch);
    for ( pArea = area_first; pArea; pArea = pArea->next )
    {
	sprintf( buf, "[%3d] %-29.29s (%-5d-%5d) %-12.12s [%d] [%-10.10s]\n\r",
	     pArea->vnum,
	     &pArea->name[8],
	     pArea->lvnum,
	     pArea->uvnum,
	     pArea->filename,
	     pArea->security,
	     pArea->builders );
	send_to_char(buf, ch);
    }
    return;
}


void hedit( CHAR_DATA *ch, char *argument )
{
    HELP_DATA *pHelp;
    char command[MAX_INPUT_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    int  cmd;

	if(str_cmp(argument, "change"))
		EDIT_HELP(ch, pHelp);
	smash_tilde( argument );
    strcpy( arg, argument );
    argument = one_argument( argument, command );

    if ( !str_cmp(command, "done") )
    {
	edit_done( ch );
	return;
    }

       /* Search Table and Dispatch Command. */
    for ( cmd = 0; hedit_table[cmd].name != NULL; cmd++ )
    {
	if ( !str_prefix( command, hedit_table[cmd].name ) )
	{
	    (*hedit_table[cmd].olc_fun) ( ch, argument );
	    return;
	}
    }

    /* Default to Standard Interpreter. */
    interpret( ch, arg );
    return;
}


void do_hedit(CHAR_DATA *ch, char *argument )
{
/* 	HELP_DATA *pHelp; */
char arg1[MAX_INPUT_LENGTH + 20];

    argument = one_argument( argument, arg1 );
if (ch->level < (MAX_LEVEL - 10)){
	send_to_char("huh?\n\r", ch);
return;	}
if (!str_cmp( arg1, "create"))
{
	hedit_create(ch, argument);
	ch->desc->editor = ED_HELP;
	return;
}
else if (!str_cmp( arg1, "change"))
{
	hedit_change(ch, argument);
	ch->desc->editor = ED_HELP;
	return;
}
else if(!str_cmp(arg1, "index"))
{
	hedit_index(ch, argument);
	ch->desc->editor = ED_HELP;
	return;
}
else if(!str_cmp(arg1, "delete"))
{
	hedit_delete(ch, argument);
	ch->desc->editor = ED_HELP;
	return;
}
else 
{
	send_to_char("Hedit mode entered, no default command or help to edit.\n\r", ch);
	ch->desc->editor = ED_HELP;
	return;
}
}





*****************************************
 *  File: olc_act.c                                                        *
 *                                                                         *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 *                                                                         *
 *  This code was freely distributed with the The Isles 1.1 source code,   *
 *  and has been used here for OLC - OLC would not be what it is without   *
 *  all the previous coders who released their source code.                *
 *                                                                         *
 ***************************************************************************/



#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <limits.h>	/* OLC 1.1b */
#include "merc.h"
#include "olc.h"


#define HEDIT( fun )        bool fun( CHAR_DATA *ch, char *argument )



struct olc_help_type
{
    char *command;
    const void *structure;
    char *desc;
};
HELP_DATA *new_help(void)
{   
        HELP_DATA *pHelp;
        pHelp = alloc_perm( sizeof(*pHelp));
        pHelp->level = 0;
                return pHelp;
}


bool show_version( CHAR_DATA *ch, char *argument )
{
    send_to_char( VERSION, ch );
    send_to_char( "\n\r", ch );
    send_to_char( AUTHOR, ch );
    send_to_char( "\n\r", ch );
    send_to_char( DATE, ch );
    send_to_char( "\n\r", ch );
    send_to_char( CREDITS, ch );
    send_to_char( "\n\r", ch );

    return FALSE;
}    

/*
 * This table contains help commands and a brief description of each.
 * ------------------------------------------------------------------
 */
const struct olc_help_type help_table[] =
{
    {	"area",		area_flags,	 "Area attributes."		},
    {	"room",		room_flags,	 "Room attributes."		},
    {	"sector",	sector_flags,	 "Sector types, terrain."	},
    {	"exit",		exit_flags,	 "Exit types."			},
    {	"type",		type_flags,	 "Types of objects."		},
    {	"extra",	extra_flags,	 "Object attributes."		},
    {	"wear",		wear_flags,	 "Where to wear object."	},
    {	"spec",		spec_table,	 "Available special programs." 	},
    {	"sex",		sex_flags,	 "Sexes."			},
    {	"act",		act_flags,	 "Mobile attributes."		},
    {	"affect",	affect_flags,	 "Mobile affects."		},
    {	"wear-loc",	wear_loc_flags,	 "Where mobile wears object."	},
    {	"spells",	skill_table,	 "Names of current spells." 	},
    {	"weapon",	weapon_flags,	 "Type of weapon." 		},
    {	"container",	container_flags, "Container status."		},
    {	"liquid",	liquid_flags,	 "Types of liquids."		},
    {	"",		0,		 ""				}
};



/*****************************************************************************
 Name:		show_flag_cmds
 Purpose:	Displays settable flags and stats.
 Called by:	show_help(olc_act.c).
 ****************************************************************************/
void show_flag_cmds( CHAR_DATA *ch, const struct flag_type *flag_table )
{
    char buf  [ MAX_STRING_LENGTH ];
    char buf1 [ MAX_STRING_LENGTH ];
    int  flag;
    int  col;
 
    buf1[0] = '\0';
    col = 0;
    for (flag = 0; *flag_table[flag].name; flag++)
    {
	if ( flag_table[flag].settable )
	{
	    sprintf( buf, "%-19.18s", flag_table[flag].name );
	    strcat( buf1, buf );
	    if ( ++col % 4 == 0 )
		strcat( buf1, "\n\r" );
	}
    }
 
    if ( col % 4 != 0 )
	strcat( buf1, "\n\r" );

    send_to_char( buf1, ch );
    return;
}



/*****************************************************************************
 Name:		show_skill_cmds
 Purpose:	Displays all skill functions.
 		Does remove those damn immortal commands from the list.
 		Could be improved by:
 		(1) Adding a check for a particular class.
 		(2) Adding a check for a level range.
 Called by:	show_help(olc_act.c).
 ****************************************************************************/
void show_skill_cmds( CHAR_DATA *ch, int tar )
{
    char buf  [ MAX_STRING_LENGTH ];
    char buf1 [ MAX_STRING_LENGTH*2 ];
    int  sn;
    int  col;
 
    buf1[0] = '\0';
    col = 0;
    for (sn = 0; sn < MAX_SKILL; sn++)
    {
	if ( !skill_table[sn].name )
	    break;

	if ( !str_cmp( skill_table[sn].name, "reserved" )
	  || skill_table[sn].spell_fun == spell_null )
	    continue;

	if ( tar == -1 || skill_table[sn].target == tar )
	{
	    sprintf( buf, "%-19.18s", skill_table[sn].name );
	    strcat( buf1, buf );
	    if ( ++col % 4 == 0 )
		strcat( buf1, "\n\r" );
	}
    }
 
    if ( col % 4 != 0 )
	strcat( buf1, "\n\r" );

    send_to_char( buf1, ch );
    return;
}



/*****************************************************************************
 Name:		show_spec_cmds
 Purpose:	Displays settable special functions.
 Called by:	show_help(olc_act.c).
 ****************************************************************************/
void show_spec_cmds( CHAR_DATA *ch )
{
    char buf  [ MAX_STRING_LENGTH ];
    char buf1 [ MAX_STRING_LENGTH ];
    int  spec;
    int  col;
 
    buf1[0] = '\0';
    col = 0;
    send_to_char( "Preceed special functions with 'spec_'\n\r\n\r", ch );
    for (spec = 0; *spec_table[spec].spec_fun; spec++)
    {
	sprintf( buf, "%-19.18s", &spec_table[spec].spec_name[5] );
	strcat( buf1, buf );
	if ( ++col % 4 == 0 )
	    strcat( buf1, "\n\r" );
    }
 
    if ( col % 4 != 0 )
	strcat( buf1, "\n\r" );

    send_to_char( buf1, ch );
    return;
}



/*****************************************************************************
 Name:		show_help
 Purpose:	Displays help for many tables used in OLC.
 Called by:	olc interpreters.
 ****************************************************************************/
bool show_help( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    char spell[MAX_INPUT_LENGTH];
    int cnt;

    argument = one_argument( argument, arg );
    one_argument( argument, spell );

    /*
     * Display syntax.
     */
    if ( arg[0] == '\0' )
    {
	send_to_char( "Syntax:  ? [command]\n\r\n\r", ch );
	send_to_char( "[command]  [description]\n\r", ch );
	for (cnt = 0; help_table[cnt].command[0] != '\0'; cnt++)
	{
	    sprintf( buf, "%-10.10s -%s\n\r",
	        capitalize( help_table[cnt].command ),
		help_table[cnt].desc );
	    send_to_char( buf, ch );
	}
	return FALSE;
    }

    /*
     * Find the command, show changeable data.
     * ---------------------------------------
     */
    for (cnt = 0; *help_table[cnt].command; cnt++)
    {
        if (  arg[0] == help_table[cnt].command[0]
          && !str_prefix( arg, help_table[cnt].command ) )
	{
	    if ( help_table[cnt].structure == spec_table )
	    {
		show_spec_cmds( ch );
		return FALSE;
	    }
	    else
	    if ( help_table[cnt].structure == skill_table )
	    {

		if ( spell[0] == '\0' )
		{
		    send_to_char( "Syntax:  ? spells "
		        "[ignore/attack/defend/self/object/all]\n\r", ch );
		    return FALSE;
		}

		if ( !str_prefix( spell, "all" ) )
		    show_skill_cmds( ch, -1 );
		else if ( !str_prefix( spell, "ignore" ) )
		    show_skill_cmds( ch, TAR_IGNORE );
		else if ( !str_prefix( spell, "attack" ) )
		    show_skill_cmds( ch, TAR_CHAR_OFFENSIVE );
		else if ( !str_prefix( spell, "defend" ) )
		    show_skill_cmds( ch, TAR_CHAR_DEFENSIVE );
		else if ( !str_prefix( spell, "self" ) )
		    show_skill_cmds( ch, TAR_CHAR_SELF );
		else if ( !str_prefix( spell, "object" ) )
		    show_skill_cmds( ch, TAR_OBJ_INV );
		else
		    send_to_char( "Syntax:  ? spell "
		        "[ignore/attack/defend/self/object/all]\n\r", ch );
		    
		return FALSE;
	    }
	    else
	    {
		show_flag_cmds( ch, help_table[cnt].structure );
		return FALSE;
	    }
	}
    }

    show_help( ch, "" );
    return FALSE;
}



bool redit_mlist( CHAR_DATA *ch, char *argument )
{
    MOB_INDEX_DATA	*pMobIndex;
    AREA_DATA		*pArea;
    char		buf  [ MAX_STRING_LENGTH   ];
    char		buf1 [ MAX_STRING_LENGTH*2 ];
    char		arg  [ MAX_INPUT_LENGTH    ];
    bool fAll, found;
    int vnum;
    int  col = 0;

    one_argument( argument, arg );
    if ( arg[0] == '\0' )
    {
	send_to_char( "Syntax:  mlist <all/name>\n\r", ch );
	return FALSE;
    }

    pArea = ch->in_room->area;
    buf1[0] = '\0';
    fAll    = !str_cmp( arg, "all" );
    found   = FALSE;

    for ( vnum = pArea->lvnum; vnum <= pArea->uvnum; vnum++ )
    {
	if ( ( pMobIndex = get_mob_index( vnum ) ) )
	{
	    if ( fAll || is_name( arg, pMobIndex->player_name ) )
	    {
		found = TRUE;
		sprintf( buf, "[%5d] %-17.16s",
		    pMobIndex->vnum, capitalize( pMobIndex->short_descr ) );
		strcat( buf1, buf );
		if ( ++col % 3 == 0 )
		    strcat( buf1, "\n\r" );
	    }
	}
    }

    if ( !found )
    {
	send_to_char( "Mobile(s) not found in this area.\n\r", ch);
	return FALSE;
    }

    if ( col % 3 != 0 )
	strcat( buf1, "\n\r" );

    send_to_char( buf1, ch );
    return FALSE;
}



bool redit_olist( CHAR_DATA *ch, char *argument )
{
    OBJ_INDEX_DATA	*pObjIndex;
    AREA_DATA		*pArea;
    char		buf  [ MAX_STRING_LENGTH   ];
    char		buf1 [ MAX_STRING_LENGTH*2 ];
    char		arg  [ MAX_INPUT_LENGTH    ];
    bool fAll, found;
    int vnum;
    int  col = 0;

    one_argument( argument, arg );
    if ( arg[0] == '\0' )
    {
	send_to_char( "Syntax:  olist <all/name/item_type>\n\r", ch );
	return FALSE;
    }

    pArea = ch->in_room->area;
    buf1[0] = '\0';
    fAll    = !str_cmp( arg, "all" );
    found   = FALSE;

    for ( vnum = pArea->lvnum; vnum <= pArea->uvnum; vnum++ )
    {
	if ( ( pObjIndex = get_obj_index( vnum ) ) )
	{
	    if ( fAll || is_name( arg, pObjIndex->name )
	    || flag_value( type_flags, arg ) == pObjIndex->item_type )
	    {
		found = TRUE;
		sprintf( buf, "[%5d] %-17.16s",
		    pObjIndex->vnum, capitalize( pObjIndex->short_descr ) );
		strcat( buf1, buf );
		if ( ++col % 3 == 0 )
		    strcat( buf1, "\n\r" );
	    }
	}
    }

    if ( !found )
    {
	send_to_char( "Object(s) not found in this area.\n\r", ch);
	return FALSE;
    }

    if ( col % 3 != 0 )
	strcat( buf1, "\n\r" );

    send_to_char( buf1, ch );
    return FALSE;
}



bool redit_mshow( CHAR_DATA *ch, char *argument )
{
    MOB_INDEX_DATA *pMob;
    int value;

    if ( argument[0] == '\0' )
    {
	send_to_char( "Syntax:  mshow <vnum>\n\r", ch );
	return FALSE;
    }

    if ( is_number( argument ) )
    {
	value = atoi( argument );
	if ( !( pMob = get_mob_index( value ) ))
	{
	    send_to_char( "REdit:  That mobile does not exist.\n\r", ch );
	    return FALSE;
	}

	ch->desc->pEdit = (void *)pMob;
    }
 
    medit_show( ch, argument );
    ch->desc->pEdit = (void *)ch->in_room;
    return FALSE; 
}



bool redit_oshow( CHAR_DATA *ch, char *argument )
{
    OBJ_INDEX_DATA *pObj;
    int value;

    if ( argument[0] == '\0' )
    {
	send_to_char( "Syntax:  oshow <vnum>\n\r", ch );
	return FALSE;
    }

    if ( is_number( argument ) )
    {
	value = atoi( argument );
	if ( !( pObj = get_obj_index( value ) ))
	{
	    send_to_char( "REdit:  That object does not exist.\n\r", ch );
	    return FALSE;
	}

	ch->desc->pEdit = (void *)pObj;
    }
 
    oedit_show( ch, argument );
    ch->desc->pEdit = (void *)ch->in_room;
    return FALSE; 
}



/*****************************************************************************
 Name:		check_range( lower vnum, upper vnum )
 Purpose:	Ensures the range spans only one area.
 Called by:	aedit_vnum(olc_act.c).
 ****************************************************************************/
bool check_range( int lower, int upper )
{
    AREA_DATA *pArea;
    int cnt = 0;

    for ( pArea = area_first; pArea; pArea = pArea->next )
    {
	/*
	 * lower < area < upper
	 */
	if ( ( lower <= pArea->lvnum && upper >= pArea->lvnum )
	||   ( upper >= pArea->uvnum && lower <= pArea->uvnum ) )
	    cnt++;

	if ( cnt > 1 )
	    return FALSE;
    }
    return TRUE;
}



AREA_DATA *get_vnum_area( int vnum )
{
    AREA_DATA *pArea;

    for ( pArea = area_first; pArea; pArea = pArea->next )
    {
        if ( vnum >= pArea->lvnum
          && vnum <= pArea->uvnum )
            return pArea;
    }

    return 0;
}



/*
 * Area Editor Functions.
 */
bool aedit_show( CHAR_DATA *ch, char *argument )
{
    AREA_DATA *pArea;
    char buf  [MAX_STRING_LENGTH];

    EDIT_AREA(ch, pArea);

    sprintf( buf, "Name:     [%5d] %s\n\r", pArea->vnum, pArea->name );
    send_to_char( buf, ch );

    sprintf( buf, "Recall:   [%5d] %s\n\r", pArea->recall,
	get_room_index( pArea->recall )
	? get_room_index( pArea->recall )->name : "none" );
    send_to_char( buf, ch );

    sprintf( buf, "File:     %s\n\r", pArea->filename );
    send_to_char( buf, ch );

    sprintf( buf, "Vnums:    [%d-%d]\n\r", pArea->lvnum, pArea->uvnum );
    send_to_char( buf, ch );

    sprintf( buf, "Age:      [%d]\n\r",	pArea->age );
    send_to_char( buf, ch );

    sprintf( buf, "Players:  [%d]\n\r", pArea->nplayer );
    send_to_char( buf, ch );

    sprintf( buf, "Security: [%d]\n\r", pArea->security );
    send_to_char( buf, ch );

    sprintf( buf, "Builders: [%s]\n\r", pArea->builders );
    send_to_char( buf, ch );

    sprintf( buf, "Flags:    [%s]\n\r", flag_string( area_flags, pArea->area_flags ) );
    send_to_char( buf, ch );

    return FALSE;
}



bool aedit_reset( CHAR_DATA *ch, char *argument )
{
    AREA_DATA *pArea;

    EDIT_AREA(ch, pArea);

    reset_area( pArea );
    send_to_char( "Area reset.\n\r", ch );

    return FALSE;
}



bool aedit_create( CHAR_DATA *ch, char *argument )
{
    AREA_DATA *pArea;

    if ( top_area >= INT_MAX )	/* OLC 1.1b */
    {
	send_to_char( "We're out of vnums for new areas.\n\r", ch );
	return FALSE;
    }

    pArea               =   new_area();
    area_last->next     =   pArea;
    area_last		=   pArea;	/* Thanks, Walker. */
    ch->desc->pEdit     =   (void *)pArea;

    SET_BIT( pArea->area_flags, AREA_ADDED );
    send_to_char( "Area Created.\n\r", ch );
    return TRUE;	/* OLC 1.1b */
}



bool aedit_name( CHAR_DATA *ch, char *argument )
{
    AREA_DATA *pArea;

    EDIT_AREA(ch, pArea);

    if ( argument[0] == '\0' )
    {
	send_to_char( "Syntax:   name [$name]\n\r", ch );
	return FALSE;
    }

    free_string( pArea->name );
    pArea->name = str_dup( argument );

    send_to_char( "Name set.\n\r", ch );
    return TRUE;
}



bool aedit_file( CHAR_DATA *ch, char *argument )
{
    AREA_DATA *pArea;
    char file[MAX_STRING_LENGTH];
    int i, length;

    EDIT_AREA(ch, pArea);

    one_argument( argument, file );	/* Forces Lowercase */

    if ( argument[0] == '\0' )
    {
	send_to_char( "Syntax:  filename [$file]\n\r", ch );
	return FALSE;
    }

    /*
     * Simple Syntax Check.
     */
    length = strlen( argument );
    if ( length > 8 )
    {
	send_to_char( "No more than eight characters allowed.\n\r", ch );
	return FALSE;
    }

    /*
     * Allow only letters and numbers.
     */
    for ( i = 0; i < length; i++ )
    {
	if ( !isalnum( file[i] ) )
	{
	    send_to_char( "Only letters and numbers are valid.\n\r", ch );
	    return FALSE;
	}
    }    

    free_string( pArea->filename );
    strcat( file, ".are" );
    pArea->filename = str_dup( file );

    send_to_char( "Filename set.\n\r", ch );
    return TRUE;
}



bool aedit_age( CHAR_DATA *ch, char *argument )
{
    AREA_DATA *pArea;
    char age[MAX_STRING_LENGTH];

    EDIT_AREA(ch, pArea);

    one_argument( argument, age );

    if ( !is_number( age ) || age[0] == '\0' )
    {
	send_to_char( "Syntax:  age [#age]\n\r", ch );
	return FALSE;
    }

    pArea->age = atoi( age );

    send_to_char( "Age set.\n\r", ch );
    return TRUE;
}



bool aedit_recall( CHAR_DATA *ch, char *argument )
{
    AREA_DATA *pArea;
    char room[MAX_STRING_LENGTH];
    int  value;

    EDIT_AREA(ch, pArea);

    one_argument( argument, room );

    if ( !is_number( argument ) || argument[0] == '\0' )
    {
	send_to_char( "Syntax:  recall [#rvnum]\n\r", ch );
	return FALSE;
    }

    value = atoi( room );

    if ( !get_room_index( value ) )
    {
	send_to_char( "AEdit:  Room vnum does not exist.\n\r", ch );
	return FALSE;
    }

    pArea->recall = value;

    send_to_char( "Recall set.\n\r", ch );
    return TRUE;
}



bool aedit_security( CHAR_DATA *ch, char *argument )
{
    AREA_DATA *pArea;
    char sec[MAX_STRING_LENGTH];
    char buf[MAX_STRING_LENGTH];
    int  value;

    EDIT_AREA(ch, pArea);

    one_argument( argument, sec );

    if ( !is_number( sec ) || sec[0] == '\0' )
    {
	send_to_char( "Syntax:  security [#level]\n\r", ch );
	return FALSE;
    }

    value = atoi( sec );

    if ( value > ch->pcdata->security || value < 0 )
    {
	if ( ch->pcdata->security != 0 )
	{
	    sprintf( buf, "Security is 0-%d.\n\r", ch->pcdata->security );
	    send_to_char( buf, ch );
	}
	else
	    send_to_char( "Security is 0 only.\n\r", ch );
	return FALSE;
    }

    pArea->security = value;

    send_to_char( "Security set.\n\r", ch );
    return TRUE;
}



bool aedit_builder( CHAR_DATA *ch, char *argument )
{
    AREA_DATA *pArea;
    char name[MAX_STRING_LENGTH];
    char buf[MAX_STRING_LENGTH];

    EDIT_AREA(ch, pArea);

    one_argument( argument, name );

    if ( name[0] == '\0' )
    {
	send_to_char( "Syntax:  builder [$name]  -toggles builder\n\r", ch );
	send_to_char( "Syntax:  builder All      -allows everyone\n\r", ch );
	return FALSE;
    }

    name[0] = UPPER( name[0] );

    if ( strstr( pArea->builders, name ) != '\0' )
    {
	pArea->builders = string_replace( pArea->builders, name, "\0" );
	pArea->builders = string_unpad( pArea->builders );

	if ( pArea->builders[0] == '\0' )
	{
	    free_string( pArea->builders );
	    pArea->builders = str_dup( "None" );
	}
	send_to_char( "Builder removed.\n\r", ch );
	return TRUE;
    }
    else
    {
	buf[0] = '\0';
	if ( strstr( pArea->builders, "None" ) != '\0' )
	{
	    pArea->builders = string_replace( pArea->builders, "None", "\0" );
	    pArea->builders = string_unpad( pArea->builders );
	}

	if (pArea->builders[0] != '\0' )
	{
	    strcat( buf, pArea->builders );
	    strcat( buf, " " );
	}
	strcat( buf, name );
	free_string( pArea->builders );
	pArea->builders = string_proper( str_dup( buf ) );

	send_to_char( "Builder added.\n\r", ch );
	return TRUE;
    }

    return FALSE;
}



bool aedit_vnum( CHAR_DATA *ch, char *argument )
{
    AREA_DATA *pArea;
    char lower[MAX_STRING_LENGTH];
    char upper[MAX_STRING_LENGTH];
    int  ilower;
    int  iupper;

    EDIT_AREA(ch, pArea);

    argument = one_argument( argument, lower );
    one_argument( argument, upper );

    if ( !is_number( lower ) || lower[0] == '\0'
    || !is_number( upper ) || upper[0] == '\0' )
    {
	send_to_char( "Syntax:  vnum [#lower] [#upper]\n\r", ch );
	return FALSE;
    }

    if ( ( ilower = atoi( lower ) ) > ( iupper = atoi( upper ) ) )
    {
	send_to_char( "AEdit:  Upper must be larger then lower.\n\r", ch );
	return FALSE;
    }
    
    /* OLC 1.1b */
    if ( ilower <= 0 || ilower >= INT_MAX || iupper <= 0 || iupper >= INT_MAX )
    {
	char output[MAX_STRING_LENGTH];

	sprintf( output, "AEdit: vnum must be between 0 and %d.\n\r", INT_MAX );
	send_to_char( output, ch );
	return FALSE;
    }

    if ( !check_range( ilower, iupper ) )
    {
	send_to_char( "AEdit:  Range must include only this area.\n\r", ch );
	return FALSE;
    }

    if ( get_vnum_area( ilower )
    && get_vnum_area( ilower ) != pArea )
    {
	send_to_char( "AEdit:  Lower vnum already assigned.\n\r", ch );
	return FALSE;
    }

    pArea->lvnum = ilower;
    send_to_char( "Lower vnum set.\n\r", ch );

    if ( get_vnum_area( iupper )
    && get_vnum_area( iupper ) != pArea )
    {
	send_to_char( "AEdit:  Upper vnum already assigned.\n\r", ch );
	return TRUE;	/* The lower value has been set. */
    }

    pArea->uvnum = iupper;
    send_to_char( "Upper vnum set.\n\r", ch );

    return TRUE;
}



bool aedit_lvnum( CHAR_DATA *ch, char *argument )
{
    AREA_DATA *pArea;
    char lower[MAX_STRING_LENGTH];
    int  ilower;
    int  iupper;

    EDIT_AREA(ch, pArea);

    one_argument( argument, lower );

    if ( !is_number( lower ) || lower[0] == '\0' )
    {
	send_to_char( "Syntax:  lvnum [#lower]\n\r", ch );
	return FALSE;
    }

    if ( ( ilower = atoi( lower ) ) > ( iupper = pArea->uvnum ) )
    {
	send_to_char( "AEdit:  Value must be less than the uvnum.\n\r", ch );
	return FALSE;
    }
    
    /* OLC 1.1b */
    if ( ilower <= 0 || ilower >= INT_MAX || iupper <= 0 || iupper >= INT_MAX )
    {
	char output[MAX_STRING_LENGTH];

	sprintf( output, "AEdit: vnum must be between 0 and %d.\n\r", INT_MAX );
	send_to_char( output, ch );
	return FALSE;
    }

    if ( !check_range( ilower, iupper ) )
    {
	send_to_char( "AEdit:  Range must include only this area.\n\r", ch );
	return FALSE;
    }

    if ( get_vnum_area( ilower )
    && get_vnum_area( ilower ) != pArea )
    {
	send_to_char( "AEdit:  Lower vnum already assigned.\n\r", ch );
	return FALSE;
    }

    pArea->lvnum = ilower;
    send_to_char( "Lower vnum set.\n\r", ch );
    return TRUE;
}



bool aedit_uvnum( CHAR_DATA *ch, char *argument )
{
    AREA_DATA *pArea;
    char upper[MAX_STRING_LENGTH];
    int  ilower;
    int  iupper;

    EDIT_AREA(ch, pArea);

    one_argument( argument, upper );

    if ( !is_number( upper ) || upper[0] == '\0' )
    {
	send_to_char( "Syntax:  uvnum [#upper]\n\r", ch );
	return FALSE;
    }

    if ( ( ilower = pArea->lvnum ) > ( iupper = atoi( upper ) ) )
    {
	send_to_char( "AEdit:  Upper must be larger then lower.\n\r", ch );
	return FALSE;
    }
    
    /* OLC 1.1b */
    if ( ilower <= 0 || ilower >= INT_MAX || iupper <= 0 || iupper >= INT_MAX )
    {
	char output[MAX_STRING_LENGTH];

	sprintf( output, "AEdit: vnum must be between 0 and %d.\n\r", INT_MAX );
	send_to_char( output, ch );
	return FALSE;
    }

    if ( !check_range( ilower, iupper ) )
    {
	send_to_char( "AEdit:  Range must include only this area.\n\r", ch );
	return FALSE;
    }

    if ( get_vnum_area( iupper )
    && get_vnum_area( iupper ) != pArea )
    {
	send_to_char( "AEdit:  Upper vnum already assigned.\n\r", ch );
	return FALSE;
    }

    pArea->uvnum = iupper;
    send_to_char( "Upper vnum set.\n\r", ch );

    return TRUE;
}



/*
 * Room Editor Functions.
 */
bool redit_show( CHAR_DATA *ch, char *argument )
{
    ROOM_INDEX_DATA	*pRoom;
    char		buf  [MAX_STRING_LENGTH];
    char		buf1 [2*MAX_STRING_LENGTH];
    OBJ_DATA		*obj;
    CHAR_DATA		*rch;
    int			door;
    bool		fcnt;
    
    EDIT_ROOM(ch, pRoom);

    buf1[0] = '\0';
    
    sprintf( buf, "Description:\n\r%s", pRoom->description );
    strcat( buf1, buf );

    sprintf( buf, "Name:       [%s]\n\rArea:       [%5d] %s\n\r",
	    pRoom->name, pRoom->area->vnum, pRoom->area->name );
    strcat( buf1, buf );

    sprintf( buf, "Vnum:       [%5d]\n\rSector:     [%s]\n\r",
	    pRoom->vnum, flag_string( sector_flags, pRoom->sector_type ) );
    strcat( buf1, buf );

    sprintf( buf, "Room flags: [%s]\n\r",
	    flag_string( room_flags, pRoom->room_flags ) );
    strcat( buf1, buf );

    if ( pRoom->extra_descr )
    {
	EXTRA_DESCR_DATA *ed;

	strcat( buf1, "Desc Kwds:  [" );
	for ( ed = pRoom->extra_descr; ed; ed = ed->next )
	{
	    strcat( buf1, ed->keyword );
	    if ( ed->next )
		strcat( buf1, " " );
	}
	strcat( buf1, "]\n\r" );
    }

    strcat( buf1, "Characters: [" );
    fcnt = FALSE;
    for ( rch = pRoom->people; rch; rch = rch->next_in_room )
    {
	one_argument( rch->name, buf );
	strcat( buf1, buf );
	strcat( buf1, " " );
	fcnt = TRUE;
    }

    if ( fcnt )
    {
	int end;

	end = strlen(buf1) - 1;
	buf1[end] = ']';
	strcat( buf1, "\n\r" );
    }
    else
	strcat( buf1, "none]\n\r" );

    strcat( buf1, "Objects:    [" );
    fcnt = FALSE;
    for ( obj = pRoom->contents; obj; obj = obj->next_content )
    {
	one_argument( obj->name, buf );
	strcat( buf1, buf );
	strcat( buf1, " " );
	fcnt = TRUE;
    }

    if ( fcnt )
    {
	int end;

	end = strlen(buf1) - 1;
	buf1[end] = ']';
	strcat( buf1, "\n\r" );
    }
    else
	strcat( buf1, "none]\n\r" );

    for ( door = 0; door < MAX_DIR; door++ )
    {
	EXIT_DATA *pexit;

	if ( ( pexit = pRoom->exit[door] ) )
	{
	    char word[MAX_INPUT_LENGTH];
	    char reset_state[MAX_STRING_LENGTH];
	    char *state;
	    int i, length;

	    sprintf( buf, "-%-5s to [%5d] Key: [%5d]",
		capitalize(dir_name[door]),
		pexit->to_room ? pexit->to_room->vnum : 0,
		pexit->key );
	    strcat( buf1, buf );

	    /*
	     * Format up the exit info.
	     * Capitalize all flags that are not part of the reset info.
	     */
	    strcpy( reset_state, flag_string( exit_flags, pexit->rs_flags ) );
	    state = flag_string( exit_flags, pexit->exit_info );
	    strcat( buf1, " Exit flags: [" );
	    for (; ;)
	    {
		state = one_argument( state, word );

		if ( word[0] == '\0' )
		{
		    int end;

		    end = strlen(buf1) - 1;
		    buf1[end] = ']';
		    strcat( buf1, "\n\r" );
		    break;
		}

		if ( str_infix( word, reset_state ) )
		{
		    length = strlen(word);
		    for (i = 0; i < length; i++)
			word[i] = toupper(word[i]);
		}
		strcat( buf1, word );
		strcat( buf1, " " );
	    }

	    if ( pexit->keyword && pexit->keyword[0] != '\0' )
	    {
		sprintf( buf, "Kwds: [%s]\n\r", pexit->keyword );
		strcat( buf1, buf );
	    }
	    if ( pexit->description && pexit->description[0] != '\0' )
	    {
		sprintf( buf, "%s", pexit->description );
		strcat( buf1, buf );
	    }
	}
    }

    send_to_char( buf1, ch );
    return FALSE;
}


/* OLC 1.1b */
/*****************************************************************************
 Name:		change_exit
 Purpose:	Command interpreter for changing exits.
 Called by:	redit_<dir>.  This is a local function.
 ****************************************************************************/
bool change_exit( CHAR_DATA *ch, char *argument, int door )
{
    ROOM_INDEX_DATA *pRoom;
    char command[MAX_INPUT_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    char total_arg[MAX_STRING_LENGTH];
    int  rev;
    int  value;

    EDIT_ROOM(ch, pRoom);

    /* Often used data. */
    rev = rev_dir[door];
    
    if ( argument[0] == '\0' )
    {
	do_help( ch, "EXIT" );
	return FALSE;
    }

    /*
     * Now parse the arguments.
     */
    strcpy( total_arg, argument );
    argument = one_argument( argument, command );
    one_argument( argument, arg );

    if ( !str_cmp( command, "delete" ) )
    {	
	if ( !pRoom->exit[door] )
	{
	    send_to_char( "REdit:  Exit does not exist.\n\r", ch );
	    return FALSE;
	}

	/*
	 * Remove To Room Exit.
	 */
	if ( pRoom->exit[door]->to_room->exit[rev] )
	{
	    free_exit( pRoom->exit[door]->to_room->exit[rev] );
	    pRoom->exit[door]->to_room->exit[rev] = NULL;
	}

	/*
	 * Remove this exit.
	 */
	free_exit( pRoom->exit[door] );
	pRoom->exit[door] = NULL;

	send_to_char( "Exit unlinked.\n\r", ch );
	return TRUE;
    }

    /*
     * Create a two-way exit.
     */
    if ( !str_cmp( command, "link" ) )
    {
	EXIT_DATA	*pExit;
	ROOM_INDEX_DATA	*pLinkRoom;

	if ( arg[0] == '\0' || !is_number( arg ) )
	{
	    send_to_char( "Syntax:  [direction] link [vnum]\n\r", ch );
	    return FALSE;
	}

	if ( !( pLinkRoom = get_room_index( atoi(arg) ) ) )
	{
	    send_to_char( "REdit:  Non-existant room.\n\r", ch );
	    return FALSE;
	}

	if ( !IS_BUILDER( ch, pLinkRoom->area ) )
	{
	    send_to_char( "REdit:  Cannot link to that area.\n\r", ch );
	    return FALSE;
	}

	if ( pLinkRoom->exit[rev] )
	{
	    send_to_char( "REdit:  Remote side's exit exists.\n\r", ch );
	    return FALSE;
	}

	if ( !pRoom->exit[door] )		/* No exit.		*/
	    pRoom->exit[door] = new_exit();

	pRoom->exit[door]->to_room = pLinkRoom;	/* Assign data.		*/
	pRoom->exit[door]->vnum = value;

	pExit			= new_exit();	/* No remote exit.	*/

	pExit->to_room		= ch->in_room;	/* Assign data.		*/
	pExit->vnum		= ch->in_room->vnum;

	pLinkRoom->exit[rev]	= pExit;	/* Link exit to room.	*/

	send_to_char( "Two-way link established.\n\r", ch );
	return TRUE;
    }

    /*
     * Create room and make two-way exit.
     */
    if ( !str_cmp( command, "dig" ) )
    {
	char buf[MAX_INPUT_LENGTH];
	char buf2[MAX_INPUT_LENGTH];	
	if ( arg[0] == '\0' || !is_number( arg ) )
	{
	    send_to_char( "Syntax: [direction] dig <vnum>\n\r", ch );
	    return FALSE;
	}
	
	redit_create( ch, arg );		/* Create the room.	*/
	sprintf( buf, "link %s", arg );
	sprintf( buf2, "changed");
	do_asave(ch,buf2);
	change_exit( ch, buf, door);		/* Create the exits.	*/
	return TRUE;
    }

    /*
     * Create one-way exit.
     */
    if ( !str_cmp( command, "room" ) )
    {
	ROOM_INDEX_DATA *pLinkRoom;

	if ( arg[0] == '\0' || !is_number( arg ) )
	{
	    send_to_char( "Syntax:  [direction] room [vnum]\n\r", ch );
	    return FALSE;
	}

	if ( !( pLinkRoom = get_room_index( atoi( arg ) ) ) )
	{
	    send_to_char( "REdit:  Non-existant room.\n\r", ch );
	    return FALSE;
	}

	if ( !pRoom->exit[door] )
	    pRoom->exit[door] = new_exit();

	pRoom->exit[door]->to_room = pLinkRoom;
	pRoom->exit[door]->vnum = value;

	send_to_char( "One-way link established.\n\r", ch );
	return TRUE;
    }

    if ( !str_cmp( command, "remove" ) )
    {
	if ( arg[0] == '\0' )
	{
	    send_to_char( "Syntax:  [direction] remove [key/name/desc]\n\r", ch );
	    return FALSE;
	}

	if ( !pRoom->exit[door] )
	{
	    send_to_char( "REdit:  Exit does not exist.\n\r", ch );
	    return FALSE;
	}

	if ( !str_cmp( argument, "key" ) )
	{
	    pRoom->exit[door]->key = 0;
            send_to_char( "Exit key removed.\n\r", ch );                        
            return TRUE;
	}

	if ( !str_cmp( argument, "name" ) )
	{
	    free_string( pRoom->exit[door]->keyword );
	    pRoom->exit[door]->keyword = &str_empty[0];
            send_to_char( "Exit name removed.\n\r", ch );                        
            return TRUE;
	}

	if ( argument[0] == 'd' && !str_prefix( argument, "description" ) )
	{
	    free_string( pRoom->exit[door]->description );
	    pRoom->exit[door]->description = &str_empty[0];
            send_to_char( "Exit description removed.\n\r", ch );                        
            return TRUE;
	}

	send_to_char( "Syntax:  [direction] remove [key/name/desc]\n\r", ch );
	return FALSE;
    }

    if ( !str_cmp( command, "key" ) )
    {
	OBJ_INDEX_DATA *pObjIndex;

	if ( arg[0] == '\0' || !is_number( arg ) )
	{
	    send_to_char( "Syntax:  [direction] key [vnum]\n\r", ch );
	    return FALSE;
	}

	if ( !( pObjIndex = get_obj_index( atoi( arg ) ) ) )
	{
	    send_to_char( "REdit:  Item does not exist.\n\r", ch );
	    return FALSE;
	}

	if ( pObjIndex->item_type != ITEM_KEY )
	{
	    send_to_char( "REdit:  Item is not a key.\n\r", ch );
	    return FALSE;
	}

	if ( !pRoom->exit[door] )
	    pRoom->exit[door] = new_exit();

	pRoom->exit[door]->key = pObjIndex->vnum;

	send_to_char( "Exit key set.\n\r", ch );
	return TRUE;
    }

    if ( !str_cmp( command, "name" ) )
    {
	if ( arg[0] == '\0' )
	{
	    send_to_char( "Syntax:  [direction] name [string]\n\r", ch );
	    return FALSE;
	}

	if ( !pRoom->exit[door] )
	    pRoom->exit[door] = new_exit();

	free_string( pRoom->exit[door]->keyword );
	pRoom->exit[door]->keyword = str_dup( argument );

	send_to_char( "Exit name set.\n\r", ch );
	return TRUE;
    }

    if ( command[0] == 'd' && !str_prefix( command, "description" ) )
    {
	if ( arg[0] == '\0' )
	{
	    if ( !pRoom->exit[door] )
	        pRoom->exit[door] = new_exit();

	    string_append( ch, &pRoom->exit[door]->description );
	    return TRUE;
	}

	send_to_char( "Syntax:  [direction] desc\n\r", ch );
	return FALSE;
    }

    /*
     * Set the exit flags, needs full argument.
     * ----------------------------------------
     */
    if ( ( value = flag_value( exit_flags, total_arg ) ) != NO_FLAG )
    {
	ROOM_INDEX_DATA *pToRoom;

	/*
	 * Create an exit if none exists.
	 */
	if ( !pRoom->exit[door] )
	    pRoom->exit[door] = new_exit();

	/*
	 * Set door bits for this room.
	 */
	TOGGLE_BIT(pRoom->exit[door]->rs_flags, value);
	pRoom->exit[door]->exit_info = pRoom->exit[door]->rs_flags;

	/*
	 * Set door bits of connected room.
	 * Skip one-way exits and non-existant rooms.
	 */
	if ( ( pToRoom = pRoom->exit[door]->to_room ) && pToRoom->exit[rev] )
	{
	    TOGGLE_BIT(pToRoom->exit[rev]->rs_flags, value);
	    pToRoom->exit[rev]->exit_info =  pToRoom->exit[rev]->rs_flags;
	}

	send_to_char( "Exit flag toggled.\n\r", ch );
	return TRUE;
    }

    return FALSE;
}



bool redit_north( CHAR_DATA *ch, char *argument )
{
    if ( change_exit( ch, argument, DIR_NORTH ) )
	return TRUE;

    return FALSE;
}



bool redit_south( CHAR_DATA *ch, char *argument )
{
    if ( change_exit( ch, argument, DIR_SOUTH ) )
	return TRUE;

    return FALSE;
}



bool redit_east( CHAR_DATA *ch, char *argument )
{
    if ( change_exit( ch, argument, DIR_EAST ) )
	return TRUE;

    return FALSE;
}



bool redit_west( CHAR_DATA *ch, char *argument )
{
    if ( change_exit( ch, argument, DIR_WEST ) )
	return TRUE;

    return FALSE;
}



bool redit_up( CHAR_DATA *ch, char *argument )
{
    if ( change_exit( ch, argument, DIR_UP ) )
	return TRUE;

    return FALSE;
}



bool redit_down( CHAR_DATA *ch, char *argument )
{
    if ( change_exit( ch, argument, DIR_DOWN ) )
	return TRUE;

    return FALSE;
}


/* OLC 1.1b */
bool redit_move( CHAR_DATA *ch, char *argument )
{
    interpret( ch, argument );
    return FALSE;
}



bool redit_ed( CHAR_DATA *ch, char *argument )
{
    ROOM_INDEX_DATA *pRoom;
    EXTRA_DESCR_DATA *ed;
    char command[MAX_INPUT_LENGTH];
    char keyword[MAX_INPUT_LENGTH];

    EDIT_ROOM(ch, pRoom);

    argument = one_argument( argument, command );
    one_argument( argument, keyword );

    if ( command[0] == '\0' || keyword[0] == '\0' )
    {
	send_to_char( "Syntax:  ed add [keyword]\n\r", ch );
	send_to_char( "         ed edit [keyword]\n\r", ch );
	send_to_char( "         ed delete [keyword]\n\r", ch );
	send_to_char( "         ed format [keyword]\n\r", ch );
	return FALSE;
    }

    if ( !str_cmp( command, "add" ) )
    {
	if ( keyword[0] == '\0' )
	{
	    send_to_char( "Syntax:  ed add [keyword]\n\r", ch );
	    return FALSE;
	}

	ed			=   new_extra_descr();
	ed->keyword		=   str_dup( keyword );
	ed->description		=   str_dup( "" );
	ed->next		=   pRoom->extra_descr;
	pRoom->extra_descr	=   ed;

	string_append( ch, &ed->description );

	return TRUE;
    }


    if ( !str_cmp( command, "edit" ) )
    {
	if ( keyword[0] == '\0' )
	{
	    send_to_char( "Syntax:  ed edit [keyword]\n\r", ch );
	    return FALSE;
	}

	for ( ed = pRoom->extra_descr; ed; ed = ed->next )
	{
	    if ( is_name( keyword, ed->keyword ) )
		break;
	}

	if ( !ed )
	{
	    send_to_char( "REdit:  Extra description keyword not found.\n\r", ch );
	    return FALSE;
	}

	string_append( ch, &ed->description );

	return TRUE;
    }


    if ( !str_cmp( command, "delete" ) )
    {
	EXTRA_DESCR_DATA *ped = NULL;

	if ( keyword[0] == '\0' )
	{
	    send_to_char( "Syntax:  ed delete [keyword]\n\r", ch );
	    return FALSE;
	}

	for ( ed = pRoom->extra_descr; ed; ed = ed->next )
	{
	    if ( is_name( keyword, ed->keyword ) )
		break;
	    ped = ed;
	}

	if ( !ed )
	{
	    send_to_char( "REdit:  Extra description keyword not found.\n\r", ch );
	    return FALSE;
	}

	if ( !ped )
	    pRoom->extra_descr = ed->next;
	else
	    ped->next = ed->next;

	free_extra_descr( ed );

	send_to_char( "Extra description deleted.\n\r", ch );
	return TRUE;
    }


    if ( !str_cmp( command, "format" ) )
    {
	if ( keyword[0] == '\0' )
	{
	    send_to_char( "Syntax:  ed format [keyword]\n\r", ch );
	    return FALSE;
	}

	for ( ed = pRoom->extra_descr; ed; ed = ed->next )
	{
	    if ( is_name( keyword, ed->keyword ) )
		break;
	}

	if ( !ed )
	{
	    send_to_char( "REdit:  Extra description keyword not found.\n\r", ch );
	    return FALSE;
	}

	/* OLC 1.1b */
	if ( strlen(ed->description) >= (MAX_STRING_LENGTH - 4) )
	{
	    send_to_char( "String too long to be formatted.\n\r", ch );
	    return FALSE;
	}

	ed->description = format_string( ed->description );

	send_to_char( "Extra description formatted.\n\r", ch );
	return TRUE;
    }

    redit_ed( ch, "" );
    return FALSE;
}



bool redit_create( CHAR_DATA *ch, char *argument )
{
    AREA_DATA *pArea;
    ROOM_INDEX_DATA *pRoom;
    int value;
    int iHash;
    
    EDIT_ROOM(ch, pRoom);

    value = atoi( argument );

    /* OLC 1.1b */
    if ( argument[0] == '\0' || value <= 0 || value >= INT_MAX )
    {
	char output[MAX_STRING_LENGTH];

	sprintf( output, "Syntax:  create [0 < vnum < %d]\n\r", INT_MAX );
	send_to_char( output, ch );
	return FALSE;
    }

    if ( argument[0] == '\0' || value <= 0 )
    {
	send_to_char( "Syntax:  create [vnum > 0]\n\r", ch );
	return FALSE;
    }

    pArea = get_vnum_area( value );
    if ( !pArea )
    {
	send_to_char( "REdit:  That vnum is not assigned an area.\n\r", ch );
	return FALSE;
    }

    if ( !IS_BUILDER( ch, pArea ) )
    {
	send_to_char( "REdit:  Vnum in an area you cannot build in.\n\r", ch );
	return FALSE;
    }

    if ( get_room_index( value ) )
    {
	send_to_char( "REdit:  Room vnum already exists.\n\r", ch );
	return FALSE;
    }

    pRoom			= new_room_index();
    pRoom->area			= pArea;
    pRoom->vnum			= value;

    if ( value > top_vnum_room )
        top_vnum_room = value;

    iHash			= value % MAX_KEY_HASH;
    pRoom->next			= room_index_hash[iHash];
    room_index_hash[iHash]	= pRoom;
    ch->desc->pEdit		= (void *)pRoom;

    send_to_char( "Room created.\n\r", ch );
    return TRUE;
}



bool redit_name( CHAR_DATA *ch, char *argument )
{
    ROOM_INDEX_DATA *pRoom;

    EDIT_ROOM(ch, pRoom);

    if ( argument[0] == '\0' )
    {
	send_to_char( "Syntax:  name [name]\n\r", ch );
	return FALSE;
    }

    free_string( pRoom->name );
    pRoom->name = str_dup( argument );

    send_to_char( "Name set.\n\r", ch );
    return TRUE;
}



bool redit_desc( CHAR_DATA *ch, char *argument )
{
    ROOM_INDEX_DATA *pRoom;

    EDIT_ROOM(ch, pRoom);

    if ( argument[0] == '\0' )
    {
	string_append( ch, &pRoom->description );
	return TRUE;
    }

    send_to_char( "Syntax:  desc\n\r", ch );
    return FALSE;
}




bool redit_format( CHAR_DATA *ch, char *argument )
{
    ROOM_INDEX_DATA *pRoom;

    EDIT_ROOM(ch, pRoom);

    /* OLC 1.1b */
    if ( strlen(pRoom->description) >= (MAX_STRING_LENGTH - 4) )
    {
	send_to_char( "String too long to be formatted.\n\r", ch );
	return FALSE;
    }

    pRoom->description = format_string( pRoom->description );

    send_to_char( "String formatted.\n\r", ch );
    return TRUE;
}



bool redit_mreset( CHAR_DATA *ch, char *argument )
{
    ROOM_INDEX_DATA	*pRoom;
    MOB_INDEX_DATA	*pMobIndex;
    CHAR_DATA		*newmob;
    char		arg [ MAX_INPUT_LENGTH ];

    RESET_DATA		*pReset;
    char		output [ MAX_STRING_LENGTH ];

    EDIT_ROOM(ch, pRoom);

    argument = one_argument( argument, arg );

    if ( arg[0] == '\0' || !is_number( arg ) )
    {
	send_to_char ( "Syntax:  mreset <vnum> <max #>\n\r", ch );
	return FALSE;
    }

    if ( !( pMobIndex = get_mob_index( atoi( arg ) ) ) )
    {
	send_to_char( "REdit: No mobile has that vnum.\n\r", ch );
	return FALSE;
    }

    if ( pMobIndex->area != pRoom->area )
    {
	send_to_char( "REdit: No such mobile in this area.\n\r", ch );
	return FALSE;
    }

    /*
     * Create the mobile reset.
     */
    pReset = new_reset_data();
    pReset->command	= 'M';
    pReset->arg1	= pMobIndex->vnum;
    pReset->arg2	= is_number( argument ) ? atoi( argument ) : MAX_MOB;
    pReset->arg3	= pRoom->vnum;
    add_reset( pRoom, pReset, 0/* Last slot*/ );

    /*
     * Create the mobile.
     */
    newmob = create_mobile( pMobIndex );
    char_to_room( newmob, pRoom );

    sprintf( output, "%s (%d) has been loaded and added to resets.\n\r"
	"There will be a maximum of %d loaded to this room.\n\r",
	capitalize( pMobIndex->short_descr ),
	pMobIndex->vnum,
	pReset->arg2 );
    send_to_char( output, ch );
    act( "$n has created $N!", ch, NULL, newmob, TO_ROOM );
    return TRUE;
}

struct wear_type
{
    int	wear_loc;
    int	wear_bit;
};



const struct wear_type wear_table[] =
{
    {	WEAR_NONE,	ITEM_TAKE		},
    {	WEAR_LIGHT,	ITEM_LIGHT		},
    {	WEAR_FINGER_L,	ITEM_WEAR_FINGER	},
    {	WEAR_FINGER_R,	ITEM_WEAR_FINGER	},
    {	WEAR_NECK_1,	ITEM_WEAR_NECK		},
    {	WEAR_NECK_2,	ITEM_WEAR_NECK		},
    {	WEAR_BODY,	ITEM_WEAR_BODY		},
    {	WEAR_HEAD,	ITEM_WEAR_HEAD		},
    {	WEAR_LEGS,	ITEM_WEAR_LEGS		},
    {	WEAR_FEET,	ITEM_WEAR_FEET		},
    {	WEAR_HANDS,	ITEM_WEAR_HANDS		},
    {	WEAR_ARMS,	ITEM_WEAR_ARMS		},
    {	WEAR_SHIELD,	ITEM_WEAR_SHIELD	},
    {	WEAR_ABOUT,	ITEM_WEAR_ABOUT		},
    {	WEAR_WAIST,	ITEM_WEAR_WAIST		},
    {	WEAR_WRIST_L,	ITEM_WEAR_WRIST		},
    {	WEAR_WRIST_R,	ITEM_WEAR_WRIST		},
    {	WEAR_WIELD,	ITEM_WIELD		},
    {	WEAR_HOLD,	ITEM_HOLD		},
    {	NO_FLAG,	NO_FLAG			}
};



/*****************************************************************************
 Name:		wear_loc
 Purpose:	Returns the location of the bit that matches the count.
 		1 = first match, 2 = second match etc.
 Called by:	oedit_reset(olc_act.c).
 ****************************************************************************/
int wear_loc(int bits, int count)
{
    int flag;
 
    for (flag = 0; wear_table[flag].wear_bit != NO_FLAG; flag++)
    {
        if ( IS_SET(bits, wear_table[flag].wear_bit) && --count < 1)
            return wear_table[flag].wear_loc;
    }
 
    return NO_FLAG;
}



/*****************************************************************************
 Name:		wear_bit
 Purpose:	Converts a wear_loc into a bit.
 Called by:	redit_oreset(olc_act.c).
 ****************************************************************************/
int wear_bit(int loc)
{
    int flag;
 
    for (flag = 0; wear_table[flag].wear_loc != NO_FLAG; flag++)
    {
        if ( loc == wear_table[flag].wear_loc )
            return wear_table[flag].wear_bit;
    }
 
    return 0;
}



bool redit_oreset( CHAR_DATA *ch, char *argument )
{
    ROOM_INDEX_DATA	*pRoom;
    OBJ_INDEX_DATA	*pObjIndex;
    OBJ_DATA		*newobj;
    OBJ_DATA		*to_obj;
    CHAR_DATA		*to_mob;
    char		arg1 [ MAX_INPUT_LENGTH ];
    char		arg2 [ MAX_INPUT_LENGTH ];
    int			olevel = 0;

    RESET_DATA		*pReset;
    char		output [ MAX_STRING_LENGTH ];

    EDIT_ROOM(ch, pRoom);

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if ( arg1[0] == '\0' || !is_number( arg1 ) )
    {
	send_to_char ( "Syntax:  oreset <vnum> <args>\n\r", ch );
	send_to_char ( "        -no_args               = into room\n\r", ch );
	send_to_char ( "        -<obj_name>            = into obj\n\r", ch );
	send_to_char ( "        -<mob_name> <wear_loc> = into mob\n\r", ch );
	return FALSE;
    }

    if ( !( pObjIndex = get_obj_index( atoi( arg1 ) ) ) )
    {
	send_to_char( "REdit: No object has that vnum.\n\r", ch );
	return FALSE;
    }

    if ( pObjIndex->area != pRoom->area )
    {
	send_to_char( "REdit: No such object in this area.\n\r", ch );
	return FALSE;
    }

    /*
     * Load into room.
     */
    if ( arg2[0] == '\0' )
    {
	pReset		= new_reset_data();
	pReset->command	= 'O';
	pReset->arg1	= pObjIndex->vnum;
	pReset->arg2	= 0;
	pReset->arg3	= pRoom->vnum;
	add_reset( pRoom, pReset, 0/* Last slot*/ );

	newobj = create_object( pObjIndex, number_fuzzy( olevel ) );
	obj_to_room( newobj, pRoom );

	sprintf( output, "%s (%d) has been loaded and added to resets.\n\r",
	    capitalize( pObjIndex->short_descr ),
	    pObjIndex->vnum );
	send_to_char( output, ch );
    }
    else
    /*
     * Load into object's inventory.
     */
    if ( argument[0] == '\0'
    && ( ( to_obj = get_obj_list( ch, arg2, pRoom->contents ) ) != NULL ) )
    {
	pReset		= new_reset_data();
	pReset->command	= 'P';
	pReset->arg1	= pObjIndex->vnum;
	pReset->arg2	= 0;
	pReset->arg3	= to_obj->pIndexData->vnum;
	add_reset( pRoom, pReset, 0/* Last slot*/ );

	newobj = create_object( pObjIndex, number_fuzzy( olevel ) );
	newobj->cost = 0;
	obj_to_obj( newobj, to_obj );

	sprintf( output, "%s (%d) has been loaded into "
	    "%s (%d) and added to resets.\n\r",
	    capitalize( newobj->short_descr ),
	    newobj->pIndexData->vnum,
	    to_obj->short_descr,
	    to_obj->pIndexData->vnum );
	send_to_char( output, ch );
    }
    else
    /*
     * Load into mobile's inventory.
     */
    if ( ( to_mob = get_char_room( ch, arg2 ) ) != NULL )
    {
	int	wear_loc;

	/*
	 * Make sure the location on mobile is valid.
	 */
	if ( (wear_loc = flag_value( wear_loc_flags, argument )) == NO_FLAG )
	{
	    send_to_char( "REdit: Invalid wear_loc.  '? wear-loc'\n\r", ch );
	    return FALSE;
	}

	/*
	 * Disallow loading a sword(WEAR_WIELD) into WEAR_HEAD.
	 */
	if ( !IS_SET( pObjIndex->wear_flags, wear_bit(wear_loc) ) )
	{
	    sprintf( output,
	        "%s (%d) has wear flags: [%s]\n\r",
	        capitalize( pObjIndex->short_descr ),
	        pObjIndex->vnum,
		flag_string( wear_flags, pObjIndex->wear_flags ) );
	    send_to_char( output, ch );
	    return FALSE;
	}

	/*
	 * Can't load into same position.
	 */
	if ( get_eq_char( to_mob, wear_loc ) )
	{
	    send_to_char( "REdit:  Object already equipped.\n\r", ch );
	    return FALSE;
	}

	pReset		= new_reset_data();
	pReset->arg1	= pObjIndex->vnum;
	pReset->arg2	= wear_loc;
	if ( pReset->arg2 == WEAR_NONE )
	    pReset->command = 'G';
	else
	    pReset->command = 'E';
	pReset->arg3	= wear_loc;

	add_reset( pRoom, pReset, 0/* Last slot*/ );

	olevel  = URANGE( 0, to_mob->level - 2, LEVEL_HERO );
        newobj = create_object( pObjIndex, number_fuzzy( olevel ) );

	if ( to_mob->pIndexData->pShop )	/* Shop-keeper? */
	{
	    switch ( pObjIndex->item_type )
	    {
	    default:		olevel = 0;				break;
	    case ITEM_PILL:	olevel = number_range(  0, 10 );	break;
	    case ITEM_POTION:	olevel = number_range(  0, 10 );	break;
	    case ITEM_SCROLL:	olevel = number_range(  5, 15 );	break;
	    case ITEM_WAND:	olevel = number_range( 10, 20 );	break;
	    case ITEM_STAFF:	olevel = number_range( 15, 25 );	break;
	    case ITEM_ARMOR:	olevel = number_range(  5, 15 );	break;
	    case ITEM_WEAPON:	if ( pReset->command == 'G' )
	    			    olevel = number_range( 5, 15 );
				else
				    olevel = number_fuzzy( olevel );
		break;
	    }

	    newobj = create_object( pObjIndex, olevel );
	    if ( pReset->arg2 == WEAR_NONE )
		SET_BIT( newobj->extra_flags, ITEM_INVENTORY );
	}
	else
	    newobj = create_object( pObjIndex, number_fuzzy( olevel ) );

	obj_to_char( newobj, to_mob );
	if ( pReset->command == 'E' )
	    equip_char( to_mob, newobj, pReset->arg3 );

	sprintf( output, "%s (%d) has been loaded "
	    "%s of %s (%d) and added to resets.\n\r",
	    capitalize( pObjIndex->short_descr ),
	    pObjIndex->vnum,
	    flag_string( wear_loc_strings, pReset->arg3 ),
	    to_mob->short_descr,
	    to_mob->pIndexData->vnum );
	send_to_char( output, ch );
    }
    else	/* Display Syntax */
    {
	send_to_char( "REdit:  That mobile isn't here.\n\r", ch );
	return FALSE;
    }

    act( "$n has created $p!", ch, newobj, NULL, TO_ROOM );
    return TRUE;
}



/*
 * Object Editor Functions.
 */
void show_obj_values( CHAR_DATA *ch, OBJ_INDEX_DATA *obj )
{
    char buf[MAX_STRING_LENGTH];

    switch( obj->item_type )
    {
	default:	/* No values. */
	    break;
            
	case ITEM_LIGHT:
            if ( obj->value[2] == -1 )
		sprintf( buf, "[v2] Light:  Infinite[-1]\n\r" );
            else
		sprintf( buf, "[v2] Light:  [%d]\n\r", obj->value[2] );
	    send_to_char( buf, ch );
	    break;

	case ITEM_WAND:
	case ITEM_STAFF:
            sprintf( buf,
		"[v0] Level:          [%d]\n\r"
		"[v1] Charges Total:  [%d]\n\r"
		"[v2] Charges Left:   [%d]\n\r"
		"[v3] Spell:          %s\n\r",
		obj->value[0],
		obj->value[1],
		obj->value[2],
		obj->value[3] != -1 ? skill_table[obj->value[3]].name
		                    : "none" );
	    send_to_char( buf, ch );
	    break;

	case ITEM_SCROLL:
	case ITEM_POTION:
	case ITEM_PILL:
            sprintf( buf,
		"[v0] Level:  [%d]\n\r"
		"[v1] Spell:  %s\n\r"
		"[v2] Spell:  %s\n\r"
		"[v3] Spell:  %s\n\r",
		obj->value[0],
		obj->value[1] != -1 ? skill_table[obj->value[1]].name
		                    : "none",
		obj->value[2] != -1 ? skill_table[obj->value[2]].name
                                    : "none",
		obj->value[3] != -1 ? skill_table[obj->value[3]].name
		                    : "none" );
	    send_to_char( buf, ch );
	    break;

	case ITEM_WEAPON:
            sprintf( buf,
 		"[v0] ItemAffects:    %d\n\r"
        	"[v1] Damage minimum: [%d]\n\r"
        	"[v2] Damage maximum: [%d]\n\r"
		"[v3] Type:           %s\n\r",
		obj->value[0],
		obj->value[1],
		obj->value[2],
		flag_string( weapon_flags, obj->value[3] ) );
	    send_to_char( buf, ch );
	    break;
	case ITEM_ARMOR:
	    sprintf(buf, 
		"[v0] Armor Class:  %d\n\r"
		"[v3] ItemAffects:  %d\n\r",
		obj->value[0],
		obj->value[3]);
		break;
	case ITEM_CONTAINER:
	    sprintf( buf,
		"[v0] Weight: [%d kg]\n\r"
		"[v1] Flags:  [%s]\n\r"
		"[v2] Key:    %s [%d]\n\r",
		obj->value[0],
		flag_string( container_flags, obj->value[1] ),
                get_obj_index(obj->value[2])
                    ? get_obj_index(obj->value[2])->short_descr
                    : "none", obj->value[2]);
	    send_to_char( buf, ch );
	    break;

	case ITEM_DRINK_CON:
	    sprintf( buf,
	        "[v0] Liquid Total: [%d]\n\r"
	        "[v1] Liquid Left:  [%d]\n\r"
	        "[v2] Liquid:       %s\n\r"
	        "[v3] Poisoned:     %s\n\r",
	        obj->value[0],
	        obj->value[1],
	        flag_string( liquid_flags, obj->value[2] ),
	        obj->value[3] != 0 ? "Yes" : "No" );
	    send_to_char( buf, ch );
	    break;

	case ITEM_FOOD:
	    sprintf( buf,
		"[v0] Food hours: [%d]\n\r"
		"[v3] Poisoned:   %s\n\r",
		obj->value[0],
		obj->value[3] != 0 ? "Yes" : "No" );
	    send_to_char( buf, ch );
	    break;

	case ITEM_MONEY:
            sprintf( buf, "[v0] Gold:   [%d]\n\r", obj->value[0] );
	    send_to_char( buf, ch );
	    break;
    }

    return;
}



bool set_obj_values( CHAR_DATA *ch, OBJ_INDEX_DATA *pObj, int value_num, char *argument)
{
    switch( pObj->item_type )
    {
        default:
            break;
            
        case ITEM_LIGHT:
	    switch ( value_num )
	    {
	        default:
		    do_help( ch, "ITEM_LIGHT" );
	            return FALSE;
	        case 2:
	            send_to_char( "HOURS OF LIGHT SET.\n\r\n\r", ch );
	            pObj->value[2] = atoi( argument );
	            break;
	    }
            break;

        case ITEM_WAND:
        case ITEM_STAFF:
	    switch ( value_num )
	    {
	        default:
		    do_help( ch, "ITEM_STAFF_WAND" );
	            return FALSE;
	        case 0:
	            send_to_char( "SPELL LEVEL SET.\n\r\n\r", ch );
	            pObj->value[0] = atoi( argument );
	            break;
	        case 1:
	            send_to_char( "TOTAL NUMBER OF CHARGES SET.\n\r\n\r", ch );
	            pObj->value[1] = atoi( argument );
	            break;
	        case 2:
	            send_to_char( "CURRENT NUMBER OF CHARGES SET.\n\r\n\r", ch );
	            pObj->value[2] = atoi( argument );
	            break;
	        case 3:
	            send_to_char( "SPELL TYPE SET.\n\r", ch );
	            pObj->value[3] = skill_lookup( argument );
	            break;
	    }
            break;

        case ITEM_SCROLL:
        case ITEM_POTION:
        case ITEM_PILL:
	    switch ( value_num )
	    {
	        default:
		    do_help( ch, "ITEM_SCROLL_POTION_PILL" );
	            return FALSE;
	        case 0:
	            send_to_char( "SPELL LEVEL SET.\n\r\n\r", ch );
	            pObj->value[0] = atoi( argument );
	            break;
	        case 1:
	            send_to_char( "SPELL TYPE 1 SET.\n\r\n\r", ch );
	            pObj->value[1] = skill_lookup( argument );
	            break;
	        case 2:
	            send_to_char( "SPELL TYPE 2 SET.\n\r\n\r", ch );
	            pObj->value[2] = skill_lookup( argument );
	            break;
	        case 3:
	            send_to_char( "SPELL TYPE 3 SET.\n\r\n\r", ch );
	            pObj->value[3] = skill_lookup( argument );
	            break;
	    }
            break;
	case ITEM_ARMOR:
	    switch ( value_num )
	    {
		default:
			return FALSE;
		case 0:
			send_to_char("V0 SET.\n\r\n\r", ch );
			pObj->value[0] = atoi(argument);
			break;
		case 3:
			send_to_char("V3 SET.\n\r\n\r", ch );
			pObj->value[3] = atoi(argument);
			break;
	    }
	break;
        case ITEM_WEAPON:
	    switch ( value_num )
	    {
	        default:
		    do_help( ch, "ITEM_WEAPON" );
	            return FALSE;
		case 0:
			send_to_char(" V0 SET.\n\r\n\r", ch);
			pObj->value[0] = atoi(argument);
			break;
	        case 1:
	            send_to_char( "MINIMUM DAMAGE SET.\n\r\n\r", ch );
	            pObj->value[1] = atoi( argument );
	            break;
	        case 2:
	            send_to_char( "MAXIMUM DAMAGE SET.\n\r\n\r", ch );
	            pObj->value[2] = atoi( argument );
	            break;
	        case 3:
	            send_to_char( "WEAPON TYPE SET.\n\r\n\r", ch );
	            pObj->value[3] = flag_value( weapon_flags, argument );
	            break;
	    }
            break;

        case ITEM_CONTAINER:
	    switch ( value_num )
	    {
		int value;
		
		default:
		    do_help( ch, "ITEM_CONTAINER" );
	            return FALSE;
		case 0:
	            send_to_char( "WEIGHT CAPACITY SET.\n\r\n\r", ch );
	            pObj->value[0] = atoi( argument );
	            break;
		case 1:
	            if ( ( value = flag_value( container_flags, argument ) )
	              != NO_FLAG )
	        	TOGGLE_BIT(pObj->value[1], value);
		    else
		    {
			do_help ( ch, "ITEM_CONTAINER" );
			return FALSE;
		    }
	            send_to_char( "CONTAINER TYPE SET.\n\r\n\r", ch );
	            break;
		case 2:
		    if ( atoi(argument) != 0 )
		    {
			if ( !get_obj_index( atoi( argument ) ) )
			{
			    send_to_char( "THERE IS NO SUCH ITEM.\n\r\n\r", ch );
			    return FALSE;
			}

			if ( get_obj_index( atoi( argument ) )->item_type != ITEM_KEY )
			{
			    send_to_char( "THAT ITEM IS NOT A KEY.\n\r\n\r", ch );
			    return FALSE;
			}
		    }
		    send_to_char( "CONTAINER KEY SET.\n\r\n\r", ch );
		    pObj->value[2] = atoi( argument );
		    break;
	    }
	    break;

	case ITEM_DRINK_CON:
	    switch ( value_num )
	    {
	        default:
		    do_help( ch, "ITEM_DRINK" );
	            return FALSE;
	        case 0:
	            send_to_char( "MAXIMUM AMOUT OF LIQUID HOURS SET.\n\r\n\r", ch );
	            pObj->value[0] = atoi( argument );
	            break;
	        case 1:
	            send_to_char( "CURRENT AMOUNT OF LIQUID HOURS SET.\n\r\n\r", ch );
	            pObj->value[1] = atoi( argument );
	            break;
	        case 2:
	            send_to_char( "LIQUID TYPE SET.\n\r\n\r", ch );
	            pObj->value[2] = flag_value( liquid_flags, argument );
	            break;
	        case 3:
	            send_to_char( "POISON VALUE TOGGLED.\n\r\n\r", ch );
	            pObj->value[3] = ( pObj->value[3] == 0 ) ? 1 : 0;
	            break;
	    }
            break;

	case ITEM_FOOD:
	    switch ( value_num )
	    {
	        default:
		    do_help( ch, "ITEM_FOOD" );
	            return FALSE;
	        case 0:
	            send_to_char( "HOURS OF FOOD SET.\n\r\n\r", ch );
	            pObj->value[0] = atoi( argument );
	            break;
	        case 3:
	            send_to_char( "POISON VALUE TOGGLED.\n\r\n\r", ch );
	            pObj->value[3] = ( pObj->value[3] == 0 ) ? 1 : 0;
	            break;
	    }
            break;

	case ITEM_MONEY:
	    switch ( value_num )
	    {
	        default:
		    do_help( ch, "ITEM_MONEY" );
	            return FALSE;
	        case 0:
	            send_to_char( "GOLD AMOUNT SET.\n\r\n\r", ch );
	            pObj->value[0] = atoi( argument );
	            break;
	    }
            break;
    }

    show_obj_values( ch, pObj );

    return TRUE;
}



bool oedit_show( CHAR_DATA *ch, char *argument )
{
    OBJ_INDEX_DATA *pObj;
    char buf[MAX_STRING_LENGTH];
    AFFECT_DATA *paf;
    int cnt;

    EDIT_OBJ(ch, pObj);

    sprintf( buf, "Name:        [%s]\n\rArea:        [%5d] %s\n\r",
	pObj->name,
	!pObj->area ? -1        : pObj->area->vnum,
	!pObj->area ? "No Area" : pObj->area->name );
    send_to_char( buf, ch );


    sprintf( buf, "Vnum:        [%5d]\n\rType:        [%s]\n\r",
	pObj->vnum,
	flag_string( type_flags, pObj->item_type ) );
    send_to_char( buf, ch );

    sprintf( buf, "Wear flags:  [%s]\n\r",
	flag_string( wear_flags, pObj->wear_flags ) );
    send_to_char( buf, ch );

    sprintf( buf, "Extra flags: [%s]\n\r",
	flag_string( extra_flags, pObj->extra_flags ) );
    send_to_char( buf, ch );

    sprintf( buf, "Weight:      [%d]\n\rCost:        [%d]\n\r",
	pObj->weight, pObj->cost );
    send_to_char( buf, ch );

    if ( pObj->extra_descr )
    {
	EXTRA_DESCR_DATA *ed;

	send_to_char( "Ex desc kwd: ", ch );

	for ( ed = pObj->extra_descr; ed; ed = ed->next )
	{
	    send_to_char( "[", ch );
	    send_to_char( ed->keyword, ch );
	    send_to_char( "]", ch );
	}

	send_to_char( "\n\r", ch );
    }

    sprintf( buf, "Short desc:  %s\n\rLong desc:\n\r     %s\n\r",
	pObj->short_descr, pObj->description );
    send_to_char( buf, ch );

    for ( cnt = 0, paf = pObj->affected; paf; paf = paf->next )
    {
	if ( cnt == 0 )
	{
	    send_to_char( "Number Modifier Affects\n\r", ch );
	    send_to_char( "------ -------- -------\n\r", ch );
	}
	sprintf( buf, "[%4d] %-8d %s\n\r", cnt,
	    paf->modifier,
	    flag_string( apply_flags, paf->location ) );
	send_to_char( buf, ch );
	cnt++;
    }

    show_obj_values( ch, pObj );

    return FALSE;
}


/*
 * Need to issue warning if flag isn't valid.
 */
bool oedit_addaffect( CHAR_DATA *ch, char *argument )
{
    OBJ_INDEX_DATA *pObj;
    AFFECT_DATA *pAf;
    char loc[MAX_STRING_LENGTH];
    char mod[MAX_STRING_LENGTH];

    EDIT_OBJ(ch, pObj);

    argument = one_argument( argument, loc );
    one_argument( argument, mod );

    if ( loc[0] == '\0' || mod[0] == '\0' || !is_number( mod ) )
    {
	send_to_char( "Syntax:  addaffect [location] [#mod]\n\r", ch );
	return FALSE;
    }

    pAf             =   new_affect();
    pAf->location   =   flag_value( apply_flags, loc );
    pAf->modifier   =   atoi( mod );
    pAf->type       =   -1;
    pAf->duration   =   -1;
    pAf->bitvector  =   0;
    pAf->next       =   pObj->affected;
    pObj->affected  =   pAf;

    send_to_char( "Affect added.\n\r", ch);
    return TRUE;
}



/*
 * My thanks to Hans Hvidsten Birkeland and Noam Krendel(Walker)
 * for really teaching me how to manipulate pointers.
 */
bool oedit_delaffect( CHAR_DATA *ch, char *argument )
{
    OBJ_INDEX_DATA *pObj;
    AFFECT_DATA *pAf;
    AFFECT_DATA *pAf_next;
    char affect[MAX_STRING_LENGTH];
    int  value;
    int  cnt = 0;

    EDIT_OBJ(ch, pObj);

    one_argument( argument, affect );

    if ( !is_number( affect ) || affect[0] == '\0' )
    {
	send_to_char( "Syntax:  delaffect [#affect]\n\r", ch );
	return FALSE;
    }

    value = atoi( affect );

    if ( value < 0 )
    {
	send_to_char( "Only non-negative affect-numbers allowed.\n\r", ch );
	return FALSE;
    }

    if ( !( pAf = pObj->affected ) )
    {
	send_to_char( "OEdit:  Non-existant affect.\n\r", ch );
	return FALSE;
    }

    if( value == 0 )	/* First case: Remove first affect */
    {
	pAf = pObj->affected;
	pObj->affected = pAf->next;
	free_affect( pAf );
    }
    else		/* Affect to remove is not the first */
    {
	while ( ( pAf_next = pAf->next ) && ( ++cnt < value ) )
	     pAf = pAf_next;

	if( pAf_next )		/* See if it's the next affect */
	{
	    pAf->next = pAf_next->next;
	    free_affect( pAf_next );
	}
	else                                 /* Doesn't exist */
	{
	     send_to_char( "No such affect.\n\r", ch );
	     return FALSE;
	}
    }

    send_to_char( "Affect removed.\n\r", ch);
    return TRUE;
}



bool oedit_name( CHAR_DATA *ch, char *argument )
{
    OBJ_INDEX_DATA *pObj;

    EDIT_OBJ(ch, pObj);

    if ( argument[0] == '\0' )
    {
	send_to_char( "Syntax:  name [string]\n\r", ch );
	return FALSE;
    }

    free_string( pObj->name );
    pObj->name = str_dup( argument );

    send_to_char( "Name set.\n\r", ch);
    return TRUE;
}



bool oedit_short( CHAR_DATA *ch, char *argument )
{
    OBJ_INDEX_DATA *pObj;

    EDIT_OBJ(ch, pObj);

    if ( argument[0] == '\0' )
    {
	send_to_char( "Syntax:  short [string]\n\r", ch );
	return FALSE;
    }

    free_string( pObj->short_descr );
    pObj->short_descr = str_dup( argument );
    pObj->short_descr[0] = LOWER( pObj->short_descr[0] );

    send_to_char( "Short description set.\n\r", ch);
    return TRUE;
}



bool oedit_long( CHAR_DATA *ch, char *argument )
{
    OBJ_INDEX_DATA *pObj;

    EDIT_OBJ(ch, pObj);

    if ( argument[0] == '\0' )
    {
	send_to_char( "Syntax:  long [string]\n\r", ch );
	return FALSE;
    }
        
    free_string( pObj->description );
    pObj->description = str_dup( argument );
    pObj->description[0] = UPPER( pObj->description[0] );

    send_to_char( "Long description set.\n\r", ch);
    return TRUE;
}



bool set_value( CHAR_DATA *ch, OBJ_INDEX_DATA *pObj, char *argument, int value )
{
    if ( argument[0] == '\0' )
    {
	set_obj_values( ch, pObj, -1, '\0' );
	return FALSE;
    }

    if ( set_obj_values( ch, pObj, value, argument ) )
	return TRUE;

    return FALSE;
}



/*****************************************************************************
 Name:		oedit_values
 Purpose:	Finds the object and sets its value.
 Called by:	The four valueX functions below.
 ****************************************************************************/
bool oedit_values( CHAR_DATA *ch, char *argument, int value )
{
    OBJ_INDEX_DATA *pObj;

    EDIT_OBJ(ch, pObj);

    if ( set_value( ch, pObj, argument, value ) )
        return TRUE;

    return FALSE;
}


bool oedit_value0( CHAR_DATA *ch, char *argument )
{
    if ( oedit_values( ch, argument, 0 ) )
        return TRUE;

    return FALSE;
}



bool oedit_value1( CHAR_DATA *ch, char *argument )
{
    if ( oedit_values( ch, argument, 1 ) )
        return TRUE;

    return FALSE;
}



bool oedit_value2( CHAR_DATA *ch, char *argument )
{
    if ( oedit_values( ch, argument, 2 ) )
        return TRUE;

    return FALSE;
}



bool oedit_value3( CHAR_DATA *ch, char *argument )
{
    if ( oedit_values( ch, argument, 3 ) )
        return TRUE;

    return FALSE;
}



bool oedit_weight( CHAR_DATA *ch, char *argument )
{
    OBJ_INDEX_DATA *pObj;

    EDIT_OBJ(ch, pObj);

    if ( argument[0] == '\0' || !is_number( argument ) )
    {
	send_to_char( "Syntax:  weight [number]\n\r", ch );
	return FALSE;
    }

    pObj->weight = atoi( argument );

    send_to_char( "Weight set.\n\r", ch);
    return TRUE;
}



bool oedit_cost( CHAR_DATA *ch, char *argument )
{
    OBJ_INDEX_DATA *pObj;

    EDIT_OBJ(ch, pObj);

    if ( argument[0] == '\0' || !is_number( argument ) )
    {
	send_to_char( "Syntax:  cost [number]\n\r", ch );
	return FALSE;
    }

    pObj->cost = atoi( argument );

    send_to_char( "Cost set.\n\r", ch);
    return TRUE;
}



bool oedit_create( CHAR_DATA *ch, char *argument )
{
    OBJ_INDEX_DATA *pObj;
    AREA_DATA *pArea;
    int  value;
    int  iHash;

    value = atoi( argument );

    /* OLC 1.1b */
    if ( argument[0] == '\0' || value <= 0 || value >= INT_MAX )
    {
	char output[MAX_STRING_LENGTH];

	sprintf( output, "Syntax:  create [0 < vnum < %d]\n\r", INT_MAX );
	send_to_char( output, ch );
	return FALSE;
    }

    pArea = get_vnum_area( value );
    if ( !pArea )
    {
	send_to_char( "OEdit:  That vnum is not assigned an area.\n\r", ch );
	return FALSE;
    }

    if ( !IS_BUILDER( ch, pArea ) )
    {
	send_to_char( "OEdit:  Vnum in an area you cannot build in.\n\r", ch );
	return FALSE;
    }

    if ( get_obj_index( value ) )
    {
	send_to_char( "OEdit:  Object vnum already exists.\n\r", ch );
	return FALSE;
    }
        
    pObj			= new_obj_index();
    pObj->vnum			= value;
    pObj->area			= pArea;
        
    if ( value > top_vnum_obj )
	top_vnum_obj = value;

    iHash			= value % MAX_KEY_HASH;
    pObj->next			= obj_index_hash[iHash];
    obj_index_hash[iHash]	= pObj;
    ch->desc->pEdit		= (void *)pObj;

    send_to_char( "Object Created.\n\r", ch );
    return TRUE;
}



bool oedit_ed( CHAR_DATA *ch, char *argument )
{
    OBJ_INDEX_DATA *pObj;
    EXTRA_DESCR_DATA *ed;
    char command[MAX_INPUT_LENGTH];
    char keyword[MAX_INPUT_LENGTH];

    EDIT_OBJ(ch, pObj);

    argument = one_argument( argument, command );
    one_argument( argument, keyword );

    if ( command[0] == '\0' )
    {
	send_to_char( "Syntax:  ed add [keyword]\n\r", ch );
	send_to_char( "         ed delete [keyword]\n\r", ch );
	send_to_char( "         ed edit [keyword]\n\r", ch );
	send_to_char( "         ed format [keyword]\n\r", ch );
	return FALSE;
    }

    if ( !str_cmp( command, "add" ) )
    {
	if ( keyword[0] == '\0' )
	{
	    send_to_char( "Syntax:  ed add [keyword]\n\r", ch );
	    return FALSE;
	}

	ed                  =   new_extra_descr();
	ed->keyword         =   str_dup( keyword );
	ed->next            =   pObj->extra_descr;
	pObj->extra_descr   =   ed;

	string_append( ch, &ed->description );

	return TRUE;
    }

    if ( !str_cmp( command, "edit" ) )
    {
	if ( keyword[0] == '\0' )
	{
	    send_to_char( "Syntax:  ed edit [keyword]\n\r", ch );
	    return FALSE;
	}

	for ( ed = pObj->extra_descr; ed; ed = ed->next )
	{
	    if ( is_name( keyword, ed->keyword ) )
		break;
	}

	if ( !ed )
	{
	    send_to_char( "OEdit:  Extra description keyword not found.\n\r", ch );
	    return FALSE;
	}

	string_append( ch, &ed->description );

	return TRUE;
    }

    if ( !str_cmp( command, "delete" ) )
    {
	EXTRA_DESCR_DATA *ped = NULL;

	if ( keyword[0] == '\0' )
	{
	    send_to_char( "Syntax:  ed delete [keyword]\n\r", ch );
	    return FALSE;
	}

	for ( ed = pObj->extra_descr; ed; ed = ed->next )
	{
	    if ( is_name( keyword, ed->keyword ) )
		break;
	    ped = ed;
	}

	if ( !ed )
	{
	    send_to_char( "OEdit:  Extra description keyword not found.\n\r", ch );
	    return FALSE;
	}

	if ( !ped )
	    pObj->extra_descr = ed->next;
	else
	    ped->next = ed->next;

	free_extra_descr( ed );

	send_to_char( "Extra description deleted.\n\r", ch );
	return TRUE;
    }


    if ( !str_cmp( command, "format" ) )
    {
	EXTRA_DESCR_DATA *ped = NULL;

	if ( keyword[0] == '\0' )
	{
	    send_to_char( "Syntax:  ed format [keyword]\n\r", ch );
	    return FALSE;
	}

	for ( ed = pObj->extra_descr; ed; ed = ed->next )
	{
	    if ( is_name( keyword, ed->keyword ) )
		break;
	    ped = ed;
	}

	if ( !ed )
	{
                send_to_char( "OEdit:  Extra description keyword not found.\n\r", ch );
                return FALSE;
	}

	/* OLC 1.1b */
	if ( strlen(ed->description) >= (MAX_STRING_LENGTH - 4) )
	{
	    send_to_char( "String too long to be formatted.\n\r", ch );
	    return FALSE;
	}

	ed->description = format_string( ed->description );

	send_to_char( "Extra description formatted.\n\r", ch );
	return TRUE;
    }

    oedit_ed( ch, "" );
    return FALSE;
}



/*
 * Mobile Editor Functions.
 */
bool medit_show( CHAR_DATA *ch, char *argument )
{
    MOB_INDEX_DATA *pMob;
    char buf[MAX_STRING_LENGTH];

    EDIT_MOB(ch, pMob);

    sprintf( buf, "Name:        [%s]\n\rArea:        [%5d] %s\n\r",
	pMob->player_name,
	!pMob->area ? -1        : pMob->area->vnum,
	!pMob->area ? "No Area" : pMob->area->name );
    send_to_char( buf, ch );

    sprintf( buf, "Act:         [%s]\n\r",
	flag_string( act_flags, pMob->act ) );
    send_to_char( buf, ch );

    sprintf( buf, "Vnum:        [%5d]\n\rSex:         [%s]\n\r",
	pMob->vnum,
	pMob->sex == SEX_MALE    ? "male"   :
	pMob->sex == SEX_FEMALE  ? "female" : "neutral" );
    send_to_char( buf, ch );

    sprintf( buf,
	"Level:       [%2d]\n\rAlign:       [%4d]\n\r",
	pMob->level,       pMob->alignment );
    send_to_char( buf, ch );

    sprintf( buf, "Affected by: [%s]\n\r",
	flag_string( affect_flags, pMob->affected_by ) );
    send_to_char( buf, ch );

    if ( pMob->spec_fun )
    {
	sprintf( buf, "Spec fun:    [%s]\n\r",  spec_string( pMob->spec_fun ) );
	send_to_char( buf, ch );
    }

    sprintf( buf, "Short descr: %s\n\rLong descr:\n\r%s",
	pMob->short_descr,
	pMob->long_descr );
    send_to_char( buf, ch );

    sprintf( buf, "Description:\n\r%s", pMob->description );
    send_to_char( buf, ch );

    if ( pMob->pShop )
    {
	SHOP_DATA *pShop;
	int iTrade;

	pShop = pMob->pShop;

	sprintf( buf,
	  "Shop data for [%5d]:\n\r"
	  "  Markup for purchaser: %d%%\n\r"
	  "  Markdown for seller:  %d%%\n\r",
	    pShop->keeper, pShop->profit_buy, pShop->profit_sell );
	send_to_char( buf, ch );
	sprintf( buf, "  Hours: %d to %d.\n\r",
	    pShop->open_hour, pShop->close_hour );
	send_to_char( buf, ch );

	for ( iTrade = 0; iTrade < MAX_TRADE; iTrade++ )
	{
	    if ( pShop->buy_type[iTrade] != 0 )
	    {
		if ( iTrade == 0 ) {
		    send_to_char( "  Number Trades Type\n\r", ch );
		    send_to_char( "  ------ -----------\n\r", ch );
		}
		sprintf( buf, "  [%4d] %s\n\r", iTrade,
		    flag_string( type_flags, pShop->buy_type[iTrade] ) );
		send_to_char( buf, ch );
	    }
	}
    }

    return FALSE;
}



bool medit_create( CHAR_DATA *ch, char *argument )
{
    MOB_INDEX_DATA *pMob;
    AREA_DATA *pArea;
    int  value;
    int  iHash;

    value = atoi( argument );

    /* OLC 1.1b */
    if ( argument[0] == '\0' || value <= 0 || value >= INT_MAX )
    {
	char output[MAX_STRING_LENGTH];

	sprintf( output, "Syntax:  create [0 < vnum < %d]\n\r", INT_MAX );
	send_to_char( output, ch );
	return FALSE;
    }

    pArea = get_vnum_area( value );

    if ( !pArea )
    {
	send_to_char( "MEdit:  That vnum is not assigned an area.\n\r", ch );
	return FALSE;
    }

    if ( !IS_BUILDER( ch, pArea ) )
    {
	send_to_char( "MEdit:  Vnum in an area you cannot build in.\n\r", ch );
	return FALSE;
    }

    if ( get_mob_index( value ) )
    {
	send_to_char( "MEdit:  Mobile vnum already exists.\n\r", ch );
	return FALSE;
    }

    pMob			= new_mob_index();
    pMob->vnum			= value;
    pMob->area			= pArea;
        
    if ( value > top_vnum_mob )
	top_vnum_mob = value;        

    pMob->act			= ACT_IS_NPC;
    iHash			= value % MAX_KEY_HASH;
    pMob->next			= mob_index_hash[iHash];
    mob_index_hash[iHash]	= pMob;
    ch->desc->pEdit		= (void *)pMob;

    send_to_char( "Mobile Created.\n\r", ch );
    return TRUE;
}



bool medit_spec( CHAR_DATA *ch, char *argument )
{
    MOB_INDEX_DATA *pMob;

    EDIT_MOB(ch, pMob);

    if ( argument[0] == '\0' )
    {
	send_to_char( "Syntax:  spec [special function]\n\r", ch );
	return FALSE;
    }


    if ( !str_cmp( argument, "none" ) )
    {
        pMob->spec_fun = NULL;

        send_to_char( "Spec removed.\n\r", ch);
        return TRUE;
    }

    if ( spec_lookup( argument ) )
    {
	pMob->spec_fun = spec_lookup( argument );
	send_to_char( "Spec set.\n\r", ch);
	return TRUE;
    }

    send_to_char( "MEdit: No such special function.\n\r", ch );
    return FALSE;
}



bool medit_align( CHAR_DATA *ch, char *argument )
{
    MOB_INDEX_DATA *pMob;

    EDIT_MOB(ch, pMob);

    if ( argument[0] == '\0' || !is_number( argument ) )
    {
	send_to_char( "Syntax:  alignment [number]\n\r", ch );
	return FALSE;
    }

    pMob->alignment = atoi( argument );

    send_to_char( "Alignment set.\n\r", ch);
    return TRUE;
}



bool medit_level( CHAR_DATA *ch, char *argument )
{
    MOB_INDEX_DATA *pMob;

    EDIT_MOB(ch, pMob);

    if ( argument[0] == '\0' || !is_number( argument ) )
    {
	send_to_char( "Syntax:  level [number]\n\r", ch );
	return FALSE;
    }

    pMob->level = atoi( argument );

    send_to_char( "Level set.\n\r", ch);
    return TRUE;
}



bool medit_desc( CHAR_DATA *ch, char *argument )
{
    MOB_INDEX_DATA *pMob;

    EDIT_MOB(ch, pMob);

    if ( argument[0] == '\0' )
    {
	string_append( ch, &pMob->description );
	return TRUE;
    }

    send_to_char( "Syntax:  desc    - line edit\n\r", ch );
    return FALSE;
}




bool medit_long( CHAR_DATA *ch, char *argument )
{
    MOB_INDEX_DATA *pMob;

    EDIT_MOB(ch, pMob);

    if ( argument[0] == '\0' )
    {
	send_to_char( "Syntax:  long [string]\n\r", ch );
	return FALSE;
    }

    free_string( pMob->long_descr );
    strcat( argument, "\n\r" );
    pMob->long_descr = str_dup( argument );
    pMob->long_descr[0] = UPPER( pMob->long_descr[0]  );

    send_to_char( "Long description set.\n\r", ch);
    return TRUE;
}



bool medit_short( CHAR_DATA *ch, char *argument )
{
    MOB_INDEX_DATA *pMob;

    EDIT_MOB(ch, pMob);

    if ( argument[0] == '\0' )
    {
	send_to_char( "Syntax:  short [string]\n\r", ch );
	return FALSE;
    }

    free_string( pMob->short_descr );
    pMob->short_descr = str_dup( argument );

    send_to_char( "Short description set.\n\r", ch);
    return TRUE;
}



bool medit_name( CHAR_DATA *ch, char *argument )
{
    MOB_INDEX_DATA *pMob;

    EDIT_MOB(ch, pMob);

    if ( argument[0] == '\0' )
    {
	send_to_char( "Syntax:  name [string]\n\r", ch );
	return FALSE;
    }

    free_string( pMob->player_name );
    pMob->player_name = str_dup( argument );

    send_to_char( "Name set.\n\r", ch);
    return TRUE;
}




bool medit_shop( CHAR_DATA *ch, char *argument )
{
    MOB_INDEX_DATA *pMob;
    char command[MAX_INPUT_LENGTH];
    char arg1[MAX_INPUT_LENGTH];

    argument = one_argument( argument, command );
    argument = one_argument( argument, arg1 );

    EDIT_MOB(ch, pMob);

    if ( command[0] == '\0' )
    {
	send_to_char( "Syntax:  shop hours [#opening] [#closing]\n\r", ch );
	send_to_char( "         shop profit [#buying%] [#selling%]\n\r", ch );
	send_to_char( "         shop type [#0-4] [item type]\n\r", ch );
	send_to_char( "         shop delete [#0-4]\n\r", ch );
	return FALSE;
    }


    if ( !str_cmp( command, "hours" ) )
    {
	if ( arg1[0] == '\0' || !is_number( arg1 )
	|| argument[0] == '\0' || !is_number( argument ) )
	{
	    send_to_char( "Syntax:  shop hours [#opening] [#closing]\n\r", ch );
	    return FALSE;
	}

	if ( !pMob->pShop )
	{
	    pMob->pShop         = new_shop();
	    pMob->pShop->keeper = pMob->vnum;
	    shop_last->next     = pMob->pShop;
	}

	pMob->pShop->open_hour = atoi( arg1 );
	pMob->pShop->close_hour = atoi( argument );

	send_to_char( "Shop hours set.\n\r", ch);
	return TRUE;
    }


    if ( !str_cmp( command, "profit" ) )
    {
	if ( arg1[0] == '\0' || !is_number( arg1 )
	|| argument[0] == '\0' || !is_number( argument ) )
	{
	    send_to_char( "Syntax:  shop profit [#buying%] [#selling%]\n\r", ch );
	    return FALSE;
	}

	if ( !pMob->pShop )
	{
	    pMob->pShop         = new_shop();
	    pMob->pShop->keeper = pMob->vnum;
	    shop_last->next     = pMob->pShop;
	}

	pMob->pShop->profit_buy     = atoi( arg1 );
	pMob->pShop->profit_sell    = atoi( argument );

	send_to_char( "Shop profit set.\n\r", ch);
	return TRUE;
    }


    if ( !str_cmp( command, "type" ) )
    {
	char buf[MAX_INPUT_LENGTH];
	int value;

	if ( arg1[0] == '\0' || !is_number( arg1 )
	|| argument[0] == '\0' )
	{
	    send_to_char( "Syntax:  shop type [#0-4] [item type]\n\r", ch );
	    return FALSE;
	}

	if ( atoi( arg1 ) >= MAX_TRADE )
	{
	    sprintf( buf, "REdit:  May sell %d items max.\n\r", MAX_TRADE );
	    send_to_char( buf, ch );
	    return FALSE;
	}

	if ( ( value = flag_value( type_flags, argument ) ) == NO_FLAG )
	{
	    send_to_char( "REdit:  That type of item is not known.\n\r", ch );
	    return FALSE;
	}

	if ( !pMob->pShop )
	{
	    pMob->pShop         = new_shop();
	    pMob->pShop->keeper = pMob->vnum;
	    shop_last->next     = pMob->pShop;
	}

	pMob->pShop->buy_type[atoi( arg1 )] = value;

	send_to_char( "Shop type set.\n\r", ch);
	return TRUE;
    }


    if ( !str_cmp( command, "delete" ) )
    {
	SHOP_DATA *pShop;
	SHOP_DATA *pShop_next;
	int value;
	int cnt = 0;
	
	if ( arg1[0] == '\0' || !is_number( arg1 ) )
	{
	    send_to_char( "Syntax:  shop delete [#0-4]\n\r", ch );
	    return FALSE;
	}

	value = atoi( argument );
	
	if ( !pMob->pShop )
	{
	    send_to_char( "REdit:  Non-existant shop.\n\r", ch );
	    return FALSE;
	}

	if ( value == 0 )
	{
	    pShop = pMob->pShop;
	    pMob->pShop = pMob->pShop->next;
	    free_shop( pShop );
	}
	else
	for ( pShop = pMob->pShop, cnt = 0; pShop; pShop = pShop_next, cnt++ )
	{
	    pShop_next = pShop->next;
	    if ( cnt+1 == value )
	    {
		pShop->next = pShop_next->next;
		free_shop( pShop_next );
		break;
	    }
	}

	send_to_char( "Shop deleted.\n\r", ch);
	return TRUE;
    }

    medit_shop( ch, "" );
    return FALSE;
}


/*
help editor by blade */
HEDIT( hedit_level )
{
    HELP_DATA *pHelp;

    EDIT_HELP(ch, pHelp);

    if ( argument[0] == '\0' || !is_number( argument ) )
    {
	send_to_char( "Syntax:  level [number]\n\r", ch );
	return FALSE;
    }

    pHelp->level = atoi( argument );

    send_to_char( "Level set.\n\r", ch);
    return TRUE;
}
/* reset keyword */
HEDIT( hedit_keyword )
{
    HELP_DATA *pHelp;
	HELP_DATA *tHelp;

    EDIT_HELP(ch, pHelp);

    if ( !is_number( argument ) )    {
	for (tHelp = help_first; tHelp != NULL; tHelp = tHelp->next )
    {
	if (is_name(argument, tHelp->keyword))
    { send_to_char("{b That keyword already exits.{x\n\r", ch);
			   return FALSE; }
    }
pHelp->keyword = str_dup(argument);
	return TRUE;
    }
	send_to_char("Syntax: keyword [word(s)]\n\r", ch);
    return FALSE;
}

/* mod current help text */
HEDIT( hedit_text )
{
	HELP_DATA *pHelp;
	
	EDIT_HELP(ch, pHelp);

	if ( argument[0] == '\0')
    {
    string_append( ch, &pHelp->text );	
	return TRUE;
    }
else {
	send_to_char("Syntax: text [no arguments!]\n\r", ch);
	return FALSE;
}
}

/* kill a help */
HEDIT( hedit_delete )
{		
		extern int top_help;
	extern HELP_DATA *help_last;	
	HELP_DATA *target;
	HELP_DATA *previous;
	
	previous = NULL;

	
if (argument[0] == '\0')
	{
	send_to_char("{r Synatx: Hedit delete 'keyword'{x\n\r", ch);
		return FALSE;
	}
for(target = help_first; target != NULL; target = target->next)
{
 if (is_name(argument, target->keyword))
 {
	 if (target == help_first)
	 {
		 previous = target->next;
		 help_first = previous;
		 top_help--;
		 send_to_char("{rHelp removed.{x\n\r", ch);
		 return TRUE;
	 }
	 else if (target == help_last)
	 {
  previous->next = NULL;
  help_last = previous;
  top_help--;
  send_to_char("{rHelp removed.{x\n\r", ch);
  return TRUE;
	 }

	 else {
  previous->next = target->next; 
  top_help--;
  send_to_char("{rHelp removed.{x\n\r", ch);
  return TRUE;
	 }
 }
 previous = target; /* set previous to last target */
}
send_to_char(" {rNo Help with that keyword found to delete!{x\n\r", ch);
return FALSE;
}

/* mod an existing help - throw into text editor */
HEDIT( hedit_change )
{
HELP_DATA *tHelp;

if (argument[0] == '\0')
	{
	send_to_char(" Syntax: Hedit change 'keyword'\n\r", ch);
		return FALSE;
	}
for (tHelp = help_first; tHelp != NULL; tHelp = tHelp->next )
{
	if (is_name(argument, tHelp->keyword))
{ send_to_char(" Help found, Entering String editor\n\r", ch);

	ch->desc->pEdit		= (void *)tHelp;
 send_to_char( tHelp->keyword, ch);
 send_to_char("\n\r", ch);

string_append( ch, &tHelp->text );
return TRUE;
	}
}
send_to_char(" {bNo Help by that keyword available,\n\r  Try 'hedit index' for a listing of current helps.{x\n\r Remember, keywords must match exactly!\n\r", ch);
	return FALSE;
}

/* list all helps by keyword */
HEDIT( hedit_index)
{
HELP_DATA *pHelp;
int level;
	char output[MAX_STRING_LENGTH];
        char buf[MAX_STRING_LENGTH];
                int bob;

        for ( pHelp = help_first; pHelp != NULL; pHelp = pHelp->next )
    {
        level = (pHelp->level < 0) ? -1 * pHelp->level - 1 : pHelp->level;
 
        if (level > get_trust( ch ) )
            continue;
        sprintf(buf,"%-17.16s  ", pHelp->keyword);
        strcat(output, buf);
                if (++bob % 3 == 0)  /* column check */
                strcat(output, "\n\r");
        }
        send_to_char(output,ch);
        send_to_char("\n\r", ch);
        return TRUE;
}


/* create a new help */
HEDIT( hedit_create )
{
	extern int top_help;
	extern HELP_DATA *help_last;
	HELP_DATA *pHelp;
	HELP_DATA *tHelp;	

if (argument[0] == '\0')
	{
	send_to_char("{r Synatx: Hedit create 'keyword'{x\n\r", ch);
		return FALSE;
	}

for (tHelp = help_first; tHelp != NULL; tHelp = tHelp->next )
{
	if (is_name(argument, tHelp->keyword))
{ send_to_char("{b That Help already exits.{x\n\r", ch);
			   return FALSE; }
}
/* make the help in memory and initialize */

pHelp = new_help();
pHelp->level = 0;
pHelp->keyword = str_dup(argument);
if ( help_first == NULL )
	    help_first = pHelp;
	if ( help_last  != NULL )
	    help_last->next = pHelp;

	help_last	= pHelp;
	pHelp->next	= NULL;
	top_help++;
    
pHelp->text = str_dup(" ");

 ch->desc->pEdit		= (void *)pHelp;
 send_to_char( pHelp->keyword, ch);
 send_to_char("{x\n\r", ch);

string_append( ch, &pHelp->text );


	return TRUE;
}





 *  File: olc_save.c                                                       *
 *                                                                         *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 *                                                                         *
 *  This code was freely distributed with the The Isles 1.1 source code,   *
 *  and has been used here for OLC - OLC would not be what it is without   *
 *  all the previous coders who released their source code.                *
 *                                                                         *
 ***************************************************************************/
/* OLC_SAVE.C
 * This takes care of saving all the .are information.
 * Notes:
 * -If a good syntax checker is used for setting vnum ranges of areas
 *  then it would become possible to just cycle through vnums instead
 *  of using the iHash stuff and checking that the room or reset or
 *  mob etc is part of that area.
 */

#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"
#include "olc.h"




/*****************************************************************************
 Name:		fix_string
 Purpose:	Returns a string without \r and ~.
 ****************************************************************************/
char *fix_string( const char *str )
{
    static char strfix[MAX_STRING_LENGTH];
    int i;
    int o;

    if ( str == NULL )
        return '\0';

    for ( o = i = 0; str[i+o] != '\0'; i++ )
    {
        if (str[i+o] == '\r' || str[i+o] == '~')
            o++;
        strfix[i] = str[i+o];
    }
    strfix[i] = '\0';
    return strfix;
}



/*****************************************************************************
 Name:		save_area_list
 Purpose:	Saves the listing of files to be loaded at startup.
 Called by:	do_asave(olc_save.c).
 ****************************************************************************/
void save_area_list()
{
    FILE *fp;
    AREA_DATA *pArea;

    if ( ( fp = fopen( "area.lst", "w" ) ) == NULL )
    {
	bug( "Save_area_list: fopen", 0 );
	perror( "area.lst" );
    }
    else
    {
	/*
	 * Add any help files that need to be loaded at
	 * startup to this section.
	 */
	fprintf( fp, "help.are\n" );

	for( pArea = area_first; pArea; pArea = pArea->next )
	{
	    fprintf( fp, "%s\n", pArea->filename );
	}

	fprintf( fp, "$\n" );
	fclose( fp );
    }

    return;
}



/*****************************************************************************
 Name:		save_mobiles
 Purpose:	Save #MOBILES secion of an area file.
 Called by:	save_area(olc_save.c).
 ****************************************************************************/
void save_mobiles( FILE *fp, AREA_DATA *pArea )
{
    int vnum;
    MOB_INDEX_DATA *pMobIndex;

    fprintf( fp, "#MOBILES\n" );
    for( vnum = pArea->lvnum; vnum <= pArea->uvnum; vnum++ )
    {
	if( ( pMobIndex = get_mob_index(vnum) ) )
	{
	    if ( pMobIndex->area == pArea )
            {
                fprintf( fp, "#%d\n",		pMobIndex->vnum );
                fprintf( fp, "%s~\n",		pMobIndex->player_name );
                fprintf( fp, "%s~\n",		pMobIndex->short_descr );
                fprintf( fp, "%s~\n",		fix_string( pMobIndex->long_descr ) );
                fprintf( fp, "%s~\n",		fix_string( pMobIndex->description ) );
                fprintf( fp, "%d ",		pMobIndex->act );
                fprintf( fp, "%d ",		pMobIndex->affected_by );
                fprintf( fp, "%d S\n",		pMobIndex->alignment );
                fprintf( fp, "%d ",		pMobIndex->level );
                fprintf( fp, "%d ",		pMobIndex->hitroll );
                fprintf( fp, "%d ",		pMobIndex->ac );
                fprintf( fp, "%dd%d+%d ",	pMobIndex->hitnodice, 
                                                pMobIndex->hitsizedice, 
                                                pMobIndex->hitplus );
                fprintf( fp, "%dd%d+%d\n",	pMobIndex->damnodice, 
                                                pMobIndex->damsizedice, 
                                                pMobIndex->damplus );
                fprintf( fp, "%d ",		pMobIndex->gold );
		fprintf( fp, "0\n0 0 " );
                fprintf( fp, "%d\n",  pMobIndex->sex );
            }
        }
    }
    fprintf( fp, "#0\n\n\n\n" );
    return;
}



/*****************************************************************************
 Name:		save_objects
 Purpose:	Save #OBJECTS section of an area file.
 Called by:	save_area(olc_save.c).
 ****************************************************************************/
void save_objects( FILE *fp, AREA_DATA *pArea )
{
    int vnum;
    OBJ_INDEX_DATA *pObjIndex;
    AFFECT_DATA *pAf;
    EXTRA_DESCR_DATA *pEd;

    fprintf( fp, "#OBJECTS\n" );
    for( vnum = pArea->lvnum; vnum <= pArea->uvnum; vnum++ )
    {
	if( ( pObjIndex = get_obj_index(vnum) ) )
	{
	    if ( pObjIndex->area == pArea )
            {
                fprintf( fp, "#%d\n",    pObjIndex->vnum );
                fprintf( fp, "%s~\n",    pObjIndex->name );
                fprintf( fp, "%s~\n",    pObjIndex->short_descr );
                fprintf( fp, "%s~\n",    fix_string( pObjIndex->description ) );
                fprintf( fp, "~\n" );
                fprintf( fp, "%d ",      pObjIndex->item_type );
                fprintf( fp, "%d ",      pObjIndex->extra_flags );
                fprintf( fp, "%d\n",     pObjIndex->wear_flags);

                switch ( pObjIndex->item_type )
                {
                default:
                fprintf( fp, "%d %d %d %d\n",
			pObjIndex->value[0],
			pObjIndex->value[1],
			pObjIndex->value[2],
			pObjIndex->value[3] );
                    break;
               case ITEM_PILL:
                case ITEM_POTION:
                case ITEM_SCROLL:
                fprintf( fp, "%d '%s' '%s' '%s'\n",
                        pObjIndex->value[0],   
                        pObjIndex->value[1] != -1 ?
                              skill_table[pObjIndex->value[1]].name
                            : " ",
                        pObjIndex->value[2] != -1 ?
                              skill_table[pObjIndex->value[2]].name
                            : " ",
                        pObjIndex->value[3] != -1 ?
                              skill_table[pObjIndex->value[3]].name
                            : " " );
                    break;
                
                case ITEM_STAFF: 
                case ITEM_WAND:
                fprintf( fp, "%d %d %d '%s'\n",
                        pObjIndex->value[0],
                        pObjIndex->value[1],
                        pObjIndex->value[2],
                        pObjIndex->value[3] != -1 ?
                              skill_table[pObjIndex->value[3]].name
                            : " " );
                    break;
                }
                fprintf( fp, "%d ", pObjIndex->weight );
                fprintf( fp, "%d 0\n", pObjIndex->cost );

                for( pAf = pObjIndex->affected; pAf; pAf = pAf->next )
                {
                fprintf( fp, "A\n%d %d\n",  pAf->location, pAf->modifier );
                }

                for( pEd = pObjIndex->extra_descr; pEd; pEd = pEd->next )
                {
                fprintf( fp, "E\n%s~\n%s~\n", pEd->keyword,
                                              fix_string( pEd->description ) );
                }
		fprintf( fp, "Q\n%s~\n%s~\n%s~\n%s~\n%s~\n%s~\n%d %d\n",
		pObjIndex->chpoweron, pObjIndex->chpoweroff, 
		pObjIndex->chpoweruse, pObjIndex->victpoweron,
		pObjIndex->victpoweroff, pObjIndex->victpoweruse,
		pObjIndex->spectype, pObjIndex->specpower);
            }
        }
    }
    fprintf( fp, "#0\n\n\n\n" );
    return;
}



/* OLC 1.1b */
/*****************************************************************************
 Name:		save_rooms
 Purpose:	Save #ROOMDATA section of an area file.
 Called by:	save_area(olc_save.c).
 ****************************************************************************/
void save_rooms( FILE *fp, AREA_DATA *pArea )
{
    ROOM_INDEX_DATA *pRoomIndex;
    EXTRA_DESCR_DATA *pEd;
    ROOMTEXT_DATA *prt;
    EXIT_DATA *pExit;
    int vnum;
    int door;

    fprintf( fp, "#ROOMDATA\n" );
    for( vnum = pArea->lvnum; vnum <= pArea->uvnum; vnum++ )
    {
	if( ( pRoomIndex = get_room_index(vnum) ) )
	{
	    if ( pRoomIndex->area == pArea )
	    {
		fprintf( fp, "#%d\n", pRoomIndex->vnum );
		fprintf( fp, "%s~\n", pRoomIndex->name );
		fprintf( fp, "%s~\n", fix_string( pRoomIndex->description ) );
		fprintf( fp, "0 " );
		fprintf( fp, "%d ", pRoomIndex->room_flags );
		fprintf( fp, "%d\n", pRoomIndex->sector_type );

		for ( pEd = pRoomIndex->extra_descr; pEd; pEd = pEd->next )
                {
		    fprintf( fp, "E\n%s~\n%s~\n", pEd->keyword,
			fix_string( pEd->description ) );
                }
		for (prt = pRoomIndex->roomtext; prt; prt = prt->next )
		{
		fprintf(fp, "T\n%s~\n%s~\n%s~\n%s~\n%d %d %d\n",
		prt->input, prt->output, prt->choutput,
		prt->name, prt->type, prt->power, prt->mob);
		 
		}
		for( door = 0; door < MAX_DIR; door++ )
		{
		    if ( ( pExit = pRoomIndex->exit[door] ) )
		    {
			fprintf( fp, "D%d\n", door );
			fprintf( fp, "%s~\n",
			    fix_string( pExit->description ) );
			fprintf( fp, "%s~\n", pExit->keyword );
			fprintf( fp, "%d %d %d\n", pExit->rs_flags,
			    pExit->key,
			    pExit->to_room ? pExit->to_room->vnum : 0 );
		    }
		}
		fprintf( fp, "S\n" );
	    }
	}
    }
    fprintf( fp, "#0\n\n\n\n" );
    return;
}


/* OLC 1.1b */
/*****************************************************************************
 Name:		save_specials
 Purpose:	Save #SPECIALS section of area file.
 Called by:	save_area(olc_save.c).
 ****************************************************************************/
void save_specials( FILE *fp, AREA_DATA *pArea )
{
    int vnum;
    MOB_INDEX_DATA *pMobIndex;
    
    fprintf( fp, "#SPECIALS\n" );

    for( vnum = pArea->lvnum; vnum <= pArea->uvnum; vnum++ )
    {
	if( ( pMobIndex = get_mob_index(vnum) ) )
	{
	    if ( pMobIndex->area == pArea && pMobIndex->spec_fun )
            {
                fprintf( fp, "M %d %s\n", pMobIndex->vnum,
                                          spec_string( pMobIndex->spec_fun ) );
            }
        }
    }

    fprintf( fp, "S\n\n\n\n" );
    return;
}


/* OLC 1.1b */
/*****************************************************************************
 Name:		vsave_specials
 Purpose:	Save #SPECIALS section of area file.
 		New formating thanks to Rac.
 Called by:	save_area(olc_save.c).
 ****************************************************************************/
void vsave_specials( FILE *fp, AREA_DATA *pArea )
{
    int vnum;
    MOB_INDEX_DATA *pMobIndex;
    
    fprintf( fp, "#SPECIALS\n" );

    for( vnum = pArea->lvnum; vnum <= pArea->uvnum; vnum++ )
    {
	if( ( pMobIndex = get_mob_index(vnum) ) )
	{
	    if ( pMobIndex->area == pArea && pMobIndex->spec_fun )
            {
                fprintf( fp, "M %d %s \t; %s\n", pMobIndex->vnum,
                                                 spec_string( pMobIndex->spec_fun ),
                                                 pMobIndex->short_descr );
            }
        }
    }

    fprintf( fp, "S\n\n\n\n" );
    return;
}



/* OLC 1.1b */
/*****************************************************************************
 Name:		save_resets
 Purpose:	Saves the #RESETS section of an area file.
                New format thanks to Rac.
 Called by:	save_area(olc_save.c)
 ****************************************************************************/
void save_resets( FILE *fp, AREA_DATA *pArea )
{
    RESET_DATA *pReset;
    MOB_INDEX_DATA *pLastMob = NULL;
    OBJ_INDEX_DATA *pLastObj;
    ROOM_INDEX_DATA *pRoomIndex;
    char buf[MAX_STRING_LENGTH];
    int vnum;

    fprintf( fp, "#RESETS\n" );

    for( vnum = pArea->lvnum; vnum <= pArea->uvnum; vnum++ )
    {
	if( ( pRoomIndex = get_room_index(vnum) ) )
	{
	    if ( pRoomIndex->area == pArea )
	    {
    for ( pReset = pRoomIndex->reset_first; pReset; pReset = pReset->next )
    {
	switch ( pReset->command )
	{
	default:
	    bug( "Save_resets: bad command %c.", pReset->command );
	    break;

	case 'M':
            pLastMob = get_mob_index( pReset->arg1 );
	    fprintf( fp, "M 0 %d %d %d\n", 
	        pReset->arg1,
                pReset->arg2,
                pReset->arg3 );
            break;

	case 'O':
            pLastObj = get_obj_index( pReset->arg1 );
	    fprintf( fp, "O 0 %d 0 %d\n", 
	        pReset->arg1,
                pReset->arg3 );
            break;

	case 'P':
            pLastObj = get_obj_index( pReset->arg1 );
	    fprintf( fp, "P 0 %d 0 %d\n", 
	        pReset->arg1,
                pReset->arg3  );
            break;

	case 'G':
	    fprintf( fp, "G 0 %d 0\n", pReset->arg1 );
            if ( !pLastMob )
            {
                sprintf( buf,
                    "Save_resets: !NO_MOB! in [%s]", pArea->filename );
                bug( buf, 0 );
            }
            break;

	case 'E':
	    fprintf( fp, "E 0 %d 0 %d\n",
	        pReset->arg1,
                pReset->arg3 );
            if ( !pLastMob )
            {
                sprintf( buf,
                    "Save_resets: !NO_MOB! in [%s]", pArea->filename );
                bug( buf, 0 );
            }
            break;

	case 'D':
            break;

	case 'R':
	    fprintf( fp, "R 0 %d %d\n", 
	        pReset->arg1,
                pReset->arg2 );
            break;
        }	/* End switch */
    }	/* End for pReset */
	    }	/* End if correct area */
	}	/* End if pRoomIndex */
    }	/* End for vnum */
    fprintf( fp, "S\n\n\n\n" );
    return;
}



/* OLC 1.1b */
/*****************************************************************************
 Name:		save_resets
 Purpose:	Saves the #RESETS section of an area file.
                New format thanks to Rac.
 Called by:	save_area(olc_save.c)
 ****************************************************************************/
void vsave_resets( FILE *fp, AREA_DATA *pArea )
{
    RESET_DATA *pReset;
    MOB_INDEX_DATA *pLastMob = NULL;
    OBJ_INDEX_DATA *pLastObj;
    ROOM_INDEX_DATA *pRoomIndex;
    char buf[MAX_STRING_LENGTH];
    int vnum;

    fprintf( fp, "#RESETS\n" );

    for( vnum = pArea->lvnum; vnum <= pArea->uvnum; vnum++ )
    {
	if( ( pRoomIndex = get_room_index(vnum) ) )
	{
	    if ( pRoomIndex->area == pArea )
	    {
    for ( pReset = pRoomIndex->reset_first; pReset; pReset = pReset->next )
    {
	switch ( pReset->command )
	{
	default:
	    bug( "Save_resets: bad command %c.", pReset->command );
	    break;

	case 'M':
            pLastMob = get_mob_index( pReset->arg1 );
	    fprintf( fp, "M 0 %d %2d %-5d \t; %s to %s\n", 
	        pReset->arg1,
                pReset->arg2,
                pReset->arg3,
                pLastMob->short_descr,
                pRoomIndex->name );
            break;

	case 'O':
            pLastObj = get_obj_index( pReset->arg1 );
	    fprintf( fp, "O 0 %d  0 %-5d \t; %s to %s\n", 
	        pReset->arg1,
                pReset->arg3,
                capitalize(pLastObj->short_descr),
                pRoomIndex->name );
            break;

	case 'P':
            pLastObj = get_obj_index( pReset->arg1 );
	    fprintf( fp, "P 0 %d  0 %-5d \t; %s inside %s\n", 
	        pReset->arg1,
                pReset->arg3,
                capitalize(get_obj_index( pReset->arg1 )->short_descr),
                pLastObj ? pLastObj->short_descr : "!NO_OBJ!" );

            if ( !pLastObj )	/* Thanks Rac! */
            {
                sprintf( buf, "Save_resets: P with !NO_OBJ! in [%s]", pArea->filename );
                bug( buf, 0 );
            }

            break;

	case 'G':
            pLastObj = get_obj_index( pReset->arg1 );
	    fprintf( fp, "G 0 %d  0      \t;   %s\n",
	        pReset->arg1,
	        capitalize(pLastObj->short_descr) );

            if ( !pLastMob )
            {
                sprintf( buf, "Save_resets: !NO_MOB! in [%s]", pArea->filename );
                bug( buf, 0 );
            }
            break;

	case 'E':
	    fprintf( fp, "E 0 %d  0 %-5d \t;   %s %s\n",
	        pReset->arg1,
                pReset->arg3,
                capitalize(get_obj_index( pReset->arg1 )->short_descr),
                flag_string( wear_loc_strings, pReset->arg3 ) );
            if ( !pLastMob )
            {
                sprintf( buf, "Save_resets: !NO_MOB! in [%s]", pArea->filename );
                bug( buf, 0 );
            }
            break;

	case 'D':
            break;

	case 'R':
	    fprintf( fp, "R 0 %d %2d      \t; Randomize %s\n", 
	        pReset->arg1,
                pReset->arg2,
                pRoomIndex->name );
            break;
        }	/* End switch */
    }	/* End for pReset */
	    }	/* End if correct area */
	}	/* End if pRoomIndex */
    }	/* End for vnum */
    fprintf( fp, "S\n\n\n\n" );
    return;
}



/* OLC 1.1b */
/*****************************************************************************
 Name:		save_shops
 Purpose:	Saves the #SHOPS section of an area file.
 Called by:	save_area(olc_save.c)
 ****************************************************************************/
void save_shops( FILE *fp, AREA_DATA *pArea )
{
    SHOP_DATA *pShopIndex;
    MOB_INDEX_DATA *pMobIndex;
    int iTrade;
    int vnum;
    
    fprintf( fp, "#SHOPS\n" );

    for( vnum = pArea->lvnum; vnum <= pArea->uvnum; vnum++ )
    {
	if( ( pMobIndex = get_mob_index(vnum) ) )
	{
	    if ( pMobIndex->area == pArea && pMobIndex->pShop )
            {
                pShopIndex = pMobIndex->pShop;

                fprintf( fp, "%d ", pShopIndex->keeper );
                for ( iTrade = 0; iTrade < MAX_TRADE; iTrade++ )
                {
                    if ( pShopIndex->buy_type[iTrade] != 0 )
                    {
                       fprintf( fp, "%d ", pShopIndex->buy_type[iTrade] );
                    }
                    else
                       fprintf( fp, "0 ");
                }
                fprintf( fp, "%d %d ", pShopIndex->profit_buy, pShopIndex->profit_sell );
                fprintf( fp, "%d %d\n", pShopIndex->open_hour, pShopIndex->close_hour );
            }
        }
    }

    fprintf( fp, "0\n\n\n\n" );
    return;
}



/* OLC 1.1b */
/*****************************************************************************
 Name:		vsave_shops
 Purpose:	Saves the #SHOPS section of an area file.
                New formating thanks to Rac.
 Called by:	save_area(olc_save.c)
 ****************************************************************************/
void vsave_shops( FILE *fp, AREA_DATA *pArea )
{
    SHOP_DATA *pShopIndex;
    MOB_INDEX_DATA *pMobIndex;
    int iTrade;
    int vnum;
    
    fprintf( fp, "#SHOPS\n" );

    for( vnum = pArea->lvnum; vnum <= pArea->uvnum; vnum++ )
    {
	if( ( pMobIndex = get_mob_index(vnum) ) )
	{
	    if ( pMobIndex->area == pArea && pMobIndex->pShop )
            {
                pShopIndex = pMobIndex->pShop;

                fprintf( fp, "%d ", pShopIndex->keeper );
                for ( iTrade = 0; iTrade < MAX_TRADE; iTrade++ )
                {
                    if ( pShopIndex->buy_type[iTrade] != 0 )
                    {
                       fprintf( fp, "%2d ", pShopIndex->buy_type[iTrade] );
                    }
                    else
                       fprintf( fp, " 0 ");
                }
                fprintf( fp, "%3d %3d ", pShopIndex->profit_buy, pShopIndex->profit_sell );
                fprintf( fp, "%2d %2d ", pShopIndex->open_hour, pShopIndex->close_hour );
                fprintf( fp, "\t; %s\n", get_mob_index( pShopIndex->keeper )->short_descr );
            }
        }
    }

    fprintf( fp, "0\n\n\n\n" );
    return;
}



/*****************************************************************************
 Name:		save_helps
 Purpose:	Save #HELPS section of an area file.
 Written by:	Walker <nkrendel@evans.Denver.Colorado.EDU>
 Called by:	save_area(olc_save.c).
 ****************************************************************************/

void save_help()
{
	FILE *fp;
	HELP_DATA *pHelp;
	char ack[10];
	rename( "help.are", "help.bak");
	if((fp=fopen( "help.are", "w")) == NULL)
	{		bug( "save_helps: fopen", 0);
	perror( "help.are" );
}
	fprintf( fp, "#HELPS\n\n");

	for ( pHelp = help_first; pHelp != NULL; pHelp = pHelp->next ){
	 	sprintf(ack, "%d", pHelp->level);
		fprintf( fp, ack);
	fprintf(fp, " ");
	fprintf(fp, pHelp->keyword);
	fprintf(fp, "~\n");
	fprintf(fp, fix_string(pHelp->text));
	fprintf(fp, "~\n\n");
	}
	fprintf(fp, "0 $~\n\n#$\n");
	fclose( fp );
}
void save_helps( FILE *fp, AREA_DATA *pArea )
{
    HELP_DATA *pHelp;
    bool found = FALSE;

    for( pHelp = help_first; pHelp; pHelp = pHelp->next )
    {
        if( pHelp->area && pHelp->area == pArea )
	{
	    if( !found )
	    {
		fprintf( fp, "#HELPS\n\n" );
		found = TRUE;
	    }
	    fprintf( fp, "%d %s~\n%s~\n", 
		pHelp->level,
		all_capitalize( pHelp->keyword ), 
		fix_string( pHelp->text ) );
	}
    }

    if( found )
        fprintf( fp, "\n0 $~\n\n" );

    return;
}



/*****************************************************************************
 Name:		save_area
 Purpose:	Save an area, note that this format is new.
 Called by:	do_asave(olc_save.c).
 ****************************************************************************/
void save_area( AREA_DATA *pArea )
{
    FILE *fp;

    fclose( fpReserve );
    if ( !( fp = fopen( pArea->filename, "w" ) ) )
    {
	bug( "Open_area: fopen", 0 );
	perror( pArea->filename );
    }

    fprintf( fp, "#AREADATA\n" );
    fprintf( fp, "Name        %s~\n",        pArea->name );
    fprintf( fp, "Builders    %s~\n",        fix_string( pArea->builders ) );
    fprintf( fp, "VNUMs       %d %d\n",      pArea->lvnum, pArea->uvnum );
    fprintf( fp, "Security    %d\n",         pArea->security );
    fprintf( fp, "Recall      %d\n",         pArea->recall );
    fprintf( fp, "End\n\n\n\n" );

    save_helps( fp, pArea );				/* OLC 1.1b */
    save_mobiles( fp, pArea );
    save_objects( fp, pArea );
    save_rooms( fp, pArea );

    if ( IS_SET(pArea->area_flags, AREA_VERBOSE) )	/* OLC 1.1b */
    {
	vsave_specials( fp, pArea );
	vsave_resets( fp, pArea );
	vsave_shops( fp, pArea );
    }
    else
    {
	save_specials( fp, pArea );
	save_resets( fp, pArea );
	save_shops( fp, pArea );
    }

    fprintf( fp, "#$\n" );

    fclose( fp );
    fpReserve = fopen( NULL_FILE, "r" );
    return;
}


/* OLC 1.1b */
/*****************************************************************************
 Name:		do_asave
 Purpose:	Entry point for saving area data.
 Called by:	interpreter(interp.c)
 ****************************************************************************/
void do_asave( CHAR_DATA *ch, char *argument )
{
    char arg1 [MAX_INPUT_LENGTH];
    AREA_DATA *pArea;
    int value;



    if ( !ch )       /* Do an autosave */
    {
	save_area_list();
	for( pArea = area_first; pArea; pArea = pArea->next )
	{
	    save_area( pArea );
	    REMOVE_BIT( pArea->area_flags, AREA_CHANGED | AREA_ADDED );
	}
	return;
    }
	if (IS_NPC(ch)) return;

	if (ch->pcdata->security < 2) {
	send_to_char("Huh?\n\r", ch );
	return;}

    argument = one_argument( argument, arg1 );

    if ( arg1[0] == '\0' )
    {
    send_to_char( "Syntax:\n\r", ch );
    send_to_char( "  asave <vnum>    - saves a particular area\n\r",	 ch );
    send_to_char( "  asave list      - saves the area.lst file\n\r",	 ch );
    send_to_char( "  asave helps    - saves the help file\n\r",	ch );
    send_to_char( "  asave area      - saves the area being edited\n\r", ch );
    send_to_char( "  asave changed   - saves all changed zones\n\r",	 ch );
    send_to_char( "  asave world     - saves the world! (db dump)\n\r",	 ch );
    send_to_char( "  asave ^ verbose - saves in verbose mode\n\r", ch );
    send_to_char( "\n\r", ch );
        return;
    }

    /* Snarf the value (which need not be numeric). */
    value = atoi( arg1 );

    /* Save the area of given vnum. */
    /* ---------------------------- */

    if ( !( pArea = get_area_data( value ) ) && is_number( arg1 ) )
    {
	send_to_char( "That area does not exist.\n\r", ch );
	return;
    }

    if ( is_number( arg1 ) )
    {
	if ( !IS_BUILDER( ch, pArea ) )
	{
	    send_to_char( "You are not a builder for this area.\n\r", ch );
	    return;
	}

	save_area_list();
	if ( !str_cmp( "verbose", argument ) )
	    SET_BIT( pArea->area_flags, AREA_VERBOSE );
	save_area( pArea );
	REMOVE_BIT( pArea->area_flags, AREA_VERBOSE );
	return;
    }

    /* Save the world, only authorized areas. */
    /* -------------------------------------- */

    if ( !str_cmp( "world", arg1 ) )
    {
	save_area_list();
	for( pArea = area_first; pArea; pArea = pArea->next )
	{
	    /* Builder must be assigned this area. */
	    if ( !IS_BUILDER( ch, pArea ) )
		continue;	  

	    if ( !str_cmp( "verbose", argument ) )
		SET_BIT( pArea->area_flags, AREA_VERBOSE );
	    save_area( pArea );
	    REMOVE_BIT( pArea->area_flags, AREA_CHANGED | AREA_ADDED | AREA_VERBOSE );
	}
	send_to_char( "You saved the world.\n\r", ch );
	return;
    }
/*
	if (!str_cmp(arg1, "helps"))
	{
		
		if (ch->level > 6){
			save_help();
			send_to_char(" Helps saved.\n\r", ch);
		}
		return;
	}
*/

    /* Save changed areas, only authorized areas. */
    /* ------------------------------------------ */

    if ( !str_cmp( "changed", arg1 ) )
    {
	char buf[MAX_INPUT_LENGTH];

	save_area_list();

	send_to_char( "Saved zones:\n\r", ch );
	sprintf( buf, "None.\n\r" );

	for( pArea = area_first; pArea; pArea = pArea->next )
	{
	    /* Builder must be assigned this area. */
	    if ( !IS_BUILDER( ch, pArea ) )
		continue;

	    /* Save changed areas. */
	    if ( IS_SET(pArea->area_flags, AREA_CHANGED)
	      || IS_SET(pArea->area_flags, AREA_ADDED) )
	    {
		if ( !str_cmp( "verbose", argument ) )
		    SET_BIT( pArea->area_flags, AREA_VERBOSE );
		save_area( pArea );
		REMOVE_BIT( pArea->area_flags, AREA_CHANGED | AREA_ADDED | AREA_VERBOSE );
		sprintf( buf, "%24s - '%s'\n\r", pArea->name, pArea->filename );
		send_to_char( buf, ch );
	    }
        }
	if ( !str_cmp( buf, "None.\n\r" ) )
	    send_to_char( buf, ch );
        return;
    }

    /* Save the area.lst file. */
    /* ----------------------- */
    if ( !str_cmp( arg1, "list" ) )
    {
	save_area_list();
	return;
    }

    /* Save area being edited, if authorized. */
    /* -------------------------------------- */
    if ( !str_cmp( arg1, "area" ) )
    {	
	/* Find the area to save. */
	switch (ch->desc->editor)
	{
	    case ED_AREA:
		pArea = (AREA_DATA *)ch->desc->pEdit;
		break;
	    case ED_ROOM:
		pArea = ch->in_room->area;
		break;
	    case ED_OBJECT:
		pArea = ( (OBJ_INDEX_DATA *)ch->desc->pEdit )->area;
		break;
	    case ED_MOBILE:
		pArea = ( (MOB_INDEX_DATA *)ch->desc->pEdit )->area;
		break;
	    default:
		pArea = ch->in_room->area;
		break;
	}

	if ( !IS_BUILDER( ch, pArea ) )
	{
	    send_to_char( "You are not a builder for this area.\n\r", ch );
	    return;
	}

	save_area_list();
	if ( !str_cmp( "verbose", argument ) )
	    SET_BIT( pArea->area_flags, AREA_VERBOSE );
	save_area( pArea );
	REMOVE_BIT( pArea->area_flags, AREA_CHANGED | AREA_ADDED | AREA_VERBOSE );
	send_to_char( "Area saved.\n\r", ch );
	return;
    }

    /* Show correct syntax. */
    /* -------------------- */
    do_asave( ch, "" );
    return;
}




 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *


 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *


 *                                                                         *


 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *


 *  Chastain, Michael Quan, and Mitchell Tse.                              *


 *                                                                         *


 *  In order to use any part of this Merc Diku Mud, you must comply with   *


 *  both the original Diku license in 'license.doc' as well the Merc       *


 *  license in 'license.txt'.  In particular, you may not remove either of *


 *  these copyright notices.                                               *


 *                                                                         *


 *  Much time and thought has gone into this software and you are          *


 *  benefitting.  We hope that you share your changes too.  What goes      *


 *  around, comes around.                                                  *


 ***************************************************************************/





#if defined(macintosh)


#include <types.h>


#else


#include <sys/types.h>


#endif


#include <stdio.h>


#include <stdlib.h>


#include <string.h>


#include <time.h>


#include "merc.h"











void do_pset( CHAR_DATA *ch, char *argument )


{


    char arg1 [MAX_INPUT_LENGTH];


    char arg2 [MAX_INPUT_LENGTH];


    char arg3 [MAX_INPUT_LENGTH];


    char arg4 [MAX_INPUT_LENGTH];


    char buf[MAX_STRING_LENGTH];


    CHAR_DATA *victim;


    int value;





    sprintf(buf,"%s: Pset %s",ch->name,argument);


    if (ch->level < NO_WATCH) do_watching(ch,buf);





    smash_tilde( argument );


    argument = one_argument( argument, arg1 );


    argument = one_argument( argument, arg2 );


    argument = one_argument( argument, arg3 );


    strcpy(arg4, argument);


    if ( arg1[0] == '\0' || arg2[0] == '\0' || arg3[0] == '\0' )


    {


	send_to_char( "#7Syntax: pset <victim> <area> <field> <value>\n\r",ch );


	send_to_char( "\n\r",						ch );


	send_to_char( "#7Area being one of:\n\r",
ch );


	send_to_char( "  #3quest quest+ quest- weapon immune beast\n\r",
ch );


	send_to_char( "  #3blue red yellow green purple \n\r",	        ch
);


	send_to_char( "  #3mongoose crane crab viper bull mantis\n\r",	ch
); 


	send_to_char( "  #3dragon tiger monkey swallow \n\r",	        ch
);


	send_to_char( "\n\r",						ch );


	send_to_char( "#7Field being one of:\n\r",			ch
);


	send_to_char( "#3Weapon:  slice stab slash whip claw blast\n\r", ch );


        send_to_char( "#3Weapon:  pound crush grep bite pierce suck \n\r",
ch );


	send_to_char( "#3Immune:  slash stab smash animal misc charm\n\r",
ch ); 


        send_to_char( "#3Immune:  heat cold acid summon voodoo \n\r",
ch );


	send_to_char( "#3Immune:  hurl backstab shielded kick disarm\n\r",
ch );


        send_to_char( "#3Immune:  steal sleep drain sunlight\n\r",
ch );


        send_to_char( "#3         all#n\n\r",          ch );


	return;


    }





    if ( ( victim = get_char_world( ch, arg1 ) ) == NULL )


    {


	send_to_char( "They aren't here.\n\r", ch );


	return;


    }





    if (IS_SET(victim->act, PLR_GODLESS) && ch->level < NO_GODLESS)


    {


	send_to_char( "You failed.\n\r", ch );


	return;


    }





    /*


     * Snarf the value (which need not be numeric).


     */


    value = is_number( arg3 ) ? atoi( arg3 ) : -1;





    /*


     * Set something.


     */





    if ( !str_cmp( arg2, "beast" ) )


    {


	if ( IS_NPC(victim) )


	{


	    send_to_char( "Not on NPC's.\n\r", ch );


	    return;


	}





	if ( value < 0 || value > 100 )


	{


	    send_to_char( "Beast range is 0 to 100.\n\r", ch );


	    return;


	}





	if (IS_JUDGE(ch)) {


		victim->beast = value;


		send_to_char("Ok.\n\r",ch);}


	else


		send_to_char( "Sorry, no can do...\n\r", ch );


	return;


    }





    if ( !str_cmp( arg2, "quest" ) )


    {


	if ( IS_NPC(victim) )


	{


	    send_to_char( "Not on NPC's.\n\r", ch );


	    return;


	}





	if ( value < 1 || value > 15000 )


	{


	    send_to_char( "Quest range is 1 to 15000.\n\r", ch );


	    return;


	}





	if (IS_JUDGE(ch)) {


		victim->pcdata->quest = value;


		send_to_char("Ok.\n\r",ch);}


	else


		send_to_char( "Sorry, no can do...\n\r", ch );


	return;


    }





    if ( !str_cmp( arg2, "quest+" ) )


    {


	if ( IS_NPC(victim) )


	{


	    send_to_char( "Not on NPC's.\n\r", ch );


	    return;


	}





	if ( value < 1 || value + victim->pcdata->quest > 15000 )


	{


	    send_to_char( "Quest range is 1 to 15000.\n\r", ch );


	    return;


	}





	if (IS_JUDGE(ch)) {


		victim->pcdata->quest += value;


		send_to_char("Ok.\n\r",ch);}


	else


		send_to_char( "Sorry, no can do...\n\r", ch );


	return;


    }





    if ( !str_cmp( arg2, "quest-" ) )


    {


	if ( IS_NPC(victim) )


	{


	    send_to_char( "Not on NPC's.\n\r", ch );


	    return;


	}





	if ( victim->pcdata->quest - value < 1 || value > 15000 )


	{


	    send_to_char( "Quest range is 1 to 15000.\n\r", ch );


	    return;


	}





	if (IS_JUDGE(ch)) {


		victim->pcdata->quest -= value;


		send_to_char("Ok.\n\r",ch);}


	else


		send_to_char( "Sorry, no can do...\n\r", ch );


	return;


    }





    if ( !str_cmp( arg2, "viper" ) )


    {


	if ( IS_NPC(victim) )


	{


	    send_to_char( "Not on NPC's.\n\r", ch );


	    return;


	}





	if ( value < 0 || value > 200 )


	{


	    send_to_char( "Stance Viper range is 0 to 200.\n\r", ch );


	    return;


	}





	if (IS_JUDGE(ch)) {


		victim->stance[STANCE_VIPER] = value;


		send_to_char("Ok.\n\r",ch);}


	else


		send_to_char( "Sorry, no can do...\n\r", ch );


	return;


    }





    if ( !str_cmp( arg2, "crane" ) )
    {
	if ( IS_NPC(victim) )
	{
	    send_to_char( "Not on NPC's.\n\r", ch );
	    return;
	}

	if ( value < 0 || value > 200 )
	{
	    send_to_char( "Stance Crane range is 0 to 200.\n\r", ch );
	    return;
	}

	if (IS_JUDGE(ch)) {
		victim->stance[STANCE_CRANE] = value;
		send_to_char("Ok.\n\r",ch);}
	else
		send_to_char( "Sorry, no can do...\n\r", ch );
	return;
    }
    if ( !str_cmp( arg2, "kozudo" ) )
    {
        if ( IS_NPC(victim) )
        {
            send_to_char( "Not on NPC's.\n\r", ch );
            return;
        }
 
        if ( value < 0 || value > 200 )
        {
            send_to_char( "Stance kozudo range is 0 to 200.\n\r", ch );
            return;
        }
 
        if (IS_JUDGE(ch)) {
                victim->stance[STANCE_KOZUDO] = value;
                send_to_char("Ok.\n\r",ch);}
        else
                send_to_char( "Sorry, no can do...\n\r", ch );
        return;
    }



    if ( !str_cmp( arg2, "crab" ) )


    {


	if ( IS_NPC(victim) )


	{


	    send_to_char( "Not on NPC's.\n\r", ch );


	    return;


	}





	if ( value < 0 || value > 200 )


	{


	    send_to_char( "Stance Crab range is 0 to 200.\n\r", ch );


	    return;


	}





	if (IS_JUDGE(ch)) {


		victim->stance[STANCE_CRAB] = value;


		send_to_char("Ok.\n\r",ch);}


	else


		send_to_char( "Sorry, no can do...\n\r", ch );


	return;


    }





    if ( !str_cmp( arg2, "mongoose" ) )


    {


	if ( IS_NPC(victim) )


	{


	    send_to_char( "Not on NPC's.\n\r", ch );


	    return;


	}





	if ( value < 0 || value > 200 )


	{


	    send_to_char( "Stance Mongoose range is 0 to 200.\n\r", ch );


	    return;


	}





	if (IS_JUDGE(ch)) {


		victim->stance[STANCE_MONGOOSE] = value;


		send_to_char("Ok.\n\r",ch);}


	else


		send_to_char( "Sorry, no can do...\n\r", ch );


	return;


    }





    if ( !str_cmp( arg2, "bull" ) )


    {


	if ( IS_NPC(victim) )


	{


	    send_to_char( "Not on NPC's.\n\r", ch );


	    return;


	}





	if ( value < 0 || value > 200 )


	{


	    send_to_char( "Stance Bull range is 0 to 200.\n\r", ch );


	    return;


	}





	if (IS_JUDGE(ch)) {


		victim->stance[STANCE_BULL] = value;


		send_to_char("Ok.\n\r",ch);}


	else


		send_to_char( "Sorry, no can do...\n\r", ch );


	return;


    }





    if ( !str_cmp( arg2, "mantis" ) )


    {


	if ( IS_NPC(victim) )


	{


	    send_to_char( "Not on NPC's.\n\r", ch );


	    return;


	}





	if ( value < 0 || value > 200 )


	{


	    send_to_char( "Stance Mantis range is 0 to 200.\n\r", ch );


	    return;


	}





	if (IS_JUDGE(ch)) {


		victim->stance[STANCE_MANTIS] = value;


		victim->stance[STANCE_CRANE]  = 200;


		victim->stance[STANCE_VIPER]  = 200;


		send_to_char("Ok.\n\r",ch);}


	else


		send_to_char( "Sorry, no can do...\n\r", ch );


	return;


    }





    if ( !str_cmp( arg2, "dragon" ) )


    {


	if ( IS_NPC(victim) )


	{


	    send_to_char( "Not on NPC's.\n\r", ch );


	    return;


	}





	if ( value < 0 || value > 200 )


	{


	    send_to_char( "Stance Dragon range is 0 to 200.\n\r", ch );


	    return;


	}





	if (IS_JUDGE(ch)) {


		victim->stance[STANCE_DRAGON] = value;


		victim->stance[STANCE_CRAB]   = 200;


		victim->stance[STANCE_BULL]   = 200;


		send_to_char("Ok.\n\r",ch);}


	else


		send_to_char( "Sorry, no can do...\n\r", ch );


	return;


    }





    if ( !str_cmp( arg2, "tiger" ) )


    {


	if ( IS_NPC(victim) )


	{


	    send_to_char( "Not on NPC's.\n\r", ch );


	    return;


	}





	if ( value < 0 || value > 200 )


	{


	    send_to_char( "Stance Tiger range is 0 to 200.\n\r", ch );


	    return;


	}





	if (IS_JUDGE(ch)) {


		victim->stance[STANCE_TIGER] = value;


		victim->stance[STANCE_BULL]  = 200;


		victim->stance[STANCE_VIPER] = 200;


		send_to_char("Ok.\n\r",ch);}


	else


		send_to_char( "Sorry, no can do...\n\r", ch );


	return;


    }





    if ( !str_cmp( arg2, "monkey" ) )


    {


	if ( IS_NPC(victim) )


	{


	    send_to_char( "Not on NPC's.\n\r", ch );


	    return;


	}





	if ( value < 0 || value > 200 )


	{


	    send_to_char( "Stance Monkey range is 0 to 200.\n\r", ch );


	    return;


	}





	if (IS_JUDGE(ch)) {





		victim->stance[STANCE_MONKEY] = value;


		victim->stance[STANCE_MONGOOSE]  = 200;


		victim->stance[STANCE_CRANE]  = 200;


		send_to_char("Ok.\n\r",ch);}


	else


		send_to_char( "Sorry, no can do...\n\r", ch );


	return;


    }





    if ( !str_cmp( arg2, "swallow" ) )


    {


	if ( IS_NPC(victim) )


	{


	    send_to_char( "Not on NPC's.\n\r", ch );


	    return;


	}





	if ( value < 0 || value > 200 )


	{


	    send_to_char( "Stance Swallow range is 0 to 200.\n\r", ch );


	    return;


	}





	if (IS_JUDGE(ch)) {


		victim->stance[STANCE_SWALLOW] = value;


		victim->stance[STANCE_CRAB]  = 200;


		victim->stance[STANCE_MONGOOSE]  = 200;


		send_to_char("Ok.\n\r",ch);}


	else


		send_to_char( "Sorry, no can do...\n\r", ch );


	return;


    }





    if ( !str_cmp( arg2, "purple" ) )


    {


	if ( IS_NPC(victim) )


	{


	    send_to_char( "Not on NPC's.\n\r", ch );


	    return;


	}





	if ( IS_CLASS(victim, CLASS_MAGE) && (value < 4 || value > 240) )


	{


	    send_to_char( "Spell range is 4 to 240.\n\r", ch );


	    return;


	}


	else if ( value < 4 || value > 200 )


	{


	    send_to_char( "Spell range is 4 to 200.\n\r", ch );


	    return;


	}





	if (IS_JUDGE(ch)) {


		victim->spl[PURPLE_MAGIC] = value;


		send_to_char("Ok.\n\r",ch);}


	else


		send_to_char( "Sorry, no can do...\n\r", ch );


	return;


    }






    if ( !str_cmp( arg2, "spells" ) )
    {
	if (IS_NPC(victim))
	return;

	if (!IS_CREATOR(ch))
	{
	  do_pset(ch,"");
	  return;
	}

	if (value > 32000 || value < -32000)
	    return;

	victim->spl[RED_MAGIC]    = value;
	victim->spl[PURPLE_MAGIC] = value;
	victim->spl[GREEN_MAGIC]  = value;
	victim->spl[BLUE_MAGIC]   = value;
	victim->spl[YELLOW_MAGIC] = value;
	
	return;

     }

    if ( !str_cmp( arg2, "red" ) )


    {


	if ( IS_NPC(victim) )


	{


	    send_to_char( "Not on NPC's.\n\r", ch );


	    return;


	}





	if ( IS_CLASS(victim, CLASS_MAGE) && (value < 4 || value > 240) )


	{


	    send_to_char( "Spell range is 4 to 240.\n\r", ch );


	    return;


	}


	else if ( value < 4 || value > 200 )


	{


	    send_to_char( "Spell range is 4 to 200.\n\r", ch );


	    return;


	}





	if (IS_JUDGE(ch)) {


		victim->spl[RED_MAGIC] = value;


		send_to_char("Ok.\n\r",ch);}


	else


		send_to_char( "Sorry, no can do...\n\r", ch );


	return;


    }





    if ( !str_cmp( arg2, "blue" ) )


    {


	if ( IS_NPC(victim) )


	{


	    send_to_char( "Not on NPC's.\n\r", ch );


	    return;


	}





	if ( IS_CLASS(victim, CLASS_MAGE) && (value < 4 || value > 240) )


	{


	    send_to_char( "Spell range is 4 to 240.\n\r", ch );


	    return;


	}


	else if ( value < 4 || value > 200 )


	{


	    send_to_char( "Spell range is 4 to 200.\n\r", ch );


	    return;


	}





	if (IS_JUDGE(ch)) {


		victim->spl[BLUE_MAGIC] = value;


		send_to_char("Ok.\n\r",ch);}


	else


		send_to_char( "Sorry, no can do...\n\r", ch );


	return;


    }





    if ( !str_cmp( arg2, "green" ) )


    {


	if ( IS_NPC(victim) )


	{


	    send_to_char( "Not on NPC's.\n\r", ch );


	    return;


	}





	if ( IS_CLASS(victim, CLASS_MAGE) && (value < 4 || value > 240) )


	{


	    send_to_char( "Spell range is 4 to 240.\n\r", ch );


	    return;


	}


	else if ( value < 4 || value > 200 )


	{


	    send_to_char( "Spell range is 4 to 200.\n\r", ch );


	    return;


	}





	if (IS_JUDGE(ch)) {


		victim->spl[GREEN_MAGIC] = value;


		send_to_char("Ok.\n\r",ch);}


	else


		send_to_char( "Sorry, no can do...\n\r", ch );


	return;


    }





    if ( !str_cmp( arg2, "yellow" ) )


    {


	if ( IS_NPC(victim) )


	{


	    send_to_char( "Not on NPC's.\n\r", ch );


	    return;


	}





	if ( IS_CLASS(victim, CLASS_MAGE) && (value < 4 || value > 240) )


	{


	    send_to_char( "Spell range is 4 to 240.\n\r", ch );


	    return;


	}


	else if ( value < 4 || value > 200 )


	{


	    send_to_char( "Spell range is 4 to 200.\n\r", ch );


	    return;


	}





	if (IS_JUDGE(ch)) {


		victim->spl[YELLOW_MAGIC] = value;


		send_to_char("Ok.\n\r",ch);}


	else


		send_to_char( "Sorry, no can do...\n\r", ch );


	return;


    }





    if ( !str_cmp( arg2, "immune" ) )


    {


	if ( IS_NPC(victim) )


	{


	    send_to_char( "Not on NPC's.\n\r", ch );


	    return;


	}





        if (arg3 == '\0')


        {


	    send_to_char( "pset <victim> immune <immunity>.\n\r", ch );


	    return;         


        }





	if (IS_JUDGE(ch)) 


        {


                if (!str_cmp(arg3, "voodoo"))


                {


                  if (IS_SET(victim->immune, IMM_VOODOO))


                  {


		    REMOVE_BIT(victim->immune, IMM_VOODOO);


		    send_to_char("Ok Immunity Removed.\n\r",ch);


                    return;                    


                  }


                  else


                  {


		    SET_BIT(victim->immune, IMM_VOODOO);


		    send_to_char("Ok Immunity Added.\n\r",ch);


                    return;


                  }


                }





                if (!str_cmp(arg3, "slash"))


                {


                  if (IS_SET(victim->immune, IMM_SLASH))


                  {


		    REMOVE_BIT(victim->immune, IMM_SLASH);


		    send_to_char("Ok Immunity Removed.\n\r",ch);


                    return;                    


                  }


                  else


                  {


		    SET_BIT(victim->immune, IMM_SLASH);


		    send_to_char("Ok Immunity Added.\n\r",ch);


                    return;


                  }


                }





                if (!str_cmp(arg3, "stab"))


                {


                  if (IS_SET(victim->immune, IMM_STAB))


                  {


		    REMOVE_BIT(victim->immune, IMM_STAB);


		    send_to_char("Ok Immunity Removed.\n\r",ch);


                    return;                    


                  }


                  else


                  {


		    SET_BIT(victim->immune, IMM_STAB);


		    send_to_char("Ok Immunity Added.\n\r",ch);


                    return;


                  }


                }





                if (!str_cmp(arg3, "smash"))


                {


                  if (IS_SET(victim->immune, IMM_SMASH))


                  {


		    REMOVE_BIT(victim->immune, IMM_SMASH);


		    send_to_char("Ok Immunity Removed.\n\r",ch);


                    return;                    


                  }


                  else


                  {


		    SET_BIT(victim->immune, IMM_SMASH);


		    send_to_char("Ok Immunity Added.\n\r",ch);


                    return;


                  }


                }





                if (!str_cmp(arg3, "anmial"))


                {


                  if (IS_SET(victim->immune, IMM_ANIMAL))


                  {


		    REMOVE_BIT(victim->immune, IMM_ANIMAL);


		    send_to_char("Ok Immunity Removed.\n\r",ch);


                    return;                    


                  }


                  else


                  {


		    SET_BIT(victim->immune, IMM_ANIMAL);


		    send_to_char("Ok Immunity Added.\n\r",ch);


                    return;


                  }


                }





                if (!str_cmp(arg3, "misc"))


                {


                  if (IS_SET(victim->immune, IMM_MISC))


                  {


		    REMOVE_BIT(victim->immune, IMM_MISC);


		    send_to_char("Ok Immunity Removed.\n\r",ch);


                    return;                    


                  }


                  else


                  {


		    SET_BIT(victim->immune, IMM_MISC);


		    send_to_char("Ok Immunity Added.\n\r",ch);


                    return;


                  }


                }





                if (!str_cmp(arg3, "charm"))


                {


                  if (IS_SET(victim->immune, IMM_CHARM))


                  {


		    REMOVE_BIT(victim->immune, IMM_CHARM);


		    send_to_char("Ok Immunity Removed.\n\r",ch);


                    return;                    


                  }


                  else


                  {


		    SET_BIT(victim->immune, IMM_CHARM);


		    send_to_char("Ok Immunity Added.\n\r",ch);


                    return;


                  }


                }


                if (!str_cmp(arg3, "heat"))


                {


                  if (IS_SET(victim->immune, IMM_HEAT))


                  {


		    REMOVE_BIT(victim->immune, IMM_HEAT);


		    send_to_char("Ok Immunity Removed.\n\r",ch);


                    return;                    


                  }


                  else


                  {


		    SET_BIT(victim->immune, IMM_HEAT);


		    send_to_char("Ok Immunity Added.\n\r",ch);


                    return;


                  }


                }


                if (!str_cmp(arg3, "cold"))


                {


                  if (IS_SET(victim->immune, IMM_COLD))


                  {


		    REMOVE_BIT(victim->immune, IMM_COLD);


		    send_to_char("Ok Immunity Removed.\n\r",ch);


                    return;                    


                  }


                  else


                  {


		    SET_BIT(victim->immune, IMM_COLD);


		    send_to_char("Ok Immunity Added.\n\r",ch);


                    return;


                  }


                }





                if (!str_cmp(arg3, "lightning"))


                {


                  if (IS_SET(victim->immune, IMM_LIGHTNING))


                  {


		    REMOVE_BIT(victim->immune, IMM_LIGHTNING);


		    send_to_char("Ok Immunity Removed.\n\r",ch);


                    return;                    


                  }


                  else


                  {


		    SET_BIT(victim->immune, IMM_LIGHTNING);


		    send_to_char("Ok Immunity Added.\n\r",ch);


                    return;


                  }


                }





                if (!str_cmp(arg3, "acid"))


                {


                  if (IS_SET(victim->immune, IMM_ACID))


                  {


		    REMOVE_BIT(victim->immune, IMM_ACID);


		    send_to_char("Ok Immunity Removed.\n\r",ch);


                    return;                    


                  }


                  else


                  {


		    SET_BIT(victim->immune, IMM_ACID);


		    send_to_char("Ok Immunity Added.\n\r",ch);


                    return;


                  }


                }





                if (!str_cmp(arg3, "shield"))


                {


                  if (IS_SET(victim->immune, IMM_SHIELDED))


                  {


		    REMOVE_BIT(victim->immune, IMM_SHIELDED);


		    send_to_char("Ok Immunity Removed.\n\r",ch);


                    return;                    


                  }


                  else


                  {


		    SET_BIT(victim->immune, IMM_SHIELDED);


		    send_to_char("Ok Immunity Added.\n\r",ch);


                    return;


                  }


                }





                if (!str_cmp(arg3, "hurl"))


                {


                  if (IS_SET(victim->immune, IMM_HURL))


                  {


		    REMOVE_BIT(victim->immune, IMM_HURL);


		    send_to_char("Ok Immunity Removed.\n\r",ch);


                    return;                    


                  }


                  else


                  {


		    SET_BIT(victim->immune, IMM_HURL);


		    send_to_char("Ok Immunity Added.\n\r",ch);


                    return;


                  }


                }





                if (!str_cmp(arg3, "backstab"))


                {


                  if (IS_SET(victim->immune, IMM_BACKSTAB))


                  {


		    REMOVE_BIT(victim->immune, IMM_BACKSTAB);


		    send_to_char("Ok Immunity Removed.\n\r",ch);


                    return;                    


                  }


                  else


                  {


		    SET_BIT(victim->immune, IMM_BACKSTAB);


		    send_to_char("Ok Immunity Added.\n\r",ch);


                    return;


                  }


                }


		


                if (!str_cmp(arg3, "kick"))


                {


                  if (IS_SET(victim->immune, IMM_KICK))


                  {


		    REMOVE_BIT(victim->immune, IMM_KICK);


		    send_to_char("Ok Immunity Removed.\n\r",ch);


                    return;                    


                  }


                  else


                  {


		    SET_BIT(victim->immune, IMM_KICK);


		    send_to_char("Ok Immunity Added.\n\r",ch);


                    return;


                  }


                }





                if (!str_cmp(arg3, "disarm"))


                {


                  if (IS_SET(victim->immune, IMM_DISARM))


                  {


		    REMOVE_BIT(victim->immune, IMM_DISARM);


		    send_to_char("Ok Immunity Removed.\n\r",ch);


                    return;                    


                  }


                  else


                  {


		    SET_BIT(victim->immune, IMM_DISARM);


		    send_to_char("Ok Immunity Added.\n\r",ch);


                    return;


                  }


                }





                if (!str_cmp(arg3, "steal"))


                {


                  if (IS_SET(victim->immune, IMM_STEAL))


                  {


		    REMOVE_BIT(victim->immune, IMM_STEAL);


		    send_to_char("Ok Immunity Removed.\n\r",ch);


                    return;                    


                  }


                  else


                  {


		    SET_BIT(victim->immune, IMM_STEAL);


		    send_to_char("Ok Immunity Added.\n\r",ch);


                    return;


                  }


                }





                if (!str_cmp(arg3, "sleep"))


                {


                  if (IS_SET(victim->immune, IMM_SLEEP))


                  {


		    REMOVE_BIT(victim->immune, IMM_SLEEP);


		    send_to_char("Ok Immunity Removed.\n\r",ch);


                    return;                    


                  }


                  else


                  {


		    SET_BIT(victim->immune, IMM_SLEEP);


		    send_to_char("Ok Immunity Added.\n\r",ch);


                    return;


                  }


                }





                if (!str_cmp(arg3, "sunlight"))


                {


                  if (IS_SET(victim->immune, IMM_SUNLIGHT))


                  {


		    REMOVE_BIT(victim->immune, IMM_SUNLIGHT);


		    send_to_char("Ok Immunity Removed.\n\r",ch);


                    return;                    


                  }


                  else


                  {


		    SET_BIT(victim->immune, IMM_SUNLIGHT);


		    send_to_char("Ok Immunity Added.\n\r",ch);


                    return;


                  }


                }





                if (!str_cmp(arg3, "all"))


                {


		    SET_BIT(victim->immune, IMM_DRAIN);


		    SET_BIT(victim->immune, IMM_VOODOO);


		    SET_BIT(victim->immune, IMM_SLASH);


		    SET_BIT(victim->immune, IMM_STAB);


		    SET_BIT(victim->immune, IMM_SMASH);


		    SET_BIT(victim->immune, IMM_ANIMAL);


		    SET_BIT(victim->immune, IMM_MISC);


		    SET_BIT(victim->immune, IMM_CHARM);


		    SET_BIT(victim->immune, IMM_HEAT);


		    SET_BIT(victim->immune, IMM_COLD);


		    SET_BIT(victim->immune, IMM_LIGHTNING);


		    SET_BIT(victim->immune, IMM_ACID);


		    SET_BIT(victim->immune, IMM_HURL);


		    SET_BIT(victim->immune, IMM_BACKSTAB);


		    SET_BIT(victim->immune, IMM_KICK);


		    SET_BIT(victim->immune, IMM_DISARM);


		    SET_BIT(victim->immune, IMM_STEAL);


		    SET_BIT(victim->immune, IMM_SLEEP);


		    send_to_char("Ok All Immunities Added.\n\r",ch);


                    return;


                }





                send_to_char("No such immunity exists.\n\r",ch);


                return;


        }


	else


		send_to_char( "Sorry, no can do...\n\r", ch );


	return;


    }





    if ( !str_cmp( arg2, "weapon" ) )


    {


	if ( IS_NPC(victim) )


	{


	    send_to_char( "Not on NPC's.\n\r", ch );


	    return;


	}





        argument = one_argument( argument, arg4 );


        /*


         * Snarf the value (which need not be numeric).


         */


        value = is_number( arg4 ) ? atoi( arg4 ) : -1;





	if (!IS_CREATOR(ch))
	{
	if ( value < 0 || value > 200 )


	{


	    send_to_char( "Weapon skill range is 0 to 200.\n\r", ch );


	    return;


	}


	}

	if (IS_JUDGE(ch)) 


        {


                if (!str_cmp(arg3, "unarmed"))


                {


		  victim->wpn[0] = value;


		  send_to_char("Ok.\n\r",ch);


                  return;


                }





                if (!str_cmp(arg3, "slice"))


                {


		  victim->wpn[1] = value;


		  send_to_char("Ok.\n\r",ch);


                  return;


                }





                if (!str_cmp(arg3, "stab"))


                {


		  victim->wpn[2] = value;


		  send_to_char("Ok.\n\r",ch);


                  return;


                }





                if (!str_cmp(arg3, "slash"))


                {


		  victim->wpn[3] = value;


		  send_to_char("Ok.\n\r",ch);


                  return;


                }





                if (!str_cmp(arg3, "whip"))


                {


		  victim->wpn[4] = value;


		  send_to_char("Ok.\n\r",ch);


                  return;


                }





                if (!str_cmp(arg3, "claw"))


                {


		  victim->wpn[5] = value;


		  send_to_char("Ok.\n\r",ch);


                  return;


                }





                if (!str_cmp(arg3, "blast"))


                {


		  victim->wpn[6] = value;


		  send_to_char("Ok.\n\r",ch);


                  return;


                }





                if (!str_cmp(arg3, "pound"))


                {


		  victim->wpn[7] = value;


		  send_to_char("Ok.\n\r",ch);


                  return;


                }





                if (!str_cmp(arg3, "crush"))


                {


		  victim->wpn[8] = value;


		  send_to_char("Ok.\n\r",ch);


                  return;


                }





                if (!str_cmp(arg3, "grep"))


                {


		  victim->wpn[9] = value;


		  send_to_char("Ok.\n\r",ch);


                  return;


                }





                if (!str_cmp(arg3, "bite"))


                {


		  victim->wpn[10] = value;


		  send_to_char("Ok.\n\r",ch);


                  return;


                }





                if (!str_cmp(arg3, "pierce"))


                {


		  victim->wpn[11] = value;


		  send_to_char("Ok.\n\r",ch);


                  return;


                }





                if (!str_cmp(arg3, "suck"))


                {


		  victim->wpn[12] = value;


		  send_to_char("Ok.\n\r",ch);


                  return;


                }





                if (!str_cmp(arg3, "all"))


                {


		  victim->wpn[0] = value;


		  victim->wpn[1] = value;


		  victim->wpn[2] = value;


		  victim->wpn[3] = value;


		  victim->wpn[4] = value;


		  victim->wpn[5] = value;


		  victim->wpn[6] = value;


		  victim->wpn[7] = value;


		  victim->wpn[8] = value;


		  victim->wpn[8] = value;


		  victim->wpn[9] = value;


		  victim->wpn[10] = value;


                  victim->wpn[11] = value;


		  victim->wpn[12] = value;


		  send_to_char("Ok.\n\r",ch);


                  return;


                }


                send_to_char("No such weapon skill exists.\n\r",ch);


                return;


        }


	else


		send_to_char( "Sorry, no can do...\n\r", ch );


	return;


    }





    /*


     * Generate usage message.


     */


    do_pset( ch, "" );


    return;


}








void do_paradox( CHAR_DATA *ch, char *argument)  {


	char arg[MAX_INPUT_LENGTH];


	CHAR_DATA *victim;


        DESCRIPTOR_DATA *d;        


        argument = one_argument(argument, arg);        





	if (arg[0] == '\0') {


		send_to_char("Paradox whom?\n\r", ch );


		return;}





    if ( get_trust(ch) >=  MAX_LEVEL - 2 && !str_cmp(arg,"all"))


    {


        for (d = descriptor_list; d != NULL; d = d->next)


        {


	    victim = d->character;





	    if (victim == NULL || IS_NPC(victim))


		continue;


                


          


            { paradox(victim); }


        }


    }





    if ( ( victim = get_char_world( ch, arg ) ) == NULL )


    {


        send_to_char( "They aren't here.\n\r", ch );


        return;


    }


	paradox(victim);


	send_to_char("Done!\n\r", ch );


}








void paradox( CHAR_DATA *ch )


{


    char            buf[MAX_STRING_LENGTH]; 





    send_to_char("The sins of your past strike back!\n\r",  ch);


    send_to_char("The paradox has come for your soul!\n\r",  ch);


    sprintf( buf, "%s is struck by a paradox.\n\r", ch->name);


    do_info(ch, buf);


    ch->paradox[1] = 0;


    ch->paradox[2] = 0;





/*  Chris please sort this out.  KaVir. */





    ch->hit     =  -10;


    update_pos( ch );


    do_escape(ch, "");    
     SET_BIT(ch->extra, TIED_UP);
        SET_BIT(ch->extra, GAGGED);
        SET_BIT(ch->extra, BLINDFOLDED);
    
/*  Commented out, as it's a very pointless piece of code.





    if (ch->paradox[0] <= 15)


    {


    	ch->hit     =  -10;


    	update_pos( ch );


    	do_escape(ch, "");


    	SET_BIT(ch->extra, TIED_UP);


    	SET_BIT(ch->extra, GAGGED);


    	SET_BIT(ch->extra, BLINDFOLDED);


    }


    else if (ch->paradox[0] <= 55)


    {


    	ch->hit     =  -10;


    	update_pos( ch );


    	do_escape(ch, "");


    	SET_BIT(ch->extra, TIED_UP);


    	SET_BIT(ch->extra, GAGGED);


    	SET_BIT(ch->extra, BLINDFOLDED);


    }


    else if (ch->paradox[0] <= 99)


    {


    	ch->hit     =  -10;


    	update_pos( ch );


    	do_escape(ch, "");


    	SET_BIT(ch->extra, TIED_UP);


    	SET_BIT(ch->extra, GAGGED);


    	SET_BIT(ch->extra, BLINDFOLDED);


    }


    else if (ch->paradox[0] >= 100)


    {


    	ch->hit     =  -10;


    	update_pos( ch );


    	do_escape(ch, "");


    	SET_BIT(ch->extra, TIED_UP);


    	SET_BIT(ch->extra, GAGGED);


    	SET_BIT(ch->extra, BLINDFOLDED);


    }


*/


    return;


}







50201552  10566

 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *


 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *


 *                                                                         *


 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *


 *  Chastain, Michael Quan, and Mitchell Tse.                              *


 *                                                                         *


 *  In order to use any part of this Merc Diku Mud, you must comply with   *


 *  both the original Diku license in 'license.doc' as well the Merc       *


 *  license in 'license.txt'.  In particular, you may not remove either of *


 *  these copyright notices.                                               *


 *                                                                         *


 *  Much time and thought has gone into this software and you are          *


 *  benefitting.  We hope that you share your changes too.  What goes      *


 *  around, comes around.                                                  *


 ***************************************************************************/





#if defined(macintosh)


#include <types.h>


#else


#include <sys/types.h>


#endif


#include <stdio.h>


#include <stdlib.h>


#include <string.h>


#include <time.h>


#include "merc.h"





void format_string_spaces args ( (char *argument,int spaces) );





/* 


 * Donate Command


 */


void do_donate(CHAR_DATA *ch, char *argument)


{


 char Object_Name[MAX_INPUT_LENGTH];


 ROOM_INDEX_DATA *xRoom;


 OBJ_DATA *xObject;


 int DONATION_ROOM;





 argument = one_argument(argument, Object_Name);


 if ( Object_Name == '\0' )


 {


   send_to_char("Donate WHAT Object?",ch);


   return;  


 }


 if ( ( xObject= get_obj_carry(ch,Object_Name)) == NULL)


 {


   send_to_char("You can't donate that item! You have not got it!",ch);


   return;


 }


 switch(xObject->item_type)


 {


   case ITEM_WEAPON :


       DONATION_ROOM=DONATION_ROOM_WEAPON;


       break;   


   case ITEM_ARMOR  :


       DONATION_ROOM=DONATION_ROOM_ARMOR;


       break;   


   default :


       DONATION_ROOM=DONATION_ROOM_REST;


       break;   


 }


 if ( ( xRoom = get_room_index(DONATION_ROOM)) == NULL)


 {


   bug("Donate Room Does Not Exist : %d",DONATION_ROOM);


   return;


 }


 act("$p vanishes from your hands in a pink mist.",ch,xObject,NULL,TO_CHAR);


 act("$p vanishes from $n's hands in a pink mist.",ch,xObject,NULL,TO_ROOM);


 obj_from_char(xObject);


 obj_to_room(xObject,xRoom);


 act("$p appears in a pink mist in the room.",ch,xObject,NULL,TO_ROOM);


 return;


}





/* 


 * OutPuts Current Mud Code Version


 */ 


void do_version( CHAR_DATA *ch, char *argument)


{


   char buf[MAX_INPUT_LENGTH];





   sprintf(buf, "\n\r*************************************\n\rCrusade:- %d\n\r*************************************\n\r",VERSION_NUMBER);


   send_to_char(buf,ch);


   return;


}






/*
 * This procedure adds spaces to string if it is not long enough


 */





void format_string_spaces(char *argument,int spaces)


{


  int loop_counter;


  int string_length=strlen(argument);





  if (string_length < spaces)


  {


     for (loop_counter=string_length;loop_counter<=spaces;loop_counter++)


     {


        strcat(argument," ");


     }


  }


  return;


}






 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
 *                                                                         *
 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
 *  Chastain, Michael Quan, and Mitchell Tse.                              *
 *                                                                         *
 *  In order to use any part of this Merc Diku Mud, you must comply with   *
 *  both the original Diku license in 'license.doc' as well the Merc       *
 *  license in 'license.txt'.  In particular, you may not remove either of *
 *  these copyright notices.                                               *
 *                                                                         *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 ***************************************************************************/

#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "merc.h"

#if !defined(macintosh)
extern  int     _filbuf         args( (FILE *) );
#endif



/*
 * Array of containers read for proper re-nesting of objects.
 */
#define MAX_NEST        100
static  OBJ_DATA *      rgObjNest       [MAX_NEST];



/*
 * Local functions.
 */
void    fwrite_char_old args( ( CHAR_DATA *ch,  FILE *fp ) );
void    fwrite_char     args( ( CHAR_DATA *ch,  FILE *fp ) );
void    fwrite_obj      args( ( CHAR_DATA *ch,  OBJ_DATA  *obj,
			    FILE *fp, int iNest ) );
void    fread_char_old  args( ( CHAR_DATA *ch,  FILE *fp ) );
void    fread_char      args( ( CHAR_DATA *ch,  FILE *fp ) );
void    fread_obj       args( ( CHAR_DATA *ch,  FILE *fp ) );
void    save_char_obj_finger    args( ( CHAR_DATA *ch ) );

void    convert_old_new args( ( CHAR_DATA *ch ) );

/*
 * Save a character and inventory.
 * Would be cool to save NPC's too for quest purposes,
 *   some of the infrastructure is provided.
 */
void save_char_obj( CHAR_DATA *ch )
{
    char strsave[MAX_STRING_LENGTH];
    FILE *fp;

    if ( IS_NPC(ch) || ch->level < 2 )
	return;

    if ( ch->desc != NULL && ch->desc->connected != CON_PLAYING )
	return;

    if ( ch->desc != NULL && ch->desc->original != NULL )
	ch = ch->desc->original;
/*
    save_char_obj_backup( ch );
*/

    ch->save_time = current_time;
    fclose( fpReserve );
    sprintf( strsave, "%s%s", PLAYER_DIR, capitalize( ch->pcdata->switchname ) );
    if ( ( fp = fopen( strsave, "w" ) ) == NULL )
    {
	bug( "Save_char_obj: fopen", 0 );
	perror( strsave );
    }
    else
    {
	if ( ch->class == -1 )
		fwrite_char_old( ch, fp );
	else
		fwrite_char( ch, fp );
		
	if ( ch->carrying != NULL )
	    fwrite_obj( ch, ch->carrying, fp, 0 );
	fprintf( fp, "#END\n" );
    }
    fflush( fp );
    fclose( fp );
    fpReserve = fopen( NULL_FILE, "r" );
    save_char_obj_finger( ch );
    return;
}

void save_char_obj_backup( CHAR_DATA *ch )
{
    char chlevel [15];
    char buf [MAX_INPUT_LENGTH];
    char strsave[MAX_STRING_LENGTH];
    FILE *fp;

    if ( IS_NPC(ch) || ch->level < 2 )
	return;

    if ( ch->desc != NULL && ch->desc->original != NULL )
	ch = ch->desc->original;

    ch->save_time = current_time;
    fclose( fpReserve );
    sprintf( strsave, "%sstore/%s", PLAYER_DIR, capitalize(ch->pcdata->switchname) );
    if ( ( fp = fopen( strsave, "w" ) ) == NULL )
    {
	bug( "Save_char_obj: fopen", 0 );
	perror( strsave );
    }
    else
    {
	if (ch->class == -1)
		fwrite_char_old( ch, fp );
	else
		fwrite_char( ch, fp );

	if ( ch->carrying != NULL )
	    fwrite_obj( ch, ch->carrying, fp, 0 );
	fprintf( fp, "#END\n" );
	if      (ch->level >= 11) sprintf(chlevel,"<Implementor>");
	else if (ch->level == 10) sprintf(chlevel,"<High Judge>");
	else if (ch->level == 9 ) sprintf(chlevel,"<Judge>");
	else if (ch->level == 8 ) sprintf(chlevel,"<Enforcer>");
	else if (ch->level == 7 ) sprintf(chlevel,"<Quest Maker>");
	else if (ch->level == 6 ) sprintf(chlevel,"<Builder>");
	else if (ch->level == 5 ) sprintf(chlevel,"<Avatar>");
	else if (ch->level == 4 ) sprintf(chlevel,"<Avatar>");
	else if (ch->level == 3 ) sprintf(chlevel,"<Avatar>");
	else                      sprintf(chlevel,"<Mortal>");
	if (strlen(ch->lasttime) > 1)
	    sprintf(buf,"%s Last logged in on %s.\n\r", chlevel, ch->lasttime);
	else
	    sprintf(buf,"%s New player logged in on %s.\n\r", chlevel, ch->createtime);
	fprintf( fp, buf);
    }
    fflush( fp );
    fclose( fp );
    fpReserve = fopen( NULL_FILE, "r" );
    return;
}

void save_char_obj_finger( CHAR_DATA *ch )
{
    char strsave[MAX_STRING_LENGTH];
    FILE *fp;

    if ( IS_NPC(ch) || ch->level < 2 )
	return;

    if ( ch->desc != NULL && ch->desc->original != NULL )
	ch = ch->desc->original;

    ch->save_time = current_time;
    fclose( fpReserve );
    sprintf( strsave, "%sbackup/%s", PLAYER_DIR, capitalize(ch->pcdata->switchname) );
    if ( ( fp = fopen( strsave, "w" ) ) == NULL )
    {
	bug( "Save_char_obj: fopen", 0 );
	perror( strsave );
    }
    else
    {
	fprintf( fp, "%s~\n",   ch->name                );
	fprintf( fp, "%s~\n",   ch->pcdata->title       );
	fprintf( fp, "%s~\n",   ch->lasthost            );
	fprintf( fp, "%s~\n",   ch->lasttime            );
	fprintf( fp, "%d\n",    ch->extra               );
	fprintf( fp, "%d\n",    ch->sex                 );
	fprintf( fp, "%s~\n",   ch->pcdata->conception  );
	fprintf( fp, "%s~\n",   ch->createtime          );
	fprintf( fp, "%d\n",    ch->level               );
	fprintf( fp, "%d\n",    ch->race                );
	fprintf( fp, "%d\n",
	    ch->played + (int) (current_time - ch->logon));
	fprintf( fp, "%s~\n",   ch->pcdata->marriage    );
	fprintf( fp, "%d\n",    ch->pkill );
	fprintf( fp, "%d\n",    ch->pdeath );
	fprintf( fp, "%d\n",    ch->pcdata->awins       );
	fprintf( fp, "%d\n",    ch->pcdata->alosses     );
	fprintf( fp, "%d\n",    ch->mkill );
	fprintf( fp, "%d\n",    ch->mdeath );
	fprintf( fp, "%s~\n",   ch->pcdata->email       );
    }
    fflush( fp );
    fclose( fp );
    fpReserve = fopen( NULL_FILE, "r" );
    return;
}



/*
 * Write the char.
 */
void fwrite_char_old( CHAR_DATA *ch, FILE *fp )
{
    AFFECT_DATA *paf;
    int sn;

    fprintf( fp, "#%s\n", IS_NPC(ch) ? "MOB" : "PLAYER"         );

    fprintf( fp, "Name         %s~\n",  ch->name                );
    fprintf( fp, "Switchname   %s~\n",  ch->pcdata->switchname  );
    fprintf( fp, "ShortDescr   %s~\n",  ch->short_descr         );
    fprintf( fp, "LongDescr    %s~\n",  ch->long_descr          );
    fprintf( fp, "ObjDesc      %s~\n",  ch->objdesc		);
    fprintf( fp, "Description  %s~\n",  ch->description         );
    fprintf( fp, "Lord         %s~\n",  ch->lord                );
    fprintf( fp, "Kingdom      %d\n", ch->pcdata->kingdom	);
    fprintf( fp, "CPower %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", ch->power[0],ch->power[1],ch->power[2],ch->power[3],ch->power[4], ch->power[5],ch->power[6],ch






















->power[7],ch->power[8],ch->power[9], ch->power[10],ch->power[11],ch->power[12],ch->power[13],ch->power[14], ch->power[15],ch->power[16],ch->power[17],ch->power[18],ch->power[19], ch->power[20],ch->power[21],ch->power[22],ch->power[23],ch->power[24], ch->






















power[25],ch->power[26],ch->power[27],ch->power[28],ch->power[29], ch->power[30],ch->power[31],ch->power[32],ch->power[33],ch->power[34], ch->power[35],ch->power[36],ch->power[37],ch->power[38],ch->power[39], ch->power[40],ch->power[41],ch->power[42],ch->






















power[43]);
    fprintf( fp, "Morph        %s~\n",  ch->morph               );
    fprintf( fp, "DiscRese     %d\n",   ch->pcdata->disc_research  );
    fprintf( fp, "DiscPoin     %d\n",   ch->pcdata->disc_points );
    fprintf( fp, "Createtime   %s~\n",  ch->createtime          );
    fprintf( fp, "Lasttime     %s~\n",  ch->lasttime            );
    fprintf( fp, "Lasthost     %s~\n",  ch->lasthost            );
    fprintf( fp, "Poweraction  %s~\n",  ch->poweraction         );
    fprintf( fp, "Powertype    %s~\n",  ch->powertype           );
    fprintf( fp, "Prompt       %s~\n",  ch->prompt              );
    fprintf( fp, "Cprompt      %s~\n",  ch->cprompt             );
    fprintf( fp, "Sex          %d\n",   ch->sex                 );
    fprintf( fp, "Race         %d\n",   ch->race                );
    fprintf( fp, "Immune       %d\n",   ch->immune              );
    fprintf( fp, "Polyaff      %d\n",   ch->polyaff             );
/* New Dh */
    fprintf( fp, "CurrentForm  %d\n",   ch->cur_form            );
    fprintf( fp, "Rage	       %d\n",   ch->rage         );
    fprintf( fp, "Generation   %d\n",   ch->generation          );
    fprintf( fp, "Flag2       %d\n",   ch->flag2                );
    fprintf( fp, "Flag3       %d\n",   ch->flag3                );
    fprintf( fp, "Flag4       %d\n",   ch->flag4                );
    fprintf( fp, "SilTol      %d\n",   ch->siltol               );
    fprintf( fp, "Souls       %d\n",   ch->pcdata->souls        );
/* Done */
    fprintf( fp, "Itemaffect   %d\n",   ch->itemaffect          );
    fprintf( fp, "Spectype     %d\n",   ch->spectype            );
    fprintf( fp, "Specpower    %d\n",   ch->specpower           );
    fprintf( fp, "Home         %d\n",   ch->home                );
    fprintf( fp, "Level        %d\n",   ch->level               );
    fprintf( fp, "Trust        %d\n",   ch->trust               );
    fprintf( fp, "Security     %d\n",   ch->pcdata->security    );  /* OLC */
    fprintf( fp, "Paradox      %d %d %d\n", ch->paradox[0], ch->paradox[1], 
					     ch->paradox[2] ); 
    fprintf( fp, "Played       %d\n",
	ch->played + (int) (current_time - ch->logon)           );
    fprintf( fp, "Room         %d\n",
	(  ch->in_room == get_room_index( ROOM_VNUM_LIMBO )
	&& ch->was_in_room != NULL )
	    ? ch->was_in_room->vnum
	    : ch->in_room->vnum );

    fprintf( fp, "PkPdMkMd     %d %d %d %d\n",
	ch->pkill, ch->pdeath, ch->mkill, ch->mdeath );
    fprintf( fp, "Alos	       %d\n", ch->pcdata->alosses);
    fprintf( fp, "Awin	       %d\n", ch->pcdata->awins);
    fprintf( fp, "Wwin	       %d\n", ch->pcdata->wwins);
    fprintf( fp, "Wlos	       %d\n", ch->pcdata->wlosses);
    fprintf( fp, "Weapons      %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
	ch->wpn[0], ch->wpn[1], ch->wpn[2], ch->wpn[3], ch->wpn[4], 
	ch->wpn[5], ch->wpn[6], ch->wpn[7], ch->wpn[8], ch->wpn[9], 
	ch->wpn[10], ch->wpn[11], ch->wpn[12] );
    fprintf( fp, "Spells       %d %d %d %d %d\n",
	ch->spl[0], ch->spl[1], ch->spl[2], ch->spl[3], ch->spl[4] );
    fprintf( fp, "Combat       %d %d %d %d %d %d %d %d\n",
	ch->cmbt[0], ch->cmbt[1], ch->cmbt[2], ch->cmbt[3],
	ch->cmbt[4], ch->cmbt[5], ch->cmbt[6], ch->cmbt[7] );
    fprintf( fp, "Stance       %d %d %d %d %d %d %d %d %d %d %d %d\n",
	ch->stance[0], ch->stance[1], ch->stance[2], ch->stance[3],
	ch->stance[4], ch->stance[5], ch->stance[6], ch->stance[7],
	ch->stance[8], ch->stance[9], ch->stance[10], ch->stance[11] );
    fprintf( fp, "Stance2      %d %d %d %d %d %d %d %d %d %d %d %d\n",
        ch->stance[12], ch->stance[13], ch->stance[14], ch->stance[15],
        ch->stance[12], ch->stance[12], ch->stance[12], ch->stance[12],
        ch->stance[12], ch->stance[12], ch->stance[12], ch->stance[12] );
    fprintf( fp, "Locationhp   %d %d %d %d %d %d %d\n",
	ch->loc_hp[0], ch->loc_hp[1], ch->loc_hp[2], ch->loc_hp[3],
	ch->loc_hp[4], ch->loc_hp[5], ch->loc_hp[6] );
    fprintf( fp, "HpManaMove   %d %d %d %d %d %d\n",
	ch->hit, ch->max_hit, ch->mana, ch->max_mana, ch->move, ch->max_move );
    fprintf( fp, "Gold         %d\n",   ch->gold                );
    if (IS_CLASS(ch, CLASS_DEMON))
    {
    fprintf( fp, "Warps        %d\n",   ch->warp                );
    fprintf( fp, "WarpCount    %d\n",   ch->warpcount           );
    }
    fprintf( fp, "Monkstuff    %d\n",   ch->monkstuff		);
    fprintf( fp, "Monkcrap     %d\n",   ch->monkcrap		);
    fprintf( fp, "Chi	    %d %d\n",  ch->chi[0], ch->chi[1]   );
    fprintf( fp, "Focus     %d %d\n",  ch->focus[0], ch->focus[1] );
    fprintf( fp, "Monkab     %d %d %d %d\n", ch->monkab[0], ch->monkab[1], ch->monkab[2], ch->monkab[3] );
    fprintf( fp, "Gifts    %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n\r",
      ch->gifts[0],  ch->gifts[1],  ch->gifts[2],
      ch->gifts[3],  ch->gifts[4],  ch->gifts[5],
      ch->gifts[6],  ch->gifts[7],  ch->gifts[8],
      ch->gifts[9],  ch->gifts[10], ch->gifts[11],
      ch->gifts[12], ch->gifts[13], ch->gifts[14],
      ch->gifts[15], ch->gifts[16], ch->gifts[17],
      ch->gifts[18], ch->gifts[19], ch->gifts[20] );
    fprintf( fp, "Garou1	%d\n", ch->garou1 );
    fprintf( fp, "Garou2	%d\n", ch->garou2 );
    fprintf( fp, "Explevel     %d\n",   ch->explevel            );
    fprintf( fp, "Expgained    %d\n",   ch->expgained           );
    fprintf( fp, "Exp          %d\n",   ch->exp                 );
    fprintf( fp, "Levelexp     %d\n",   ch->levelexp            );
    fprintf( fp, "Act          %d\n",   ch->act                 );
    fprintf( fp, "Extra        %d\n",   ch->extra               );
    fprintf( fp, "AffectedBy   %d\n",   ch->affected_by         );
    /* Bug fix from Alander */
    fprintf( fp, "Position     %d\n",
	ch->position == POS_FIGHTING ? POS_STANDING : ch->position );

    fprintf( fp, "Practice     %d\n",   ch->practice            );
    fprintf( fp, "SavingThrow  %d\n",   ch->saving_throw        );
    fprintf( fp, "Alignment    %d\n",   ch->alignment           );
    fprintf( fp, "XHitroll     %d\n",   ch->xhitroll            );
    fprintf( fp, "XDamroll     %d\n",   ch->xdamroll            );
    fprintf( fp, "Hitroll      %d\n",   ch->hitroll             );
    fprintf( fp, "Damroll      %d\n",   ch->damroll             );
    fprintf( fp, "Armor        %d\n",   ch->armor               );
    fprintf( fp, "Wimpy        %d\n",   ch->wimpy               );
    fprintf( fp, "Deaf         %d\n",   ch->deaf                );

    if ( IS_NPC(ch) )
    {
	fprintf( fp, "Vnum         %d\n",       ch->pIndexData->vnum    );
    }
    else
    {
	fprintf( fp, "Password     %s~\n",      ch->pcdata->pwd         );
	fprintf( fp, "Bamfin       %s~\n",      ch->pcdata->bamfin      );
	fprintf( fp, "Bamfout      %s~\n",      ch->pcdata->bamfout     );
	fprintf( fp, "Title        %s~\n",      ch->pcdata->title       );
	fprintf( fp, "Conception   %s~\n",      ch->pcdata->conception  );
	fprintf( fp, "Parents      %s~\n",      ch->pcdata->parents     );
	fprintf( fp, "Cparents     %s~\n",      ch->pcdata->cparents    );
	fprintf( fp, "Marriage     %s~\n",      ch->pcdata->marriage    );
	fprintf( fp, "Email        %s~\n",      ch->pcdata->email       );
	fprintf( fp, "AttrPerm     %d %d %d %d %d\n",
	    ch->pcdata->perm_str,
	    ch->pcdata->perm_int,
	    ch->pcdata->perm_wis,
	    ch->pcdata->perm_dex,
	    ch->pcdata->perm_con );

	fprintf( fp, "AttrMod      %d %d %d %d %d\n",
	    ch->pcdata->mod_str, 
	    ch->pcdata->mod_int, 
	    ch->pcdata->mod_wis,
	    ch->pcdata->mod_dex, 
	    ch->pcdata->mod_con );

	fprintf( fp, "Quest        %d\n", ch->pcdata->quest );
	fprintf( fp, "Wolf         %d\n", ch->pcdata->wolf );
	fprintf( fp, "Rank         %d\n", ch->pcdata->rank );
	fprintf( fp, "Language     %d %d\n",
	    ch->pcdata->language[0],
	    ch->pcdata->language[1] );
	fprintf( fp, "Stage        %d %d %d\n",
	    ch->pcdata->stage[0],
	    ch->pcdata->stage[1],
	    ch->pcdata->stage[2] );
	fprintf( fp, "Wolfform     %d %d\n",
	    ch->pcdata->wolfform[0],
	    ch->pcdata->wolfform[1] );
	fprintf( fp, "Score        %d %d %d %d %d %d\n",
	    ch->pcdata->score[0],
	    ch->pcdata->score[1],
	    ch->pcdata->score[2],
	    ch->pcdata->score[3],
	    ch->pcdata->score[4],
	    ch->pcdata->score[5]);
	fprintf( fp, "Runes        %d %d %d %d\n",
	    ch->pcdata->runes[0],
	    ch->pcdata->runes[1],
	    ch->pcdata->runes[2],
	    ch->pcdata->runes[3]);
	fprintf( fp, "Disc         %d %d %d %d %d %d %d %d %d %d %d\n",
	    ch->pcdata->disc_a[0],
	    ch->pcdata->disc_a[1],
	    ch->pcdata->disc_a[2],
	    ch->pcdata->disc_a[3],
	    ch->pcdata->disc_a[4],
	    ch->pcdata->disc_a[5],
	    ch->pcdata->disc_a[6],
	    ch->pcdata->disc_a[7],
	    ch->pcdata->disc_a[8],
	    ch->pcdata->disc_a[9],
	    ch->pcdata->disc_a[10]);
	fprintf( fp, "Genes        %d %d %d %d %d %d %d %d %d %d\n",
	    ch->pcdata->genes[0],
	    ch->pcdata->genes[1],
	    ch->pcdata->genes[2],
	    ch->pcdata->genes[3],
	    ch->pcdata->genes[4],
	    ch->pcdata->genes[5],
	    ch->pcdata->genes[6],
	    ch->pcdata->genes[7],
	    ch->pcdata->genes[8],
	    ch->pcdata->genes[9] );
	fprintf( fp, "Power        %d %d\n",
	    ch->pcdata->powers[0],
	    ch->pcdata->powers[1] );

	fprintf( fp, "FakeCon      %d %d %d %d %d %d %d %d\n",
	    ch->pcdata->fake_skill, 
	    ch->pcdata->fake_stance, 
	    ch->pcdata->fake_hit,
	    ch->pcdata->fake_dam,
	    ch->pcdata->fake_ac,
	    ch->pcdata->fake_hp,
	    ch->pcdata->fake_mana,
	    ch->pcdata->fake_move);

	if (ch->pcdata->obj_vnum != 0)
	    fprintf( fp, "Objvnum      %d\n", ch->pcdata->obj_vnum );

	fprintf( fp, "Condition    %d %d %d\n",
	    ch->pcdata->condition[0],
	    ch->pcdata->condition[1],
	    ch->pcdata->condition[2] );

	fprintf( fp, "StatAbility  %d %d %d %d\n",
	    ch->pcdata->stat_ability[0],
	    ch->pcdata->stat_ability[1],
	    ch->pcdata->stat_ability[2],
	    ch->pcdata->stat_ability[3] );

	fprintf( fp, "StatAmount   %d %d %d %d\n",
	    ch->pcdata->stat_amount[0],
	    ch->pcdata->stat_amount[1],
	    ch->pcdata->stat_amount[2],
	    ch->pcdata->stat_amount[3] );

	fprintf( fp, "StatDuration %d %d %d %d\n",
	    ch->pcdata->stat_duration[0],
	    ch->pcdata->stat_duration[1],
	    ch->pcdata->stat_duration[2],
	    ch->pcdata->stat_duration[3] );

	fprintf( fp, "Exhaustion   %d\n", ch->pcdata->exhaustion );

	for ( sn = 0; sn < MAX_SKILL; sn++ )
	{
	    if ( skill_table[sn].name != NULL && ch->pcdata->learned[sn] > 0 )
	    {
		fprintf( fp, "Skill        %d '%s'\n",
		    ch->pcdata->learned[sn], skill_table[sn].name );
	    }
	}
    }

    for ( paf = ch->affected; paf != NULL; paf = paf->next )
    {
	/* Thx Alander */
	if ( paf->type < 0 || paf->type >= MAX_SKILL )
	    continue;

	fprintf( fp, "AffectData   '%s' %3d %3d %3d %10d\n",
	    skill_table[paf->type].name,
	    paf->duration,
	    paf->modifier,
	    paf->location,
	    paf->bitvector
	    );
    }

    fprintf( fp, "End\n\n" );
    return;
}

/*
 * Write the char.
 */
void fwrite_char( CHAR_DATA *ch, FILE *fp )
{
    AFFECT_DATA *paf;
    int sn;
    int i;

    fprintf( fp, "#%s\n", IS_NPC(ch) ? "MOB" : "PLAYERS"                );

    fprintf( fp, "Name         %s~\n",  ch->name                );
    fprintf( fp, "Switchname   %s~\n",  ch->pcdata->switchname  );
    fprintf( fp, "ShortDescr   %s~\n",  ch->short_descr         );
    fprintf( fp, "LongDescr    %s~\n",  ch->long_descr          );
    fprintf( fp, "ObjDesc      %s~\n",  ch->objdesc		);
    fprintf( fp, "Description  %s~\n",  ch->description         );
    fprintf( fp, "Lord         %s~\n",  ch->lord                );
    fprintf( fp, "Kingdom      %d\n", ch->pcdata->kingdom	);
    fprintf( fp, "CPower %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", ch->power[0],ch->power[1],ch->power[2],ch->power[3],ch->power[4], ch->power[5],ch->power[6],ch
















->power[7],ch->power[8],ch->power[9], ch->power[10],ch->power[11],ch->power[12],ch->power[13],ch->power[14], ch->power[15],ch->power[16],ch->power[17],ch->power[18],ch->power[19], ch->power[20],ch->power[21],ch->power[22],ch->power[23],ch->power[24], ch->
















power[25],ch->power[26],ch->power[27],ch->power[28],ch->power[29], ch->power[30],ch->power[31],ch->power[32],ch->power[33],ch->power[34], ch->power[35],ch->power[36],ch->power[37],ch->power[38],ch->power[39], ch->power[40],ch->power[41],ch->power[42],ch->
















power[43]);
    fprintf( fp, "DiscRese     %d\n",   ch->pcdata->disc_research);
    fprintf( fp, "DiscPoin     %d\n",   ch->pcdata->disc_points );
    fprintf( fp, "Class        %d\n",   ch->class               );
    fprintf( fp, "Morph        %s~\n",  ch->morph               );
    fprintf( fp, "Createtime   %s~\n",  ch->createtime          );
    fprintf( fp, "Lasttime     %s~\n",  ch->lasttime            );
    fprintf( fp, "Lasthost     %s~\n",  ch->lasthost            );
    fprintf( fp, "Poweraction  %s~\n",  ch->poweraction         );
    fprintf( fp, "Powertype    %s~\n",  ch->powertype           );
    fprintf( fp, "Prompt       %s~\n",  ch->prompt              );
    fprintf( fp, "Cprompt      %s~\n",  ch->cprompt             );
    fprintf( fp, "Sex          %d\n",   ch->sex                 );
    fprintf( fp, "Race         %d\n",   ch->race                );
    fprintf( fp, "Immune       %d\n",   ch->immune              );
    fprintf( fp, "Polyaff      %d\n",   ch->polyaff             );
/* Dh Crap */
    fprintf( fp, "CurrentForm  %d\n",   ch->cur_form            );
    fprintf( fp, "Rage         %d\n",   ch->rage                );
    fprintf( fp, "Generation   %d\n",   ch->generation          );
    fprintf( fp, "Flag2       %d\n",   ch->flag2              );
    fprintf( fp, "Flag3       %d\n",   ch->flag3              );
    fprintf( fp, "Flag4       %d\n",   ch->flag4              ); 
    fprintf( fp, "SilTol      %d\n",   ch->siltol               );
    fprintf( fp, "Souls	      %d\n",   ch->pcdata->souls        );
/* Lala */
    fprintf( fp, "Itemaffect   %d\n",   ch->itemaffect          );
    fprintf( fp, "Form         %d\n",   ch->form                );
    fprintf( fp, "Beast        %d\n",   ch->beast               );
    fprintf( fp, "Spectype     %d\n",   ch->spectype            );
    fprintf( fp, "Specpower    %d\n",   ch->specpower           );
    fprintf( fp, "Home         %d\n",   ch->home                );
    fprintf( fp, "Level        %d\n",   ch->level               );
    fprintf( fp, "Trust        %d\n",   ch->trust               );
    fprintf( fp, "Security     %d\n",    ch->pcdata->security    );  /* OLC */

    fprintf( fp, "Paradox      %d %d %d\n", ch->paradox[0], ch->paradox[1], 
					     ch->paradox[2] ); 
    fprintf( fp, "Played       %d\n",
	ch->played + (int) (current_time - ch->logon)           );
    fprintf( fp, "Room         %d\n",
	(  ch->in_room == get_room_index( ROOM_VNUM_LIMBO )
	&& ch->was_in_room != NULL )
	    ? ch->was_in_room->vnum
	    : ch->in_room->vnum );

    fprintf( fp, "PkPdMkMd     %d %d %d %d\n",
	ch->pkill, ch->pdeath, ch->mkill, ch->mdeath );
    fprintf( fp, "Alos         %d\n", ch->pcdata->alosses);
    fprintf( fp, "Awin         %d\n", ch->pcdata->awins); 
    fprintf( fp, "Wwin	       %d\n", ch->pcdata->wwins);
    fprintf( fp, "Wlos         %d\n", ch->pcdata->wlosses);
    fprintf( fp, "Weapons      %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
	ch->wpn[0], ch->wpn[1], ch->wpn[2], ch->wpn[3], ch->wpn[4], 
	ch->wpn[5], ch->wpn[6], ch->wpn[7], ch->wpn[8], ch->wpn[9], 
	ch->wpn[10], ch->wpn[11], ch->wpn[12] );
    fprintf( fp, "Spells       %d %d %d %d %d\n",
	ch->spl[0], ch->spl[1], ch->spl[2], ch->spl[3], ch->spl[4] );
    fprintf( fp, "Combat       %d %d %d %d %d %d %d %d\n",
	ch->cmbt[0], ch->cmbt[1], ch->cmbt[2], ch->cmbt[3],
	ch->cmbt[4], ch->cmbt[5], ch->cmbt[6], ch->cmbt[7] );
    fprintf( fp, "Stance       %d %d %d %d %d %d %d %d %d %d %d %d\n",
	ch->stance[0], ch->stance[1], ch->stance[2], ch->stance[3],
	ch->stance[4], ch->stance[5], ch->stance[6], ch->stance[7],
	ch->stance[8], ch->stance[9], ch->stance[10], ch->stance[11] );
    fprintf( fp, "Stance2      %d %d %d %d %d %d %d %d %d %d %d %d\n",
        ch->stance[12], ch->stance[13], ch->stance[14], ch->stance[15],
        ch->stance[12], ch->stance[12], ch->stance[12], ch->stance[12],
        ch->stance[12], ch->stance[12], ch->stance[12], ch->stance[12] );
    fprintf( fp, "Locationhp   %d %d %d %d %d %d %d\n",
	ch->loc_hp[0], ch->loc_hp[1], ch->loc_hp[2], ch->loc_hp[3],
	ch->loc_hp[4], ch->loc_hp[5], ch->loc_hp[6] );
    fprintf( fp, "HpManaMove   %d %d %d %d %d %d\n",
	ch->hit, ch->max_hit, ch->mana, ch->max_mana, ch->move, ch->max_move );
    fprintf( fp, "Gold         %d\n",   ch->gold                );
    if (IS_CLASS(ch, CLASS_DEMON))
    {
    fprintf( fp, "Warps        %d\n",   ch->warp                );
    fprintf( fp, "WarpCount    %d\n",   ch->warpcount           );
    }
    fprintf( fp, "Monkstuff    %d\n",   ch->monkstuff           );
    fprintf( fp, "Monkcrap     %d\n",   ch->monkcrap            );
    fprintf( fp, "Chi       %d %d\n",  ch->chi[0], ch->chi[1]   );
    fprintf( fp, "Focus     %d %d\n",  ch->focus[0], ch->focus[1] );
    fprintf( fp, "Monkab     %d %d %d %d\n", ch->monkab[0], ch->monkab[1],
                                            ch->monkab[2], ch->monkab[3]);
    fprintf( fp, "Gifts    %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n\r",
      ch->gifts[0],  ch->gifts[1],  ch->gifts[2],
      ch->gifts[3],  ch->gifts[4],  ch->gifts[5],
      ch->gifts[6],  ch->gifts[7],  ch->gifts[8],
      ch->gifts[9],  ch->gifts[10], ch->gifts[11],
      ch->gifts[12], ch->gifts[13], ch->gifts[14],
      ch->gifts[15], ch->gifts[16], ch->gifts[17],
      ch->gifts[18], ch->gifts[19], ch->gifts[20] );
    fprintf( fp, "Garou1        %d\n", ch->garou1 );
    fprintf( fp, "Garou2        %d\n", ch->garou2 );
    fprintf( fp, "Explevel     %d\n",   ch->explevel            );
    fprintf( fp, "Expgained    %d\n",   ch->expgained           );
    fprintf( fp, "Exp          %d\n",   ch->exp                 );
    fprintf( fp, "Levelexp     %d\n",   ch->levelexp            );
    fprintf( fp, "Act          %d\n",   ch->act                 );
    fprintf( fp, "Special      %d\n",   ch->special             );
    fprintf( fp, "Newbits      %d\n",   ch->newbits             );

    fprintf( fp, "Extra        %d\n",   ch->extra               );
    fprintf( fp, "AffectedBy   %d\n",   ch->affected_by         );
    fprintf( fp, "Position     %d\n",
	ch->position == POS_FIGHTING ? POS_STANDING : ch->position );

    fprintf( fp, "Practice     %d\n",   ch->practice            );
    fprintf( fp, "SavingThrow  %d\n",   ch->saving_throw        );
    fprintf( fp, "Alignment    %d\n",   ch->alignment           );
    fprintf( fp, "XHitroll     %d\n",   ch->xhitroll            );
    fprintf( fp, "XDamroll     %d\n",   ch->xdamroll            );
    fprintf( fp, "Hitroll      %d\n",   ch->hitroll             );
    fprintf( fp, "Damroll      %d\n",   ch->damroll             );
    fprintf( fp, "Armor        %d\n",   ch->armor               );
    fprintf( fp, "Wimpy        %d\n",   ch->wimpy               );
    fprintf( fp, "Deaf         %d\n",   ch->deaf                );




    if ( IS_NPC(ch) )
    {
	fprintf( fp, "Vnum         %d\n",       ch->pIndexData->vnum    );
    }
    else
    {
	fprintf( fp, "Password     %s~\n",      ch->pcdata->pwd         );
	fprintf( fp, "Bamfin       %s~\n",      ch->pcdata->bamfin      );
	fprintf( fp, "Bamfout      %s~\n",      ch->pcdata->bamfout     );
	fprintf( fp, "Title        %s~\n",      ch->pcdata->title       );
/*	fprintf( fp, "Bounty	    %d\n",      ch->pcdata->bounty
);*/
	fprintf( fp, "Conception   %s~\n",      ch->pcdata->conception  );
	fprintf( fp, "Parents      %s~\n",      ch->pcdata->parents     );
	fprintf( fp, "Cparents     %s~\n",      ch->pcdata->cparents    );
	fprintf( fp, "Marriage     %s~\n",      ch->pcdata->marriage    );
	fprintf( fp, "Email        %s~\n",      ch->pcdata->email       );
	fprintf( fp, "AttrPerm     %d %d %d %d %d\n",
	    ch->pcdata->perm_str,
	    ch->pcdata->perm_int,
	    ch->pcdata->perm_wis,
	    ch->pcdata->perm_dex,
	    ch->pcdata->perm_con );

	fprintf( fp, "AttrMod      %d %d %d %d %d\n",
	    ch->pcdata->mod_str, 
	    ch->pcdata->mod_int, 
	    ch->pcdata->mod_wis,
	    ch->pcdata->mod_dex, 
	    ch->pcdata->mod_con );

	fprintf( fp, "Quest        %d\n", ch->pcdata->quest );
	fprintf( fp, "Wolf         %d\n", ch->rage      );
	fprintf( fp, "Rank         %d\n", ch->pcdata->rank );
	fprintf( fp, "Language     %d %d\n",
	    ch->pcdata->language[0],
	    ch->pcdata->language[1] );
	fprintf( fp, "Stage        %d %d %d\n",
	    ch->pcdata->stage[0],
	    ch->pcdata->stage[1],
	    ch->pcdata->stage[2] );
	fprintf( fp, "Score        %d %d %d %d %d %d\n",
	    ch->pcdata->score[0],
	    ch->pcdata->score[1],
	    ch->pcdata->score[2],
	    ch->pcdata->score[3],
	    ch->pcdata->score[4],
	    ch->pcdata->score[5]);
	fprintf( fp, "Genes        %d %d %d %d %d %d %d %d %d %d\n",
	    ch->pcdata->genes[0],
	    ch->pcdata->genes[1],
	    ch->pcdata->genes[2],
	    ch->pcdata->genes[3],
	    ch->pcdata->genes[4],
	    ch->pcdata->genes[5],
	    ch->pcdata->genes[6],
	    ch->pcdata->genes[7],
	    ch->pcdata->genes[8],
	    ch->pcdata->genes[9] );
	fprintf( fp, "Power        ");
	    for (sn=0; sn < 20; sn++)
	    {
		fprintf(fp, "%d ", ch->pcdata->powers[sn]);
	    }
	    fprintf(fp, "\n");

	fprintf( fp, "Stats        ");
	    for (sn=0; sn < 12; sn++)
	    {
		fprintf(fp, "%d ", ch->pcdata->stats[sn]);
	    }
	    fprintf(fp, "\n");

	fprintf( fp, "FakeCon      %d %d %d %d %d %d %d %d\n",
	    ch->pcdata->fake_skill, 
	    ch->pcdata->fake_stance, 
	    ch->pcdata->fake_hit,
	    ch->pcdata->fake_dam,
	    ch->pcdata->fake_ac,
	    ch->pcdata->fake_hp,
	    ch->pcdata->fake_mana,
	    ch->pcdata->fake_move);

	if (ch->pcdata->obj_vnum != 0)
	    fprintf( fp, "Objvnum      %d\n", ch->pcdata->obj_vnum );

	fprintf( fp, "Condition    %d %d %d\n",
	    ch->pcdata->condition[0],
	    ch->pcdata->condition[1],
	    ch->pcdata->condition[2] );

	fprintf( fp, "StatAbility  %d %d %d %d\n",
	    ch->pcdata->stat_ability[0],
	    ch->pcdata->stat_ability[1],
	    ch->pcdata->stat_ability[2],
	    ch->pcdata->stat_ability[3] );

	fprintf( fp, "StatAmount   %d %d %d %d\n",
	    ch->pcdata->stat_amount[0],
	    ch->pcdata->stat_amount[1],
	    ch->pcdata->stat_amount[2],
	    ch->pcdata->stat_amount[3] );

	fprintf( fp, "StatDuration %d %d %d %d\n",
	    ch->pcdata->stat_duration[0],
	    ch->pcdata->stat_duration[1],
	    ch->pcdata->stat_duration[2],
	    ch->pcdata->stat_duration[3] );

	fprintf( fp, "Exhaustion   %d\n", ch->pcdata->exhaustion );

	fprintf( fp, "ww_researching   %d\n", ch->pcdata->ww_researching[TOTEM_RESEARCHING] );
	fprintf( fp, "ww_completed   %d\n", ch->pcdata->ww_completed[AMOUNT_COMPLETED]   );

	/* Save note board status */
	/* Save number of boards in case that number changes */
	fprintf (fp, "Boards       %d ", MAX_BOARD);
	for (i = 0; i < MAX_BOARD; i++)
	fprintf (fp, "%s %ld ", boards[i].short_name, ch->pcdata->last_note[i]);
	fprintf (fp, "\n");
	


	for ( sn = 0; sn < MAX_SKILL; sn++ )
	{
	    if ( skill_table[sn].name != NULL && ch->pcdata->learned[sn] > 0 )
	    {
		fprintf( fp, "Skill        %d '%s'\n",
		    ch->pcdata->learned[sn], skill_table[sn].name );
	    }
	}
    }

    for ( paf = ch->affected; paf != NULL; paf = paf->next )
    {
	/* Thx Alander */
	if ( paf->type < 0 || paf->type >= MAX_SKILL )
	    continue;

	fprintf( fp, "AffectData   '%s' %3d %3d %3d %10d\n",
	    skill_table[paf->type].name,
	    paf->duration,
	    paf->modifier,
	    paf->location,
	    paf->bitvector
	    );
    }

    fprintf( fp, "End\n\n" );
    return;
}



/*
 * Write an object and its contents.
 */
void fwrite_obj( CHAR_DATA *ch, OBJ_DATA *obj, FILE *fp, int iNest )
{
    EXTRA_DESCR_DATA *ed;
    AFFECT_DATA *paf;
/*
    int vnum = obj->pIndexData->vnum;

     *
     * Slick recursion to write lists backwards,
     *   so loading them will load in forwards order.
     */
    if ( obj->next_content != NULL )
	fwrite_obj( ch, obj->next_content, fp, iNest );

    /*
     * Castrate storage characters.
     */

    if ( (obj->chobj != NULL && (!IS_NPC(obj->chobj) &&
	obj->chobj->pcdata->obj_vnum != 0)) || obj->item_type == ITEM_KEY)
	return;

    fprintf( fp, "#OBJECT\n" );
    fprintf( fp, "Nest         %d\n",   iNest                        );
    fprintf( fp, "Name         %s~\n",  obj->name                    );
    fprintf( fp, "ShortDescr   %s~\n",  obj->short_descr             );
    fprintf( fp, "Description  %s~\n",  obj->description             );
    if (obj->chpoweron != NULL && strlen(obj->chpoweron) > 1 && str_cmp(obj->chpoweron,"(null)") )
	fprintf( fp, "Poweronch    %s~\n",      obj->chpoweron       );
    if (obj->chpoweroff != NULL && strlen(obj->chpoweroff) > 1 && str_cmp(obj->chpoweroff,"(null)"))
	fprintf( fp, "Poweroffch   %s~\n",      obj->chpoweroff      );
    if (obj->chpoweruse != NULL && strlen(obj->chpoweruse) > 1 && str_cmp(obj->chpoweruse,"(null)"))
	fprintf( fp, "Powerusech   %s~\n",      obj->chpoweruse      );
    if (obj->victpoweron != NULL && strlen(obj->victpoweron) > 1 && str_cmp(obj->victpoweron,"(null)"))
	fprintf( fp, "Poweronvict  %s~\n",      obj->victpoweron     );
    if (obj->victpoweroff != NULL && strlen(obj->victpoweroff) > 1 && str_cmp(obj->victpoweroff,"(null)"))
	fprintf( fp, "Poweroffvict %s~\n",      obj->victpoweroff    );
    if (obj->victpoweruse != NULL && strlen(obj->victpoweruse) > 1 && str_cmp(obj->victpoweruse,"(null)"))
	fprintf( fp, "Powerusevict %s~\n",      obj->victpoweruse    );
    if (obj->questmaker != NULL && strlen(obj->questmaker) > 1)
	fprintf( fp, "Questmaker   %s~\n",      obj->questmaker      );
    if (obj->questowner != NULL && strlen(obj->questowner) > 1)
	fprintf( fp, "Questowner   %s~\n",      obj->questowner      );

    fprintf( fp, "Vnum         %d\n",   obj->pIndexData->vnum        );

    fprintf( fp, "ExtraFlags   %d\n",   obj->extra_flags             );
    fprintf( fp, "ExtraFlags2  %d\n",   obj->extra_flags2            );
    fprintf( fp, "WeapFlags    %d\n",   obj->weapflags               );
    fprintf( fp, "WearFlags    %d\n",   obj->wear_flags              );
    fprintf( fp, "WearLoc      %d\n",   obj->wear_loc                );
    fprintf( fp, "ItemType     %d\n",   obj->item_type               );
    fprintf( fp, "Weight       %d\n",   obj->weight                  );
    if (obj->spectype != 0)
	fprintf( fp, "Spectype     %d\n",       obj->spectype        );
    if (obj->specpower != 0)
	fprintf( fp, "Specpower    %d\n",       obj->specpower       );
    fprintf( fp, "Condition    %d\n",   obj->condition               );
    fprintf( fp, "Toughness    %d\n",   obj->toughness               );
    fprintf( fp, "Resistance   %d\n",   obj->resistance              );
    if (obj->quest != 0)
	fprintf( fp, "Quest        %d\n",       obj->quest           );
    if (obj->points != 0)
	fprintf( fp, "Points       %d\n",       obj->points          );
    fprintf( fp, "Level        %d\n",   obj->level                   );
    fprintf( fp, "Timer        %d\n",   obj->timer                   );
    fprintf( fp, "Cost         %d\n",   obj->cost                    );
    fprintf( fp, "Values       %d %d %d %d\n",
	obj->value[0], obj->value[1], obj->value[2], obj->value[3]           );

    switch ( obj->item_type )
    {
    case ITEM_POTION:
	if ( obj->value[1] > 0 )
	{
	    fprintf( fp, "Spell 1      '%s'\n", 
		skill_table[obj->value[1]].name );
	}

	if ( obj->value[2] > 0 )
	{
	    fprintf( fp, "Spell 2      '%s'\n", 
		skill_table[obj->value[2]].name );
	}

	if ( obj->value[3] > 0 )
	{
	    fprintf( fp, "Spell 3      '%s'\n", 
		skill_table[obj->value[3]].name );
	}

	break;

    case ITEM_SCROLL:
	if ( obj->value[1] > 0 )
	{
	    fprintf( fp, "Spell 1      '%s'\n", 
		skill_table[obj->value[1]].name );
	}

	if ( obj->value[2] > 0 )
	{
	    fprintf( fp, "Spell 2      '%s'\n", 
		skill_table[obj->value[2]].name );
	}

	if ( obj->value[3] > 0 )
	{
	    fprintf( fp, "Spell 3      '%s'\n", 
		skill_table[obj->value[3]].name );
	}

	break;

    case ITEM_PILL:
    case ITEM_STAFF:
    case ITEM_WAND:
	if ( obj->value[3] > 0 )
	{
	    fprintf( fp, "Spell 3      '%s'\n", 
		skill_table[obj->value[3]].name );
	}

	break;
    }

    for ( paf = obj->affected; paf != NULL; paf = paf->next )
    {
/*
	if ( paf->type < 0 || paf->type >= MAX_SKILL ) continue;
*/
	fprintf( fp, "AffectData   %d %d %d\n",
	    paf->duration, paf->modifier, paf->location );
    }
/*
    if ( vnum >= 17 && ( vnum < 3 || vnum > 30037 ) )
    {
	for ( paf = obj->pIndexData->affected; paf != NULL; paf = paf->next )
	{
**
	    if ( paf->type < 0 || paf->type >= MAX_SKILL ) continue;
**
	    fprintf( fp, "AffectData   %d %d %d\n",
		paf->duration, paf->modifier, paf->location );
	}
    }
*/
    for ( ed = obj->extra_descr; ed != NULL; ed = ed->next )
    {
	fprintf( fp, "ExtraDescr   %s~ %s~\n",
	    ed->keyword, ed->description );
    }
/*
    if ( vnum >= 17 && ( vnum < 3 || vnum > 30037 ) )
    {
	for ( ed = obj->pIndexData->extra_descr; ed != NULL; ed = ed->next )
	{
	    fprintf( fp, "ExtraDescr   %s~ %s~\n",
		ed->keyword, ed->description );
	}
    }
*/
    fprintf( fp, "End\n\n" );

    if ( obj->contains != NULL )
	fwrite_obj( ch, obj->contains, fp, iNest + 1 );

    return;
}



/*
 * Load a char and inventory into a new ch structure.
 */
bool load_char_obj( DESCRIPTOR_DATA *d, char *name )
{
    static PC_DATA pcdata_zero;
    char strsave[MAX_STRING_LENGTH];
    char *strtime;
    CHAR_DATA *ch;
    FILE *fp;
    bool found;
    int sn;

    if ( char_free == NULL )
    {
	ch                              = alloc_perm( sizeof(*ch) );
    }
    else
    {
	ch                              = char_free;
	char_free                       = char_free->next;
    }
    clear_char( ch );

    if ( pcdata_free == NULL )
    {
	ch->pcdata                      = alloc_perm( sizeof(*ch->pcdata) );
    }
    else
    {
	ch->pcdata                      = pcdata_free;
	pcdata_free                     = pcdata_free->next;
    }
    *ch->pcdata                         = pcdata_zero;

    d->character                        = ch;
    ch->desc                            = d;
    ch->name                            = str_dup( name );
    ch->pcdata->switchname              = str_dup( name );
    ch->act                             = PLR_BLANK
					| PLR_COMBINE
					| PLR_PROMPT;
 
	/* every characters starts at default board from login.. this board
	   should be read_level == 0 !
	*/   
	ch->pcdata->board               = &boards[DEFAULT_BOARD];
				
   
    ch->extra                           = 0;
    ch->special                         = 0;
    ch->newbits                         = 0;
    ch->class                           = -1;
    ch->pcdata->familiar                = NULL;
    ch->pcdata->partner                 = NULL;
    ch->pcdata->propose                 = NULL;
    ch->pcdata->chobj                   = NULL;
    ch->pcdata->memorised               = NULL;
    ch->pcdata->pwd                     = str_dup( "" );
    ch->pcdata->bamfin                  = str_dup( "" );
    ch->pcdata->bamfout                 = str_dup( "" );
    ch->pcdata->title                   = str_dup( "" );
/*    ch->pcdata->bounty			= 0;*/
    ch->pcdata->conception              = str_dup( "" );
    ch->pcdata->parents                 = str_dup( "" );
    ch->pcdata->cparents                = str_dup( "" );
    ch->pcdata->marriage                = str_dup( "" );
    ch->pcdata->email                   = str_dup( "" );
    ch->pcdata->disc_research           = -1;
    ch->lord                            = str_dup( "" );
    ch->morph                           = str_dup( "" );
    ch->pload                           = str_dup( "" );
    ch->prompt                          = str_dup( "" );
    ch->cprompt                         = str_dup( "" );
    strtime = ctime( &current_time );
    strtime[strlen(strtime)-1] = '\0';
    free_string(ch->lasttime);
    ch->createtime                      = str_dup( strtime );
    ch->lasttime                        = str_dup( "" );
    ch->lasthost                        = str_dup( "" );
    ch->poweraction                     = str_dup( "" );
    ch->powertype                       = str_dup( "" );
    ch->hunting                         = str_dup( "" );
    ch->pcdata->followers               = 0;
    ch->spectype                        = 0;
    ch->specpower                       = 0;
    ch->mounted                         = 0;
    ch->home                            = 3001;
    ch->vampgen_a                       = 0;
    ch->paradox[0]                      = 0;    /* Total paradox */
    ch->paradox[1]                      = 0;    /* Current Paradox */
    ch->paradox[2]                      = 0;    /* Paradox Ticker */
    ch->damcap[0]                       = 1000;
    ch->damcap[1]                       = 0;
    ch->vampaff_a                       = 0;
    ch->itemaffect                      = 0;
    ch->vamppass_a                      = -1;
    ch->polyaff                         = 0;
    ch->immune                          = 0;
    ch->form                            = 32767;
    ch->beast                           = 15;
    for( sn=0 ; sn < 7 ; sn ++ )
	ch->loc_hp[sn]                  = 0;
    for( sn=0 ; sn < 13 ; sn++ )
	 ch->wpn[sn]                    = 0;
    for( sn=0 ; sn < 5 ; sn++ )
	 ch->spl[sn]                    = 0;
    for( sn=0 ; sn < 8 ; sn++ )
	 ch->cmbt[sn]                   = 0;
    for( sn=0 ; sn < 11 ; sn++ )
	 ch->cmbt[sn]                   = 0;

    ch->pkill                           = 0;
    ch->pdeath                          = 0;
    ch->mkill                           = 0;
    ch->mdeath                          = 0;
    ch->class                           = -1;
    ch->pcdata->followers               = 0;
    ch->pcdata->perm_str                = 13;
    ch->pcdata->perm_int                = 13; 
    ch->pcdata->perm_wis                = 13;
    ch->pcdata->perm_dex                = 13;
    ch->pcdata->perm_con                = 13;
    ch->pcdata->quest                   = 0;
	ch->pcdata->kingdom		= 0;
    ch->pcdata->wolf                    = 0;
    ch->pcdata->rank                    = 0;
    ch->pcdata->language[0]             = 0;
    ch->pcdata->language[1]             = 0;
    ch->pcdata->stage[0]                = 0;
    ch->pcdata->stage[1]                = 0;
    ch->pcdata->stage[2]                = 0;
    ch->pcdata->wolfform[0]             = 1;
    ch->pcdata->wolfform[1]             = 1;
    ch->pcdata->score[0]                = 0;
    ch->pcdata->score[1]                = 0;
    ch->pcdata->score[2]                = 0;
    ch->pcdata->score[3]                = 0;
    ch->pcdata->score[4]                = 0;
    ch->pcdata->score[5]                = 0;

    for( sn=0 ; sn < 11 ; sn++ )
	 ch->pcdata->disc_a[sn]         = 0;

    for( sn=0 ; sn < 10 ; sn++ )
	 ch->pcdata->genes[sn]          = 0;

    for ( sn=0 ; sn < 20 ; sn++)
	ch->pcdata->powers[sn]          = 0;

    for ( sn=0 ; sn < 12 ; sn++)
	ch->pcdata->stats[sn]           = 0;

    ch->pcdata->security                = 0;    /* OLC */

    ch->pcdata->fake_skill              = 0;
    ch->pcdata->fake_stance             = 0;
    ch->pcdata->fake_hit                = 0;
    ch->pcdata->fake_dam                = 0;
    ch->pcdata->fake_ac                 = 0;
    ch->pcdata->fake_hp                 = 0;
    ch->pcdata->fake_mana               = 0;
    ch->pcdata->fake_move               = 0;
    ch->pcdata->obj_vnum                = 0;
    ch->pcdata->condition[COND_THIRST]  = 48;
    ch->pcdata->condition[COND_FULL]    = 48;
    ch->pcdata->stat_ability[STAT_STR]  = 0;
    ch->pcdata->stat_ability[STAT_END]  = 0;
    ch->pcdata->stat_ability[STAT_REF]  = 0;
    ch->pcdata->stat_ability[STAT_FLE]  = 0;
    ch->pcdata->stat_amount[STAT_STR]   = 0;
    ch->pcdata->stat_amount[STAT_END]   = 0;
    ch->pcdata->stat_amount[STAT_REF]   = 0;
    ch->pcdata->stat_amount[STAT_FLE]   = 0;
    ch->pcdata->stat_duration[STAT_STR] = 0;
    ch->pcdata->stat_duration[STAT_END] = 0;
    ch->pcdata->stat_duration[STAT_REF] = 0;
    ch->pcdata->stat_duration[STAT_FLE] = 0;
    ch->pcdata->exhaustion              = 0;
    ch->pcdata->ww_researching[TOTEM_RESEARCHING] = 0;
    ch->pcdata->ww_completed[AMOUNT_COMPLETED] = 0;

    found = FALSE;
    fclose( fpReserve );
    sprintf( strsave, "%s%s", PLAYER_DIR, capitalize( name ) );
    if ( ( fp = fopen( strsave, "r" ) ) != NULL )
    {
	int iNest;

	for ( iNest = 0; iNest < MAX_NEST; iNest++ )
	    rgObjNest[iNest] = NULL;

	found = TRUE;
	for ( ; ; )
	{
	    char letter;
	    char *word;

	    letter = fread_letter( fp );
	    if ( letter == '*' )
	    {
		fread_to_eol( fp );
		continue;
	    }

	    if ( letter != '#' )
	    {
		bug( "Load_char_obj: # not found.", 0 );
		break;
	    }

	    word = fread_word( fp );
	    if      ( !str_cmp( word, "PLAYER" ) ) 
	    {
		fread_char_old ( ch, fp );
		convert_old_new( ch );
	    }
	    else if ( !str_cmp( word, "PLAYERS" ) ) fread_char    ( ch, fp );
	    else if ( !str_cmp( word, "OBJECT" ) ) fread_obj      ( ch, fp );
	    else if ( !str_cmp( word, "END"    ) ) break;
	    else
	    {
		bug( "Load_char_obj: bad section.", 0 );
		break;
	    }
	}
	fclose( fp );
    }

    fpReserve = fopen( NULL_FILE, "r" );
    return found;
}



bool load_char_short( DESCRIPTOR_DATA *d, char *name )
{
    static PC_DATA pcdata_zero;
    char strsave[MAX_STRING_LENGTH];
    CHAR_DATA *ch;
    char *strtime;
    FILE *fp;
    bool found;

    if ( char_free == NULL )
    {
	ch                              = alloc_perm( sizeof(*ch) );
    }
    else
    {
	ch                              = char_free;
	char_free                       = char_free->next;
    }
    clear_char( ch );

    if ( pcdata_free == NULL )
    {
	ch->pcdata                      = alloc_perm( sizeof(*ch->pcdata) );
    }
    else
    {
	ch->pcdata                      = pcdata_free;
	pcdata_free                     = pcdata_free->next;
    }
    *ch->pcdata                         = pcdata_zero;

    d->character                        = ch;
    ch->desc                            = d;
    ch->name                            = str_dup( name );
    ch->pcdata->switchname              = str_dup( name );
    ch->act                             = PLR_BLANK
					| PLR_COMBINE
					| PLR_PROMPT;
    ch->extra                           = 0;
    ch->pcdata->familiar                = NULL;
    ch->pcdata->partner                 = NULL;
    ch->pcdata->propose                 = NULL;
    ch->pcdata->chobj                   = NULL;
    ch->pcdata->memorised               = NULL;
    ch->pcdata->pwd                     = str_dup( "" );
    ch->pcdata->bamfin                  = str_dup( "" );
    ch->pcdata->bamfout                 = str_dup( "" );
    ch->pcdata->title                   = str_dup( "" );
    ch->pcdata->conception              = str_dup( "" );
    ch->pcdata->parents                 = str_dup( "" );
    ch->pcdata->cparents                = str_dup( "" );
    ch->pcdata->marriage                = str_dup( "" );
    ch->pcdata->email                   = str_dup( "" );
    ch->pcdata->disc_research           = -1;
    ch->lord                            = str_dup( "" );
    ch->morph                           = str_dup( "" );
    ch->pload                           = str_dup( "" );
    ch->prompt                          = str_dup( "" );
    ch->cprompt                         = str_dup( "" );
    strtime = ctime( &current_time );
    strtime[strlen(strtime)-1] = '\0';
    free_string(ch->lasttime);
    ch->createtime                      = str_dup( strtime );
    ch->lasttime                        = str_dup( "" );
    ch->lasthost                        = str_dup( "" );
    ch->poweraction                     = str_dup( "" );
    ch->powertype                       = str_dup( "" );
    ch->hunting                         = str_dup( "" );
    ch->spectype                        = 0;
    ch->specpower                       = 0;
    ch->mounted                         = 0;
    ch->home                            = 3001;
    ch->vampgen_a                       = 0;
    ch->paradox[0]                      = 0;    /* Total paradox */
    ch->paradox[1]                      = 0;    /* Current Paradox */
    ch->paradox[2]                      = 0;    /* Paradox Ticker */
    ch->damcap[0]                       = 1000;
    ch->damcap[1]                       = 0;
    ch->vampaff_a                       = 0;
    ch->itemaffect                      = 0;
    ch->vamppass_a                      = -1;
    ch->polyaff                         = 0;
    ch->immune                          = 0;
    ch->form                            = 32767;
    ch->beast                           = 15;
    ch->loc_hp[0]                       = 0;
    ch->loc_hp[1]                       = 0;
    ch->loc_hp[2]                       = 0;
    ch->loc_hp[3]                       = 0;
    ch->loc_hp[4]                       = 0;
    ch->loc_hp[5]                       = 0;
    ch->loc_hp[6]                       = 0;
    ch->wpn[0]                          = 0;
    ch->wpn[1]                          = 0;
    ch->wpn[2]                          = 0;
    ch->wpn[3]                          = 0;
    ch->wpn[4]                          = 0;
    ch->wpn[5]                          = 0;
    ch->wpn[6]                          = 0;
    ch->wpn[7]                          = 0;
    ch->wpn[8]                          = 0;
    ch->wpn[9]                          = 0;
    ch->wpn[10]                         = 0;
    ch->wpn[11]                         = 0;
    ch->wpn[12]                         = 0;
    ch->spl[0]                          = 4;
    ch->spl[1]                          = 4;
    ch->spl[2]                          = 4;
    ch->spl[3]                          = 4;
    ch->spl[4]                          = 4;
    ch->cmbt[0]                         = 0;
    ch->cmbt[1]                         = 0;
    ch->cmbt[2]                         = 0;
    ch->cmbt[3]                         = 0;
    ch->cmbt[4]                         = 0;
    ch->cmbt[5]                         = 0;
    ch->cmbt[6]                         = 0;
    ch->cmbt[7]                         = 0;
    ch->stance[0]                       = 0;
    ch->stance[1]                       = 0;
    ch->stance[2]                       = 0;
    ch->stance[3]                       = 0;
    ch->stance[4]                       = 0;
    ch->stance[5]                       = 0;
    ch->stance[6]                       = 0;
    ch->stance[7]                       = 0;
    ch->stance[8]                       = 0;
    ch->stance[9]                       = 0;
    ch->stance[10]                      = 0;
    ch->stance[11]                      = 0;
    ch->stance[12]                      = 0;
    ch->stance[13]			= 0;
    ch->stance[14]			= 0;
    ch->stance[15]			= 0;
    ch->pkill                           = 0;
    ch->pdeath                          = 0;
    ch->mkill                           = 0;
    ch->mdeath                          = 0;
    ch->class                           = -1;
    ch->pcdata->followers               = 0;
    ch->pcdata->perm_str                = 13;
    ch->pcdata->perm_int                = 13; 
    ch->pcdata->perm_wis                = 13;
    ch->pcdata->perm_dex                = 13;
    ch->pcdata->perm_con                = 13;
    ch->pcdata->quest                   = 0;
	ch->pcdata->kingdom		= 0;
    ch->pcdata->wolf                    = 0;
    ch->pcdata->rank                    = 0;
    ch->pcdata->language[0]             = 0;
    ch->pcdata->language[1]             = 0;
    ch->pcdata->stage[0]                = 0;
    ch->pcdata->stage[1]                = 0;
    ch->pcdata->stage[2]                = 0;
    ch->pcdata->wolfform[0]             = 1;
    ch->pcdata->wolfform[1]             = 1;
    ch->pcdata->score[0]                = 0;
    ch->pcdata->score[1]                = 0;
    ch->pcdata->score[2]                = 0;
    ch->pcdata->score[3]                = 0;
    ch->pcdata->score[4]                = 0;
    ch->pcdata->score[5]                = 0;
    ch->pcdata->runes[0]                = 0;
    ch->pcdata->runes[1]                = 0;
    ch->pcdata->runes[2]                = 0;
    ch->pcdata->runes[3]                = 0;
    ch->pcdata->disc_a[0]                       = 0;
    ch->pcdata->disc_a[1]                       = 0;
    ch->pcdata->disc_a[2]                       = 0;
    ch->pcdata->disc_a[3]                       = 0;
    ch->pcdata->disc_a[4]                       = 0;
    ch->pcdata->disc_a[5]                       = 0;
    ch->pcdata->disc_a[6]                       = 0;
    ch->pcdata->disc_a[7]                       = 0;
    ch->pcdata->disc_a[8]                       = 0;
    ch->pcdata->disc_a[9]                       = 0;
    ch->pcdata->disc_a[10]              = 0;
    ch->pcdata->genes[0]                = 0;
    ch->pcdata->genes[1]                = 0;
    ch->pcdata->genes[2]                = 0;
    ch->pcdata->genes[3]                = 0;
    ch->pcdata->genes[4]                = 0;
    ch->pcdata->genes[5]                = 0;
    ch->pcdata->genes[6]                = 0;
    ch->pcdata->genes[7]                = 0;
    ch->pcdata->genes[8]                = 0;
    ch->pcdata->genes[9]                = 0;
    ch->pcdata->powers[0]               = 0;
    ch->pcdata->powers[1]               = 0;
    ch->pcdata->fake_skill              = 0;
    ch->pcdata->fake_stance             = 0;
    ch->pcdata->fake_hit                = 0;
    ch->pcdata->fake_dam                = 0;
    ch->pcdata->fake_ac                 = 0;
    ch->pcdata->fake_hp                 = 0;
    ch->pcdata->fake_mana               = 0;
    ch->pcdata->fake_move               = 0;
    ch->pcdata->obj_vnum                = 0;
    ch->pcdata->condition[COND_THIRST]  = 48;
    ch->pcdata->condition[COND_FULL]    = 48;
    ch->pcdata->stat_ability[STAT_STR]  = 0;
    ch->pcdata->stat_ability[STAT_END]  = 0;
    ch->pcdata->stat_ability[STAT_REF]  = 0;
    ch->pcdata->stat_ability[STAT_FLE]  = 0;
    ch->pcdata->stat_amount[STAT_STR]   = 0;
    ch->pcdata->stat_amount[STAT_END]   = 0;
    ch->pcdata->stat_amount[STAT_REF]   = 0;
    ch->pcdata->stat_amount[STAT_FLE]   = 0;
    ch->pcdata->stat_duration[STAT_STR] = 0;
    ch->pcdata->stat_duration[STAT_END] = 0;
    ch->pcdata->stat_duration[STAT_REF] = 0;
    ch->pcdata->stat_duration[STAT_FLE] = 0;
    ch->pcdata->exhaustion              = 0;

    found = FALSE;
    fclose( fpReserve );
    sprintf( strsave, "%s%s", PLAYER_DIR, capitalize( name ) );
    if ( ( fp = fopen( strsave, "r" ) ) != NULL )
    {
	int iNest;

	for ( iNest = 0; iNest < MAX_NEST; iNest++ )
	    rgObjNest[iNest] = NULL;

	found = TRUE;
	for ( ; ; )
	{
	    char letter;
	    char *word;

	    letter = fread_letter( fp );
	    if ( letter == '*' )
	    {
		fread_to_eol( fp );
		continue;
	    }

	    if ( letter != '#' )
	    {
		bug( "Load_char_obj: # not found.", 0 );
		break;
	    }

	    word = fread_word( fp );
	    if      ( !str_cmp( word, "PLAYER" ) ) fread_char_old ( ch, fp );
	    if      ( !str_cmp( word, "PLAYERS" ) ) fread_char ( ch, fp );
	    else if ( !str_cmp( word, "OBJECT" ) ) break;
	    else if ( !str_cmp( word, "END"    ) ) break;
	    else
	    {
		bug( "Load_char_obj: bad section.", 0 );
		break;
	    }
	}
	fclose( fp );
    }

    fpReserve = fopen( NULL_FILE, "r" );
    return found;
}



/*
 * Read in a char.
 */

#if defined(KEY)
#undef KEY
#endif

#define KEY( literal, field, value )    if ( !str_cmp( word, literal ) ){field  = value;fMatch = TRUE;break;}

void fread_char_old( CHAR_DATA *ch, FILE *fp )
{
    char buf[MAX_STRING_LENGTH];
    char *word;
    bool fMatch;
    int  dummy;
    char *nothing;

    for ( ; ; )
    {
	word   = feof( fp ) ? "End" : fread_word( fp );
	fMatch = FALSE;

	switch ( UPPER(word[0]) )
	{
	case '*':
	    fMatch = TRUE;
	    fread_to_eol( fp );
	    break;

	case 'A':
	    KEY( "Act",         ch->act,                fread_number( fp ) );
	    KEY( "AffectedBy",  ch->affected_by,        fread_number( fp ) );
	    KEY( "Alignment",   ch->alignment,          fread_number( fp ) );
	    KEY( "Armor",       ch->armor,              fread_number( fp ) );
	    KEY( "Awin",        ch->pcdata->awins,      fread_number( fp ) );
	    KEY( "Alos",        ch->pcdata->alosses,    fread_number( fp ) );
	    if ( !str_cmp( word, "Affect" ) || !str_cmp( word, "AffectData" ) )
	    {
		AFFECT_DATA *paf;

		if ( affect_free == NULL )
		{
		    paf         = alloc_perm( sizeof(*paf) );
		}
		else
		{
		    paf         = affect_free;
		    affect_free = affect_free->next;
		}

		if ( !str_cmp( word, "Affect" ) )
		{
		    /* Obsolete 2.0 form. */
		    paf->type   = fread_number( fp );
		}
		else
		{
		    int sn;

		    sn = skill_lookup( fread_word( fp ) );
		    if ( sn < 0 )
			bug( "Fread_char: unknown skill.", 0 );
		    else
			paf->type = sn;
		}

		paf->duration   = fread_number( fp );
		paf->modifier   = fread_number( fp );
		paf->location   = fread_number( fp );
		paf->bitvector  = fread_number( fp );
		paf->next       = ch->affected;
		ch->affected    = paf;
		fMatch = TRUE;
		break;
	    }

	    if ( !str_cmp( word, "AttrMod"  ) )
	    {
		ch->pcdata->mod_str  = fread_number( fp );
		ch->pcdata->mod_int  = fread_number( fp );
		ch->pcdata->mod_wis  = fread_number( fp );
		ch->pcdata->mod_dex  = fread_number( fp );
		ch->pcdata->mod_con  = fread_number( fp );
		fMatch = TRUE;
		break;
	    }

	    if ( !str_cmp( word, "AttrPerm" ) )
	    {
		ch->pcdata->perm_str = fread_number( fp );
		ch->pcdata->perm_int = fread_number( fp );
		ch->pcdata->perm_wis = fread_number( fp );
		ch->pcdata->perm_dex = fread_number( fp );
		ch->pcdata->perm_con = fread_number( fp );
		fMatch = TRUE;
		break;
	    }
	    break;

	case 'B':
	    KEY( "Bamfin",      ch->pcdata->bamfin,     fread_string( fp ) );
	    KEY( "Bamfout",     ch->pcdata->bamfout,    fread_string( fp ) );
	    KEY( "Beast",       ch->beast,              fread_number( fp ) );

		/* Read in board status */          
	    if (!str_cmp(word, "Boards" ))
	    {
			int i,num = fread_number (fp); /* number of boards saved */
			char *boardname;
			
			for (; num ; num-- ) /* for each of the board saved */
			{
				boardname = fread_word (fp);
				i = board_lookup (boardname); /* find board number */
				
				if (i == BOARD_NOTFOUND) /* Does board still exist ? */
				{
					sprintf (buf, "fread_char: %s had unknown board name: %s. Skipped.", ch->name, boardname);                                      
					log_string (buf);
					fread_number (fp); /* read last_note and skip info */
				}
				else /* Save it */
					ch->pcdata->last_note[i] = fread_number(fp);
			}        /* for */
			
			fMatch = TRUE;
	    } /* Boards */
/*       	    KEY( "Bounty",  ch->pcdata->bounty,
fread_number( fp ));    */
	    break;

	case 'C':
	    KEY( "Clan", 	nothing,		fread_string(fp));
	    KEY( "Class",       dummy,                  fread_number( fp ) );
	KEY( "CurrentForm", ch->cur_form, fread_number( fp ) );

	    if ( !str_cmp( word, "Chi" ) )
	    {
		ch->chi[0] = fread_number( fp );
		ch->chi[1] = fread_number( fp );
		fMatch = TRUE;
		break;
	    }

	    if ( !str_cmp( word, "Combat" ) )
	    {
		ch->cmbt[0]     = fread_number( fp );
		ch->cmbt[1]     = fread_number( fp );
		ch->cmbt[2]     = fread_number( fp );
		ch->cmbt[3]     = fread_number( fp );
		ch->cmbt[4]     = fread_number( fp );
		ch->cmbt[5]     = fread_number( fp );
		ch->cmbt[6]     = fread_number( fp );
		ch->cmbt[7]     = fread_number( fp );
		fMatch = TRUE;
		break;
	    }

	    KEY( "Conception",  ch->pcdata->conception, fread_string( fp ) );

	    if ( !str_cmp( word, "Condition" ) )
	    {
		ch->pcdata->condition[0] = fread_number( fp );
		ch->pcdata->condition[1] = fread_number( fp );
		ch->pcdata->condition[2] = fread_number( fp );
		fMatch = TRUE;
		break;
	    }

	    if ( !str_cmp( word, "CPower" ) )
	    {
		ch->power[0] = fread_number(fp);
                ch->power[1] = fread_number(fp);
                ch->power[2] = fread_number(fp);
                ch->power[3] = fread_number(fp);
                ch->power[4] = fread_number(fp);
                ch->power[5] = fread_number(fp);
                ch->power[6] = fread_number(fp);
                ch->power[7] = fread_number(fp);
                ch->power[8] = fread_number(fp);
                ch->power[9] = fread_number(fp);
                ch->power[10] = fread_number(fp);
                ch->power[11] = fread_number(fp);
                ch->power[12] = fread_number(fp);
                ch->power[13] = fread_number(fp);
                ch->power[14] = fread_number(fp);
                ch->power[15] = fread_number(fp);
                ch->power[16] = fread_number(fp);
                ch->power[17] = fread_number(fp);
                ch->power[18] = fread_number(fp);
                ch->power[19] = fread_number(fp);
                ch->power[20] = fread_number(fp);
                ch->power[21] = fread_number(fp);
                ch->power[22] = fread_number(fp);
                ch->power[23] = fread_number(fp);
                ch->power[24] = fread_number(fp);
                ch->power[25] = fread_number(fp);
                ch->power[26] = fread_number(fp);
                ch->power[27] = fread_number(fp);
                ch->power[28] = fread_number(fp);
                ch->power[29] = fread_number(fp);
                ch->power[30] = fread_number(fp);
                ch->power[31] = fread_number(fp);
                ch->power[32] = fread_number(fp);
                ch->power[33] = fread_number(fp);
                ch->power[34] = fread_number(fp);
                ch->power[35] = fread_number(fp);
                ch->power[36] = fread_number(fp);
                ch->power[37] = fread_number(fp);
                ch->power[38] = fread_number(fp);
                ch->power[39] = fread_number(fp);
                ch->power[40] = fread_number(fp);
                ch->power[41] = fread_number(fp);
                ch->power[42] = fread_number(fp);
                ch->power[43] = fread_number(fp);
		fMatch = TRUE;
                break;

	    }

	    KEY( "Cparents",    ch->pcdata->cparents,   fread_string( fp ) );
	    KEY( "Cprompt",     ch->cprompt,            fread_string( fp ) );
	    KEY( "Createtime",  ch->createtime,         fread_string( fp ) );
	    break;

	case 'D':
	    KEY( "Damroll",     ch->damroll,            fread_number( fp ) );
	    KEY( "Deaf",        ch->deaf,               fread_number( fp ) );
	    KEY( "Demonic",     ch->pcdata->demonic_a,  fread_number( fp ) );
	    KEY( "Description", ch->description,        fread_string( fp ) );
	    KEY( "DiscRese",    ch->pcdata->disc_research, fread_number( fp ) );
	    KEY( "DiscPoin",    ch->pcdata->disc_points, fread_number( fp ) );


	    if ( !str_cmp( word, "Disc" ) )
	    {
		ch->pcdata->disc_a[0] = fread_number( fp );
		ch->pcdata->disc_a[1] = fread_number( fp );
		ch->pcdata->disc_a[2] = fread_number( fp );
		ch->pcdata->disc_a[3] = fread_number( fp );
		ch->pcdata->disc_a[4] = fread_number( fp );
		ch->pcdata->disc_a[5] = fread_number( fp );
		ch->pcdata->disc_a[6] = fread_number( fp );
		ch->pcdata->disc_a[7] = fread_number( fp );
		ch->pcdata->disc_a[8] = fread_number( fp );
		ch->pcdata->disc_a[9] = fread_number( fp );
		ch->pcdata->disc_a[10] = fread_number( fp );
		fMatch = TRUE;
		break;
	    }
	    KEY( "Drowaff",     dummy,  fread_number( fp ) ); /* Drow */
	    KEY( "Drowpwr",     dummy,  fread_number( fp ) ); /* Drow */
	    KEY( "Drowmag",     dummy,  fread_number( fp ) ); /* Drow */
	    break;

	case 'E':
	    KEY( "Email",       ch->pcdata->email,      fread_string( fp ) );
	    if ( !str_cmp( word, "End" ) )
		return;
	    KEY( "Exhaustion",  ch->pcdata->exhaustion, fread_number( fp ) );
	    KEY( "Exp",         ch->exp,                fread_number( fp ) );
	    KEY( "Explevel",    ch->explevel,           fread_number( fp ) );
	    KEY( "Expgained",   ch->expgained,          fread_number( fp ) );
	    KEY( "Extra",       ch->extra,              fread_number( fp ) );
	    break;

	case 'F':
	KEY( "Flag2", ch->flag2, fread_number( fp ) );
	KEY( "Flag3", ch->flag3, fread_number( fp ) );
	KEY( "Flag4", ch->flag4, fread_number( fp ) );

	    if ( !str_cmp( word, "Focus" ) )
	    {
		ch->focus[0] = fread_number( fp );
		ch->focus[1] = fread_number( fp );
	        fMatch = TRUE;
		break;
	    }

	    if ( !str_cmp( word, "FakeCon" ) )
	    {
		ch->pcdata->fake_skill  = fread_number( fp );
		ch->pcdata->fake_stance = fread_number( fp );
		ch->pcdata->fake_hit    = fread_number( fp );
		ch->pcdata->fake_dam    = fread_number( fp );
		ch->pcdata->fake_ac     = fread_number( fp );
		ch->pcdata->fake_hp     = fread_number( fp );
		ch->pcdata->fake_mana   = fread_number( fp );
		ch->pcdata->fake_move   = fread_number( fp );
		fMatch = TRUE;
		break;
	    }
	    KEY( "Form",        ch->form,               fread_number( fp ) );
	    break;

	case 'G':
	KEY( "Generation",  ch->generation,     fread_number( fp ) );
	    if ( !str_cmp( word, "Genes" ) )
	    {
		ch->pcdata->genes[0] = fread_number( fp );
		ch->pcdata->genes[1] = fread_number( fp );
		ch->pcdata->genes[2] = fread_number( fp );
		ch->pcdata->genes[3] = fread_number( fp );
		ch->pcdata->genes[4] = fread_number( fp );
		ch->pcdata->genes[5] = fread_number( fp );
		ch->pcdata->genes[6] = fread_number( fp );
		ch->pcdata->genes[7] = fread_number( fp );
		ch->pcdata->genes[8] = fread_number( fp );
		ch->pcdata->genes[9] = fread_number( fp );
		fMatch = TRUE;
		break;
	    }

	if ( !str_cmp( word, "Gifts" ) )
        {
	    ch->gifts[0]  = fread_number( fp );
	    ch->gifts[1]  = fread_number( fp );
	    ch->gifts[2]  = fread_number( fp );
	    ch->gifts[3]  = fread_number( fp );
	    ch->gifts[4]  = fread_number( fp );
	    ch->gifts[5]  = fread_number( fp );
	    ch->gifts[6]  = fread_number( fp );
	    ch->gifts[7]  = fread_number( fp );
	    ch->gifts[8]  = fread_number( fp );
	    ch->gifts[9]  = fread_number( fp );
	    ch->gifts[10] = fread_number( fp );
	    ch->gifts[11] = fread_number( fp );
	    ch->gifts[12] = fread_number( fp );
	    ch->gifts[13] = fread_number( fp );
	    ch->gifts[14] = fread_number( fp );
	    ch->gifts[15] = fread_number( fp );
	    ch->gifts[16] = fread_number( fp );
	    ch->gifts[17] = fread_number( fp );
	    ch->gifts[18] = fread_number( fp );
	    ch->gifts[19] = fread_number( fp );
	    ch->gifts[20] = fread_number( fp );
	    fMatch = TRUE;
	    break;
	}	


	KEY( "Garou1",	ch->garou1,	fread_number( fp ) );
	KEY( "Garou2",  ch->garou2,	fread_number( fp ) );

	    KEY( "Gold",        ch->gold,               fread_number( fp ) );
	    break;

	case 'H':
	    KEY( "Hitroll",     ch->hitroll,            fread_number( fp ) );
	    KEY( "Home",        ch->home,               fread_number( fp ) );

	    if ( !str_cmp( word, "HpManaMove" ) )
	    {
		ch->hit         = fread_number( fp );
		ch->max_hit     = fread_number( fp );
		ch->mana        = fread_number( fp );
		ch->max_mana    = fread_number( fp );
		ch->move        = fread_number( fp );
		ch->max_move    = fread_number( fp );
		fMatch = TRUE;
		break;
	    }
	    break;

	case 'I':
	    KEY( "Immune",        ch->immune,           fread_number( fp ) );
	    KEY( "Itemaffect",    ch->itemaffect,       fread_number( fp ) );
	    break;

	case 'K':
	KEY("Kingdom",	ch->pcdata->kingdom,		fread_number(fp));
		break;

	case 'L':
	    if ( !str_cmp( word, "Language" ) )
	    {
		ch->pcdata->language[0] = fread_number( fp );
		ch->pcdata->language[1] = fread_number( fp );
		fMatch = TRUE;
		break;
	    }

	    KEY( "Lasthost",    ch->lasthost,           fread_string( fp ) );
	    KEY( "Lasttime",    ch->lasttime,           fread_string( fp ) );
	    KEY( "Level",       ch->level,              fread_number( fp ) );
	    if ( !str_cmp( word, "Locationhp" ) )
	    {
		ch->loc_hp[0]   = fread_number( fp );
		ch->loc_hp[1]   = fread_number( fp );
		ch->loc_hp[2]   = fread_number( fp );
		ch->loc_hp[3]   = fread_number( fp );
		ch->loc_hp[4]   = fread_number( fp );
		ch->loc_hp[5]   = fread_number( fp );
		ch->loc_hp[6]   = fread_number( fp );
		fMatch = TRUE;
		break;
	    }
	    KEY( "Levelexp",    ch->levelexp,           fread_number( fp ) );
	    KEY( "LongDescr",   ch->long_descr,         fread_string( fp ) );
	    KEY( "Lord",        ch->lord,               fread_string( fp ) );
	    break;

	case 'M':
	if ( !str_cmp( word, "Monkab" ) )
	{
	    ch->monkab[0] = fread_number( fp );
	    ch->monkab[1] = fread_number( fp );
	    ch->monkab[2] = fread_number( fp );
	    ch->monkab[3] = fread_number( fp );
	    fMatch = TRUE;
	    break;
	}
          
	KEY( "Monkstuff",	ch->monkstuff, fread_number( fp ) );
	KEY( "Monkcrap",	ch->monkcrap, fread_number( fp ) );
	    KEY( "Marriage",    ch->pcdata->marriage,   fread_string( fp ) );
	    KEY( "Morph",       ch->morph,              fread_string( fp ) );
	    break;

	case 'N':
		    KEY( "Newbits",     ch->newbits,    fread_number( fp )
);
  
	    if ( !str_cmp( word, "Name" ) )
	    {
		/*
		 * Name already set externally.
		 */
		fread_to_eol( fp );
		fMatch = TRUE;
		break;
	    }

	    break;

	case 'O':
	    KEY( "Objvnum",     ch->pcdata->obj_vnum,   fread_number( fp ) );
	    KEY( "ObjDesc",	ch->objdesc,		fread_string( fp ) );
	    break;

	case 'P':
	    if ( !str_cmp( word, "Paradox" ) )
	    {
		ch->paradox[0]  = fread_number( fp );
		ch->paradox[1]  = fread_number( fp );
		ch->paradox[2]  = fread_number( fp );
		fMatch = TRUE;
		break;
	    }

	    KEY( "Parents",     ch->pcdata->parents,    fread_string( fp ) );
	    KEY( "Password",    ch->pcdata->pwd,        fread_string( fp ) );
	    KEY( "Played",      ch->played,             fread_number( fp ) );
	    KEY( "Polyaff",     ch->polyaff,            fread_number( fp ) );
	    KEY( "Power_Point", dummy,                  fread_number( fp ) ); /* drow */

	    if ( !str_cmp( word, "Power" ) )
	    {
		ch->pcdata->powers[0] = fread_number( fp );
		ch->pcdata->powers[1] = fread_number( fp );
		fMatch = TRUE;
		break;
	    }

	    KEY( "Poweraction", ch->poweraction,        fread_string( fp ) );
	    KEY( "Powertype",   ch->powertype,          fread_string( fp ) );
	    KEY( "Position",    ch->position,           fread_number( fp ) );
	    KEY( "Practice",    ch->practice,           fread_number( fp ) );
	    if ( !str_cmp( word, "PkPdMkMd" ) )
	    {
		ch->pkill       = fread_number( fp );
		ch->pdeath      = fread_number( fp );
		ch->mkill       = fread_number( fp );
		ch->mdeath      = fread_number( fp );
		fMatch = TRUE;
		break;
	    }
	    KEY( "Prompt",      ch->prompt,             fread_string( fp ) );
	    break;

	case 'Q':
	    KEY( "Quest",        ch->pcdata->quest,     fread_number( fp ) );
	    break;

	case 'R':
	    KEY( "Race",        ch->race,               fread_number( fp ) );
	KEY( "Rage",  ch->rage, fread_number( fp ) );
	    KEY( "Rank",        ch->pcdata->rank,       fread_number( fp ) );

	    if ( !str_cmp( word, "Room" ) )
	    {
		ch->in_room = get_room_index( fread_number( fp ) );
		if ( ch->in_room == NULL )
		    ch->in_room = get_room_index( ROOM_VNUM_LIMBO );
		fMatch = TRUE;
		break;
	    }

	    if ( !str_cmp( word, "Runes" ) )
	    {
		ch->pcdata->runes[0] = fread_number( fp );
		ch->pcdata->runes[1] = fread_number( fp );
		ch->pcdata->runes[2] = fread_number( fp );
		ch->pcdata->runes[3] = fread_number( fp );
		fMatch = TRUE;
		break;
	    }

	    break;

	case 'S':
	    KEY( "SavingThrow", ch->saving_throw,       fread_number( fp ) );
	    KEY( "Switchname",  ch->pcdata->switchname, fread_string( fp ) );
	KEY( "SilTol", ch->siltol, fread_number( fp ) );
	KEY( "Souls",  ch->pcdata->souls, fread_number( fp ) );
	    if ( !str_cmp( word, "Score" ) )
	    {
		ch->pcdata->score[0] = fread_number( fp );
		ch->pcdata->score[1] = fread_number( fp );
		ch->pcdata->score[2] = fread_number( fp );
		ch->pcdata->score[3] = fread_number( fp );
		ch->pcdata->score[4] = fread_number( fp );
		ch->pcdata->score[5] = fread_number( fp );
		fMatch = TRUE;
		break;
	    }

	    KEY( "Sex",         ch->sex,                fread_number( fp ) );
	    KEY( "ShortDescr",  ch->short_descr,        fread_string( fp ) );
	    KEY( "Security",    ch->pcdata->security,   fread_number( fp ) );
	    if ( !str_cmp( word, "Skill" ) )
	    {
		int sn;
		int value;

		value = fread_number( fp );
		sn    = skill_lookup( fread_word( fp ) );
/*
		if ( sn < 0 )
		    bug( "Fread_char: unknown skill.", 0 );
		else
		    ch->pcdata->learned[sn] = value;
*/
		if ( sn >= 0 )
		    ch->pcdata->learned[sn] = value;
		fMatch = TRUE;
	    }

	    KEY( "Specpower",   ch->specpower,  fread_number( fp ) );
	    KEY( "Spectype",    ch->spectype,   fread_number( fp ) );

	    if ( !str_cmp( word, "Spells" ) )
	    {
		ch->spl[0]      = fread_number( fp );
		ch->spl[1]      = fread_number( fp );
		ch->spl[2]      = fread_number( fp );
		ch->spl[3]      = fread_number( fp );
		ch->spl[4]      = fread_number( fp );
		fMatch = TRUE;
		break;
	    }

	    if ( !str_cmp( word, "Stage" ) )
	    {
		ch->pcdata->stage[0] = fread_number( fp );
		ch->pcdata->stage[1] = fread_number( fp );
		ch->pcdata->stage[2] = fread_number( fp );
		fMatch = TRUE;
		break;
	    }

	    if ( !str_cmp( word, "Stance" ) )
	    {
		ch->stance[0]   = fread_number( fp );
		ch->stance[1]   = fread_number( fp );
		ch->stance[2]   = fread_number( fp );
		ch->stance[3]   = fread_number( fp );
		ch->stance[4]   = fread_number( fp );
		ch->stance[5]   = fread_number( fp );
		ch->stance[6]   = fread_number( fp );
		ch->stance[7]   = fread_number( fp );
		ch->stance[8]   = fread_number( fp );
		ch->stance[9]   = fread_number( fp );
		ch->stance[10]  = fread_number( fp );
		ch->stance[11]  = fread_number( fp );
		fMatch = TRUE;
		break;

	    }

            if( !str_cmp( word, "Stance2" ) )
            {
               int x = 0;
               ch->stance[12] = fread_number(fp);
               ch->stance[13] = fread_number(fp);
               ch->stance[14] = fread_number(fp);
               ch->stance[15] = fread_number(fp);
               x = fread_number(fp);
               x = fread_number(fp);
               x = fread_number(fp);
               x = fread_number(fp);
               x = fread_number(fp);
               x = fread_number(fp);
               x = fread_number(fp);
               x = fread_number(fp);
               fMatch = TRUE;
               break;
            }

	    if ( !str_cmp( word, "StatAbility" ) )
	    {
		ch->pcdata->stat_ability[0] = fread_number( fp );
		ch->pcdata->stat_ability[1] = fread_number( fp );
		ch->pcdata->stat_ability[2] = fread_number( fp );
		ch->pcdata->stat_ability[3] = fread_number( fp );
		fMatch = TRUE;
		break;
	    }

	    if ( !str_cmp( word, "StatAmount" ) )
	    {
		ch->pcdata->stat_amount[0] = fread_number( fp );
		ch->pcdata->stat_amount[1] = fread_number( fp );
		ch->pcdata->stat_amount[2] = fread_number( fp );
		ch->pcdata->stat_amount[3] = fread_number( fp );
		fMatch = TRUE;
		break;
	    }

	    if ( !str_cmp( word, "StatDuration" ) )
	    {
		ch->pcdata->stat_duration[0] = fread_number( fp );
		ch->pcdata->stat_duration[1] = fread_number( fp );
		ch->pcdata->stat_duration[2] = fread_number( fp );
		ch->pcdata->stat_duration[3] = fread_number( fp );
		fMatch = TRUE;
		break;
	    }

	    break;

	case 'T':
	    KEY( "Trust",       ch->trust,              fread_number( fp ) );

	    if ( !str_cmp( word, "Title" ) )
	    {
		ch->pcdata->title = fread_string( fp );
		if ( isalpha(ch->pcdata->title[0])
		||   isdigit(ch->pcdata->title[0]) )
		{
		    sprintf( buf, " %s", ch->pcdata->title );
		    free_string( ch->pcdata->title );
		    ch->pcdata->title = str_dup( buf );
		}
		fMatch = TRUE;
		break;
	    }

	    break;

	case 'V':
	    KEY( "Vampaff",        ch->vampaff_a,       fread_number( fp ) );
	    KEY( "Vampgen",        ch->vampgen_a,       fread_number( fp ) );
	    KEY( "Vamppass",       ch->vamppass_a,      fread_number( fp ) );
	    if ( !str_cmp( word, "Vnum" ) )
	    {
		ch->pIndexData = get_mob_index( fread_number( fp ) );
		fMatch = TRUE;
		break;
	    }
	    break;

	case 'W':
	    KEY( "Warps",       ch->warp,       fread_number( fp ) );
	    KEY( "WarpCount",   ch->warpcount,  fread_number( fp ) );
	    if ( !str_cmp( word, "Weapons" ) )
	    {
		ch->wpn[0]      = fread_number( fp );
		ch->wpn[1]      = fread_number( fp );
		ch->wpn[2]      = fread_number( fp );
		ch->wpn[3]      = fread_number( fp );
		ch->wpn[4]      = fread_number( fp );
		ch->wpn[5]      = fread_number( fp );
		ch->wpn[6]      = fread_number( fp );
		ch->wpn[7]      = fread_number( fp );
		ch->wpn[8]      = fread_number( fp );
		ch->wpn[9]      = fread_number( fp );
		ch->wpn[10]     = fread_number( fp );
		ch->wpn[11]     = fread_number( fp );
		ch->wpn[12]     = fread_number( fp );
		fMatch = TRUE;
		break;
	    }
	    KEY( "Wimpy",       ch->wimpy,              fread_number( fp ) );
	    KEY( "Wolf",        ch->pcdata->wolf,       fread_number( fp ) );
	    if ( !str_cmp( word, "Wolfform" ) )
	    {
		ch->pcdata->wolfform[0] = fread_number( fp );
		ch->pcdata->wolfform[1] = fread_number( fp );
		fMatch = TRUE;
		break;
	    }
            KEY( "ww_completed",   ch->pcdata->ww_completed[AMOUNT_COMPLETED],   fread_number( fp ) );
	    KEY( "ww_researching", ch->pcdata->ww_researching[TOTEM_RESEARCHING], fread_number( fp ) );
            KEY( "WWComplete",   ch->pcdata->ww_completed[AMOUNT_COMPLETED],   fread_number( fp ) );
            KEY( "WWResearching", ch->pcdata->ww_researching[TOTEM_RESEARCHING], fread_number( fp ) );
	    KEY( "Wwin",	ch->pcdata->wwins,	fread_number( fp ) );
	    KEY( "Wlos",	ch->pcdata->wlosses,	fread_number( fp ) );
	    break;
	case 'X':
	KEY( "XHitroll", ch->xhitroll, fread_number( fp ) );
	KEY( "XDamroll", ch->xdamroll, fread_number( fp ) );
	break;
	}

	if ( !fMatch )
	{
	    sprintf(buf, "Fread_char: no match. WORD: %s", word); 
	    bug( buf, 0 );
	    fread_to_eol( fp );
	}
    }
}



void fread_obj( CHAR_DATA *ch, FILE *fp )
{
    static OBJ_DATA obj_zero;
    OBJ_DATA *obj;
    char *word;
    int iNest;
    bool fMatch;
    bool fNest;
    bool fVnum;

    if ( obj_free == NULL )
    {
	obj             = alloc_perm( sizeof(*obj) );
    }
    else
    {
	obj             = obj_free;
	obj_free        = obj_free->next;
    }

    *obj                = obj_zero;
    obj->name           = str_dup( "" );
    obj->short_descr    = str_dup( "" );
    obj->description    = str_dup( "" );
    obj->chpoweron      = str_dup( "(null)" );
    obj->chpoweroff     = str_dup( "(null)" );
    obj->chpoweruse     = str_dup( "(null)" );
    obj->victpoweron    = str_dup( "(null)" );
    obj->victpoweroff   = str_dup( "(null)" );
    obj->victpoweruse   = str_dup( "(null)" );
    obj->questmaker     = str_dup( "" );
    obj->questowner     = str_dup( "" );
    obj->spectype       = 0;
    obj->specpower      = 0;
    obj->condition      = 100;
    obj->toughness      = 0;
    obj->resistance     = 100;
    obj->quest          = 0;
    obj->points         = 0;

    fNest               = FALSE;
    fVnum               = TRUE;
    iNest               = 0;

    for ( ; ; )
    {
	word   = feof( fp ) ? "End" : fread_word( fp );
	fMatch = FALSE;

	switch ( UPPER(word[0]) )
	{
	case '*':
	    fMatch = TRUE;
	    fread_to_eol( fp );
	    break;

	case 'A':
	    if ( !str_cmp( word, "Affect" ) || !str_cmp( word, "AffectData" ) )
	    {
		AFFECT_DATA *paf;

		if ( affect_free == NULL )
		{
		    paf         = alloc_perm( sizeof(*paf) );
		}
		else
		{
		    paf         = affect_free;
		    affect_free = affect_free->next;
		}

		paf->type       = 0;
		paf->duration   = fread_number( fp );
		paf->modifier   = fread_number( fp );
		paf->location   = fread_number( fp );
		paf->bitvector  = 0;
		paf->next       = obj->affected;
		obj->affected   = paf;
		fMatch          = TRUE;
		break;
	    }
	    break;

	case 'C':
	    KEY( "Condition",   obj->condition,         fread_number( fp ) );
	    KEY( "Cost",        obj->cost,              fread_number( fp ) );
	    break;

	case 'D':
	    KEY( "Description", obj->description,       fread_string( fp ) );
	    break;

	case 'E':
	    KEY( "ExtraFlags",  obj->extra_flags,       fread_number( fp ) );
	    KEY( "ExtraFlags2", obj->extra_flags2,      fread_number( fp ) );

	    if ( !str_cmp( word, "ExtraDescr" ) )
	    {
		EXTRA_DESCR_DATA *ed;

		if ( extra_descr_free == NULL )
		{
		    ed                  = alloc_perm( sizeof(*ed) );
		}
		else
		{
		    ed                  = extra_descr_free;
		    extra_descr_free    = extra_descr_free->next;
		}

		ed->keyword             = fread_string( fp );
		ed->description         = fread_string( fp );
		ed->next                = obj->extra_descr;
		obj->extra_descr        = ed;
		fMatch = TRUE;
	    }

	    if ( !str_cmp( word, "End" ) )
	    {
		if ( !fNest || !fVnum )
		{
		    bug( "Fread_obj: incomplete object.", 0 );
		    free_string( obj->name        );
		    free_string( obj->description );
		    free_string( obj->short_descr );
		    obj->next = obj_free;
		    obj_free  = obj;
		    return;
		}
		else
		{
		    obj->next   = object_list;
		    object_list = obj;
		    obj->pIndexData->count++;
		    if ( iNest == 0 || rgObjNest[iNest] == NULL )
			obj_to_char( obj, ch );
		    else
			obj_to_obj( obj, rgObjNest[iNest-1] );
		    return;
		}
	    }
	    break;

	case 'I':
	    KEY( "ItemType",    obj->item_type,         fread_number( fp ) );
	    break;

	case 'L':
	    KEY( "Level",       obj->level,             fread_number( fp ) );
	    break;

	case 'N':

	    KEY( "Name",        obj->name,              fread_string( fp ) );

	    if ( !str_cmp( word, "Nest" ) )
	    {
		iNest = fread_number( fp );
		if ( iNest < 0 || iNest >= MAX_NEST )
		{
		    bug( "Fread_obj: bad nest %d.", iNest );
		}
		else
		{
		    rgObjNest[iNest] = obj;
		    fNest = TRUE;
		}
		fMatch = TRUE;
	    }
	    break;

	case 'P':
	    KEY( "Points",      obj->points,            fread_number( fp ) );
	    KEY( "Poweronch",   obj->chpoweron,         fread_string( fp ) );
	    KEY( "Poweroffch",  obj->chpoweroff,        fread_string( fp ) );
	    KEY( "Powerusech",  obj->chpoweruse,        fread_string( fp ) );
	    KEY( "Poweronvict", obj->victpoweron,       fread_string( fp ) );
	    KEY( "Poweroffvict",obj->victpoweroff,      fread_string( fp ) );
	    KEY( "Powerusevict",obj->victpoweruse,      fread_string( fp ) );
	    break;

	case 'Q':
	    KEY( "Quest",       obj->quest,             fread_number( fp ) );
	    KEY( "Questmaker",  obj->questmaker,        fread_string( fp ) );
	    KEY( "Questowner",  obj->questowner,        fread_string( fp ) );
	    break;

	case 'R':
	    KEY( "Resistance",  obj->resistance,        fread_number( fp ) );
	    break;

	case 'S':
	    KEY( "ShortDescr",  obj->short_descr,       fread_string( fp ) );
	    KEY( "Spectype",    obj->spectype,          fread_number( fp ) );
	    KEY( "Specpower",   obj->specpower,         fread_number( fp ) );

	    if ( !str_cmp( word, "Spell" ) )
	    {
		int iValue;
		int sn;

		iValue = fread_number( fp );
		sn     = skill_lookup( fread_word( fp ) );
		if ( iValue < 0 || iValue > 3 )
		{
		    bug( "Fread_obj: bad iValue %d.", iValue );
		}
		else if ( sn < 0 )
		{
		    bug( "Fread_obj: unknown skill.", 0 );
		}
		else
		{
		    obj->value[iValue] = sn;
		}
		fMatch = TRUE;
		break;
	    }
	    break;

	case 'T':
	    KEY( "Timer",       obj->timer,             fread_number( fp ) );
	    KEY( "Toughness",   obj->toughness,         fread_number( fp ) );
	    break;

	case 'V':
	    if ( !str_cmp( word, "Values" ) )
	    {
		obj->value[0]   = fread_number( fp );
		obj->value[1]   = fread_number( fp );
		obj->value[2]   = fread_number( fp );
		obj->value[3]   = fread_number( fp );
		fMatch          = TRUE;
		break;
	    }

	    if ( !str_cmp( word, "Vnum" ) )     /* OLC */
	    {
		int vnum;

		vnum = fread_number( fp );
		if ( !( obj->pIndexData = get_obj_index( vnum ) ) )
			obj->pIndexData = get_obj_index( OBJ_VNUM_DUMMY );
    
		fVnum = TRUE;
		fMatch = TRUE;
		break;
	    }
	    break;

	case 'W':
	    KEY( "WeapFlags",   obj->weapflags,         fread_number( fp ) );
	    KEY( "WearFlags",   obj->wear_flags,        fread_number( fp ) );
	    KEY( "WearLoc",     obj->wear_loc,          fread_number( fp ) );
	    KEY( "Weight",      obj->weight,            fread_number( fp ) );
	    break;
	}
	if ( !fMatch )
	{
	    bug( "Fread_obj: no match.", 0 );
	    fread_to_eol( fp );
	}
    }

}



void fread_char( CHAR_DATA *ch, FILE *fp )
{
    char buf[MAX_STRING_LENGTH];
    char *word;
    bool fMatch;
    int  dummy;
    int sn;
	char *nothing;

    for ( ; ; )
    {
	word   = feof( fp ) ? "End" : fread_word( fp );
	fMatch = FALSE;

	switch ( UPPER(word[0]) )
	{
	case '*':
	    fMatch = TRUE;
	    fread_to_eol( fp );
	    break;

	case 'A':
	    KEY( "Act",         ch->act,                fread_number( fp ) );
	    KEY( "AffectedBy",  ch->affected_by,        fread_number( fp ) );
	    KEY( "Alignment",   ch->alignment,          fread_number( fp ) );
	    KEY( "Armor",       ch->armor,              fread_number( fp ) );
	    KEY( "Awin",        ch->pcdata->awins,      fread_number( fp ) );
	    KEY( "Alos",        ch->pcdata->alosses,    fread_number( fp ) );
	    if ( !str_cmp( word, "Affect" ) || !str_cmp( word, "AffectData" ) )
	    {
		AFFECT_DATA *paf;

		if ( affect_free == NULL )
		{
		    paf         = alloc_perm( sizeof(*paf) );
		}
		else
		{
		    paf         = affect_free;
		    affect_free = affect_free->next;
		}

		if ( !str_cmp( word, "Affect" ) )
		{
		    /* Obsolete 2.0 form. */
		    paf->type   = fread_number( fp );
		}
		else
		{
		    int sn;

		    sn = skill_lookup( fread_word( fp ) );
		    if ( sn < 0 )
			bug( "Fread_char: unknown skill.", 0 );
		    else
			paf->type = sn;
		}

		paf->duration   = fread_number( fp );
		paf->modifier   = fread_number( fp );
		paf->location   = fread_number( fp );
		paf->bitvector  = fread_number( fp );
		paf->next       = ch->affected;
		ch->affected    = paf;
		fMatch = TRUE;
		break;
	    }

	    if ( !str_cmp( word, "AttrMod"  ) )
	    {
		ch->pcdata->mod_str  = fread_number( fp );
		ch->pcdata->mod_int  = fread_number( fp );
		ch->pcdata->mod_wis  = fread_number( fp );
		ch->pcdata->mod_dex  = fread_number( fp );
		ch->pcdata->mod_con  = fread_number( fp );
		fMatch = TRUE;
		break;
	    }

	    if ( !str_cmp( word, "AttrPerm" ) )
	    {
		ch->pcdata->perm_str = fread_number( fp );
		ch->pcdata->perm_int = fread_number( fp );
		ch->pcdata->perm_wis = fread_number( fp );
		ch->pcdata->perm_dex = fread_number( fp );
		ch->pcdata->perm_con = fread_number( fp );
		fMatch = TRUE;
		break;
	    }
	    break;

	case 'B':
	    KEY( "Bamfin",      ch->pcdata->bamfin,     fread_string( fp ) );
	    KEY( "Bamfout",     ch->pcdata->bamfout,    fread_string( fp ) );
	    KEY( "Beast",       ch->beast,              fread_number( fp ) );

		/* Read in board status */          
	    if (!str_cmp(word, "Boards" ))
	    {
			int i,num = fread_number (fp); /* number of boards saved */
			char *boardname;
			
			for (; num ; num-- ) /* for each of the board saved */
			{
				boardname = fread_word (fp);
				i = board_lookup (boardname); /* find board number */
				
				if (i == BOARD_NOTFOUND) /* Does board still exist ? */
				{
					sprintf (buf, "fread_char: %s had unknown board name: %s. Skipped.", ch->name, boardname);                                      
					log_string (buf);
					fread_number (fp); /* read last_note and skip info */
				}
				else /* Save it */
					ch->pcdata->last_note[i] = fread_number(fp);
			}        /* for */
			
			fMatch = TRUE;
	    } /* Boards */
	    



	    break;

	case 'C':
	KEY("Clan",nothing,	fread_string(fp));
	    KEY( "Class",       ch->class,              fread_number( fp ) );
	KEY( "CurrentForm",  ch->cur_form,      fread_number( fp ) );
	    if ( !str_cmp( word, "Combat" ) )
	    {
		ch->cmbt[0]     = fread_number( fp );
		ch->cmbt[1]     = fread_number( fp );
		ch->cmbt[2]     = fread_number( fp );
		ch->cmbt[3]     = fread_number( fp );
		ch->cmbt[4]     = fread_number( fp );
		ch->cmbt[5]     = fread_number( fp );
		ch->cmbt[6]     = fread_number( fp );
		ch->cmbt[7]     = fread_number( fp );
		fMatch = TRUE;
		break;
	    }

	    if ( !str_cmp( word, "Chi" ) )
            {
                ch->chi[0] = fread_number( fp );
                ch->chi[1] = fread_number( fp );
                fMatch = TRUE;
                break;
            } 

	    KEY( "Conception",  ch->pcdata->conception, fread_string( fp ) );

	    if ( !str_cmp( word, "Condition" ) )
	    {
		ch->pcdata->condition[0] = fread_number( fp );
		ch->pcdata->condition[1] = fread_number( fp );
		ch->pcdata->condition[2] = fread_number( fp );
		fMatch = TRUE;
		break;
	    }

	    if ( !str_cmp( word, "CPower" ) )
	    {
		ch->power[0] = fread_number(fp);
                ch->power[1] = fread_number(fp);
                ch->power[2] = fread_number(fp);
                ch->power[3] = fread_number(fp);
                ch->power[4] = fread_number(fp);
                ch->power[5] = fread_number(fp);
                ch->power[6] = fread_number(fp);
                ch->power[7] = fread_number(fp);
                ch->power[8] = fread_number(fp);
                ch->power[9] = fread_number(fp);
                ch->power[10] = fread_number(fp);
                ch->power[11] = fread_number(fp);
                ch->power[12] = fread_number(fp);
                ch->power[13] = fread_number(fp);
                ch->power[14] = fread_number(fp);
                ch->power[15] = fread_number(fp);
                ch->power[16] = fread_number(fp);
                ch->power[17] = fread_number(fp);
                ch->power[18] = fread_number(fp);
                ch->power[19] = fread_number(fp);
                ch->power[20] = fread_number(fp);
                ch->power[21] = fread_number(fp);
                ch->power[22] = fread_number(fp);
                ch->power[23] = fread_number(fp);
                ch->power[24] = fread_number(fp);
                ch->power[25] = fread_number(fp);
                ch->power[26] = fread_number(fp);
                ch->power[27] = fread_number(fp);
                ch->power[28] = fread_number(fp);
                ch->power[29] = fread_number(fp);
                ch->power[30] = fread_number(fp);
                ch->power[31] = fread_number(fp);
                ch->power[32] = fread_number(fp);
                ch->power[33] = fread_number(fp);
                ch->power[34] = fread_number(fp);
                ch->power[35] = fread_number(fp);
                ch->power[36] = fread_number(fp);
                ch->power[37] = fread_number(fp);
                ch->power[38] = fread_number(fp);
                ch->power[39] = fread_number(fp);
                ch->power[40] = fread_number(fp);
                ch->power[41] = fread_number(fp);
                ch->power[42] = fread_number(fp);
                ch->power[43] = fread_number(fp);
                fMatch = TRUE;
                break;
	    }

	    KEY( "Cparents",    ch->pcdata->cparents,   fread_string( fp ) );
	    KEY( "Cprompt",     ch->cprompt,            fread_string( fp ) );
	    KEY( "Createtime",  ch->createtime,         fread_string( fp ) );
	    break;

	case 'D':
	    KEY( "Damroll",     ch->damroll,            fread_number( fp ) );
	    KEY( "Deaf",        ch->deaf,               fread_number( fp ) );
	    KEY( "Demonic",     dummy,          fread_number( fp ) );
	    KEY( "Description", ch->description,        fread_string( fp ) );
	    KEY( "DiscRese",    ch->pcdata->disc_research, fread_number( fp ) );
	    KEY( "DiscPoin",    ch->pcdata->disc_points, fread_number( fp ) );

	    if ( !str_cmp( word, "Disc" ) )
	    {
		dummy = fread_number( fp );
		dummy = fread_number( fp );
		dummy = fread_number( fp );
		dummy = fread_number( fp );
		dummy = fread_number( fp );
		dummy = fread_number( fp );
		dummy = fread_number( fp );
		dummy = fread_number( fp );
		dummy = fread_number( fp );
		dummy = fread_number( fp );
		dummy = fread_number( fp );
		fMatch = TRUE;
		break;
	    }
	    KEY( "Drowaff",     dummy,  fread_number( fp ) ); /* Drow */
	    KEY( "Drowpwr",     dummy,  fread_number( fp ) ); /* Drow */
	    KEY( "Drowmag",     dummy,  fread_number( fp ) ); /* Drow */
	    break;

	case 'E':
	    KEY( "Email",       ch->pcdata->email,      fread_string( fp ) );
	    if ( !str_cmp( word, "End" ) )
		return;
	    KEY( "Exhaustion",  ch->pcdata->exhaustion, fread_number( fp ) );
	    KEY( "Exp",         ch->exp,                fread_number( fp ) );
	    KEY( "Explevel",    ch->explevel,           fread_number( fp ) );
	    KEY( "Expgained",   ch->expgained,          fread_number( fp ) );
	    KEY( "Extra",       ch->extra,              fread_number( fp ) );
	    break;

	case 'F':
	    if ( !str_cmp( word, "FakeCon" ) )
	    {
		ch->pcdata->fake_skill  = fread_number( fp );
		ch->pcdata->fake_stance = fread_number( fp );
		ch->pcdata->fake_hit    = fread_number( fp );
		ch->pcdata->fake_dam    = fread_number( fp );
		ch->pcdata->fake_ac     = fread_number( fp );
		ch->pcdata->fake_hp     = fread_number( fp );
		ch->pcdata->fake_mana   = fread_number( fp );
		ch->pcdata->fake_move   = fread_number( fp );
		fMatch = TRUE;
		break;
	    }
            if ( !str_cmp( word, "Focus" ) )
            {
                ch->focus[0] = fread_number( fp );
                ch->focus[1] = fread_number( fp );
                fMatch = TRUE;
                break;
            }
	KEY( "Flag2",  ch->flag2, fread_number( fp ) );
	KEY( "Flag3",  ch->flag3, fread_number( fp ) );
	KEY( "Flag4",  ch->flag4, fread_number( fp ) );
	    KEY( "Form",        ch->form,               fread_number( fp ) );
	    break;

	case 'G':
	KEY( "Generation", ch->generation, fread_number( fp ) );
	    if ( !str_cmp( word, "Genes" ) )
	    {
		ch->pcdata->genes[0] = fread_number( fp );
		ch->pcdata->genes[1] = fread_number( fp );
		ch->pcdata->genes[2] = fread_number( fp );
		ch->pcdata->genes[3] = fread_number( fp );
		ch->pcdata->genes[4] = fread_number( fp );
		ch->pcdata->genes[5] = fread_number( fp );
		ch->pcdata->genes[6] = fread_number( fp );
		ch->pcdata->genes[7] = fread_number( fp );
		ch->pcdata->genes[8] = fread_number( fp );
		ch->pcdata->genes[9] = fread_number( fp );
		fMatch = TRUE;
		break;
	    }

        KEY( "Garou1",  ch->garou1,     fread_number( fp ) );
        KEY( "Garou2",  ch->garou2,     fread_number( fp ) );

	if ( !str_cmp( word, "Gifts" ) )
        {
	    ch->gifts[0]  = fread_number( fp );
	    ch->gifts[1]  = fread_number( fp );
	    ch->gifts[2]  = fread_number( fp );
	    ch->gifts[3]  = fread_number( fp );
	    ch->gifts[4]  = fread_number( fp );
	    ch->gifts[5]  = fread_number( fp );
	    ch->gifts[6]  = fread_number( fp );
	    ch->gifts[7]  = fread_number( fp );
	    ch->gifts[8]  = fread_number( fp );
	    ch->gifts[9]  = fread_number( fp );
	    ch->gifts[10] = fread_number( fp );
	    ch->gifts[11] = fread_number( fp );
	    ch->gifts[12] = fread_number( fp );
	    ch->gifts[13] = fread_number( fp );
	    ch->gifts[14] = fread_number( fp );
	    ch->gifts[15] = fread_number( fp );
	    ch->gifts[16] = fread_number( fp );
	    ch->gifts[17] = fread_number( fp );
	    ch->gifts[18] = fread_number( fp );
	    ch->gifts[19] = fread_number( fp );
	    ch->gifts[20] = fread_number( fp );
	    fMatch = TRUE;
	    break;
	}

	    KEY( "Gold",        ch->gold,               fread_number( fp ) );
	    break;

	case 'H':
	    KEY( "Hitroll",     ch->hitroll,            fread_number( fp ) );
	    KEY( "Home",        ch->home,               fread_number( fp ) );

	    if ( !str_cmp( word, "HpManaMove" ) )
	    {
		ch->hit         = fread_number( fp );
		ch->max_hit     = fread_number( fp );
		ch->mana        = fread_number( fp );
		ch->max_mana    = fread_number( fp );
		ch->move        = fread_number( fp );
		ch->max_move    = fread_number( fp );
		fMatch = TRUE;
		break;
	    }
	    break;

	case 'I':
	    KEY( "Immune",        ch->immune,           fread_number( fp ) );
	    KEY( "Itemaffect",    ch->itemaffect,       fread_number( fp ) );
	    break;

	case 'K':
	KEY("Kingdom",	ch->pcdata->kingdom,	fread_number(fp));
	break;

	case 'L':
	    if ( !str_cmp( word, "Language" ) )
	    {
		ch->pcdata->language[0] = fread_number( fp );
		ch->pcdata->language[1] = fread_number( fp );
		fMatch = TRUE;
		break;
	    }

	    KEY( "Lasthost",    ch->lasthost,           fread_string( fp ) );
	    KEY( "Lasttime",    ch->lasttime,           fread_string( fp ) );
	    KEY( "Level",       ch->level,              fread_number( fp ) );
	    KEY( "Levelexp",    ch->levelexp,           fread_number( fp ) );
	    if ( !str_cmp( word, "Locationhp" ) )
	    {
		ch->loc_hp[0]   = fread_number( fp );
		ch->loc_hp[1]   = fread_number( fp );
		ch->loc_hp[2]   = fread_number( fp );
		ch->loc_hp[3]   = fread_number( fp );
		ch->loc_hp[4]   = fread_number( fp );
		ch->loc_hp[5]   = fread_number( fp );
		ch->loc_hp[6]   = fread_number( fp );
		fMatch = TRUE;
		break;
	    }
	    KEY( "LongDescr",   ch->long_descr,         fread_string( fp ) );
	    KEY( "Lord",        ch->lord,               fread_string( fp ) );
	    break;

	case 'M':
	if ( !str_cmp( word, "Monkab" ) )
        {
            ch->monkab[0] = fread_number( fp );
            ch->monkab[1] = fread_number( fp );
            ch->monkab[2] = fread_number( fp );
            ch->monkab[3] = fread_number( fp );
            fMatch = TRUE;
            break;
        }
	KEY( "Monkstuff",       ch->monkstuff, fread_number( fp ) );
        KEY( "Monkcrap",        ch->monkcrap, fread_number( fp ) );
	    KEY( "Marriage",    ch->pcdata->marriage,   fread_string( fp ) );
	    KEY( "Morph",       ch->morph,              fread_string( fp ) );
	    break;
	case 'N':
	    KEY( "Newbits",     ch->newbits,    fread_number( fp ) );

	    if ( !str_cmp( word, "Name" ) )
	    {
		/*
		 * Name already set externally.
		 */
		fread_to_eol( fp );
		fMatch = TRUE;
		break;
	    }

	    break;

	case 'O':
	    KEY( "Objvnum",     ch->pcdata->obj_vnum,   fread_number( fp ) );
	    KEY( "ObjDesc",	ch->objdesc,		fread_string( fp ) );
	    break;

	case 'P':
	    if ( !str_cmp( word, "Paradox" ) )
	    {
		ch->paradox[0]  = fread_number( fp );
		ch->paradox[1]  = fread_number( fp );
		ch->paradox[2]  = fread_number( fp );
		fMatch = TRUE;
		break;
	    }

	    KEY( "Parents",     ch->pcdata->parents,    fread_string( fp ) );
	    KEY( "Password",    ch->pcdata->pwd,        fread_string( fp ) );
	    KEY( "Played",      ch->played,             fread_number( fp ) );
	    KEY( "Polyaff",     ch->polyaff,            fread_number( fp ) );
	    KEY( "Power_Point", dummy,  fread_number( fp ) ); /* drow */

	    if ( !str_cmp( word, "Power" ) )
	    {
		for ( sn = 0; sn < 20 ; sn++ )
			ch->pcdata->powers[sn] = fread_number( fp );

		fMatch = TRUE;
		break;
	    }

	    KEY( "Poweraction", ch->poweraction,        fread_string( fp ) );
	    KEY( "Powertype",   ch->powertype,          fread_string( fp ) );
	    KEY( "Position",    ch->position,           fread_number( fp ) );
	    KEY( "Practice",    ch->practice,           fread_number( fp ) );
	    if ( !str_cmp( word, "PkPdMkMd" ) )
	    {
		ch->pkill       = fread_number( fp );
		ch->pdeath      = fread_number( fp );
		ch->mkill       = fread_number( fp );
		ch->mdeath      = fread_number( fp );
		fMatch = TRUE;
		break;
	    }
	    KEY( "Prompt",      ch->prompt,             fread_string( fp ) );
	    break;

	case 'Q':
	    KEY( "Quest",        ch->pcdata->quest,     fread_number( fp ) );
	    break;

	case 'R':
	    KEY( "Race",        ch->race,               fread_number( fp ) );
	KEY( "Rage",    ch->rage, fread_number( fp ) );
	    KEY( "Rank",        ch->pcdata->rank,       fread_number( fp ) );

	    if ( !str_cmp( word, "Room" ) )
	    {
		ch->in_room = get_room_index( fread_number( fp ) );
		if ( ch->in_room == NULL )
		    ch->in_room = get_room_index( ROOM_VNUM_LIMBO );
		fMatch = TRUE;
		break;
	    }

	    if ( !str_cmp( word, "Runes" ) )
	    {
		dummy = fread_number( fp );
		dummy = fread_number( fp );
		dummy = fread_number( fp );
		dummy = fread_number( fp );
		fMatch = TRUE;
		break;
	    }

	    break;

	case 'S':
	    KEY( "SavingThrow", ch->saving_throw,       fread_number( fp ) );
	    KEY( "Switchname",  ch->pcdata->switchname, fread_string( fp ) );
	KEY( "SilTol", ch->siltol, fread_number( fp ) );
	KEY( "Souls",  ch->pcdata->souls, fread_number( fp ) );
	    if ( !str_cmp( word, "Score" ) )
	    {
		ch->pcdata->score[0] = fread_number( fp );
		ch->pcdata->score[1] = fread_number( fp );
		ch->pcdata->score[2] = fread_number( fp );
		ch->pcdata->score[3] = fread_number( fp );
		ch->pcdata->score[4] = fread_number( fp );
		ch->pcdata->score[5] = fread_number( fp );
		fMatch = TRUE;
		break;
	    }

	    KEY( "Sex",         ch->sex,                fread_number( fp ) );
	    KEY( "ShortDescr",  ch->short_descr,        fread_string( fp ) );
		KEY( "Security", ch->pcdata->security,  fread_number(fp));
	    if ( !str_cmp( word, "Skill" ) )
	    {
		int sn;
		int value;

		value = fread_number( fp );
		sn    = skill_lookup( fread_word( fp ) );
/*
		if ( sn < 0 )
		    bug( "Fread_char: unknown skill.", 0 );
		else
		    ch->pcdata->learned[sn] = value;
*/
		if ( sn >= 0 )
		    ch->pcdata->learned[sn] = value;
		fMatch = TRUE;
	    }

	    KEY( "Specpower",   ch->specpower,  fread_number( fp ) );
	    KEY( "Spectype",    ch->spectype,   fread_number( fp ) );
	    KEY( "Special",     ch->special,    fread_number( fp ) );


	    if ( !str_cmp( word, "Spells" ) )
	    {
		ch->spl[0]      = fread_number( fp );
		ch->spl[1]      = fread_number( fp );
		ch->spl[2]      = fread_number( fp );
		ch->spl[3]      = fread_number( fp );
		ch->spl[4]      = fread_number( fp );
		fMatch = TRUE;
		break;
	    }

	    if ( !str_cmp( word, "Stage" ) )
	    {
		ch->pcdata->stage[0] = fread_number( fp );
		ch->pcdata->stage[1] = fread_number( fp );
		ch->pcdata->stage[2] = fread_number( fp );
		fMatch = TRUE;
		break;
	    }

	    if ( !str_cmp( word, "Stance" ) )
	    {
		ch->stance[0]   = fread_number( fp );
		ch->stance[1]   = fread_number( fp );
		ch->stance[2]   = fread_number( fp );
		ch->stance[3]   = fread_number( fp );
		ch->stance[4]   = fread_number( fp );
		ch->stance[5]   = fread_number( fp );
		ch->stance[6]   = fread_number( fp );
		ch->stance[7]   = fread_number( fp );
		ch->stance[8]   = fread_number( fp );
		ch->stance[9]   = fread_number( fp );
		ch->stance[10]  = fread_number( fp );
		ch->stance[11]  = fread_number( fp );
		fMatch = TRUE;
		break;
	    }

            if( !str_cmp( word, "Stance2" ) )
            {
               int x = 0;
               ch->stance[12] = fread_number(fp);
               ch->stance[13] = fread_number(fp);
               ch->stance[14] = fread_number(fp);
               ch->stance[15] = fread_number(fp);
               x = fread_number(fp);
               x = fread_number(fp);
               x = fread_number(fp);
               x = fread_number(fp);
               x = fread_number(fp);
               x = fread_number(fp);
               x = fread_number(fp);
               x = fread_number(fp);
               fMatch = TRUE;
               break;
            }

	    if ( !str_cmp( word, "StatAbility" ) )
	    {
		ch->pcdata->stat_ability[0] = fread_number( fp );
		ch->pcdata->stat_ability[1] = fread_number( fp );
		ch->pcdata->stat_ability[2] = fread_number( fp );
		ch->pcdata->stat_ability[3] = fread_number( fp );
		fMatch = TRUE;
		break;
	    }

	    if ( !str_cmp( word, "StatAmount" ) )
	    {
		ch->pcdata->stat_amount[0] = fread_number( fp );
		ch->pcdata->stat_amount[1] = fread_number( fp );
		ch->pcdata->stat_amount[2] = fread_number( fp );
		ch->pcdata->stat_amount[3] = fread_number( fp );
		fMatch = TRUE;
		break;
	    }

	    if ( !str_cmp( word, "StatDuration" ) )
	    {
		ch->pcdata->stat_duration[0] = fread_number( fp );
		ch->pcdata->stat_duration[1] = fread_number( fp );
		ch->pcdata->stat_duration[2] = fread_number( fp );
		ch->pcdata->stat_duration[3] = fread_number( fp );
		fMatch = TRUE;
		break;
	    }


	    if ( !str_cmp( word, "Stats" ) )
	    {
		for ( sn = 0; sn < 12 ; sn++ )
			ch->pcdata->stats[sn] = fread_number( fp );
		fMatch = TRUE;
		break;
	    }

	    break;

	case 'T':
	    KEY( "Trust",       ch->trust,              fread_number( fp ) );

	    if ( !str_cmp( word, "Title" ) )
	    {
		ch->pcdata->title = fread_string( fp );
		if ( isalpha(ch->pcdata->title[0])
		||   isdigit(ch->pcdata->title[0]) )
		{
		    sprintf( buf, " %s", ch->pcdata->title );
		    free_string( ch->pcdata->title );
		    ch->pcdata->title = str_dup( buf );
		}
		fMatch = TRUE;
		break;
	    }

	    break;

	case 'V':
	    KEY( "Vampaff",        dummy,               fread_number( fp ) );
	    KEY( "Vampgen",        dummy,               fread_number( fp ) );
	    KEY( "Vamppass",       dummy,               fread_number( fp ) );
	    if ( !str_cmp( word, "Vnum" ) )
	    {
		ch->pIndexData = get_mob_index( fread_number( fp ) );
		fMatch = TRUE;
		break;
	    }
	    break;

	case 'W':
	    KEY( "Warps",        ch->warp,       fread_number( fp ) );
	    KEY( "WarpCount",   ch->warpcount,  fread_number( fp ) );
	    if ( !str_cmp( word, "Weapons" ) )
	    {
		ch->wpn[0]      = fread_number( fp );
		ch->wpn[1]      = fread_number( fp );
		ch->wpn[2]      = fread_number( fp );
		ch->wpn[3]      = fread_number( fp );
		ch->wpn[4]      = fread_number( fp );
		ch->wpn[5]      = fread_number( fp );
		ch->wpn[6]      = fread_number( fp );
		ch->wpn[7]      = fread_number( fp );
		ch->wpn[8]      = fread_number( fp );
		ch->wpn[9]      = fread_number( fp );
		ch->wpn[10]     = fread_number( fp );
		ch->wpn[11]     = fread_number( fp );
		ch->wpn[12]     = fread_number( fp );
		fMatch = TRUE;
		break;
	    }
	    KEY( "Wimpy",       ch->wimpy,              fread_number( fp ) );
	    KEY( "Wolf",        dummy,          fread_number( fp ) );
	    if ( !str_cmp( word, "Wolfform" ) )
	    {
		dummy = fread_number( fp );
		dummy = fread_number( fp );
		fMatch = TRUE;
		break;
	    }
            KEY( "ww_completed",   ch->pcdata->ww_completed[AMOUNT_COMPLETED],   fread_number( fp ) );
	    KEY( "ww_researching", ch->pcdata->ww_researching[TOTEM_RESEARCHING], fread_number( fp ) );
            KEY( "WWComplete",   ch->pcdata->ww_completed[AMOUNT_COMPLETED],   fread_number( fp ) );
            KEY( "WWResearching", ch->pcdata->ww_researching[TOTEM_RESEARCHING], fread_number( fp ) );
            KEY( "Wwin",       ch->pcdata->wwins,      fread_number( fp ) );
            KEY( "Wlos",        ch->pcdata->wlosses,       fread_number( fp ) );
	    break;
	case 'X':
	KEY( "XHitroll", ch->xhitroll, fread_number( fp ) );
	KEY( "XDamroll", ch->xdamroll, fread_number( fp ) );
	break;
	}

	if ( !fMatch )
	{
	    sprintf(buf, "Fread_char: no match. WORD: %s", word); 
	    bug( buf, 0 );
	    fread_to_eol( fp );
	}
    }
}

void convert_old_new( CHAR_DATA *ch )
{
	char buf[MAX_STRING_LENGTH];
	ch->class = 0;
	sprintf( buf, "%s has been avatar upgraded!", ch->name);
	log_string( buf );
	return;

}



****************************
 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
 *                                                                         *
 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
 *  Chastain, Michael Quan, and Mitchell Tse.                              *
 *                                                                         *
 *  In order to use any part of this Merc Diku Mud, you must comply with   *
 *  both the original Diku license in 'license.doc' as well the Merc       *
 *  license in 'license.txt'.  In particular, you may not remove either of *
 *  these copyright notices.                                               *
 *                                                                         *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 ***************************************************************************/

#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"



/*
 * The following special functions are available for mobiles.
 */
DECLARE_SPEC_FUN(	spec_breath_any		);
DECLARE_SPEC_FUN(	spec_breath_acid	);
DECLARE_SPEC_FUN(	spec_breath_fire	);
DECLARE_SPEC_FUN(	spec_breath_frost	);
DECLARE_SPEC_FUN(	spec_breath_gas		);
DECLARE_SPEC_FUN(	spec_breath_lightning	);
DECLARE_SPEC_FUN(	spec_cast_adept		);
DECLARE_SPEC_FUN(	spec_cast_cleric	);
DECLARE_SPEC_FUN(	spec_cast_judge		);
DECLARE_SPEC_FUN(	spec_cast_mage		);
DECLARE_SPEC_FUN(	spec_cast_undead	);
DECLARE_SPEC_FUN(	spec_fido		);
DECLARE_SPEC_FUN(	spec_guard		);
DECLARE_SPEC_FUN(	spec_janitor		);
DECLARE_SPEC_FUN(	spec_mayor		);
DECLARE_SPEC_FUN(	spec_poison		);
DECLARE_SPEC_FUN(	spec_thief		);
DECLARE_SPEC_FUN(	spec_eater		);
DECLARE_SPEC_FUN(	spec_gremlin_original	);
DECLARE_SPEC_FUN(	spec_gremlin_born	);
DECLARE_SPEC_FUN(	spec_rogue		);
DECLARE_SPEC_FUN(	spec_zombie_lord	);
DECLARE_SPEC_FUN(	spec_dog		);
DECLARE_SPEC_FUN(       spec_guard_demon	);
DECLARE_SPEC_FUN(	spec_guard_vampire	);
DECLARE_SPEC_FUN(	spec_guard_werewolf	);
DECLARE_SPEC_FUN(	spec_guard_mage		);
DECLARE_SPEC_FUN(	spec_guard_drow		);
DECLARE_SPEC_FUN(	spec_guard_ninja	);
DECLARE_SPEC_FUN(	spec_guard_monk		);


bool spec_guard_werewolf(CHAR_DATA *ch)
{
   DESCRIPTOR_DATA       *d;
   CHAR_DATA             *victim;
   char                  buf[MAX_STRING_LENGTH];


   if (ch->fighting) return FALSE;

   if (ch->in_room == NULL) return FALSE;

   for (d = descriptor_list; d != NULL; d = d->next)
   {
       if (!IS_PLAYING(d)
	   || (victim = d->character) == NULL
           || IS_NPC(victim)
           || IS_IMMORTAL(victim)
	   || victim->in_room == NULL
           || victim->pcdata->chobj != NULL
           || victim->in_room->area != ch->in_room->area
           || victim->in_room == ch->in_room
	   || IS_CLASS(victim, CLASS_WEREWOLF))
	{
            continue;
        }

        if (ch->in_room!=victim->in_room)
        {
           act("$n disappears in a swirl of smoke!",ch,NULL,NULL,TO_ROOM);
           act("You disappear in a swirl of smoke!",ch,NULL,NULL,TO_CHAR);

           char_from_room( ch );
           char_to_room(ch, victim->in_room);

           act("$n appears in a swirl of smoke!",ch,NULL,NULL,TO_ROOM);
           act("You appear in a swirl of smoke!",ch,NULL,NULL,TO_CHAR);
        }

        spell_curse( 24 , 100 , ch , victim ); /* No Recall */

        if (victim->position <= POS_MORTAL && IS_HERO(victim) &&
	  ch->position == POS_STANDING)
        {
           char_from_room( victim );
           char_to_room(victim, get_room_index(ROOM_VNUM_ALTAR));
           continue;
        }
        sprintf( buf,"%s is invading the sacred Caern!\n\r",victim->name); 
        do_howl( ch , buf);
      
        multi_hit( ch, victim, gsn_punch);

        return TRUE;

   }
   return FALSE;
}

bool spec_guard_vampire(CHAR_DATA *ch)
{
   DESCRIPTOR_DATA       *d;
   CHAR_DATA             *victim;
   char                  buf[MAX_STRING_LENGTH];


   if (ch->fighting) return FALSE;

   if (ch->in_room == NULL) return FALSE;

   for (d = descriptor_list; d != NULL; d = d->next)
   {
       if (!IS_PLAYING(d)
	   || (victim = d->character) == NULL
           || IS_NPC(victim)
           || IS_IMMORTAL(victim)
	   || victim->in_room == NULL
           || victim->pcdata->chobj != NULL
           || victim->in_room->area != ch->in_room->area
           || victim->in_room == ch->in_room
	   || IS_CLASS(victim, CLASS_VAMPIRE))
	{
            continue;
        }

        if (ch->in_room!=victim->in_room)
        {
           act("$n disappears in a swirl of smoke!",ch,NULL,NULL,TO_ROOM);
           act("You disappear in a swirl of smoke!",ch,NULL,NULL,TO_CHAR);

           char_from_room( ch );
           char_to_room(ch, victim->in_room);

           act("$n appears in a swirl of smoke!",ch,NULL,NULL,TO_ROOM);
           act("You appear in a swirl of smoke!",ch,NULL,NULL,TO_CHAR);
        }

        spell_curse( 24 , 100 , ch , victim ); /* No Recall */

        if (victim->position <= POS_MORTAL && IS_HERO(victim) &&
	  ch->position == POS_STANDING)
        {
           char_from_room( victim );
           char_to_room(victim, get_room_index(ROOM_VNUM_ALTAR));
           continue;
        }
        sprintf( buf,"%s is invading the Kindred's Grounds!\n\r", victim->name); 
        do_vamptalk( ch , buf);
      
        multi_hit( ch, victim, gsn_punch);

        return TRUE;

   }
   return FALSE;
}

bool spec_guard_demon(CHAR_DATA *ch)
{
   DESCRIPTOR_DATA       *d;
   CHAR_DATA             *victim;
   char                  buf[MAX_STRING_LENGTH];


   if (ch->fighting) return FALSE;

   if (ch->in_room == NULL) return FALSE;

   for (d = descriptor_list; d != NULL; d = d->next)
   {
       if (!IS_PLAYING(d)
	   || (victim = d->character) == NULL
           || IS_NPC(victim)
           || IS_IMMORTAL(victim)
	   || victim->in_room == NULL
           || victim->pcdata->chobj != NULL
           || victim->in_room->area != ch->in_room->area
           || victim->in_room == ch->in_room
	   || IS_CLASS(victim, CLASS_DEMON))
	{
            continue;
        }

        if (ch->in_room!=victim->in_room)
        {
           act("$n disappears in a swirl of smoke!",ch,NULL,NULL,TO_ROOM);
           act("You disappear in a swirl of smoke!",ch,NULL,NULL,TO_CHAR);

           char_from_room( ch );
           char_to_room(ch, victim->in_room);

           act("$n appears in a swirl of smoke!",ch,NULL,NULL,TO_ROOM);
           act("You appear in a swirl of smoke!",ch,NULL,NULL,TO_CHAR);
        }

        spell_curse( 24 , 100 , ch , victim ); /* No Recall */

        if (victim->position <= POS_MORTAL && IS_HERO(victim) &&
	  ch->position == POS_STANDING)
        {
           char_from_room( victim );
           char_to_room(victim, get_room_index(ROOM_VNUM_ALTAR));
           continue;
        }
        sprintf( buf,"%s is invading Hell!\n\r", victim->name); 
        do_pray( ch , buf);
      
        multi_hit( ch, victim, gsn_punch);

        return TRUE;

   }
   return FALSE;
}

bool spec_guard_drow(CHAR_DATA *ch)
{
   DESCRIPTOR_DATA       *d;
   CHAR_DATA             *victim;
   char                  buf[MAX_STRING_LENGTH];


   if (ch->fighting) return FALSE;

   if (ch->in_room == NULL) return FALSE;

   for (d = descriptor_list; d != NULL; d = d->next)
   {
       if (!IS_PLAYING(d)
	   || (victim = d->character) == NULL
           || IS_NPC(victim)
           || IS_IMMORTAL(victim)
	   || victim->in_room == NULL
           || victim->pcdata->chobj != NULL
           || victim->in_room->area != ch->in_room->area
           || victim->in_room == ch->in_room
	   || IS_CLASS(victim, CLASS_DROW))
	{
            continue;
        }

        if (ch->in_room!=victim->in_room)
        {
           act("$n disappears in a swirl of smoke!",ch,NULL,NULL,TO_ROOM);
           act("You disappear in a swirl of smoke!",ch,NULL,NULL,TO_CHAR);

           char_from_room( ch );
           char_to_room(ch, victim->in_room);

           act("$n appears in a swirl of smoke!",ch,NULL,NULL,TO_ROOM);
           act("You appear in a swirl of smoke!",ch,NULL,NULL,TO_CHAR);
        }

        spell_curse( 24 , 100 , ch , victim ); /* No Recall */

        if (victim->position <= POS_MORTAL && IS_HERO(victim) &&
	  ch->position == POS_STANDING)
        {
           char_from_room( victim );
           char_to_room(victim, get_room_index(ROOM_VNUM_ALTAR));
           continue;
        }
        sprintf( buf,"%s is invading Drow Headquarters!\n\r", victim->name); 
        do_sign( ch , buf);
      
        multi_hit( ch, victim, gsn_punch);

        return TRUE;

   }
   return FALSE;
}

bool spec_guard_monk(CHAR_DATA *ch)
{
   DESCRIPTOR_DATA       *d;
   CHAR_DATA             *victim;
   char                  buf[MAX_STRING_LENGTH];


   if (ch->fighting) return FALSE;

   if (ch->in_room == NULL) return FALSE;

   for (d = descriptor_list; d != NULL; d = d->next)
   {
       if (!IS_PLAYING(d)
	   || (victim = d->character) == NULL
           || IS_NPC(victim)
           || IS_IMMORTAL(victim)
	   || victim->in_room == NULL
           || victim->pcdata->chobj != NULL
           || victim->in_room->area != ch->in_room->area
           || victim->in_room == ch->in_room
	   || IS_CLASS(victim, CLASS_MONK))
	{
            continue;
        }

        if (ch->in_room!=victim->in_room)
        {
           act("$n disappears in a swirl of smoke!",ch,NULL,NULL,TO_ROOM);
           act("You disappear in a swirl of smoke!",ch,NULL,NULL,TO_CHAR);

           char_from_room( ch );
           char_to_room(ch, victim->in_room);

           act("$n appears in a swirl of smoke!",ch,NULL,NULL,TO_ROOM);
           act("You appear in a swirl of smoke!",ch,NULL,NULL,TO_CHAR);
        }

        spell_curse( 24 , 100 , ch , victim ); /* No Recall */

        if (victim->position <= POS_MORTAL && IS_HERO(victim) &&
	  ch->position == POS_STANDING)
        {
           char_from_room( victim );
           char_to_room(victim, get_room_index(ROOM_VNUM_ALTAR));
           continue;
        }
        sprintf( buf,"%s is imposing upon the Holy Grounds!\n\r", victim->name); 
        do_shout( ch , buf);
      
        multi_hit( ch, victim, gsn_punch);

        return TRUE;

   }
   return FALSE;
}

bool spec_guard_ninja(CHAR_DATA *ch)
{
   DESCRIPTOR_DATA       *d;
   CHAR_DATA             *victim;
   char                  buf[MAX_STRING_LENGTH];


   if (ch->fighting) return FALSE;

   if (ch->in_room == NULL) return FALSE;

   for (d = descriptor_list; d != NULL; d = d->next)
   {
       if (!IS_PLAYING(d)
	   || (victim = d->character) == NULL
           || IS_NPC(victim)
           || IS_IMMORTAL(victim)
	   || victim->in_room == NULL
           || victim->pcdata->chobj != NULL
           || victim->in_room->area != ch->in_room->area
           || victim->in_room == ch->in_room
	   || IS_CLASS(victim, CLASS_NINJA))
	{
            continue;
        }

        if (ch->in_room!=victim->in_room)
        {
           act("$n disappears in a swirl of smoke!",ch,NULL,NULL,TO_ROOM);
           act("You disappear in a swirl of smoke!",ch,NULL,NULL,TO_CHAR);

           char_from_room( ch );
           char_to_room(ch, victim->in_room);

           act("$n appears in a swirl of smoke!",ch,NULL,NULL,TO_ROOM);
           act("You appear in a swirl of smoke!",ch,NULL,NULL,TO_CHAR);
        }

        spell_curse( 24 , 100 , ch , victim ); /* No Recall */

        if (victim->position <= POS_MORTAL && IS_HERO(victim) &&
	  ch->position == POS_STANDING)
        {
           char_from_room( victim );
           char_to_room(victim, get_room_index(ROOM_VNUM_ALTAR));
           continue;
        }
        sprintf( buf,"%s is violating our Sanctuary!\n\r", victim->name); 
        do_miktalk( ch , buf);
      
        multi_hit( ch, victim, gsn_punch);

        return TRUE;

   }
   return FALSE;
}

/*
 * Core procedure for dragons.
 */
bool dragon( CHAR_DATA *ch, char *spell_name )
{
    CHAR_DATA *victim;
    CHAR_DATA *v_next;
    int sn;

    if ( ch->position != POS_FIGHTING )
	return FALSE;

    for ( victim = ch->in_room->people; victim != NULL; victim = v_next )
    {
	v_next = victim->next_in_room;
	if ( victim->fighting == ch && number_bits( 2 ) == 0 )
	    break;
    }

    if ( victim == NULL )
	return FALSE;

    if ( ( sn = skill_lookup( spell_name ) ) < 0 )
	return FALSE;
    (*skill_table[sn].spell_fun) ( sn, ch->level, ch, victim );
    return TRUE;
}



/*
 * Special procedures for mobiles.
 */
bool spec_breath_any( CHAR_DATA *ch )
{
    if ( ch->position != POS_FIGHTING )
	return FALSE;

    switch ( number_bits( 3 ) )
    {
    case 0: return spec_breath_fire		( ch );
    case 1:
    case 2: return spec_breath_lightning	( ch );
    case 3: return spec_breath_gas		( ch );
    case 4: return spec_breath_acid		( ch );
    case 5:
    case 6:
    case 7: return spec_breath_frost		( ch );
    }

    return FALSE;
}



bool spec_breath_acid( CHAR_DATA *ch )
{
    return dragon( ch, "acid breath" );
}



bool spec_breath_fire( CHAR_DATA *ch )
{
    return dragon( ch, "fire breath" );
}



bool spec_breath_frost( CHAR_DATA *ch )
{
    return dragon( ch, "frost breath" );
}



bool spec_breath_gas( CHAR_DATA *ch )
{
    int sn;

    if ( ch->position != POS_FIGHTING )
	return FALSE;

    if ( ( sn = skill_lookup( "gas breath" ) ) < 0 )
	return FALSE;
    (*skill_table[sn].spell_fun) ( sn, ch->level, ch, NULL );
    return TRUE;
}



bool spec_breath_lightning( CHAR_DATA *ch )
{
    return dragon( ch, "lightning breath" );
}



bool spec_cast_adept( CHAR_DATA *ch )
{
    CHAR_DATA *victim;
    CHAR_DATA *v_next;

    if ( !IS_AWAKE(ch) )
	return FALSE;

    for ( victim = ch->in_room->people; victim != NULL; victim = v_next )
    {
	v_next = victim->next_in_room;
	if ( victim != ch && can_see( ch, victim ) && number_bits( 1 ) == 0 )
	    break;
    }

    if ( victim == NULL )
	return FALSE;

    switch ( number_bits( 3 ) )
    {
    case 0:
	act( "$n utters the word 'tehctah'.", ch, NULL, NULL, TO_ROOM );
	spell_armor( skill_lookup( "armor" ), ch->level, ch, victim );
	return TRUE;

    case 1:
	act( "$n utters the word 'nhak'.", ch, NULL, NULL, TO_ROOM );
	spell_bless( skill_lookup( "bless" ), ch->level, ch, victim );
	return TRUE;

    case 2:
	act( "$n utters the word 'yeruf'.", ch, NULL, NULL, TO_ROOM );
	spell_cure_blindness( skill_lookup( "cure blindness" ),
	    ch->level, ch, victim );
	return TRUE;

    case 3:
	act( "$n utters the word 'garf'.", ch, NULL, NULL, TO_ROOM );
	spell_cure_light( skill_lookup( "cure light" ),
	    ch->level, ch, victim );
	return TRUE;

    case 4:
	act( "$n utters the words 'rozar'.", ch, NULL, NULL, TO_ROOM );
	spell_cure_poison( skill_lookup( "cure poison" ),
	    ch->level, ch, victim );
	return TRUE;

    case 5:
	act( "$n utters the words 'nadroj'.", ch, NULL, NULL, TO_ROOM );
	spell_refresh( skill_lookup( "refresh" ), ch->level, ch, victim );
	return TRUE;

    }

    return FALSE;
}



bool spec_cast_cleric( CHAR_DATA *ch )
{
    CHAR_DATA *victim;
    CHAR_DATA *v_next;
    char *spell;
    int sn;

    if ( ch->position != POS_FIGHTING )
	return FALSE;

    for ( victim = ch->in_room->people; victim != NULL; victim = v_next )
    {
	v_next = victim->next_in_room;
	if ( victim->fighting == ch && number_bits( 2 ) == 0 )
	    break;
    }

    if ( victim == NULL )
	return FALSE;

    for ( ;; )
    {
	int min_level;

	switch ( number_bits( 4 ) )
	{
	case  0: min_level =  0; spell = "blindness";      break;
	case  1: min_level =  3; spell = "cause serious";  break;
	case  2: min_level =  7; spell = "earthquake";     break;
	case  3: min_level =  9; spell = "cause critical"; break;
	case  4: min_level = 10; spell = "dispel evil";    break;
	case  5: min_level = 12; spell = "curse";          break;
	case  6: min_level = 12; spell = "change sex";     break;
	case  7: min_level = 13; spell = "flamestrike";    break;
	case  8:
	case  9:
	case 10: min_level = 15; spell = "harm";           break;
	default: min_level = 16; spell = "dispel magic";   break;
	}

	if ( ch->level >= min_level )
	    break;
    }

    if ( ( sn = skill_lookup( spell ) ) < 0 )
	return FALSE;
    (*skill_table[sn].spell_fun) ( sn, ch->level, ch, victim );
    return TRUE;
}



bool spec_cast_judge( CHAR_DATA *ch )
{
    CHAR_DATA *victim;
    CHAR_DATA *v_next;
    char *spell;
    int sn;

    if ( ch->position != POS_FIGHTING )
	return FALSE;

    for ( victim = ch->in_room->people; victim != NULL; victim = v_next )
    {
	v_next = victim->next_in_room;
	if ( victim->fighting == ch && number_bits( 2 ) == 0 )
	    break;
    }

    if ( victim == NULL )
	return FALSE;

    spell = "high explosive";
    if ( ( sn = skill_lookup( spell ) ) < 0 )
	return FALSE;
    (*skill_table[sn].spell_fun) ( sn, ch->level, ch, victim );
    return TRUE;
}



bool spec_cast_mage( CHAR_DATA *ch )
{
    CHAR_DATA *victim;
    CHAR_DATA *v_next;
    char *spell;
    int sn;

    if ( ch->position != POS_FIGHTING )
	return FALSE;

    for ( victim = ch->in_room->people; victim != NULL; victim = v_next )
    {
	v_next = victim->next_in_room;
	if ( victim->fighting == ch && number_bits( 2 ) == 0 )
	    break;
    }

    if ( victim == NULL )
	return FALSE;

    for ( ;; )
    {
	int min_level;

	switch ( number_bits( 4 ) )
	{
	case  0: min_level =  0; spell = "blindness";      break;
	case  1: min_level =  3; spell = "chill touch";    break;
	case  2: min_level =  7; spell = "weaken";         break;
	case  3: min_level =  8; spell = "teleport";       break;
	case  4: min_level = 11; spell = "colour spray";   break;
	case  5: min_level = 12; spell = "change sex";     break;
	case  6: min_level = 13; spell = "energy drain";   break;
	case  7:
	case  8:
	case  9: min_level = 15; spell = "fireball";       break;
	default: min_level = 20; spell = "acid blast";     break;
	}

	if ( ch->level >= min_level )
	    break;
    }

    if ( ( sn = skill_lookup( spell ) ) < 0 )
	return FALSE;
    (*skill_table[sn].spell_fun) ( sn, ch->level, ch, victim );
    return TRUE;
}



bool spec_cast_undead( CHAR_DATA *ch )
{
    CHAR_DATA *victim;
    CHAR_DATA *v_next;
    char *spell;
    int sn;

    if ( ch->position != POS_FIGHTING )
	return FALSE;

    for ( victim = ch->in_room->people; victim != NULL; victim = v_next )
    {
	v_next = victim->next_in_room;
	if ( victim->fighting == ch && number_bits( 2 ) == 0 )
	    break;
    }

    if ( victim == NULL )
	return FALSE;

    for ( ;; )
    {
	int min_level;

	switch ( number_bits( 4 ) )
	{
	case  0: min_level =  0; spell = "curse";          break;
	case  1: min_level =  3; spell = "weaken";         break;
	case  2: min_level =  6; spell = "chill touch";    break;
	case  3: min_level =  9; spell = "blindness";      break;
	case  4: min_level = 12; spell = "poison";         break;
	case  5: min_level = 15; spell = "energy drain";   break;
	case  6: min_level = 18; spell = "harm";           break;
	case  7: min_level = 21; spell = "teleport";       break;
	default: min_level = 24; spell = "gate";           break;
	}

	if ( ch->level >= min_level )
	    break;
    }

    if ( ( sn = skill_lookup( spell ) ) < 0 )
	return FALSE;
    (*skill_table[sn].spell_fun) ( sn, ch->level, ch, victim );
    return TRUE;
}



bool spec_fido( CHAR_DATA *ch )
{
    OBJ_DATA *corpse;
    OBJ_DATA *c_next;
    OBJ_DATA *obj;
    OBJ_DATA *obj_next;

    if ( !IS_AWAKE(ch) )
	return FALSE;

    for ( corpse = ch->in_room->contents; corpse != NULL; corpse = c_next )
    {
	c_next = corpse->next_content;
	if ( corpse->item_type != ITEM_CORPSE_NPC )
	    continue;

	act( "$n savagely devours a corpse.", ch, NULL, NULL, TO_ROOM );
	for ( obj = corpse->contains; obj; obj = obj_next )
	{
	    obj_next = obj->next_content;
	    obj_from_obj( obj );
	    obj_to_room( obj, ch->in_room );
	}
	if (corpse != NULL) extract_obj( corpse );
	return TRUE;
    }

    return FALSE;
}



bool spec_guard( CHAR_DATA *ch )
{
    char buf[MAX_STRING_LENGTH];
    CHAR_DATA *victim;
    CHAR_DATA *v_next;
    CHAR_DATA *ech;
    int max_evil;
    int rand;

    if ( !IS_AWAKE(ch) || ch->fighting != NULL )
	return FALSE;

    max_evil = 300;
    ech      = NULL;

    for ( victim = ch->in_room->people; victim != NULL; victim = v_next )
    {
	v_next = victim->next_in_room;

	if ( !IS_NPC(victim) && victim->race > 24 && number_percent() > 95)
	    break;

	if ( victim->fighting != NULL
	&&   victim->fighting != ch
	&&   victim->alignment < max_evil )
	{
	    max_evil = victim->alignment;
	    ech      = victim;
	}
    }

    if ( victim != NULL )
    {
	rand=number_range(1,5);
	if (rand == 1)
	{
	    sprintf( buf, "It is an honour to meet you, %s!",
	        victim->name);
	    do_say( ch, buf );
	}
	else if (rand == 2)
	{
	    act("You bow deeply before $N.",ch,NULL,victim,TO_CHAR);
	    act("$n bows deeply before you.",ch,NULL,victim,TO_VICT);
	    act("$n bows deeply before $N.",ch,NULL,victim,TO_NOTVICT);
	}
	else if (rand == 3)
	{
	    act("You shake $N's hand.",ch,NULL,victim,TO_CHAR);
	    act("$n shakes your hand.",ch,NULL,victim,TO_VICT);
	    act("$n shakes $N's hand.",ch,NULL,victim,TO_NOTVICT);
	    sprintf( buf, "It's a pleasure to see you again, %s!",
	        victim->name);
	    do_say( ch, buf );
	}
	else if (rand == 4)
	{
	    act("You pat $N on the back.",ch,NULL,victim,TO_CHAR);
	    act("$n pats you on the back.",ch,NULL,victim,TO_VICT);
	    act("$n pats $N on the back.",ch,NULL,victim,TO_NOTVICT);
	    sprintf( buf, "Greetings %s!  If you need anything, just say!",
	        victim->name);
	    do_say( ch, buf );
	}
	else
	{
	    act("You beam a smile at $N.",ch,NULL,victim,TO_CHAR);
	    act("$n beams a smile at you.",ch,NULL,victim,TO_VICT);
	    act("$n beams a smile at $N.",ch,NULL,victim,TO_NOTVICT);
	}
	return TRUE;
    }

    if ( ech != NULL )
    {
	if (!IS_NPC(ech) && ech->race >= 25)
	{
	    sprintf( buf, "How DARE you attack %s? You shall DIE!",
	        ech->name);
	    do_say( ch, buf );
	    do_rescue( ch, ech->name );
	    return TRUE;
	}
	act( "$n screams 'PROTECT THE INNOCENT!!  BANZAI!!",
	    ch, NULL, NULL, TO_ROOM );
	multi_hit( ch, ech, TYPE_UNDEFINED );
	return TRUE;
    }

    return FALSE;
}



bool spec_janitor( CHAR_DATA *ch )
{
    OBJ_DATA *trash;
    OBJ_DATA *trash_next;

    if ( !IS_AWAKE(ch) )
	return FALSE;

    for ( trash = ch->in_room->contents; trash != NULL; trash = trash_next )
    {
	trash_next = trash->next_content;
	if ( !IS_SET( trash->wear_flags, ITEM_TAKE ) )
	    continue;
	if ( trash->item_type == ITEM_DRINK_CON
	||   trash->item_type == ITEM_TRASH
	||   trash->cost < 10 )
	{
	    act( "$n picks up some trash.", ch, NULL, NULL, TO_ROOM );
	    obj_from_room( trash );
	    obj_to_char( trash, ch );
	    return TRUE;
	}
    }

    return FALSE;
}



bool spec_mayor( CHAR_DATA *ch )
{
    static const char open_path[] =
	"W3a3003b33000c111d0d111Oe333333Oe22c222112212111a1S.";

    static const char close_path[] =
	"W3a3003b33000c111d0d111CE333333CE22c222112212111a1S.";

    static const char *path;
    static int pos;
    static bool move;

    if ( !move )
    {
	if ( time_info.hour ==  6 )
	{
	    path = open_path;
	    move = TRUE;
	    pos  = 0;
	}

	if ( time_info.hour == 20 )
	{
	    path = close_path;
	    move = TRUE;
	    pos  = 0;
	}
    }

    if ( ch->fighting != NULL )
	return spec_cast_cleric( ch );
    if ( !move || ch->position < POS_SLEEPING )
	return FALSE;

    switch ( path[pos] )
    {
    case '0':
    case '1':
    case '2':
    case '3':
	move_char( ch, path[pos] - '0' );
	break;

    case 'W':
	ch->position = POS_STANDING;
	act( "$n awakens and groans loudly.", ch, NULL, NULL, TO_ROOM );
	break;

    case 'S':
	ch->position = POS_SLEEPING;
	act( "$n lies down and falls asleep.", ch, NULL, NULL, TO_ROOM );
	break;

    case 'a':
	act( "$n says 'Hello Honey!'", ch, NULL, NULL, TO_ROOM );
	break;

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

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

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

    case 'e':
	act( "$n says 'I hereby declare the city of Midgaard open!'",
	    ch, NULL, NULL, TO_ROOM );
	break;

    case 'E':
	act( "$n says 'I hereby declare the city of Midgaard closed!'",
	    ch, NULL, NULL, TO_ROOM );
	break;

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

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

    case '.' :
	move = FALSE;
	break;
    }

    pos++;
    return FALSE;
}



bool spec_poison( CHAR_DATA *ch )
{
    CHAR_DATA *victim;

    if ( ch->position != POS_FIGHTING
    || ( victim = ch->fighting ) == NULL
    ||   number_percent( ) > 2 * ch->level )
	return FALSE;

    act( "You bite $N!",  ch, NULL, victim, TO_CHAR    );
    act( "$n bites $N!",  ch, NULL, victim, TO_NOTVICT );
    act( "$n bites you!", ch, NULL, victim, TO_VICT    );
    spell_poison( gsn_poison, ch->level, ch, victim );
    return TRUE;
}



bool spec_thief( CHAR_DATA *ch )
{
    CHAR_DATA *victim;
    CHAR_DATA *v_next;
    int gold;

    if ( ch->position != POS_STANDING )
	return FALSE;

    for ( victim = ch->in_room->people; victim != NULL; victim = v_next )
    {
	v_next = victim->next_in_room;

	if ( IS_NPC(victim)
	||   (!IS_NPC(victim) && IS_IMMUNE(victim, IMM_STEAL))
	||   victim->level >= LEVEL_IMMORTAL
	||   number_bits( 2 ) != 0
	||   !can_see( ch, victim ) )	/* Thx Glop */
	    continue;

	if ( IS_AWAKE(victim) && number_range( 0, ch->level ) == 0 )
	{
	    act( "You discover $n's hands in your wallet!",
		ch, NULL, victim, TO_VICT );
	    act( "$N discovers $n's hands in $S wallet!",
		ch, NULL, victim, TO_NOTVICT );
	    return TRUE;
	}
	else
	{
	    gold = victim->gold * number_range( 1, 20 ) / 100;
	    ch->gold     += 7 * gold / 8;
	    victim->gold -= gold;
	    return TRUE;
	}
    }

    return FALSE;
}

bool spec_eater( CHAR_DATA *ch )
{
  /* The spec_eater is a hungry bugger who eats players.  If they get 
   * eaten, they get transported to the room with the same vnum as the 
   * mob Example:  A spec_eater dragon with the vnum 31305 would send 
   * anybody eaten to room 31305.
   * KaVir.
   */
   CHAR_DATA       *victim;
   ROOM_INDEX_DATA *pRoomIndex;
   if ( ch->position != POS_FIGHTING )
   {
      return FALSE;
   }
   if (number_percent() > 50 ) return FALSE;
   victim=ch->fighting;
   act( "$n stares at $N hungrily and licks $s lips!",  ch, NULL, victim, TO_NOTVICT    );
   act( "$n stares at you hungrily and licks $s lips!",  ch, NULL, victim, TO_VICT    );
   if (number_percent() > 25 ) return FALSE;
   pRoomIndex = get_room_index(ch->pIndexData->vnum);
   act( "$n opens $s mouth wide and lunges at you!", ch, NULL, victim, TO_VICT    );
   act( "$n swallows you whole!", ch, NULL, victim, TO_VICT    );
   act( "$n opens $s mouth wide and lunges at $N!",  ch, NULL, victim, TO_NOTVICT );
   act( "$n swallows $N whole!",  ch, NULL, victim, TO_NOTVICT );
   char_from_room(victim);
   char_to_room(victim,pRoomIndex);
   do_emote(ch,"burps loudly.");
   do_look(victim,"auto");
   return TRUE;
}

bool spec_gremlin_original( CHAR_DATA *ch )
{
   OBJ_DATA *object;
   OBJ_DATA *object_next;
   OBJ_DATA *obj;
   char buf  [MAX_STRING_LENGTH];

   if ( !IS_AWAKE( ch ) )
      return FALSE;

   if (number_percent() > 25)
   {
	CHAR_DATA *victim;
	CHAR_DATA *v_next;
	/* Lets make this mob DO things!  KaVir */
	int speech;
	speech = number_range(1,8);
	for ( victim = ch->in_room->people; victim != NULL; victim = v_next )
	{
	    v_next = victim->next_in_room;
	    if ( victim != ch && can_see( ch, victim ) && number_bits( 1 ) == 0 )
	        break;
	}
	if ( victim != NULL )
	{
	    if (speech == 1) 
	    {
		strcpy(buf,"Anyone got any food? I'm famished!");
		do_say(ch,buf);
	    }
	    if (speech == 2) do_emote(ch,"rubs his tummy hungrily.");
	    if (speech == 3) do_emote(ch,"looks around for any scraps of food.");
	    if (speech == 4)
	    {
		if(!IS_NPC(victim))
		    sprintf(buf,"Excuse me %s, have you got any spare food?",victim->name);
		else
		    sprintf(buf,"I wonder if %s has got any spare food?",victim->short_descr);
		do_say(ch,buf);
	    }

	    if (speech == 5)
	    {
		strcpy(buf,"If you're not hungry, drop that pie for me!");
		do_say(ch,buf);
	    }
	    if (speech == 6)
	    {
		if(!IS_NPC(victim))
		    sprintf(buf,"Do you have any food, %s?  Pleeeaaase?",victim->name);
		else
		    sprintf(buf,"I bet %s has lots of spare food!",victim->short_descr);
		do_say(ch,buf);
	    }
	    if (speech == 7)
	    {
		if(!IS_NPC(victim))
		    sprintf(buf,"Why won't you give me any food, %s?",victim->name);
		else
		    sprintf(buf,"Why won't you give me any food, %s?",victim->short_descr);
		do_say(ch,buf);
	    }
	    if (speech == 8)
	    {
		if(!IS_NPC(victim))
		    sprintf(buf,"I think i'll follow you around for a while, ok %s?",victim->name);
		else
		    sprintf(buf,"I bet %s has lots of food.",victim->short_descr);
		do_say(ch,buf);
		do_follow(ch,victim->name);
	    }
	}
	/*
        return TRUE;
	*/
   }

   do_drop(ch,"all");
   for ( object = ch->in_room->contents; object; object = object_next )
   {
      object_next = object->next_content;
      if ( !IS_SET(object->wear_flags, ITEM_TAKE) )
         continue;

      if (object == NULL) continue;

      if ( object->item_type == ITEM_FOOD
        || object->item_type == ITEM_TRASH
        || object->item_type == ITEM_CORPSE_NPC )
      {
         act( "$n picks $p up.", ch, object, NULL, TO_ROOM );
         obj_from_room( object );
         obj_to_char( object, ch );
         strcpy(buf,"Ah....foooood....goooood!");
         do_say(ch,buf);
         if (object->item_type == ITEM_CORPSE_NPC) do_get(ch,"all corpse");
         act( "$n eats $p.", ch, object, NULL, TO_ROOM );
         if (object != NULL) extract_obj(object);
	 if (number_percent() > 25) return TRUE;
         act( "$n sits down and curls up into a ball.", ch,  NULL, NULL, TO_ROOM );
         act( "You watch in amazement as a cocoon forms around $n.", ch,  NULL, NULL, TO_ROOM );
         obj=create_object(get_obj_index(30008),0);
         obj->value[0] = 30002;
         obj->timer = 1;
         obj_to_room(obj,ch->in_room);
         extract_char(ch,TRUE);
         return TRUE;
      }
   }
   return FALSE;
}

bool spec_gremlin_born( CHAR_DATA *ch )
{
   OBJ_DATA        *object;
   OBJ_DATA        *object_next;
   OBJ_DATA        *obj;
   CHAR_DATA	   *victim;
   EXIT_DATA	   *pexit;
   ROOM_INDEX_DATA *to_room;
   int		   door;
   char            buf [MAX_STRING_LENGTH];

   /* When they first appear, they try to equip themselves as best they can */
   if ( ch->max_move == 100 )
   {
         do_get(ch,"all");
         do_wear(ch,"all");
         do_drop(ch,"all");
   }
   ch->max_move = ch->max_move -1;
   if ( ch->max_move < 5 )
   {
	 strcpy(buf,"Alas, there is not enough food to go around...");
	 do_say(ch,buf);
         act( "$n falls to the floor and crumbles into dust.", ch, NULL, NULL, TO_ROOM );
         extract_char(ch,TRUE);
	 return TRUE;
   }
   else if (( ch->max_move < 35) && number_percent() > 95 )
         act( "$n's stomach growls with hunger.", ch, NULL, NULL, TO_ROOM );

   if ( !IS_AWAKE( ch ) )
      return FALSE;

   for ( object = ch->in_room->contents; object; object = object_next )
   {
      object_next = object->next_content;
      if ( !IS_SET(object->wear_flags, ITEM_TAKE) )
         continue;

      if (object == NULL) continue;

      if ( object->item_type == ITEM_FOOD
        || object->item_type == ITEM_TRASH
        || object->item_type == ITEM_CORPSE_NPC )
      {
         act( "$n picks $p up.", ch, object, NULL, TO_ROOM );
         obj_from_room( object );
         obj_to_char( object, ch );
         if (object->item_type == ITEM_CORPSE_NPC) do_get(ch,"all corpse");
         act( "$n eats $p.", ch, object, NULL, TO_ROOM );
	 if (object != NULL) extract_obj(object);
	 if (ch->max_move < 80) ch->max_move = ch->max_move + 20;
         do_wear(ch,"all");
         do_drop(ch,"all");
	 /* Increase the following if gremlins reproduce too fast, and 
	  * reduce it if they reproduce too slowly.  KaVir.
	  */
	 if (ch->max_move > 25 && number_percent() > 2)
	 {
	     if (ch->pIndexData->vnum == 30004)
             	 obj=create_object(get_obj_index(30009),0);
	     else
	     {
             	 obj=create_object(get_obj_index(30008),0);
             	 obj->value[0] = 30003;
             	 if (ch->pIndexData->vnum == 30003)
             	     obj->value[0] = 30004;
             	 obj->timer = number_range(8,10);
	     }
             act( "$n squats down and lays $p!", ch,  obj, NULL, TO_ROOM );
             obj_to_room(obj,ch->in_room);
	     if (number_percent() > 25)
	     	 ch->max_mana = ch->max_mana +50;
	 }
	 return TRUE;
      }
   }

   if ( ch->fighting != NULL )
	return spec_poison( ch );

   /* We'll give him 3 chances to find an open door */
   door = number_range(0,5);
   if (((pexit = ch->in_room->exit[door]) == NULL) || (to_room = pexit->to_room) == NULL)
	door = number_range(0,5);
   if (((pexit = ch->in_room->exit[door]) == NULL) || (to_room = pexit->to_room) == NULL)
	door = number_range(0,5);
   if (!(((pexit = ch->in_room->exit[door]) == NULL) || (to_room = pexit->to_room) == NULL))
   {
   	/* If the door is closed they'll have to open it */
   	if (IS_SET(pexit->exit_info, EX_CLOSED))
   	{
	    if (door == 0) do_open(ch,"north");
	    if (door == 1) do_open(ch,"east");
	    if (door == 2) do_open(ch,"south");
	    if (door == 3) do_open(ch,"west");
	    if (door == 4) do_open(ch,"up");
	    if (door == 5) do_open(ch,"down");
   	}
   	/* Now they know where they are going, they have to move */
   	move_char(ch,door);
/*	return FALSE; */
   }
   /* Now we check the room for someone to kill */
   for (victim = char_list; victim; victim = victim->next)
   {
      if ( victim->in_room != ch->in_room
	 || !victim->in_room
	 || victim == ch
	 || (!IS_NPC(victim) && IS_HERO(victim) && victim->hit < 0)
         || ((victim->name == ch->name) && (ch->max_move > 30))
         || ((victim->level > ch->level) && (ch->level < 12 ))
         || IS_IMMORTAL(victim) )
         continue;

      if (victim->in_room == ch->in_room)
      {
         if (victim->name == ch->name)
	 {
	     strcpy(buf,"Sorry brother, but I must eat you or I'll starve.");
	     do_say(ch,buf);
             do_kill(ch,"gremlin");
             do_kill(ch,"2.gremlin");
             return TRUE;
	 }
	 else
	 {
             do_kill(ch,victim->name);
             return TRUE;
	 }
         return TRUE;
      }
      continue;
   }
   return FALSE;
}

/* Spec_rogue, coded by Malice. */
bool spec_rogue( CHAR_DATA *ch )
{
/* To add to the life of mobs... they pickup and wear equipment */
    OBJ_DATA *object;
    OBJ_DATA *obj2;
    OBJ_DATA *object_next;
    char buf [MAX_STRING_LENGTH];

    if ( !IS_AWAKE( ch ) )
	return FALSE;

    for ( object = ch->in_room->contents; object; object = object_next )
    {
        object_next = object->next_content;
        if ( object == NULL )
	    continue;
	    
	if ( !IS_SET( object->wear_flags, ITEM_TAKE ) )
	    continue;

	if ( object->item_type == ITEM_CORPSE_NPC )
	    continue;
	    
	if ( ( object->item_type != ITEM_DRINK_CON
	    && object->item_type != ITEM_TRASH )
	    &&
	    
	   !(( IS_OBJ_STAT( object, ITEM_ANTI_EVIL   ) && IS_EVIL   ( ch ) ) ||
		 ( IS_OBJ_STAT( object, ITEM_ANTI_GOOD   ) && IS_GOOD   ( ch ) ) ||
		 ( IS_OBJ_STAT( object, ITEM_ANTI_NEUTRAL) && IS_NEUTRAL( ch ) ) ) )
		
	{
	    act( "$n picks up $p and examines it carefully.", ch, object, NULL, TO_ROOM );
	    obj_from_room( object );
	    obj_to_char( object, ch );
		/*Now compare it to what we already have*/
		for ( obj2 = ch->carrying; obj2; obj2 = obj2->next_content )
		{
		    if ( obj2->wear_loc != WEAR_NONE
			&& can_see_obj( ch, obj2 )
			&& object->item_type == obj2->item_type
			&& ( object->wear_flags & obj2->wear_flags & ~ITEM_TAKE) != 0 )
			break;
		}
		if (!obj2)
		{
		    switch (object->item_type)
		    {
			default:
			    strcpy(buf,"Hey, what a find!");
			    do_say(ch,buf);
			    break;
			case ITEM_FOOD:
			    strcpy(buf, "This looks like a tasty morsel!");
			    do_say(ch,buf);
			    do_eat(ch,object->name);
			    break;
			case ITEM_WAND:
			    strcpy(buf,"Wow, a magic wand!");
			    do_say(ch,buf);
			    wear_obj(ch,object,FALSE);
			    break;
			case ITEM_STAFF:
			    strcpy(buf,"Kewl, a magic staff!");
			    do_say(ch,buf);
			    wear_obj(ch,object,FALSE);
			    break;
			case ITEM_WEAPON:
			    strcpy(buf,"Hey, this looks like a nifty weapon!");
			    do_say(ch,buf);
			    wear_obj(ch,object,FALSE);
			    break;
			case ITEM_ARMOR:
			    strcpy(buf,"Oooh...a nice piece of armor!");
			    do_say(ch,buf);
			    wear_obj(ch,object,FALSE);
			    break;/*
			case ITEM_POTION:
			    strcpy(buf, "Great!  I was feeling a little thirsty!");
			    do_say(ch,buf);
			    act( "You quaff $p.", ch, object, NULL ,TO_CHAR );
			    act( "$n quaffs $p.", ch, object, NULL, TO_ROOM );
			    obj_cast_spell( object->value[1], object->level, ch, ch, NULL );
 			    obj_cast_spell( object->value[2], object->level, ch, ch, NULL );
			    obj_cast_spell( object->value[3], object->level, ch, ch, NULL );
			    extract_obj( object );
			    break;
			case ITEM_SCROLL:
			    strcpy(buf,"Hmmm I wonder what this says?");
			    do_say(ch,buf);
			    act( "You recite $p.", ch, object, NULL, TO_CHAR );
			    act( "$n recites $p.", ch, object, NULL, TO_ROOM );
			    obj_cast_spell( object->value[1], object->level, ch, NULL, object );
			    obj_cast_spell( object->value[2], object->level, ch, NULL, object );
			    obj_cast_spell( object->value[3], object->level, ch, NULL, object );
			    extract_obj( object );
			    break;*/
		    }
		    return TRUE;
		}
		
	    if ((object->level > obj2->level))
	    {
	    	strcpy(buf,"Now THIS looks like an improvement!");
		do_say(ch,buf);
	    	remove_obj(ch,obj2->wear_loc,TRUE);
	    	wear_obj(ch,object,FALSE);
	    }
	    else
	    {
	    	strcpy(buf,"I don't want this piece of junk!");
		do_say(ch,buf);
	    	act("You don't like the look of $p.",ch,object,NULL,TO_CHAR);
			do_drop(ch,object->name);
			do_sacrifice(ch,object->name);
		}
	    return TRUE;
	}
    }

    return FALSE;
}

/*
 * Rotains Clan Guardian Spec
 * Original Code by Malice
 */
/*
bool spec_clan_guardian(CHAR_DATA *ch)
{
   DESCRIPTOR_DATA       *d;
   CHAR_DATA             *victim;
   char                  buf[MAX_STRING_LENGTH];
   OBJ_DATA              *obj;


   if (ch->fighting) return FALSE;

   if (ch->in_room == NULL) return FALSE;
*/
   /*if (ch->in_room < 6645 && ch->in_room > 6657) break;*/
/*
   for (d = descriptor_list; d != NULL; d = d->next)
   {
       if (!IS_PLAYING(d)
	   || (victim = d->character) == NULL
           || IS_NPC(victim)
           || IS_IMMORTAL(victim)
	   || victim->in_room == NULL
           || victim->pcdata->chobj != NULL
           || victim->in_room->area != ch->in_room->area
           || victim->in_room == ch->in_room
	   || (IS_CLASS(victim, CLASS_VAMPIRE) && IS_SET(victim->special, SPC_INCONNU))
           || (victim->clan != NULL && !strcmp(victim->clan,"Manus Nigrum") ))
           {
             continue;
           }

      if ((obj = get_obj_carry(victim, "dlwr5"))
               && obj->pIndexData->vnum==6641)
      {
         return FALSE; 
      }
      else
      {
        if (ch->in_room != victim->in_room)
        {
           act("$n disappears in a haze of red!",victim,NULL,NULL,TO_ROOM);
           act("You disappear into a haze of red!",victim,NULL,NULL,TO_CHAR);

           char_from_room( victim );
           char_to_room(victim, ch->in_room);

           act("$n appears in a haze of red!",victim,NULL,NULL,TO_ROOM);
           act("You appear into a haze of red!",victim,NULL,NULL,TO_CHAR);
        }
     
        act("$n shouts at you \"You shall DIE!\"",ch,ch->long_descr,victim,TO_VICT);
        act("You let out a battlecry as you defend the clan headquaters!",ch,NULL,victim,TO_CHAR);
*//*
        spell_curse( 24 , 100 , ch , victim );
*//*
        if (victim->position <= POS_MORTAL && IS_HERO(victim) &&
	  ch->position == POS_STANDING)
        {
           char_from_room( victim );
           char_to_room(victim, get_room_index(ROOM_VNUM_ALTAR));
           continue;
        }
        sprintf( buf,"%s Is In Manus Nigrum Headquarters! Attack!\n\r",
victim->name); 
        do_shout( ch , buf);
      
        multi_hit( ch, victim, gsn_backstab); 

        return TRUE;

      }
   }
   return FALSE;
}
*/

bool spec_zombie_lord( CHAR_DATA *ch )
{
    char buf [MAX_STRING_LENGTH];
    OBJ_DATA		*obj;
    OBJ_DATA		*obj_content;
    OBJ_DATA		*obj_next;
    CHAR_DATA		*victim;
    MOB_INDEX_DATA	*pMobIndex;
    EXIT_DATA		*pexit;
    ROOM_INDEX_DATA	*to_room;
    int door;
    int consider 	= 4;
    bool north_ok 	= TRUE;
    bool east_ok 	= TRUE;
    bool south_ok 	= TRUE;
    bool west_ok 	= TRUE;
    bool up_ok 		= TRUE;
    bool down_ok 	= TRUE;
    int countup 	= 6;
    int option;

    if ( ch->position <= POS_SITTING )
    {
	do_stand(ch,"");
	return TRUE;
    }
    if ( (victim = ch->fighting) != NULL )
    {
	if (IS_AFFECTED(ch, AFF_FAERIE_FIRE))
	{
	    act("$n's eyes glow bright red for a moment.",ch,NULL,NULL,TO_ROOM);
	    spell_dispel_magic( skill_lookup( "dispel magic" ), ch->level, ch, ch );
	}
	else if (IS_AFFECTED(ch, AFF_POISON))
	{
	    act("$n's eyes glow bright blue for a moment.",ch,NULL,NULL,TO_ROOM);
	    spell_cure_poison( skill_lookup( "cure poison" ), ch->level, ch, ch );
	}
	else if (IS_AFFECTED(ch, AFF_BLIND))
	{
	    act("$n's eyes glow bright blue for a moment.",ch,NULL,NULL,TO_ROOM);
	    spell_cure_blindness( skill_lookup( "cure blindness" ), ch->level, ch, ch );
	}
	else if (IS_AFFECTED(ch, AFF_CURSE))
	{
	    act("$n's eyes glow bright purple for a moment.",ch,NULL,NULL,TO_ROOM);
	    spell_remove_curse( skill_lookup( "remove curse" ), ch->level, ch, ch );
	}
	else if (!IS_AFFECTED(ch, AFF_SANCTUARY))
	{
	    act("$n's eyes glow bright blue for a moment.",ch,NULL,NULL,TO_ROOM);
	    spell_sanctuary( skill_lookup( "sanctuary" ), ch->level, ch, ch );
	}
	else if (!is_affected(ch,skill_lookup("frenzy")) && number_percent() < 50)
	{
	    act("$n's eyes glow bright blue for a moment.",ch,NULL,NULL,TO_ROOM);
	    spell_frenzy( skill_lookup( "frenzy" ), ch->level, ch, ch );
	}
	else if (!is_affected(ch,skill_lookup("darkblessing")) && number_percent() < 50)
	{
	    act("$n's eyes glow bright blue for a moment.",ch,NULL,NULL,TO_ROOM);
	    spell_darkblessing( skill_lookup( "darkblessing" ), ch->level, ch, ch );
	}
	else if (!is_affected(ch,skill_lookup("bless")) && number_percent() < 50)
	{
	    act("$n's eyes glow bright blue for a moment.",ch,NULL,NULL,TO_ROOM);
	    spell_bless( skill_lookup( "bless" ), ch->level, ch, ch );
	}
	else if (!is_affected(ch,skill_lookup("stone skin")) && number_percent() < 50)
	{
	    act("$n's eyes glow bright blue for a moment.",ch,NULL,NULL,TO_ROOM);
	    spell_stone_skin( skill_lookup( "stone skin" ), ch->level, ch, ch );
	}
	else if (!is_affected(ch,skill_lookup("armor")) && number_percent() < 50)
	{
	    act("$n's eyes glow bright blue for a moment.",ch,NULL,NULL,TO_ROOM);
	    spell_armor( skill_lookup( "armor" ), ch->level, ch, ch );
	}
	else if (!is_affected(ch,skill_lookup("shield")) && number_percent() < 50)
	{
	    act("$n's eyes glow bright blue for a moment.",ch,NULL,NULL,TO_ROOM);
	    spell_shield( skill_lookup( "shield" ), ch->level, ch, ch );
	}
	else if (!IS_AFFECTED(victim, AFF_FAERIE_FIRE) && number_percent() < 50)
	{
	    act("$n's eyes glow bright red for a moment.",ch,NULL,NULL,TO_ROOM);
	    spell_faerie_fire( skill_lookup( "faerie fire" ), ch->level, ch, victim );
	}
	else if (!IS_AFFECTED(victim, AFF_BLIND) && number_percent() < 15)
	{
	    act("$n's eyes glow bright red for a moment.",ch,NULL,NULL,TO_ROOM);
	    spell_blindness( skill_lookup( "blindness" ), ch->level, ch, victim );
	}
	else if (!IS_AFFECTED(victim, AFF_CURSE) && number_percent() < 15)
	{
	    act("$n's eyes glow bright red for a moment.",ch,NULL,NULL,TO_ROOM);
	    spell_curse( skill_lookup( "curse" ), ch->level, ch, victim );
	}
	else if (ch->loc_hp[6] > 0)
	{
	    act("$n's eyes glow bright blue for a moment.",ch,NULL,NULL,TO_ROOM);
	    spell_clot( skill_lookup( "clot" ), ch->level, ch, ch );
	}
	else if (ch->hit < (ch->max_hit * 0.5) && number_percent() < 75)
	{
	    act("$n's eyes glow bright blue for a moment.",ch,NULL,NULL,TO_ROOM);
	    spell_heal( skill_lookup( "heal" ), ch->level, ch, ch );
	}
	else if (ch->hit < (ch->max_hit * 0.25) && number_percent() < 50)
	{
	    do_flee(ch,"");
	    ch->spectype = ZOMBIE_REST;
	}
	else if (ch->hit < (ch->max_hit * 0.1) && number_percent() < 25)
	{
	    act("$n's eyes glow bright green for a moment.",ch,NULL,NULL,TO_ROOM);
	    spell_teleport( skill_lookup( "teleport" ), ch->level, ch, ch );
	    ch->spectype = ZOMBIE_REST;
	}
	else
	{
	    switch( number_range(1,10) )
	    {
		default:
		    do_kick(ch,"");
		    break;
		case 1:
		    do_disarm(ch,"");
		    break;
		case 2:
		case 3:
		case 4:
		case 5:
		    act("$n's eyes glow bright red for a moment.",ch,NULL,NULL,TO_ROOM);
		    spell_dispel_magic( skill_lookup( "dispel magic" ), ch->level, ch, victim );
		    break;
		case 6:
		case 7:
		case 8:
		    act("$n's eyes glow bright red for a moment.",ch,NULL,NULL,TO_ROOM);
		    spell_harm( skill_lookup( "harm" ), ch->level, ch, victim );
		    break;
	    }
	}
	if ( (victim = ch->fighting) == NULL ) return TRUE;
	switch( number_percent() )
	{
	    default:
		break;
	    case 1:
		strcpy(buf,"Foolish mortal, you think you can kill what is already dead?");
		do_say(ch,buf);
		break;
	    case 2:
		if (IS_NPC(victim))
		    sprintf(buf,"I shall feast on your soul for this, %s",victim->short_descr);
		else
		    sprintf(buf,"I shall feast on your soul for this, %s",victim->name);
		do_say(ch,buf);
	    case 3:
		if (IS_NPC(victim))
		    sprintf(buf,"%s shall pay for his arrogance!",victim->short_descr);
		else
		    sprintf(buf,"%s shall pay for his arrogance!",victim->name);
		do_shout(ch,buf);
		break;
	    case 4:
		strcpy(buf,"This fight shall be your last!");
		do_say(ch,buf);
		break;
	}
	return TRUE;
    }

    if (ch->spectype != ZOMBIE_TRACKING && ch->spectype != ZOMBIE_REST)
    {
	if ((obj = get_obj_here(ch,"corpse")) != NULL)
	{
	    if ( ( pMobIndex = get_mob_index( obj->value[2] ) ) == NULL )
		return spec_rogue(ch);
	    victim = create_mobile( pMobIndex );
	    char_to_room(victim,ch->in_room);
	    sprintf(buf,"zombie %s",victim->name);
	    sprintf(buf,"The zombie of %s stands here.\n\r",victim->short_descr);
	    free_string(victim->long_descr);
	    victim->long_descr = str_dup(buf);
	    free_string(victim->name);
	    victim->name = str_dup(buf);
	    sprintf(buf,"the zombie of %s",victim->short_descr);
	    free_string(victim->short_descr);
	    victim->short_descr = str_dup(buf);
	    act("$n makes a few gestures over $p.",ch,obj,NULL,TO_ROOM);
	    act("$n clambers to $s feet.",victim,NULL,NULL,TO_ROOM);
	    free_string(victim->powertype);
	    victim->powertype = str_dup("zombie");
	    for ( obj_content = obj->contains; obj_content != NULL; obj_content = obj_next )
	    {
		obj_next = obj_content->next_content;
		obj_from_obj(obj_content);
		obj_to_char(obj_content,victim);
	    }
	    extract_obj(obj);
/*
	    victim->spec_fun = ch->spec_fun;
*/
	    do_wear(victim,"all");
	    strcpy(buf,"I shall spread the corruption!  The time of the Apocalypse is at hand!");
	    do_say(victim,buf);
	}
    	door = number_range(0,5);
	for ( door = 0; door <= 5; door++ )
	{
	    if (((pexit = ch->in_room->exit[door]) == NULL) || 
		(to_room = pexit->to_room) == NULL)
	    {
		switch (door)
		{
		    case DIR_NORTH: north_ok = FALSE; countup -= 1; break;
		    case DIR_SOUTH: south_ok = FALSE; countup -= 1; break;
		    case DIR_EAST:  east_ok  = FALSE; countup -= 1; break;
		    case DIR_WEST:  west_ok  = FALSE; countup -= 1; break;
		    case DIR_UP:    up_ok    = FALSE; countup -= 1; break;
		    case DIR_DOWN:  down_ok  = FALSE; countup -= 1; break;
		}
	    }
	}

	if (countup < 1)
	{
	    strcpy(buf,"Damn, I hate it when this happens!");
	    do_say(ch,buf);
	    do_recall(ch,"");
	    return TRUE;
	}

	for ( ; ; )
	{
	    option = number_range(0,5);
	    if (((pexit = ch->in_room->exit[option]) == NULL) || 
		(to_room = pexit->to_room) == NULL)
		continue;
	    if (countup > 1 && option == ch->specpower) continue;
	    if (IS_SET(pexit->exit_info, EX_CLOSED))
 	    {
	    	if (option == 0) do_open(ch,"north");
	    	if (option == 1) do_open(ch,"east");
	    	if (option == 2) do_open(ch,"south");
	    	if (option == 3) do_open(ch,"west");
	    	if (option == 4) do_open(ch,"up");
	    	if (option == 5) do_open(ch,"down");
   	    }
	    switch (option)
	    {
		default: break;
		case DIR_NORTH: ch->specpower = DIR_SOUTH; break;
		case DIR_SOUTH: ch->specpower = DIR_NORTH; break;
		case DIR_EAST:  ch->specpower = DIR_WEST;  break;
		case DIR_WEST:  ch->specpower = DIR_EAST;  break;
		case DIR_UP:    ch->specpower = DIR_DOWN;  break;
		case DIR_DOWN:  ch->specpower = DIR_UP;    break;
	    }
   	    move_char(ch,option);
	    break;
	}

    	for (victim = char_list; victim != NULL; victim = victim->next)
    	{
	    if (victim->in_room == NULL) continue;
    	    if ( victim->in_room != ch->in_room
	    || victim == ch
	    || (!IS_NPC(victim) && IS_HERO(victim) && victim->hit < 0)
            || IS_IMMORTAL(victim)
	    || is_safe(ch,victim)
	    || !IS_NPC(victim)
	    || !can_see(ch,victim) )
	    	continue;

	    if (IS_NPC(victim) && !str_cmp(victim->powertype,"zombie")) continue;
	    if (IS_NPC(victim) && victim->pIndexData->vnum == 30011) continue;
	    if (victim->in_room == ch->in_room)
      	    {
	    	act("$n examines $N closely, looking for $S weaknesses.",ch,NULL,victim,TO_NOTVICT);
	    	act("$n examines you closely, looking for your weaknesses.",ch,NULL,victim,TO_VICT);
	    	if      (victim->hit > (ch->hit*1.5)) consider -= 1;
	    	else if ((victim->hit*1.5) < ch->hit) consider += 1;
	    	if      (char_ac(victim)-50 > char_ac(ch)) consider -= 1;
	    	else if (char_ac(victim)+50 < char_ac(ch)) consider += 1;
	    	if      (char_hitroll(victim)+10 < char_hitroll(ch)) consider += 1;
	    	else if (char_hitroll(victim)-10 > char_hitroll(ch)) consider -= 1;
	    	if      (char_damroll(victim)+10 < char_damroll(ch)) consider += 1;
	    	else if (char_damroll(victim)-10 > char_damroll(ch)) consider -= 1;
	    	switch (consider)
	    	{
		    default: break;
		    case 8:
		    	strcpy(buf,"This shouldn't take more than a few seconds!");
			do_say(ch,buf);
		    	break;
		    case 7:
		    	strcpy(buf,"Ha! You are no match for me!");
			do_say(ch,buf);
		    	break;
		    case 6:
		    	strcpy(buf,"I should be able to win this one...");
			do_say(ch,buf);
		    	break;
		    case 5:
		    	strcpy(buf,"Hmmm, close match, but I think I have the edge.");
			do_say(ch,buf);
		    	break;
		    case 4:
		    	strcpy(buf,"I'd rather not, my toe hurts.");
			do_say(ch,buf);
		    	break;
		    case 3:
		    	strcpy(buf,"Hmmm, I'm not sure if I can win this one.");
			do_say(ch,buf);
		    	break;
		    case 2:
		    	strcpy(buf,"Heheh better not risk it...");
			do_say(ch,buf);
		    	break;
		    case 1:
		    	strcpy(buf,"I'd need a lot of luck...better not.");
			do_say(ch,buf);
		    	break;
		    case 0:
		    	strcpy(buf,"I think I'll give this one a miss!!!");
			do_say(ch,buf);
		    	break;
	    	}
		if (IS_IMMORTAL(victim)) continue;
	    	if (consider < 3) continue;
		if (victim->level > 1200 ) continue;
	    	do_kill(ch,victim->name);
            	return TRUE;
	    }
	}
    }

    switch ( ch->spectype )
    {
    default:
    case ZOMBIE_NOTHING:
	ch->spectype = number_range(1, 3);
	return spec_rogue(ch);
    case ZOMBIE_TRACKING:
/*
	if (strlen(ch->hunting) > 1)
	{
	    ch->spectype = number_range(1, 3);
	    return spec_rogue(ch);
	}
	if      (strlen(ch->in_room->track[0]) > 1)
	    strcpy(buf,ch->in_room->track[0]);
	else if (strlen(ch->in_room->track[1]) > 1)
	    strcpy(buf,ch->in_room->track[1]);
	else if (strlen(ch->in_room->track[2]) > 1)
	    strcpy(buf,ch->in_room->track[2]);
	else if (strlen(ch->in_room->track[3]) > 1)
	    strcpy(buf,ch->in_room->track[3]);
	else if (strlen(ch->in_room->track[4]) > 1)
	    strcpy(buf,ch->in_room->track[4]);
	else {ch->spectype = number_range(1, 3);return spec_rogue(ch);}
	do_hunt(ch,buf);
	ch->spectype = number_range(1, 3);
	return spec_rogue(ch);
*/
    case ZOMBIE_ANIMATE:
    case ZOMBIE_CAST:
	if (IS_AFFECTED(ch, AFF_FAERIE_FIRE))
	{
	    act("$n's eyes glow bright red for a moment.",ch,NULL,NULL,TO_ROOM);
	    spell_dispel_magic( skill_lookup( "dispel magic" ), ch->level, ch, ch );
	}
	else if (IS_AFFECTED(ch, AFF_POISON) && number_percent() < 75)
	{
	    act("$n's eyes glow bright blue for a moment.",ch,NULL,NULL,TO_ROOM);
	    spell_cure_poison( skill_lookup( "cure poison" ), ch->level, ch, ch );
	}
	else if (IS_AFFECTED(ch, AFF_BLIND) && number_percent() < 75)
	{
	    act("$n's eyes glow bright blue for a moment.",ch,NULL,NULL,TO_ROOM);
	    spell_cure_blindness( skill_lookup( "cure blindness" ), ch->level, ch, ch );
	}
	else if (IS_AFFECTED(ch, AFF_CURSE) && number_percent() < 75)
	{
	    act("$n's eyes glow bright purple for a moment.",ch,NULL,NULL,TO_ROOM);
	    spell_remove_curse( skill_lookup( "remove curse" ), ch->level, ch, ch );
	}
	else if (!IS_AFFECTED(ch, AFF_SANCTUARY) && number_percent() < 75)
	{
	    act("$n's eyes glow bright blue for a moment.",ch,NULL,NULL,TO_ROOM);
	    spell_sanctuary( skill_lookup( "sanctuary" ), ch->level, ch, ch );
	}
	else if (!is_affected(ch,skill_lookup("frenzy")) && number_percent() < 50)
	{
	    act("$n's eyes glow bright blue for a moment.",ch,NULL,NULL,TO_ROOM);
	    spell_frenzy( skill_lookup( "frenzy" ), ch->level, ch, ch );
	}
	else if (!is_affected(ch,skill_lookup("darkblessing")) && number_percent() < 50)
	{
	    act("$n's eyes glow bright blue for a moment.",ch,NULL,NULL,TO_ROOM);
	    spell_darkblessing( skill_lookup( "darkblessing" ), ch->level, ch, ch );
	}
	else if (!is_affected(ch,skill_lookup("bless")) && number_percent() < 50)
	{
	    act("$n's eyes glow bright blue for a moment.",ch,NULL,NULL,TO_ROOM);
	    spell_bless( skill_lookup( "bless" ), ch->level, ch, ch );
	}
	else if (!is_affected(ch,skill_lookup("stone skin")) && number_percent() < 50)
	{
	    act("$n's eyes glow bright blue for a moment.",ch,NULL,NULL,TO_ROOM);
	    spell_stone_skin( skill_lookup( "stone skin" ), ch->level, ch, ch );
	}
	else if (!is_affected(ch,skill_lookup("armor")) && number_percent() < 50)
	{
	    act("$n's eyes glow bright blue for a moment.",ch,NULL,NULL,TO_ROOM);
	    spell_armor( skill_lookup( "armor" ), ch->level, ch, ch );
	}
	else if (!is_affected(ch,skill_lookup("shield")) && number_percent() < 50)
	{
	    act("$n's eyes glow bright blue for a moment.",ch,NULL,NULL,TO_ROOM);
	    spell_shield( skill_lookup( "shield" ), ch->level, ch, ch );
	}
	else if (ch->loc_hp[6] > 0)
	{
	    act("$n's eyes glow bright blue for a moment.",ch,NULL,NULL,TO_ROOM);
	    spell_clot( skill_lookup( "clot" ), ch->level, ch, ch );
	}
	else if (ch->hit < ch->max_hit)
	{
	    act("$n's eyes glow bright blue for a moment.",ch,NULL,NULL,TO_ROOM);
	    spell_heal( skill_lookup( "heal" ), ch->level, ch, ch );
	}
	else if (!is_affected(ch,skill_lookup("frenzy")))
	{
	    act("$n's eyes glow bright blue for a moment.",ch,NULL,NULL,TO_ROOM);
	    spell_frenzy( skill_lookup( "frenzy" ), ch->level, ch, ch );
	}
	else if (!is_affected(ch,skill_lookup("darkblessing")))
	{
	    act("$n's eyes glow bright blue for a moment.",ch,NULL,NULL,TO_ROOM);
	    spell_darkblessing( skill_lookup( "darkblessing" ), ch->level, ch, ch );
	}
	else if (!is_affected(ch,skill_lookup("bless")))
	{
	    act("$n's eyes glow bright blue for a moment.",ch,NULL,NULL,TO_ROOM);
	    spell_bless( skill_lookup( "bless" ), ch->level, ch, ch );
	}
	else if (!is_affected(ch,skill_lookup("stone skin")))
	{
	    act("$n's eyes glow bright blue for a moment.",ch,NULL,NULL,TO_ROOM);
	    spell_stone_skin( skill_lookup( "stone skin" ), ch->level, ch, ch );
	}
	else if (!is_affected(ch,skill_lookup("armor")))
	{
	    act("$n's eyes glow bright blue for a moment.",ch,NULL,NULL,TO_ROOM);
	    spell_armor( skill_lookup( "armor" ), ch->level, ch, ch );
	}
	else if (!is_affected(ch,skill_lookup("shield")))
	{
	    act("$n's eyes glow bright blue for a moment.",ch,NULL,NULL,TO_ROOM);
	    spell_shield( skill_lookup( "shield" ), ch->level, ch, ch );
	}
	else ch->spectype = 0;
	if (ch->hit < (ch->max_hit*0.25)) ch->spectype = ZOMBIE_REST;
	return TRUE;
    case ZOMBIE_REST:
	if (ch->hit >= ch->max_hit)
	{do_stand(ch,"");ch->spectype = 0;return TRUE;}
	if (IS_AFFECTED(ch, AFF_CURSE))
	{
	    act("$n's eyes glow bright purple for a moment.",ch,NULL,NULL,TO_ROOM);
	    spell_remove_curse( skill_lookup( "remove curse" ), ch->level, ch, ch );
	    return TRUE;
	}
	if (ch->in_room->vnum != ROOM_VNUM_ALTAR) do_recall(ch,"");
	if (ch->in_room->vnum == ROOM_VNUM_TEMPLE) do_north(ch,"");
	if (ch->position == POS_STANDING) do_rest(ch,"");
	if (ch->hit < ch->max_hit)
	{
	    act("$n's eyes glow bright blue for a moment.",ch,NULL,NULL,TO_ROOM);
	    spell_heal( skill_lookup( "heal" ), ch->level, ch, ch );
	}
	return TRUE;
    }
    return FALSE;
}

bool spec_dog( CHAR_DATA *ch )
{
    OBJ_DATA *obj;
    OBJ_DATA *o_next;
    CHAR_DATA *vch;
    CHAR_DATA *vch_next;
    EXIT_DATA		*pexit;
    ROOM_INDEX_DATA	*to_room;
    int door;
    bool north_ok 	= TRUE;
    bool east_ok 	= TRUE;
    bool south_ok 	= TRUE;
    bool west_ok 	= TRUE;
    bool up_ok 		= TRUE;
    bool down_ok 	= TRUE;
    int countup 	= 6;
    int option;
    int random = number_range(1,5);

    if ( !IS_AWAKE(ch) )
    {
	if (random <= 2)
	    do_wake(ch,"");
	return TRUE;
    }
    else if (ch->position < POS_STANDING)
    {
	if (random <= 2)
	    do_stand(ch,"");
	else
	{
	    if (ch->in_room->vnum == 29107 && number_range(1,4) <= 2)
		act("$n eats some dog food from $s food bowl",ch,NULL,NULL,TO_ROOM);
	    else if (ch->in_room->vnum == 29107)
		act("$n drinks some water from $s water bowl",ch,NULL,NULL,TO_ROOM);
	}
	return TRUE;
    }

    if (ch->in_room == NULL) return TRUE;

    if (ch->in_room->vnum == 29104 && random <= 2)
    {
	if ( (random = number_range(1,5)) == 1)
	{
	    act("$n curls up in front of the fire.",ch,NULL,NULL,TO_ROOM);
	    do_sleep(ch,"");
	}
	else if (random == 2)
	    act("$n starts scratching up the carpet.",ch,NULL,NULL,TO_ROOM);
	else if (random == 3)
	    act("$n barks loudly.",ch,NULL,NULL,TO_ROOM);
	else if (random == 4)
	{
	    act("$n jumps onto the couch.",ch,NULL,NULL,TO_ROOM);
	    do_sit(ch,"");
	}
	else if (random == 5)
	    act("$n tries to crawl under a chair.",ch,NULL,NULL,TO_ROOM);
	return TRUE;
    }
    else if (ch->in_room->vnum == 29104 && random <= 2)
    {
	if ( (random = number_range(1,5)) == 1)
	{
	    act("$n curls up under the dining table.",ch,NULL,NULL,TO_ROOM);
	    do_sleep(ch,"");
	}
	else if (random == 2)
	    act("$n starts scratching up the carpet.",ch,NULL,NULL,TO_ROOM);
	else if (random == 3)
	    act("$n barks loudly.",ch,NULL,NULL,TO_ROOM);
	else if (random == 4)
	{
	    act("$n jumps onto a chair.",ch,NULL,NULL,TO_ROOM);
	    do_sit(ch,"");
	}
	else if (random == 5)
	    act("$n tries to crawl under a chair.",ch,NULL,NULL,TO_ROOM);
	return TRUE;
    }
    else if (ch->in_room->vnum == 29113 && random <= 2)
    {
	if ( (random = number_range(1,5)) == 1)
	    act("$n starts scratching up the carpet.",ch,NULL,NULL,TO_ROOM);
	else if (random == 2)
	    act("$n tries to climb into the bath.",ch,NULL,NULL,TO_ROOM);
	else if (random == 3)
	    act("$n barks loudly.",ch,NULL,NULL,TO_ROOM);
	else if (random == 4)
	{
	    act("$n sits behind the bathroom door.",ch,NULL,NULL,TO_ROOM);
	    do_sit(ch,"");
	}
	else if (random == 5)
	    act("$n tries to squeeze behind the sink.",ch,NULL,NULL,TO_ROOM);
	return TRUE;
    }
    else if (ch->in_room->vnum == 29107 && random <= 2)
    {
	if ( (random = number_range(1,5)) == 1)
	    act("$n sniffs around for food on the kitchen floor.",ch,NULL,NULL,TO_ROOM);
	else if (random == 2)
	    act("$n looks up hungrilly at the cupboard.",ch,NULL,NULL,TO_ROOM);
	else if (random == 3)
	    act("$n barks loudly.",ch,NULL,NULL,TO_ROOM);
	else if (random == 4)
	{
	    act("$n walks over to $s food bowl.",ch,NULL,NULL,TO_ROOM);
	    do_sit(ch,"");
	}
	else if (random == 5)
	    act("$n looks out the back door for cats to chase.",ch,NULL,NULL,TO_ROOM);
	return TRUE;
    }
    else if ((ch->in_room->vnum == 29100 || ch->in_room->vnum == 29101 || 
	ch->in_room->vnum == 29117) && random <= 2)
    {
	if ( (random = number_range(1,5)) == 1)
	    act("$n sniffs a flower.",ch,NULL,NULL,TO_ROOM);
	else if (random == 2)
	    act("$n rolls around on the grass.",ch,NULL,NULL,TO_ROOM);
	else if (random == 3)
	    act("$n tries to eat a blade of grass.",ch,NULL,NULL,TO_ROOM);
	else if (random == 4)
	    act("$n pounces on a grasshopper.",ch,NULL,NULL,TO_ROOM);
	else if (random == 5)
	    act("$n sniffs the air and growls playfully.",ch,NULL,NULL,TO_ROOM);
	return TRUE;
    }
    if (random <= 2)
    {
	if ( (random = number_range(1,5)) == 1)
	    act("$n sniffs the carpet.",ch,NULL,NULL,TO_ROOM);
	else if (random == 2)
	    act("$n barks loudly.",ch,NULL,NULL,TO_ROOM);
	else if (random == 3)
	    do_sit(ch,"");
	return TRUE;
    }

    if ( number_range(1,5) <= 3 )
    {
    	door = number_range(0,5);
	for ( door = 0; door <= 5; door++ )
	{
	    if (((pexit = ch->in_room->exit[door]) == NULL) || 
		(to_room = pexit->to_room) == NULL)
	    {
		switch (door)
		{
		    case DIR_NORTH: north_ok = FALSE; countup -= 1; break;
		    case DIR_SOUTH: south_ok = FALSE; countup -= 1; break;
		    case DIR_EAST:  east_ok  = FALSE; countup -= 1; break;
		    case DIR_WEST:  west_ok  = FALSE; countup -= 1; break;
		    case DIR_UP:    up_ok    = FALSE; countup -= 1; break;
		    case DIR_DOWN:  down_ok  = FALSE; countup -= 1; break;
		}
	    }
	}

	if (countup < 1)
	{
	    if (number_percent() < 80)
		act("$n barks loudly",ch,NULL,NULL,TO_ROOM);
	    else
		do_sleep(ch,"");
	    return TRUE;
	}

	for ( ; ; )
	{
	    option = number_range(0,5);
	    if (((pexit = ch->in_room->exit[option]) == NULL) || 
		(to_room = pexit->to_room) == NULL)
		continue;
	    if (countup > 1 && option == ch->specpower) continue;
	    if (IS_SET(pexit->exit_info, EX_CLOSED))
 	    {
		if (option == 0)
		    act("$n scratches at the north door.",ch,NULL,NULL,TO_ROOM);
		if (option == 1)
		    act("$n scratches at the east door.",ch,NULL,NULL,TO_ROOM);
		if (option == 2)
		    act("$n scratches at the south door.",ch,NULL,NULL,TO_ROOM);
		if (option == 3)
		    act("$n scratches at the west door.",ch,NULL,NULL,TO_ROOM);
		if (option == 4)
		    act("$n scratches at the upward door.",ch,NULL,NULL,TO_ROOM);
		if (option == 5)
		    act("$n scratches at the downward door.",ch,NULL,NULL,TO_ROOM);
		act("$n barks loudly at the door.",ch,NULL,NULL,TO_ROOM);
		for ( vch = char_list; vch != NULL; vch = vch_next )
		{
		    vch_next	= vch->next;
		    if ( vch->in_room == NULL || IS_NPC(vch) )
			continue;
		    if ( vch->in_room == ch->in_room )
			continue;
		    if ( vch->in_room->area == ch->in_room->area )
			send_to_char("You hear the sound of a dog barking nearby.\n\r",vch);
		}
		return TRUE;
   	    }
	    switch (option)
	    {
		default: break;
		case DIR_NORTH: ch->specpower = DIR_SOUTH; break;
		case DIR_SOUTH: ch->specpower = DIR_NORTH; break;
		case DIR_EAST:  ch->specpower = DIR_WEST;  break;
		case DIR_WEST:  ch->specpower = DIR_EAST;  break;
		case DIR_UP:    ch->specpower = DIR_DOWN;  break;
		case DIR_DOWN:  ch->specpower = DIR_UP;    break;
	    }
   	    move_char(ch,option);
	    break;
	}
    }

    for ( obj = ch->in_room->contents; obj != NULL; obj = o_next )
    {
	o_next = obj->next_content;
	if (number_range(1,2) == 1) continue;
	act( "$n sniffs $p.", ch, obj, NULL, TO_ROOM );
	if ( obj->item_type == ITEM_FOOD )
	{
	    act( "$n eats $p.", ch, obj, NULL, TO_ROOM );
	    extract_obj(obj);
	}
	return TRUE;
    }
    return TRUE;
}


/*
 * Special Functions Table.     OLC
 */
const   struct  spec_type       spec_table      [ ] =
{
    /*
     * Special function commands.
     */
    { "spec_breath_any",        spec_breath_any         },
    { "spec_breath_acid",       spec_breath_acid        },
    { "spec_breath_fire",       spec_breath_fire        },
    { "spec_breath_frost",      spec_breath_frost       },
    { "spec_breath_gas",        spec_breath_gas         },
    { "spec_breath_lightning",  spec_breath_lightning   },
    { "spec_cast_adept",        spec_cast_adept         },
    { "spec_cast_cleric",       spec_cast_cleric        },
    { "spec_cast_judge",        spec_cast_judge         },
    { "spec_cast_mage",         spec_cast_mage          },
    { "spec_cast_undead",       spec_cast_undead        },
    { "spec_fido",              spec_fido               },
    { "spec_guard",             spec_guard              },
    { "spec_janitor",           spec_janitor            },
    { "spec_mayor",             spec_mayor              },
    { "spec_poison",            spec_poison             },
    { "spec_thief",             spec_thief              },
	{ "spec_eater",	spec_eater },
	{ "spec_gremlin_original", spec_gremlin_original },
	{ "spec_gremlin_born", spec_gremlin_born },
	{ "spec_rogue", spec_rogue },
	{ "spec_zombie_lord", spec_zombie_lord },
	{ "spec_guard_werewolf",	spec_guard_werewolf },
	{ "spec_guard_vampire",	spec_guard_vampire },
/*	{ "spec_guard_mage",	spec_guard_mage },*/
	{ "spec_guard_demon",	spec_guard_demon },
	{ "spec_guard_drow",	spec_guard_drow },
	{ "spec_guard_ninja",	spec_guard_ninja },
	{ "spec_guard_monk",	spec_guard_monk },

    /*
     * End of list.
     */
    { "",                       0       }
};


/*****************************************************************************
 Name:          spec_lookup
 Purpose:       Given a name, return the appropriate spec fun.
 Called by:     do_mset(act_wiz.c) load_specials,reset_area(db.c)
 ****************************************************************************/
SPEC_FUN *spec_lookup( const char *name )       /* OLC */
{   
    int cmd;

    for ( cmd = 0; *spec_table[cmd].spec_name; cmd++ )  /* OLC 1.1b */
        if ( !str_cmp( name, spec_table[cmd].spec_name ) )
            return spec_table[cmd].spec_fun;
 
    return 0;
}

/*****************************************************************************
 Name:          spec_string
 Purpose:       Given a function, return the appropriate name.
 Called by:     <???>
 ****************************************************************************/
char *spec_string( SPEC_FUN *fun )      /* OLC */
{
    int cmd;

    for ( cmd = 0; *spec_table[cmd].spec_fun; cmd++ )   /* OLC 1.1b */
        if ( fun == spec_table[cmd].spec_fun )
            return spec_table[cmd].spec_name;
    
    return 0;
}
 




 *  File: string.c                                                         *
 *                                                                         *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 *                                                                         *
 *  This code was freely distributed with the The Isles 1.1 source code,   *
 *  and has been used here for OLC - OLC would not be what it is without   *
 *  all the previous coders who released their source code.                *
 *                                                                         *
 ***************************************************************************/


#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"


/*****************************************************************************
 Name:		string_append
 Purpose:	Clears string and puts player into editing mode.
 Called by:	none
 ****************************************************************************/
void string_edit( CHAR_DATA *ch, char **pString )
{
    send_to_char( "#3-========- #7Entering EDIT Mode#3 -=========-\n\r",
ch );
    send_to_char( "#7    Type /h on a new line for help\n\r", ch );
    send_to_char( "#7 Terminate with a ~ or @ on a blank line.\n\r", ch );
    send_to_char( "#3-=======================================-\n\r", ch );

    if ( *pString == NULL )
    {
        *pString = str_dup( "" );
    }
    else
    {
        **pString = '\0';
    }

    ch->desc->pString = pString;

    return;
}



/*****************************************************************************
 Name:		string_append
 Purpose:	Puts player into append mode for given string.
 Called by:	(many)olc_act.c
 ****************************************************************************/
void string_append( CHAR_DATA *ch, char **pString )
{
    send_to_char( "#3-=======- #7Entering APPEND Mode #3-========-\n\r",
ch );
    send_to_char( "#7    Type /h on a new line for help\n\r", ch );
    send_to_char( "#7 Terminate with a ~ or @ on a blank line.\n\r", ch );
    send_to_char( "#3-=======================================-\n\r", ch );

    if ( *pString == NULL )
    {
        *pString = str_dup( "" );
    }
    send_to_char( *pString, ch );
    
    if ( *(*pString + strlen( *pString ) - 1) != '\r' )
    send_to_char( "\n\r", ch );

    ch->desc->pString = pString;

    return;
}



/*****************************************************************************
 Name:		string_replace
 Purpose:	Substitutes one string for another.
 Called by:	string_add(string.c) (aedit_builder)olc_act.c.
 ****************************************************************************/
char * string_replace( char * orig, char * old, char * new )
{
    char xbuf[MAX_STRING_LENGTH];
    int i;

    xbuf[0] = '\0';
    strcpy( xbuf, orig );
    if ( strstr( orig, old ) != NULL )
    {
        i = strlen( orig ) - strlen( strstr( orig, old ) );
        xbuf[i] = '\0';
        strcat( xbuf, new );
        strcat( xbuf, &orig[i+strlen( old )] );
        free_string( orig );
    }

    return str_dup( xbuf );
}


/* OLC 1.1b */
/*****************************************************************************
 Name:		string_add
 Purpose:	Interpreter for string editing.
 Called by:	game_loop_xxxx(comm.c).
 ****************************************************************************/
void string_add( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];

    /*
     * Thanks to James Seng
     */
    smash_tilde( argument );

    if ( *argument == '/' )
    {
        char arg1 [MAX_INPUT_LENGTH];
        char arg2 [MAX_INPUT_LENGTH];
        char arg3 [MAX_INPUT_LENGTH];

        argument = one_argument( argument, arg1 );
        argument = first_arg( argument, arg2, FALSE );
        argument = first_arg( argument, arg3, FALSE );

        if ( !str_cmp( arg1, "/c" ) )
        {
            send_to_char( "String cleared.\n\r", ch );
            **ch->desc->pString = '\0';
            return;
        }

        if ( !str_cmp( arg1, "/s" ) )
        {
            send_to_char( "String so far:\n\r", ch );
            send_to_char( *ch->desc->pString, ch );
            return;
        }

        if ( !str_cmp( arg1, "/r" ) )
        {
            if ( arg2[0] == '\0' )
            {
                send_to_char(
                    "usage:  /r \"old string\" \"new string\"\n\r", ch );
                return;
            }

            *ch->desc->pString =
                string_replace( *ch->desc->pString, arg2, arg3 );
            sprintf( buf, "'%s' replaced with '%s'.\n\r", arg2, arg3 );
            send_to_char( buf, ch );
            return;
        }

        if ( !str_cmp( arg1, "/f" ) )
        {
            *ch->desc->pString = format_string( *ch->desc->pString );
            send_to_char( "String formatted.\n\r", ch );
            return;
        }
        
        if ( !str_cmp( arg1, "/h" ) )
        {
            send_to_char( "Sedit help (commands on blank line):   \n\r", ch );
            send_to_char( "/r 'old' 'new'   - replace a substring \n\r",
ch );
            send_to_char( "                   (requires '', \"\") \n\r", ch );
            send_to_char( "/h               - get help (this info)\n\r",
ch );
            send_to_char( "/s               - show string so far  \n\r",
ch );
            send_to_char( "/f               - (word wrap) string  \n\r",
ch );
            send_to_char( "/c               - clear string so far \n\r",
ch );
            send_to_char( "@                - end string          \n\r", ch );
            return;
        }
            

        send_to_char( "SEdit:  Invalid command.\n\r", ch );
        return;
    }

    if ( *argument == '@' )
    {
        ch->desc->pString = NULL;
        return;
    }

    /*
     * Truncate strings to MAX_STRING_LENGTH.
     * --------------------------------------
     */
    if ( strlen( buf ) + strlen( argument ) >= ( MAX_STRING_LENGTH - 4 ) )
    {
        send_to_char( "String too long, last line skipped.\n\r", ch );

	/* Force character out of editing mode. */
        ch->desc->pString = NULL;
        return;
    }

    strcpy( buf, *ch->desc->pString );
    strcat( buf, argument );
    strcat( buf, "\n\r" );
    free_string( *ch->desc->pString );
    *ch->desc->pString = str_dup( buf );
    return;
}



/*
 *  Thanks to Kalgen for the new procedure (no more bug!)
 *  Original wordwrap() written by Surreality.
 */
/*****************************************************************************
 Name:		format_string
 Purpose:	Special string formating and word-wrapping.
 Called by:	string_add(string.c) (many)olc_act.c
 ****************************************************************************/
char *format_string( char *oldstring /*, bool fSpace */)
{
  char xbuf[MAX_STRING_LENGTH];
  char xbuf2[MAX_STRING_LENGTH];
  char *rdesc;
  int i=0;
  bool cap=TRUE;
  
  xbuf[0]=xbuf2[0]=0;
  
  i=0;
  
  if ( strlen(oldstring) >= (MAX_STRING_LENGTH - 4) )	/* OLC 1.1b */
  {
     bug( "String to format_string() longer than MAX_STRING_LENGTH.", 0 );
     return (oldstring);
  }

  for (rdesc = oldstring; *rdesc; rdesc++)
  {
    if (*rdesc=='\n')
    {
      if (xbuf[i-1] != ' ')
      {
        xbuf[i]=' ';
        i++;
      }
    }
    else if (*rdesc=='\r') ;
    else if (*rdesc==' ')
    {
      if (xbuf[i-1] != ' ')
      {
        xbuf[i]=' ';
        i++;
      }
    }
    else if (*rdesc==')')
    {
      if (xbuf[i-1]==' ' && xbuf[i-2]==' ' && 
          (xbuf[i-3]=='.' || xbuf[i-3]=='?' || xbuf[i-3]=='!'))
      {
        xbuf[i-2]=*rdesc;
        xbuf[i-1]=' ';
        xbuf[i]=' ';
        i++;
      }
      else
      {
        xbuf[i]=*rdesc;
        i++;
      }
    }
    else if (*rdesc=='.' || *rdesc=='?' || *rdesc=='!') {
      if (xbuf[i-1]==' ' && xbuf[i-2]==' ' && 
          (xbuf[i-3]=='.' || xbuf[i-3]=='?' || xbuf[i-3]=='!')) {
        xbuf[i-2]=*rdesc;
        if (*(rdesc+1) != '\"')
        {
          xbuf[i-1]=' ';
          xbuf[i]=' ';
          i++;
        }
        else
        {
          xbuf[i-1]='\"';
          xbuf[i]=' ';
          xbuf[i+1]=' ';
          i+=2;
          rdesc++;
        }
      }
      else
      {
        xbuf[i]=*rdesc;
        if (*(rdesc+1) != '\"')
        {
          xbuf[i+1]=' ';
          xbuf[i+2]=' ';
          i += 3;
        }
        else
        {
          xbuf[i+1]='\"';
          xbuf[i+2]=' ';
          xbuf[i+3]=' ';
          i += 4;
          rdesc++;
        }
      }
      cap = TRUE;
    }
    else
    {
      xbuf[i]=*rdesc;
      if ( cap )
        {
          cap = FALSE;
          xbuf[i] = UPPER( xbuf[i] );
        }
      i++;
    }
  }
  xbuf[i]=0;
  strcpy(xbuf2,xbuf);
  
  rdesc=xbuf2;
  
  xbuf[0]=0;
  
  for ( ; ; )
  {
    for (i=0; i<77; i++)
    {
      if (!*(rdesc+i)) break;
    }
    if (i<77)
    {
      break;
    }
    for (i=(xbuf[0]?76:73) ; i ; i--)
    {
      if (*(rdesc+i)==' ') break;
    }
    if (i)
    {
      *(rdesc+i)=0;
      strcat(xbuf,rdesc);
      strcat(xbuf,"\n\r");
      rdesc += i+1;
      while (*rdesc == ' ') rdesc++;
    }
    else
    {
      bug ("No spaces", 0);
      *(rdesc+75)=0;
      strcat(xbuf,rdesc);
      strcat(xbuf,"-\n\r");
      rdesc += 76;
    }
  }
  while (*(rdesc+i) && (*(rdesc+i)==' '||
                        *(rdesc+i)=='\n'||
                        *(rdesc+i)=='\r'))
    i--;
  *(rdesc+i+1)=0;
  strcat(xbuf,rdesc);
  if (xbuf[strlen(xbuf)-2] != '\n')
    strcat(xbuf,"\n\r");

  free_string(oldstring);
  return(str_dup(xbuf));
}



/*
 * Used above in string_add.  Because this function does not
 * modify case if fCase is FALSE and because it understands
 * parenthesis, it would probably make a nice replacement
 * for one_argument.
 */
/*****************************************************************************
 Name:		first_arg
 Purpose:	Pick off one argument from a string and return the rest.
 		Understands quates, parenthesis (barring ) ('s) and
 		percentages.
 Called by:	string_add(string.c)
 ****************************************************************************/
char *first_arg( char *argument, char *arg_first, bool fCase )
{
    char cEnd;

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

    cEnd = ' ';
    if ( *argument == '\'' || *argument == '"'
      || *argument == '%'  || *argument == '(' )
    {
        if ( *argument == '(' )
        {
            cEnd = ')';
            argument++;
        }
        else cEnd = *argument++;
    }

    while ( *argument != '\0' )
    {
	if ( *argument == cEnd )
	{
	    argument++;
	    break;
	}
    if ( fCase ) *arg_first = LOWER(*argument);
            else *arg_first = *argument;
	arg_first++;
	argument++;
    }
    *arg_first = '\0';

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

    return argument;
}




/*
 * Used in olc_act.c for aedit_builders.
 */
char * string_unpad( char * argument )
{
    char buf[MAX_STRING_LENGTH];
    char *s;

    s = argument;

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

    strcpy( buf, s );
    s = buf;

    if ( *s != '\0' )
    {
        while ( *s != '\0' )
            s++;
        s--;

        while( *s == ' ' )
            s--;
        s++;
        *s = '\0';
    }

    free_string( argument );
    return str_dup( buf );
}



/*
 * Same as capitalize but changes the pointer's data.
 * Used in olc_act.c in aedit_builder.
 */
char * string_proper( char * argument )
{
    char *s;

    s = argument;

    while ( *s != '\0' )
    {
        if ( *s != ' ' )
        {
            *s = UPPER(*s);
            while ( *s != ' ' && *s != '\0' )
                s++;
        }
        else
        {
            s++;
        }
    }

    return argument;
}



/*
 * Returns an all-caps string.		OLC 1.1b
 */
char* all_capitalize( const char *str )
{
    static char strcap [ MAX_STRING_LENGTH ];
           int  i;
    for ( i = 0; str[i] != '\0'; i++ )
	strcap[i] = UPPER( str[i] );
    strcap[i] = '\0';
    return strcap;
}




*
 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
 *                                                                         *
 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
 *  Chastain, Michael Quan, and Mitchell Tse.                              *
 *                                                                         *
 *  In order to use any part of this Merc Diku Mud, you must comply with   *
 *  both the original Diku license in 'license.doc' as well the Merc       *
 *  license in 'license.txt'.  In particular, you may not remove either of *
 *  these copyright notices.                                               *
 *                                                                         *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 ***************************************************************************/

#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"



/*
 * Local functions.
 */
int	hit_gain	args( ( CHAR_DATA *ch ) );
int	mana_gain	args( ( CHAR_DATA *ch ) );
int	move_gain	args( ( CHAR_DATA *ch ) );
void	mobile_update	args( ( void ) );
void	weather_update	args( ( void ) );
void    room_update     args( ( void ) );
void	char_update	args( ( void ) );
void	obj_update	args( ( void ) );
void	aggr_update	args( ( void ) );
void    ww_update       args( ( void ) );
void    embrace_update  args((void));

void gain_exp( CHAR_DATA *ch, int gain )
{
    CHAR_DATA *mount = NULL;
    CHAR_DATA *master = NULL;

    if ( IS_NPC(ch) && (mount = ch->mount) != NULL && !IS_NPC(mount))
    {
	if ( (master = ch->master) == NULL || master != mount )
	    mount->exp += gain;
    }

    if ( (( get_age(ch) - 17) * 2 ) < 5 )
      gain *= 3;

    if ( !IS_NPC(ch) && !IS_IMMORTAL(ch) )
	ch->exp += gain;
    return;
}



/*
 * Regeneration stuff.
 */
int hit_gain( CHAR_DATA *ch )
{
    int gain;
    int conamount;

    if ( IS_NPC(ch) )
    {
	gain = ch->level;
    }
    else
    {
	if (IS_CLASS(ch, CLASS_VAMPIRE) && ch->position != POS_MEDITATING) return 0;
	gain = number_range( 10, 20 );

	if ((conamount = (get_curr_con(ch)+1)) > 1)
	{
	    switch ( ch->position )
	    {
		case POS_MEDITATING: 
		if (IS_CLASS(ch, CLASS_VAMPIRE))
	        {
		gain *= conamount * 1.5;
	        }
	        else
		gain *= conamount * 3;	break;
		case POS_SLEEPING:   gain *= conamount;		break;
		case POS_RESTING:    gain *= conamount * 0.5;	break;
	    }
	}

	if ( ch->pcdata->condition[COND_FULL]   == 0 && !IS_HERO(ch) )
	    gain *= 0.5;

	if ( ch->pcdata->condition[COND_THIRST] == 0 && !IS_HERO(ch) )
	    gain *= 0.5;

    }

    if ( IS_AFFECTED(ch, AFF_POISON))
	gain *= 0.25;
    if ( IS_AFFECTED(ch, AFF_FLAMING))
	gain *= 0.01;


    return UMIN(gain, ch->max_hit - ch->hit);
}



int mana_gain( CHAR_DATA *ch )
{
    int gain;
    int intamount;

    if ( IS_NPC(ch) )
    {
	gain = ch->level;
    }
    else
    {
	if (IS_CLASS(ch, CLASS_VAMPIRE) && ch->position != POS_MEDITATING) return 0;
	gain = number_range( 10, 20 );

	if ((intamount = (get_curr_int(ch)+1)) > 1)
	{
	    switch ( ch->position )
	    {
		case POS_MEDITATING:
		if (IS_CLASS(ch, CLASS_VAMPIRE)) gain *= intamount * 1.5;
		else gain *= intamount * ch->level;	break;
		case POS_SLEEPING:   gain *= intamount * 1.5;break;
		case POS_RESTING:    gain *= intamount ;		break;
	    }
	}

	if ( !IS_HERO(ch) && ch->pcdata->condition[COND_THIRST] == 0 )
	    gain *= 0.5;

    }

    if ( IS_AFFECTED( ch, AFF_POISON ))
	gain *= 0.25;
    if ( IS_AFFECTED( ch, AFF_FLAMING ))
	gain *= 0.01;

    return UMIN(gain, ch->max_mana - ch->mana);
}



int move_gain( CHAR_DATA *ch )
{
    int gain;
    int dexamount;

    if ( IS_NPC(ch) )
    {
	gain = ch->level;
    }
    else
    {
	if (IS_CLASS(ch, CLASS_VAMPIRE) && ch->position != POS_MEDITATING) return 0;
	gain = number_range( 10, 20 );

	if ((dexamount = (get_curr_dex(ch)+1)) > 1)
	{
	    switch ( ch->position )
	    {
		case POS_MEDITATING:
	   if (IS_CLASS(ch, CLASS_MONK))
	        gain *= dexamount * 5;
		else if (IS_CLASS(ch, CLASS_VAMPIRE))
		gain *= dexamount * 1.5;
	   else 
		gain *= dexamount * 3;
		break;
		case POS_SLEEPING:   gain *= dexamount;		break;
		case POS_RESTING:    gain *= dexamount * 0.5;	break;
	    }
	}

	if ( !IS_HERO(ch) && ch->pcdata->condition[COND_THIRST] == 0 )
	    gain *= 0.5;
    }

    if ( IS_AFFECTED(ch, AFF_POISON))
	gain *= 0.25;
    if ( IS_AFFECTED(ch, AFF_FLAMING))
	gain *= 0.01;

    return UMIN(gain, ch->max_move - ch->move);
}



void gain_condition( CHAR_DATA *ch, int iCond, int value )
{
    int condition;

    if ( value == 0 || IS_NPC(ch) )
	return;

    if (!IS_NPC(ch) && IS_HERO(ch) && !IS_CLASS(ch, CLASS_VAMPIRE) 
	&& iCond != COND_DRUNK)
	return;

    condition				= ch->pcdata->condition[iCond];
    if (!IS_NPC(ch) && !IS_CLASS(ch, CLASS_VAMPIRE) )
	ch->pcdata->condition[iCond]	= URANGE( 0, condition + value, 48 );
    else
	ch->pcdata->condition[iCond]	= URANGE( 0, condition + value, 100 );

    if ( ch->pcdata->condition[iCond] == 0 )
    {
	switch ( iCond )
	{
	case COND_FULL:
	    if (!IS_CLASS(ch, CLASS_VAMPIRE))
	    {
		send_to_char( "You are REALLY hungry.\n\r",  ch );
		act( "You hear $n's stomach rumbling.", ch, NULL, NULL, TO_ROOM );
	    }
	    break;

	case COND_THIRST:
	    if (!IS_CLASS(ch, CLASS_VAMPIRE)) 
		send_to_char( "You are REALLY thirsty.\n\r", ch );
	    else if (ch->hit > 0)
	    {
		send_to_char( "You are DYING from lack of blood!\n\r", ch );
		act( "$n gets a hungry look in $s eyes.", ch, NULL, NULL, TO_ROOM );
		ch->hit = ch->hit - number_range(2,5);
		if (number_percent() <= ch->beast && ch->beast > 0) vamp_rage(ch);
		if (!IS_VAMPAFF(ch, VAM_FANGS)) do_fangs(ch,"");
	    }
	    break;

	case COND_DRUNK:
	    if ( condition != 0 )
		send_to_char( "You are sober.\n\r", ch );
	    break;
	}
    }
    else if ( ch->pcdata->condition[iCond] < 10 )
    {
	switch ( iCond )
	{
	case COND_FULL:
	    if (!IS_CLASS(ch, CLASS_VAMPIRE)) 
		send_to_char( "You feel hungry.\n\r",  ch );
	    break;

	case COND_THIRST:
	    if (!IS_CLASS(ch, CLASS_VAMPIRE)) 
		send_to_char( "You feel thirsty.\n\r", ch );
	    else
	    {
		send_to_char( "You crave blood.\n\r", ch );
		if (number_range(1,1000) <= ch->beast && ch->beast > 0) vamp_rage(ch);
		if (number_percent() > (ch->pcdata->condition[COND_THIRST]+75)
		    && !IS_VAMPAFF(ch, VAM_FANGS)) do_fangs(ch,"");
	    }
	    break;
	}
    }

    return;
}



/*
 * Mob autonomous action.
 * This function takes 25% to 35% of ALL Merc cpu time.
 * -- Furey
 */
void mobile_update( void )
{
    CHAR_DATA *ch;
    CHAR_DATA *ch_next;
    EXIT_DATA *pexit;
    int door;

    /* Examine all mobs. */
    for ( ch = char_list; ch != NULL; ch = ch_next )
    {
	ch_next = ch->next;

	if ( ch->in_room == NULL ) continue;

	if ( ch->hunting != NULL && ch->hunting != '\0' && 
	    strlen(ch->hunting) > 1 )
	{
	    check_hunt( ch );
	    continue;
	}

	if ( !IS_NPC(ch) )
	{
	    if (ch->pcdata->condition[COND_DRUNK] > 10 && number_range(1,10) == 1)
	    {
		send_to_char("You hiccup loudly.\n\r",ch);
		act("$n hiccups.",ch,NULL,NULL,TO_ROOM);
	    }
	    if (ch->pcdata->stage[0] > 0 || ch->pcdata->stage[2] > 0)
	    {
		CHAR_DATA *vch;
		if (ch->pcdata->stage[1] > 0 && ch->pcdata->stage[2] >= 225)
		{
		    ch->pcdata->stage[2] += 1;
		    if ( ( vch = ch->pcdata->partner ) != NULL &&
			!IS_NPC(vch) && vch->pcdata->partner == ch &&
			((vch->pcdata->stage[2] >= 200 && vch->sex == SEX_FEMALE) ||
			(ch->pcdata->stage[2] >= 200 && ch->sex == SEX_FEMALE)))
		    {
			if (ch->in_room != vch->in_room) continue;
			if (vch->pcdata->stage[2] >= 225 &&
			    ch->pcdata->stage[2] >= 225 &&
			    vch->pcdata->stage[2] < 240 &&
			    ch->pcdata->stage[2] < 240)
			{
			    ch->pcdata->stage[2] = 240;
			    vch->pcdata->stage[2] = 240;
			}
			if (ch->sex == SEX_MALE && vch->pcdata->stage[2] >= 240)
			{
			    act("You thrust deeply between $N's warm, damp thighs.",ch,NULL,vch,TO_CHAR);
			    act("$n thrusts deeply between your warm, damp thighs.",ch,NULL,vch,TO_VICT);
			    act("$n thrusts deeply between $N's warm, damp thighs.",ch,NULL,vch,TO_NOTVICT);
			    if (vch->pcdata->stage[2] > ch->pcdata->stage[2])
				ch->pcdata->stage[2] = vch->pcdata->stage[2];
			}
			else if (ch->sex == SEX_FEMALE && vch->pcdata->stage[2] >= 240)
			{
			    act("You squeeze your legs tightly around $N, moaning loudly.",ch,NULL,vch,TO_CHAR);
			    act("$n squeezes $s legs tightly around you, moaning loudly.",ch,NULL,vch,TO_VICT);
			    act("$n squeezes $s legs tightly around $N, moaning loudly.",ch,NULL,vch,TO_NOTVICT);
			    if (vch->pcdata->stage[2] > ch->pcdata->stage[2])
				ch->pcdata->stage[2] = vch->pcdata->stage[2];
			}
		    }
		    if (ch->pcdata->stage[2] >= 250)
		    {
			if ( ( vch = ch->pcdata->partner ) != NULL &&
			    !IS_NPC(vch) && vch->pcdata->partner == ch &&
			    ch->in_room == vch->in_room)
			{
			    vch->pcdata->stage[2] = 250;
			    if (ch->sex == SEX_MALE)
			    {
				stage_update(ch,vch,2);
				stage_update(vch,ch,2);
			    }
			    else
			    {
				stage_update(vch,ch,2);
				stage_update(ch,vch,2);
			    }
			    ch->pcdata->stage[0] = 0;
			    vch->pcdata->stage[0] = 0;
			    if (!IS_EXTRA(ch, EXTRA_EXP))
			    {
				send_to_char("Congratulations on achieving a simultanious orgasm!  Recieve 100000 exp!\n\r",ch);
				SET_BIT(ch->extra, EXTRA_EXP);
				ch->exp += 100000;
			    }
			    if (!IS_EXTRA(vch, EXTRA_EXP))
			    {
				send_to_char("Congratulations on achieving a simultanious orgasm!  Recieve 100000 exp!\n\r",vch);
				SET_BIT(vch->extra, EXTRA_EXP);
				vch->exp += 100000;
			    }
			}
		    }
		}
		else
		{
		    if (ch->pcdata->stage[0] > 0 && ch->pcdata->stage[2] < 1 &&
			ch->position != POS_RESTING) 
		    {
			if (ch->pcdata->stage[0] > 1)
			    ch->pcdata->stage[0] -= 1;
			else
			    ch->pcdata->stage[0] = 0;
		    }
		    else if (ch->pcdata->stage[2]>0 && ch->pcdata->stage[0] < 1)
		    {
			if (ch->pcdata->stage[2] > 10)
			    ch->pcdata->stage[2] -= 10;
			else
			    ch->pcdata->stage[2] = 0;
			if (ch->sex == SEX_MALE && ch->pcdata->stage[2] == 0)
			    send_to_char("You feel fully recovered.\n\r",ch);
		    }
		}
	    }

	    if (!IS_NPC(ch) && IS_CLASS(ch, CLASS_VAMPIRE) && IS_HERO(ch))
	    {
		if ( ch->position == POS_FIGHTING && ch->rage > 0 
		    && ch->rage < 25 && !IS_ITEMAFF(ch, ITEMA_RAGER) )
		    ch->rage += 1;
		else if (ch->rage > 0 && !IS_ITEMAFF(ch, ITEMA_RAGER))
		    ch->rage -= 1;
		if (ch->rage < 1) continue;
		if ( ch->hit < ch->max_hit || ch->mana < ch->max_mana || 
		    ch->move < ch->max_move )
		    werewolf_regen(ch);
		if (ch->loc_hp[6] > 0)
		{
		    int sn = skill_lookup( "clot" );
		    (*skill_table[sn].spell_fun) (sn,ch->level,ch,ch);
		}
		else
		{
		    if ((ch->loc_hp[0] + ch->loc_hp[1] + ch->loc_hp[2] +
			ch->loc_hp[3] + ch->loc_hp[4] + ch->loc_hp[5]) != 0)
		    reg_mend(ch);
		}
	    }

	    if (!IS_NPC(ch) && IS_CLASS(ch, CLASS_MONK) && IS_HERO(ch))
	    {
	      if ( ch->position != POS_FIGHTING )
	      {
		if ( ch->chi[CURRENT] > 0 )
	        {
		    if ( number_range( 1,4 ) == 2 )
		    {
			ch->chi[CURRENT]--;
			stc("You feel more relaxed.\n\r",ch);
			act("$n looks more relaxed.",ch,NULL,NULL,TO_ROOM);
		    }
		}
	      }
	    }

	    if (!IS_NPC(ch) && IS_CLASS(ch, CLASS_NINJA) && IS_HERO(ch))
	    {
		if ( ch->position == POS_FIGHTING && ch->rage > 0 
		    && ch->rage < 25 && !IS_ITEMAFF(ch, ITEMA_RAGER) )
		    ch->rage += 1;
		else if (ch->rage > 0 && !IS_ITEMAFF(ch, ITEMA_RAGER))
		    ch->rage -= 1;
		if (ch->rage < 1) continue;
		if ( ch->hit < ch->max_hit || ch->mana < ch->max_mana || 
		    ch->move < ch->max_move )
		    werewolf_regen(ch);
		if (ch->loc_hp[6] > 0)
		{
		    int sn = skill_lookup( "clot" );
		    (*skill_table[sn].spell_fun) (sn,ch->level,ch,ch);
		}
		else
		{
		    if ((ch->loc_hp[0] + ch->loc_hp[1] + ch->loc_hp[2] +
			ch->loc_hp[3] + ch->loc_hp[4] + ch->loc_hp[5]) != 0)
		    reg_mend(ch);
		}
	    }
	    else if (!IS_NPC(ch) && IS_CLASS(ch, CLASS_WEREWOLF) && IS_HERO(ch))
	    {
		if (ch->position == POS_FIGHTING && !IS_ITEMAFF(ch, ITEMA_RAGER))
		{
		    if (ch->rage < 200)
			ch->rage += number_range(5,10);
		    if (ch->rage < 200 &&
ch->pcdata->powers[DISC_WERE_WOLF] > 3)
			ch->rage += number_range(5,10);
		    if (!IS_SET(ch->special, SPC_WOLFMAN) && 
			ch->rage >= 100)
			do_werewolf(ch,"");
		}
		else if (ch->rage > 0 && !IS_ITEMAFF(ch, ITEMA_RAGER))
		{
		    ch->rage -= 1;
		    if (ch->rage < 100) do_unwerewolf(ch,"");
		}
		if ( ch->hit < ch->max_hit || ch->mana < ch->max_mana || 
		    ch->move < ch->max_move )
		    werewolf_regen(ch);

		if (IS_CLASS(ch,CLASS_WEREWOLF) && ch->position == POS_SLEEPING
		    && ch->power[DISC_WERE_BEAR] > 3 && ch->hit > 0)
		{
		    if ( ch->hit < ch->max_hit || ch->mana < ch->max_mana || 
			ch->move < ch->max_move )
			werewolf_regen(ch);
		    if ( ch->hit < ch->max_hit || ch->mana < ch->max_mana || 
			ch->move < ch->max_move )
			werewolf_regen(ch);
		    if ( ch->hit < ch->max_hit || ch->mana < ch->max_mana || 
			ch->move < ch->max_move )
			werewolf_regen(ch);
		    if ( ch->hit < ch->max_hit || ch->mana < ch->max_mana || 
			ch->move < ch->max_move )
			werewolf_regen(ch);
		}
		if (ch->loc_hp[6] > 0)
		{
		    int sn = skill_lookup( "clot" );
		    (*skill_table[sn].spell_fun) (sn,ch->level,ch,ch);
		}
		else
		{
		    if ((ch->loc_hp[0] + ch->loc_hp[1] + ch->loc_hp[2] +
			ch->loc_hp[3] + ch->loc_hp[4] + ch->loc_hp[5]) != 0)
		    reg_mend(ch);
		}
	    }
	    else if (IS_CLASS(ch, CLASS_VAMPIRE) &&
		(ch->power[DISC_VAMP_OBFU] > 8)
		&& ch->in_room != NULL
		&& ch->in_room->vnum == 27000)
	    {
		if ( ch->hit < ch->max_hit || ch->mana < ch->max_mana || 
		    ch->move < ch->max_move )
		    werewolf_regen(ch);
		    werewolf_regen(ch);
		if (ch->hit > 0)
		{
		    if ( ch->hit < ch->max_hit || ch->mana < ch->max_mana
|| 
			ch->move < ch->max_move )
			werewolf_regen(ch);
		    if ( ch->hit < ch->max_hit || ch->mana < ch->max_mana
|| 
			ch->move < ch->max_move )
			werewolf_regen(ch);
		    if ( ch->hit < ch->max_hit || ch->mana < ch->max_mana
|| 
			ch->move < ch->max_move )
			werewolf_regen(ch);
		    if ( ch->hit < ch->max_hit || ch->mana < ch->max_mana
|| 
			ch->move < ch->max_move )
			werewolf_regen(ch);
		      werewolf_regen(ch);
		}
		if (ch->loc_hp[6] > 0)
		{
		    int sn = skill_lookup( "clot" );
		    (*skill_table[sn].spell_fun) (sn,ch->level,ch,ch);
		}
		else
		{
		    if ((ch->loc_hp[0] + ch->loc_hp[1] + ch->loc_hp[2] +
		ch->loc_hp[3] + ch->loc_hp[4] + ch->loc_hp[5]) != 0)
		    reg_mend(ch);
		}
	    }
	else if ( ( ( IS_CLASS(ch, CLASS_DEMON)
	   && IS_HERO(ch)
	   && ch->in_room != NULL 
	   && ( ch->in_room->vnum == 30000 
	   ||   ch->in_room->vnum == 30001
	   ||   ch->in_room->vnum == 30002
	   ||   ch->in_room->vnum == 30003
	   ||   ch->in_room->vnum == 30004
	   ||   ch->in_room->vnum == 30005
	   ||   ch->in_room->vnum == 30006
	   ||   ch->in_room->vnum == 30007
	   ||   ch->in_room->vnum == 30008
	   ||   ch->in_room->vnum == 30009
	   ||   ch->in_room->vnum == 30010 ) )
	   || ( IS_CLASS(ch, CLASS_DROW)
	   && IS_HERO(ch) 
	   && ch->in_room != NULL 
	   && (ch->in_room->vnum == 26000 || ch->in_room->vnum == 26001) ) )
	   || (IS_CLASS(ch, CLASS_CYBORG)
	   && IS_HERO(ch)
	   && ch->in_room != NULL
	   && ch->in_room->vnum == 3054 ) )
	   {
		if ( ch->hit < ch->max_hit)
		ch->hit += 300;
 		if ( ch->mana < ch->max_mana)
		ch->mana += 300; 
		if ( ch->move < ch->max_move)
		    ch->move += 300;
		if (ch->hit > 0)
		{
		    if ( ch->hit < ch->max_hit || ch->mana < ch->max_mana || 
			ch->move < ch->max_move )
			werewolf_regen(ch);
		    if ( ch->hit < ch->max_hit || ch->mana < ch->max_mana || 
			ch->move < ch->max_move )
			werewolf_regen(ch);
		    if ( ch->hit < ch->max_hit || ch->mana < ch->max_mana || 
			ch->move < ch->max_move )
			werewolf_regen(ch);
		    if ( ch->hit < ch->max_hit || ch->mana < ch->max_mana || 
			ch->move < ch->max_move )
			werewolf_regen(ch);
		}
		if (ch->loc_hp[6] > 0)
		{
		    int sn = skill_lookup( "clot" );
		    (*skill_table[sn].spell_fun) (sn,ch->level,ch,ch);
		}
		else
		{
		    if ((ch->loc_hp[0] + ch->loc_hp[1] + ch->loc_hp[2] +
			ch->loc_hp[3] + ch->loc_hp[4] + ch->loc_hp[5]) != 0)
		    reg_mend(ch);
		}
	    }

	    else if (IS_CLASS(ch, CLASS_HIGHLANDER) && (get_eq_char(ch, WEAR_WIELD) != NULL))
    	    {
               int wpn = (ch->wpn[1]/3);        
		if ( ch->hit < ch->max_hit)
		ch->hit += wpn;
 		if ( ch->mana < ch->max_mana)
		ch->mana += wpn; 
		if ( ch->move < ch->max_move)
		    ch->move += wpn;
		if (ch->hit > 0)
		{
		    if ( ch->hit < ch->max_hit || ch->mana < ch->max_mana || 
			ch->move < ch->max_move )
			werewolf_regen(ch);
		    if ( ch->hit < ch->max_hit || ch->mana < ch->max_mana || 
			ch->move < ch->max_move )
			werewolf_regen(ch);
		}
		if (ch->loc_hp[6] > 0)
		{
		    int sn = skill_lookup( "clot" );
		    (*skill_table[sn].spell_fun) (sn,ch->level,ch,ch);
		}
		else
		{
		    if ((ch->loc_hp[0] + ch->loc_hp[1] + ch->loc_hp[2] +
			ch->loc_hp[3] + ch->loc_hp[4] + ch->loc_hp[5]) != 0)
		    reg_mend(ch);
		}
	    }
	else if (!IS_NPC(ch) && IS_ITEMAFF(ch, ITEMA_REGENERATE)) {
                   if ( ch->hit < ch->max_hit || ch->mana < ch->max_mana ||
                        ch->move < ch->max_move )
                        werewolf_regen(ch);
                    if ( ch->hit < ch->max_hit || ch->mana < ch->max_mana ||
                        ch->move < ch->max_move )   
                        werewolf_regen(ch);
                    if ( ch->hit < ch->max_hit || ch->mana < ch->max_mana ||
                        ch->move < ch->max_move )
                        werewolf_regen(ch);
                    if ( ch->hit < ch->max_hit || ch->mana < ch->max_mana ||
                        ch->move < ch->max_move )
                        werewolf_regen(ch);
		reg_mend(ch);
		}	
continue;
	}

	if ( IS_AFFECTED(ch, AFF_CHARM) ) continue;

	/* Examine call for special procedure */
	if ( ch->spec_fun != 0 )
	{
	    if ( (*ch->spec_fun) ( ch ) )
		continue;
	    if (ch == NULL) continue;
	}

	/* That's all for sleeping / busy monster */
	if ( ch->position != POS_STANDING )
	    continue;

	/* Scavenge */
	if ( IS_SET(ch->act, ACT_SCAVENGER)
	&&   ch->in_room->contents != NULL
	&&   number_bits( 2 ) == 0 )
	{
	    OBJ_DATA *obj;
	    OBJ_DATA *obj_best;
	    int max;

	    max         = 1;
	    obj_best    = 0;
	    for ( obj = ch->in_room->contents; obj; obj = obj->next_content )
	    {
		if ( CAN_WEAR(obj, ITEM_TAKE) && obj->cost > max )
		{
		    obj_best    = obj;
		    max         = obj->cost;
		}
	    }

	    if ( obj_best )
	    {
		obj_from_room( obj_best );
		obj_to_char( obj_best, ch );
		act( "$n picks $p up.", ch, obj_best, NULL, TO_ROOM );
		act( "You pick $p up.", ch, obj_best, NULL, TO_CHAR );
	    }
	}

	/* Wander */
	if ( !IS_SET(ch->act, ACT_SENTINEL)
	&& ( door = number_bits( 5 ) ) <= 5
	&& ( pexit = ch->in_room->exit[door] ) != NULL
	&&   pexit->to_room != NULL
	&&   !IS_SET(pexit->exit_info, EX_CLOSED)
	&&   !IS_SET(pexit->to_room->room_flags, ROOM_NO_MOB)
	&& ( ch->hunting == NULL || strlen(ch->hunting) < 2 )
	&& ( (!IS_SET(ch->act, ACT_STAY_AREA) && ch->level < 900)
	||   pexit->to_room->area == ch->in_room->area ) )
	{
	    move_char( ch, door );
	}

	/* Flee */
	if ( ch->hit < ch->max_hit / 2
	&& ( door = number_bits( 3 ) ) <= 5
	&& ( pexit = ch->in_room->exit[door] ) != NULL
	&&   pexit->to_room != NULL
	&&   !IS_AFFECTED(ch, AFF_WEBBED)
	&&   ch->level < 900
	&&   !IS_SET(pexit->exit_info, EX_CLOSED)
	&&   !IS_SET(pexit->to_room->room_flags, ROOM_NO_MOB) 
	&&   !IS_AFFECTED(ch, AFF_TENDRILS))
        {
	    CHAR_DATA *rch;
	    bool found;

	    found = FALSE;
	    for ( rch  = pexit->to_room->people;
		  rch != NULL;
		  rch  = rch->next_in_room )
	    {
		if ( !IS_NPC(rch) )
		{
		    found = TRUE;
		    break;
		}
	    }
	    if ( !found )
		move_char( ch, door );
	}

    }

    return;
}



/*
 * Update the weather.
 */
void weather_update( void )
{
    char buf[MAX_STRING_LENGTH];
    DESCRIPTOR_DATA *d;
    CHAR_DATA *ch = NULL;
    int diff;
    bool char_up;

    buf[0] = '\0';

    switch ( ++time_info.hour )
    {
    case  5:
	weather_info.sunlight = SUN_LIGHT;
	strcat( buf, "The day has begun.\n\r" );
	break;

    case  6:
	weather_info.sunlight = SUN_RISE;
	strcat( buf, "The sun rises in the east.\n\r" );
	break;

    case 19:
	weather_info.sunlight = SUN_SET;
	strcat( buf, "The sun slowly disappears in the west.\n\r" );
	break;

    case 20:
        weather_info.sunlight = SUN_DARK;
	strcat( buf, "The night has begun.\n\r" );
	break;

    case 24:
	time_info.hour = 0;
	time_info.day++;
	for ( d = descriptor_list; d != NULL; d = d->next )
	{
	    char_up = FALSE;
	    if (( d->connected == CON_PLAYING
	    ||    d->connected == CON_EDITING )
	    &&   (ch = d->character) != NULL
	    &&  !IS_NPC(ch))
	    {
		if (ch->fighting == NULL && !IS_SET(ch->newbits, NEW_NATURAL)
		 && ch->monkab[SPIRIT] >= 2 )
		  SET_BIT(ch->newbits, NEW_NATURAL);

		send_to_char( "You hear a clock in the distance strike midnight.\n\r",ch);
		if (IS_EXTRA(ch, EXTRA_ROT))
                {
                        send_to_char("Your flesh feels better.\n\r", ch);
                        REMOVE_BIT(ch->extra, EXTRA_ROT);
                        
                }
                if (IS_SET(ch->in_room->room_flags, ROOM_SILENCE))
                {
                send_to_char("The silence leaves the room.\n\r",ch);
                act("The silence leaves the room.",ch,NULL,NULL,TO_ROOM);
                REMOVE_BIT(ch->in_room->room_flags,ROOM_SILENCE);
                
                }

                if (IS_SET(ch->in_room->room_flags,ROOM_FLAMING))
                {
                send_to_char("The flames in the room die down.\n\r",ch);
                act("The flames in the room die down.",ch,NULL,NULL,TO_ROOM);
                REMOVE_BIT(ch->in_room->room_flags,ROOM_FLAMING);
                }
                if ( IS_CLASS(ch, CLASS_VAMPIRE) )
		{
		    if (ch->hit < ch->max_hit)
			{ ch->hit = ch->max_hit; char_up = TRUE; }
		    if (ch->mana < ch->max_mana)
			{ ch->mana = ch->max_mana; char_up = TRUE; }
		    if (ch->move < ch->max_move)
			{ ch->move = ch->max_move; char_up = TRUE; }
		    if (char_up) send_to_char( "You feel the strength of the kindred flow through your veins!\n\r", ch );
		    ch->position = POS_STANDING;
		    if (ch->pcdata->gentick < 23-ch->generation)
			ch->pcdata->gentick += 1;

		    if (ch->pcdata->gentick == 23-ch->generation 
  			&& ch->generation > 3 && ch->pcdata->lwrgen == FALSE )
		    {
			stc("Your blood boils and bubbles with power.\n\r",ch);
			send_to_char("You become one generation closer to Trace!\n\r",ch);
			ch->generation -=1;
			ch->pcdata->gentick=0;
			ch->pcdata->lwrgen=TRUE;
		    }



		    if (IS_EXTRA(ch, EXTRA_POTENCY))
		    { 
			send_to_char("You feel your blood potency fade away.\n\r", ch);	
			ch->generation =ch->generation +1;
			REMOVE_BIT(ch->extra, EXTRA_POTENCY);
		    }

                    if (IS_SET(ch->newbits, NEW_TIDE))
 	            {
 		     REMOVE_BIT(ch->newbits, NEW_TIDE);
                     send_to_char("The tide of vitae leaves you.\n\r", ch);
		    }

		    if (IS_SET(ch->extra, EXTRA_BAAL))
                    {
                       send_to_char("The spirit of Baal escapes you.\n\r",ch);  
                       ch->power[DISC_VAMP_POTE] -= 2;
                       ch->power[DISC_VAMP_CELE] -= 2;
                       ch->power[DISC_VAMP_FORT] -= 2;
                       REMOVE_BIT(ch->extra, EXTRA_BAAL);
                    }   

                    if (IS_EXTRA(ch, EXTRA_FLASH))
                    {
                       send_to_char("Your speed slows.\n\r",ch);  
                       ch->power[DISC_VAMP_CELE] -= 2;
                       REMOVE_BIT(ch->extra, EXTRA_FLASH);
                    }   

                   }			
		  } 
                 
	    
	}
	break;
    }

    if ( time_info.day   >= 35 )
    {
	time_info.day = 0;
	time_info.month++;
    }

    if ( time_info.month >= 17 )
    {
	time_info.month = 0;
	time_info.year++;
    }

    /*
     * Weather change.
     */
    if ( time_info.month >= 9 && time_info.month <= 16 )
	diff = weather_info.mmhg >  985 ? -2 : 2;
    else
	diff = weather_info.mmhg > 1015 ? -2 : 2;

    weather_info.change   += diff * dice(1, 4) + dice(2, 6) - dice(2, 6);
    weather_info.change    = UMAX(weather_info.change, -12);
    weather_info.change    = UMIN(weather_info.change,  12);

    weather_info.mmhg += weather_info.change;
    weather_info.mmhg  = UMAX(weather_info.mmhg,  960);
    weather_info.mmhg  = UMIN(weather_info.mmhg, 1040);

    switch ( weather_info.sky )
    {
    default: 
	bug( "Weather_update: bad sky %d.", weather_info.sky );
	weather_info.sky = SKY_CLOUDLESS;
	break;

    case SKY_CLOUDLESS:
	if ( weather_info.mmhg <  990
	|| ( weather_info.mmhg < 1010 && number_bits( 2 ) == 0 ) )
	{
	    strcat( buf, "The sky is getting cloudy.\n\r" );
	    weather_info.sky = SKY_CLOUDY;
	}
	break;

    case SKY_CLOUDY:
	if ( weather_info.mmhg <  970
	|| ( weather_info.mmhg <  990 && number_bits( 2 ) == 0 ) )
	{
	    strcat( buf, "It starts to rain.\n\r" );
	    weather_info.sky = SKY_RAINING;
	}

	if ( weather_info.mmhg > 1030 && number_bits( 2 ) == 0 )
	{
	    strcat( buf, "The clouds disappear.\n\r" );
	    weather_info.sky = SKY_CLOUDLESS;
	}
	break;

    case SKY_RAINING:
	if ( weather_info.mmhg <  970 && number_bits( 2 ) == 0 )
	{
	    strcat( buf, "Lightning flashes in the sky.\n\r" );
	    weather_info.sky = SKY_LIGHTNING;
	}

	if ( weather_info.mmhg > 1030
	|| ( weather_info.mmhg > 1010 && number_bits( 2 ) == 0 ) )
	{
	    strcat( buf, "The rain stopped.\n\r" );
	    weather_info.sky = SKY_CLOUDY;
	}
	break;

    case SKY_LIGHTNING:
	if ( weather_info.mmhg > 1010
	|| ( weather_info.mmhg >  990 && number_bits( 2 ) == 0 ) )
	{
	    strcat( buf, "The lightning has stopped.\n\r" );
	    weather_info.sky = SKY_RAINING;
	    break;
	}
	break;
    }

    if ( buf[0] != '\0' )
    {
	for ( d = descriptor_list; d != NULL; d = d->next )
	{
	    if (( d->connected == CON_PLAYING
	    ||    d->connected == CON_EDITING )
	    &&   IS_OUTSIDE(d->character)
	    &&   IS_AWAKE(d->character) )
		send_to_char( buf, d->character );
	}
    }

    return;
}


int is_wall(EXIT_DATA *ex)
{

    if (IS_SET(ex->exit_info, EX_ICE_WALL)) return 1;
    if (IS_SET(ex->exit_info, EX_FIRE_WALL)) return 2;
    if (IS_SET(ex->exit_info, EX_SWORD_WALL)) return 3;
    if (IS_SET(ex->exit_info, EX_PRISMATIC_WALL)) return 4;
    if (IS_SET(ex->exit_info, EX_IRON_WALL)) return 5;
    if (IS_SET(ex->exit_info, EX_MUSHROOM_WALL)) return 6;
    if (IS_SET(ex->exit_info, EX_CALTROP_WALL)) return 7;
    if (IS_SET(ex->exit_info, EX_ASH_WALL)) return 8;
    return 0;
}

const char * wall[MAX_WALL+1] = 
{
    "","wall of ice", "wall of fire", "wall of swords",
	"prismatic wall", "wall or iron", "wall of mushrooms",
	"wall of caltrops", "wall of ash"
};

/*
 * Update all rooooooms, like gore, poison clouds etc....
 */
void room_update( void )
{
    int i;
    char buf[MAX_STRING_LENGTH];
    ROOM_INDEX_DATA *room;

    
    for ( room = room_list; room != NULL; room = room->next_room)
    {
        
        if (RTIMER(room, RTIMER_WALL_NORTH) == 1
	    && room->exit[DIR_NORTH] != NULL
	    && is_wall(room->exit[DIR_NORTH])!= 0)
        {
	    sprintf(buf, "The %s slowly fades away.", wall[is_wall(room->exit[DIR_NORTH])]);
	    room_message(room, buf);
	    make_wall(room, DIR_NORTH, 0);
        }

        if (RTIMER(room, RTIMER_WALL_SOUTH) == 1
	    && room->exit[DIR_SOUTH] != NULL
	    && is_wall(room->exit[DIR_SOUTH])!= 0)
        {
	    sprintf(buf, "The %s slowly fades away.", wall[is_wall(room->exit[DIR_SOUTH])]);
	    room_message(room, buf);
	    make_wall(room, DIR_SOUTH, 0);
        }

        if (RTIMER(room, RTIMER_WALL_EAST) == 1
	    && room->exit[DIR_EAST] != NULL
	    && is_wall(room->exit[DIR_EAST])!= 0)
        {
	    sprintf(buf, "The %s slowly fades away.", wall[is_wall(room->exit[DIR_EAST])]);
	    room_message(room, buf);
	    make_wall(room, DIR_EAST, 0);
        }

        if (RTIMER(room, RTIMER_WALL_WEST) == 1
	    && room->exit[DIR_WEST] != NULL
	    && is_wall(room->exit[DIR_WEST])!= 0)
        {
	    sprintf(buf, "The %s slowly fades away.", wall[is_wall(room->exit[DIR_WEST])]);
	    room_message(room, buf);
	    make_wall(room, DIR_WEST, 0);
        }

        if (RTIMER(room, RTIMER_WALL_UP) == 1
	    && room->exit[DIR_UP] != NULL
	    && is_wall(room->exit[DIR_UP])!= 0)
        {
	    sprintf(buf, "The %s slowly fades away.", wall[is_wall(room->exit[DIR_UP])]);
	    room_message(room, buf);
	    make_wall(room, DIR_UP, 0);
        }

        if (RTIMER(room, RTIMER_WALL_DOWN) == 1
	    && room->exit[DIR_DOWN] != NULL
	    && is_wall(room->exit[DIR_DOWN])!= 0)
        {
	    sprintf(buf, "The %s slowly fades away.", wall[is_wall(room->exit[DIR_DOWN])]);
	    room_message(room, buf);
	    make_wall(room, DIR_DOWN, 0);
        }


	if (RTIMER(room, RTIMER_STINKING_CLOUD) == 1)
	    room_message(room, "The poisonous vapours dissipate and clear.");

	if (RTIMER(room, RTIMER_HIDE_ROOM) == 1)
	    room_message(room, "The shroud leaves the room.");

	if (RTIMER(room, RTIMER_GHOST_LIGHT) == 2)
	    room_message(room, "The vapourous ghosts start howling insanely.");

	if (RTIMER(room, RTIMER_GHOST_LIGHT) == 3)
	    room_message(room, "The vapourous ghosts start moaning.");

	if (RTIMER(room, RTIMER_GHOST_LIGHT) == 1)
	    room_message(room, "The vapourous ghosts dissipate and vanish.");

	if (RTIMER(room, RTIMER_GLYPH_PROTECTION) == 1)
	    room_message(room, "The glyph of protection flares and vanishes.");

	if (RTIMER(room, RTIMER_SWARM_BEES) == 1)
	    room_message(room, "The bees fly away into the sky.");

	if (RTIMER(room, RTIMER_DISCORD) == 1)
	    room_message(room, "The banging and crashing stops.");

	if (RTIMER(room, RTIMER_SWARM_BATS) == 1)
	    room_message(room, "The bats flap away into the night.");

	if (RTIMER(room, RTIMER_SWARM_RATS) == 1)
	    room_message(room, "The rats scurry away into the floorboards.");
  
      if (RTIMER(room, RTIMER_SILENCE) == 1)
	    room_message(room, "The silence disappates.");

	for (i = 0 ; i < MAX_RTIMER ; i++)
	    room->tick_timer[i] = UMAX(room->tick_timer[i] - 1, 0);

    }

    return;

}



/*
 * Update all chars, including mobs.
 * This function is performance sensitive.
 */
void char_update( void )
{   
    CHAR_DATA *ch;
    CHAR_DATA *ch_next;
    CHAR_DATA *ch_save;
    CHAR_DATA *ch_quit;
    bool is_obj;
    bool drop_out = FALSE;
    time_t save_time;

    save_time	= current_time;
    ch_save	= NULL;
    ch_quit	= NULL;

    for ( ch = char_list; ch != NULL; ch = ch_next )
    {
	AFFECT_DATA *paf;
	AFFECT_DATA *paf_next;
	int i;
	ch_next = ch->next;
 

	if (!IS_NPC(ch) && (IS_HEAD(ch,LOST_HEAD) || IS_EXTRA(ch,EXTRA_OSWITCH)))
	    is_obj = TRUE;
	else if (!IS_NPC(ch) && ch->pcdata->obj_vnum != 0)
	    {is_obj = TRUE;SET_BIT(ch->extra, EXTRA_OSWITCH);}
	else
	    is_obj = FALSE;
	/*
	 * Find dude with oldest save time.
	 */
	if ( !IS_NPC(ch)
	&& ( ch->desc == NULL || ch->desc->connected == CON_PLAYING )
	&&   ch->level >= 2
	&&   ch->save_time < save_time )
	{
	    ch_save	= ch;
	    save_time	= ch->save_time;
	}
/*
	if (!IS_NPC(ch) && IS_CLASS(ch, CLASS_WEREWOLF) && !is_obj &&
	    ch->power[DISC_WERE_BEAR] > 3 && ch->position == POS_SLEEPING)
	{
	    if ( ch->hit  < ch->max_hit  ) ch->hit  = ch->max_hit;
	    if ( ch->mana < ch->max_mana ) ch->mana = ch->max_mana;
	    if ( ch->move < ch->max_move ) ch->move = ch->max_move;
	}
*/
	if (ch->fighting == NULL && !IS_NPC(ch)) 

	if ( !IS_NPC(ch) && IS_CLASS(ch, CLASS_WEREWOLF) 
	  && ch->gnosis[GMAXIMUM] > 0 && ch->gnosis[GMAXIMUM]
	   > ch->gnosis[GCURRENT] )
	{
	  if ( ch->position == POS_SLEEPING )
	    ch->gnosis[GCURRENT] += number_range(2,3);
	  else if ( ch->position == POS_RESTING )
	    ch->gnosis[GCURRENT] += number_range(1,3);
	  else if ( ch->position == POS_FIGHTING )
	    ch->gnosis[GCURRENT] += 0;
	  else
	    ch->gnosis[GCURRENT] += number_range( 1, 2 );
	}



	if ( IS_CLASS(ch, CLASS_VAMPIRE) && ch->beast > 0
	  && ch->pcdata->condition[COND_THIRST] <= 15 )
	{
	  act("You bare your fangs and scream in rage from lack of blood.",ch,NULL,NULL,TO_CHAR);
	  act("$n bares $s fangs and screams in rage.",ch,NULL,NULL,TO_ROOM);
	  do_berserk(ch,"");
	  do_beastlike(ch,"");
	}

	/* Character Tick Timers */

        if (ch->tick_timer[TIMER_CAN_CALL_WAR_HORSE] == 1)
	    send_to_char("You may now call your war horse again.\n\r", ch);

 	if (ch->tick_timer[TIMER_CAN_POLYMORPH] == 1)
	    send_to_char("You may now polymorph again.\n\r", ch);

 	if (ch->tick_timer[TIMER_MAKE_SNOWMAN] == 1)
	    send_to_char("You are ready to make another snowman now.\n\r", ch);

        if (ch->tick_timer[TIMER_CANMAJESTY] == 1)
            stc("You can once again use majesty.\n\r",ch);

	if (IS_CLASS(ch, CLASS_NINJA) && ch->pcdata->powers[NPOWER_CHIKYU] >= 6
	   && ch->pcdata->powers[HARA_KIRI] > 0) {
		if (ch->pcdata->powers[HARA_KIRI] == 1)
		send_to_char("Your HaraKiri wears off.\n\r", ch );
		ch->pcdata->powers[HARA_KIRI]--;	

	}

        if (ch->tick_timer[TIMER_MAJESTY] == 1)
        {
	    REMOVE_BIT(ch->affected_by, AFF_PEACE);
	    stc("You feel less imposing.\n\r",ch);
	    act("$n looks less imposing.",ch,NULL,NULL,TO_ROOM);
        }

 	if (ch->tick_timer[TIMER_SPHINX_ROAR] == 1)
	    send_to_char("You are ready to roar again.\n\r", ch);

 	if (ch->tick_timer[TIMER_NEWBIE_IMM] == 1)
	    send_to_char("You are no longer protected by the gods.\n\r", ch);

 	if (ch->tick_timer[TIMER_CAN_DO_NEXUS] == 1)
	    send_to_char("You may now create another nexus.\n\r", ch);

        if (ch->tick_timer[TIMER_INFERNO] == 1)
	    stc("You are able to use Inferno again.\n\r",ch);

 	if (ch->tick_timer[TIMER_CAN_SHRIEK] == 1)
	    send_to_char("Your voice has recovered.\n\r", ch);

 	if (ch->tick_timer[TIMER_CAN_CALL_ROCKS] == 1)
	    send_to_char("You may now call the Bane.\n\r", ch);

 	if (ch->tick_timer[TIMER_HELLFIRE_SUMMON] == 1)
	    send_to_char("You may now summon hellfire once more.\n\r", ch);

 	if (ch->tick_timer[TIMER_ENTOMB] == 1)
	    send_to_char("You may now use the entomb ability again.\n\r", ch);

 	if (ch->tick_timer[TIMER_CAN_BREATHE_FROST] == 1)
	    send_to_char("You are ready to breathe frost again.\n\r", ch);

 	if (ch->tick_timer[TIMER_CAN_FEATHER] == 1)
	    send_to_char("You are ready to make another feather.\n\r", ch);

	    if (ch->tick_timer[TIMER_THIRD_ARM_GROWING] == 1)
	    {
	 	send_to_char("A third arm bursts out of your stomach.\n\r", ch);
		act("An arm bursts out of $n's stomach, spraying blood everywhere.", ch, NULL, NULL, TO_ROOM);
		SET_BIT(ch->newbits, THIRD_HAND);
	    }

	    if (ch->tick_timer[TIMER_FOURTH_ARM_GROWING] == 1)
	    {
	 	send_to_char("Another arm bursts out of your stomach.\n\r", ch);
		act("An arm bursts out of $n's stomach, spraying blood everywhere.", ch, NULL, NULL, TO_ROOM);
		SET_BIT(ch->newbits, FOURTH_HAND);
	    }

	for (i = 0; i < MAX_TIMER; i++)
	    if (ch->tick_timer[i] > 0) ch->tick_timer[i] -= 1;

	if (ch->fighting == NULL
	&& !IS_SET(ch->newbits, NEW_CLOAK)
	&& !IS_NPC(ch)
	&& !is_obj
	&& IS_CLASS(ch, CLASS_MONK)
	&& ch->pcdata->powers[PMONK] > 10)
	{
	   SET_BIT(ch->newbits, NEW_CLOAK);
	   send_to_char("Your Cloak of Life is restored.\n\r",ch);
	}


	if ( ch->position > POS_STUNNED && !is_obj)
	{
	    if ( ch->hit  < ch->max_hit )
		ch->hit  += hit_gain(ch);

	    if ( ch->mana < ch->max_mana )
		ch->mana += mana_gain(ch);

	    if ( ch->move < ch->max_move )
		ch->move += move_gain(ch);
	}

	if ( ch->position == POS_STUNNED && !is_obj)
	{
            ch->hit = ch->hit + number_range(2,4);
	    update_pos( ch );
/*
            if (ch->position > POS_STUNNED)
            {
                act( "$n clambers back to $s feet.", ch, NULL, NULL, TO_ROOM );
                act( "You clamber back to your feet.", ch, NULL, NULL, TO_CHAR );
            }
*/
	}

	if ( !IS_NPC(ch) && ch->level < LEVEL_IMMORTAL && !is_obj)
	{
	    OBJ_DATA *obj;
	    int blood;

	    if ( ( ( obj = get_eq_char( ch, WEAR_WIELD ) ) != NULL
	    &&   obj->item_type == ITEM_LIGHT
	    &&   obj->value[2] > 0 )
	    || ( ( obj = get_eq_char( ch, WEAR_HOLD ) ) != NULL
	    &&   obj->item_type == ITEM_LIGHT
	    &&   obj->value[2] > 0 ) )
	    {
		if ( --obj->value[2] == 0 && ch->in_room != NULL )
		{
		    --ch->in_room->light;
		    act( "$p goes out.", ch, obj, NULL, TO_ROOM );
		    act( "$p goes out.", ch, obj, NULL, TO_CHAR );
		    extract_obj( obj );
		}
	    }

	    if ( ++ch->timer >= 12 )
	    {
		if ( ch->was_in_room == NULL && ch->in_room != NULL )
		{
		    ch->was_in_room = ch->in_room;
		    if ( ch->fighting != NULL )
			stop_fighting( ch, TRUE );
		    act( "$n disappears into the void.",
			ch, NULL, NULL, TO_ROOM );
		    send_to_char( "You disappear into the void.\n\r", ch );
		    save_char_obj( ch );
		    char_from_room( ch );
		    char_to_room( ch, get_room_index( ROOM_VNUM_LIMBO ) );
		}
	    }

	    if ( ch->timer > 30 ) ch_quit = ch;

	    gain_condition( ch, COND_DRUNK,  -1 );
	    if (!IS_CLASS(ch, CLASS_VAMPIRE))
	    {
	    	gain_condition( ch, COND_FULL, -1 );
	    	gain_condition( ch, COND_THIRST, -1 );
	    }
	    else
	    {
		blood = -1;
		if (ch->beast > 0)
		{
		    if (IS_VAMPAFF(ch, VAM_CLAWS)) blood -= number_range(1,3);
		    if (IS_VAMPAFF(ch, VAM_FANGS)) blood -= 1;
		    if (IS_VAMPAFF(ch, VAM_NIGHTSIGHT)) blood -= 1;
		    if (IS_VAMPAFF(ch, AFF_SHADOWSIGHT)) blood -= number_range(1,3);
		    if (IS_SET(ch->act, PLR_HOLYLIGHT)) blood -= number_range(1,5);
		    if (IS_VAMPAFF(ch, VAM_DISGUISED)) blood -= number_range(5,10);
		    if (IS_VAMPAFF(ch, VAM_CHANGED)) blood -= number_range(5,10);
		    if (IS_VAMPAFF(ch, IMM_SHIELDED)) blood -= number_range(1,3);
		    if (IS_POLYAFF(ch, POLY_SERPENT)) blood -= number_range(1,3);
		}
               ch->pcdata->condition[COND_THIRST] += blood;
               
               if (ch->pcdata->condition[COND_THIRST] <= 0)
               {
                ch->pcdata->condition[COND_THIRST] = 0;
               } 
	    }
	}

	for ( paf = ch->affected; paf != NULL; paf = paf_next )
	{
	    paf_next	= paf->next;
	    if ( paf->duration > 0 )
		paf->duration--;
	    else if ( paf->duration < 0 )
		;
	    else
	    {
		if ( paf_next == NULL
		||   paf_next->type != paf->type
		||   paf_next->duration > 0 )
		{
		    if ( paf->type > 0 && skill_table[paf->type].msg_off && !is_obj)
		    {
			send_to_char( skill_table[paf->type].msg_off, ch );
			send_to_char( "\n\r", ch );
		    }
		}
	  
		affect_remove( ch, paf );
	    }
	}

	/*
	 * Careful with the damages here,
	 *   MUST NOT refer to ch after damage taken,
	 *   as it may be lethal damage (on NPC).
	 */
	if ( ch->loc_hp[6] > 0 && !is_obj && ch->in_room != NULL )
	{
	    int dam = 0;
	    int minhit = 0;
	    if (!IS_NPC(ch)) minhit = -11;
	    if (IS_BLEEDING(ch,BLEEDING_HEAD) && (ch->hit-dam) > minhit )
	    {
		act( "A spray of blood shoots from the stump of $n's neck.", ch, NULL, NULL, TO_ROOM );
		send_to_char( "A spray of blood shoots from the stump of your neck.\n\r", ch );
		dam += number_range(20,50);
	    }
	    if (IS_BLEEDING(ch,BLEEDING_THROAT) && (ch->hit-dam) > minhit )
	    {
		act( "Blood pours from the slash in $n's throat.", ch, NULL, NULL, TO_ROOM );
		send_to_char( "Blood pours from the slash in your throat.\n\r", ch );
		dam += number_range(10,20);
	    }
	    if (IS_BLEEDING(ch,BLEEDING_ARM_L) && (ch->hit-dam) > minhit )
	    {
		act( "A spray of blood shoots from the stump of $n's left arm.", ch, NULL, NULL, TO_ROOM );
		send_to_char( "A spray of blood shoots from the stump of your left arm.\n\r", ch );
		dam += number_range(10,20);
	    }
	    else if (IS_BLEEDING(ch,BLEEDING_HAND_L) && (ch->hit-dam) > minhit )
	    {
		act( "A spray of blood shoots from the stump of $n's left wrist.", ch, NULL, NULL, TO_ROOM );
		send_to_char( "A spray of blood shoots from the stump of your left wrist.\n\r", ch );
		dam += number_range(5,10);
	    }
	    if (IS_BLEEDING(ch,BLEEDING_ARM_R) && (ch->hit-dam) > minhit )
	    {
		act( "A spray of blood shoots from the stump of $n's right arm.", ch, NULL, NULL, TO_ROOM );
		send_to_char( "A spray of blood shoots from the stump of your right arm.\n\r", ch );
		dam += number_range(10,20);
	    }
	    else if (IS_BLEEDING(ch,BLEEDING_HAND_R) && (ch->hit-dam) > minhit )
	    {
		act( "A spray of blood shoots from the stump of $n's right wrist.", ch, NULL, NULL, TO_ROOM );
		send_to_char( "A spray of blood shoots from the stump of your right wrist.\n\r", ch );
		dam += number_range(5,10);
	    }
	    if (IS_BLEEDING(ch,BLEEDING_LEG_L) && (ch->hit-dam) > minhit )
	    {
		act( "A spray of blood shoots from the stump of $n's left leg.", ch, NULL, NULL, TO_ROOM );
		send_to_char( "A spray of blood shoots from the stump of your left leg.\n\r", ch );
		dam += number_range(10,20);
	    }
	    else if (IS_BLEEDING(ch,BLEEDING_FOOT_L) && (ch->hit-dam) > minhit )
	    {
		act( "A spray of blood shoots from the stump of $n's left ankle.", ch, NULL, NULL, TO_ROOM );
		send_to_char( "A spray of blood shoots from the stump of your left ankle.\n\r", ch );
		dam += number_range(5,10);
	    }
	    if (IS_BLEEDING(ch,BLEEDING_LEG_R) && (ch->hit-dam) > minhit )
	    {
		act( "A spray of blood shoots from the stump of $n's right leg.", ch, NULL, NULL, TO_ROOM );
		send_to_char( "A spray of blood shoots from the stump of your right leg.\n\r", ch );
		dam += number_range(10,20);
	    }
	    else if (IS_BLEEDING(ch,BLEEDING_FOOT_R) && (ch->hit-dam) > minhit )
	    {
		act( "A spray of blood shoots from the stump of $n's right ankle.", ch, NULL, NULL, TO_ROOM );
		send_to_char( "A spray of blood shoots from the stump of your right ankle.\n\r", ch );
		dam += number_range(5,10);
	    }
	    if (IS_HERO(ch)) { ch->hit = ch->hit - dam;
		if (ch->hit < 1) ch->hit = 1; }
	    else ch->hit = ch->hit - dam;
	    update_pos(ch);
	    ch->in_room->blood += dam;
	    if (ch->in_room->blood > 1000) ch->in_room->blood = 1000;
	    if (ch->hit <=-11 || (IS_NPC(ch) && ch->hit < 1))
	    {
		do_killperson(ch,ch->name);
		drop_out = TRUE;
	    }
	}
	if (IS_EXTRA(ch,EXTRA_ROT) && !is_obj && !drop_out)
	{
	 int dam;
	 if (IS_NPC(ch)) break;
         act( "$n's flesh shrivels and tears.", ch, NULL, NULL, TO_ROOM);
	 send_to_char( "Your flesh shrivels and tears.\n\r", ch);
         dam = number_range(250,500);
         ch->hit = ch->hit - dam;
         update_pos(ch);
         if (ch->hit < -10)
         {
            do_killperson(ch,ch->name);
            drop_out = TRUE;
         }
        }
/*
	if (IS_SET(ch->in_room->room_flags,ROOM_FLAMING) && !IS_AFFECTED(ch,AFF_FLAMING))
        {
        send_to_char("You catch on fire!\n\r",ch);
        SET_BIT(ch->affected_by, AFF_FLAMING);
        sprintf(buf,"%s catches on fire!\n\r",ch->name);
        act(buf,ch,NULL,NULL,TO_ROOM);
        }
*/

     if ( IS_AFFECTED(ch, AFF_FLAMING) && !is_obj && !drop_out && ch->in_room != NULL )
	{
	    int dam;
	    if (IS_NPC(ch)) break;
	    act( "$n's flesh burns and crisps.", ch, NULL, NULL, TO_ROOM );
	    send_to_char( "Your flesh burns and crisps.\n\r", ch );
	    dam = number_range(250,300);
	    ch->hit = ch->hit - dam;
	    update_pos(ch);
	    if (ch->hit <=-9)
	    {
		update_pos(ch);
		drop_out = TRUE;
	    }
	}
	else if ( IS_CLASS(ch, CLASS_VAMPIRE) && (!IS_AFFECTED(ch,AFF_SHADOWPLANE)) &&
	    (!IS_NPC(ch) && !IS_IMMUNE(ch,IMM_SUNLIGHT)) && ch->in_room != NULL &&
	    (!ch->in_room->sector_type == SECT_INSIDE) && !is_obj &&
	    (!room_is_dark(ch->in_room)) && (weather_info.sunlight != SUN_DARK) )
	{
	    act( "$n's flesh smolders in the sunlight!", ch, NULL, NULL, TO_ROOM );
	    send_to_char( "Your flesh smolders in the sunlight!\n\r", ch );
	    /* This one's to keep Zarkas quiet ;) */
	    if (IS_POLYAFF(ch, POLY_SERPENT))
	    	ch->hit = ch->hit - number_range(2,4);
	    else
	    	ch->hit = ch->hit - number_range(5,10);
	    update_pos(ch);
	    if (ch->hit <=-11)
	    {
		do_killperson(ch,ch->name);
		drop_out = TRUE;
	    }
	}
	else if ( IS_AFFECTED(ch, AFF_POISON) && !is_obj && !drop_out )
	{
	    act( "$n shivers and suffers.", ch, NULL, NULL, TO_ROOM );
	    send_to_char( "You shiver and suffer.\n\r", ch );
	    damage( ch, ch, 2, gsn_poison );
	}/*
	else if ( !IS_NPC( ch ) && ch->paradox[1] > 0 )
	{
	    if ( ch->paradox[1] > 50 ) paradox( ch );
	    else if ( ch->paradox[2] == 0 && ch->paradox[1] > 0 )
	    {
		ch->paradox[1] --;
		ch->paradox[2] = PARADOX_TICK;
	    }
	    else ch->paradox[3] --;
	}*/
	else if ( ch->position == POS_INCAP && !is_obj && !drop_out )
	{
	    if (ch->level > 0)
                ch->hit = ch->hit + number_range(2,4);
	    else
                ch->hit = ch->hit - number_range(1,2);
	    update_pos( ch );
            if (ch->position > POS_INCAP)
            {
                act( "$n's wounds stop bleeding and seal up.", ch, NULL, NULL, TO_ROOM );
                send_to_char( "Your wounds stop bleeding and seal up.\n\r", ch );
            }
            if (ch->position > POS_STUNNED)
            {
                act( "$n clambers back to $s feet.", ch, NULL, NULL, TO_ROOM );
                send_to_char( "You clamber back to your feet.\n\r", ch );
            }
	}
	else if ( ch->position == POS_MORTAL && !is_obj && !drop_out )
	{
	    drop_out = FALSE;
	   /* if (ch->level > 0)*/
                ch->hit = ch->hit + number_range(2,4);
/*	    else
	    {
                ch->hit = ch->hit - number_range(1,2);
		if (!IS_NPC(ch) && (ch->hit <=-11))
		    do_killperson(ch,ch->name);
		drop_out = TRUE;
	    }*/
	    if (!drop_out)
	    {
	    	update_pos( ch );
            	if (ch->position == POS_INCAP)
            	{
                    act( "$n's wounds begin to close, and $s bones pop back into place.", ch, NULL, NULL, TO_ROOM );
                    send_to_char( "Your wounds begin to close, and your bones pop back into place.\n\r", ch );
            	}
	    }
	}
	else if ( ch->position == POS_DEAD && !is_obj && !drop_out )
	{
	   update_pos(ch);
	   if (!IS_NPC(ch))
		do_killperson(ch,ch->name);
	}
	drop_out = FALSE;
    }

    /*
     * Autosave and autoquit.
     * Check that these chars still exist.
     */
    if ( ch_save != NULL || ch_quit != NULL )
    {
	for ( ch = char_list; ch != NULL; ch = ch_next )
	{
	    ch_next = ch->next;
	    if ( ch == ch_save )
		save_char_obj( ch );
	    if ( ch == ch_quit )
		do_quit( ch, "" );
	}
    }

    return;
}



/*
 * Update all objs.
 * This function is performance sensitive.
 */
void obj_update( void )
{   
    OBJ_DATA *obj;
    OBJ_DATA *obj_next;

    for ( obj = object_list; obj != NULL; obj = obj_next )
    {
	CHAR_DATA *rch;
	char *message;

	obj_next = obj->next;
	if ( obj->timer <= 0 || --obj->timer > 0 )
	    continue;

	switch ( obj->item_type )
	{
	default:              message = "$p vanishes.";         	break;
	case ITEM_FOUNTAIN:   message = "$p dries up.";         	break;
	case ITEM_CORPSE_NPC: message = "$p decays into dust."; 	break;
	case ITEM_CORPSE_PC:  message = "$p decays into dust."; 	break;
	case ITEM_FOOD:       message = "$p decomposes.";		break;
	case ITEM_TRASH:      message = "$p crumbles into dust.";	break;
	case ITEM_EGG:        message = "$p cracks open.";		break;
	case ITEM_WEAPON:     message = "$p turns to fine dust and blows away."; break;
        case ITEM_WALL:       message = "$p flows back into the ground.";break;
	}

	if ( obj->carried_by != NULL && !IS_OBJ_STAT2(obj, ITEM_DAEMONSEED) )
	{
	    act( message, obj->carried_by, obj, NULL, TO_CHAR );
	}
	else if ( obj->in_room != NULL
	&&      ( rch = obj->in_room->people ) != NULL && !IS_OBJ_STAT2(obj, ITEM_DAEMONSEED) )
	{
	    act( message, rch, obj, NULL, TO_ROOM );
	    act( message, rch, obj, NULL, TO_CHAR );
	}

	/* If the item is an egg, we need to create a mob and shell!
	 * KaVir
	 */
	if ( obj->item_type == ITEM_EGG && !IS_OBJ_STAT2(obj, ITEM_DAEMONSEED))
	{
	    CHAR_DATA      *creature;
	    OBJ_DATA       *egg;
	    if ( get_mob_index( obj->value[0] ) != NULL )
	    {
		if (obj->carried_by != NULL && obj->carried_by->in_room != NULL)
		{
	    	    creature = create_mobile( get_mob_index( obj->value[0] ) );
		    char_to_room(creature,obj->carried_by->in_room);
		}
		else if (obj->in_room != NULL)
		{
	    	    creature = create_mobile( get_mob_index( obj->value[0] ) );
		    char_to_room(creature,obj->in_room);
		}
		else
		{
	    	    creature = create_mobile( get_mob_index( obj->value[0] ) );
		    char_to_room(creature,get_room_index(ROOM_VNUM_HELL));
		}
	    	egg = create_object( get_obj_index( OBJ_VNUM_EMPTY_EGG ), 0 );
	    	egg->timer = 2;
	    	obj_to_room( egg, creature->in_room );
	    	act( "$n clambers out of $p.", creature, obj, NULL, TO_ROOM );
	    }
	    else if (obj->in_room != NULL)
	    {
	    	egg = create_object( get_obj_index( OBJ_VNUM_EMPTY_EGG ), 0 );
	    	egg->timer = 2;
	    	obj_to_room( egg, obj->in_room );
	    }
	}

        if (IS_OBJ_STAT2(obj, ITEM_DAEMONSEED)
	    && obj != NULL
	    && obj->in_obj == NULL
	    && (locate_obj(obj))->people )
	{
	    char buf[MAX_STRING_LENGTH];
	    CHAR_DATA *vch;
	    int wdam;

	    sprintf(buf, "%s suddenly explodes in a ball of flame, incinerating you!\n\r",obj->short_descr);
	    buf[0] = UPPER(buf[0]);
	    if ((locate_obj(obj))->people == NULL) break;
	    for ( vch = (locate_obj(obj))->people; vch != NULL;vch=vch->next_in_room )
    	    {
		if (vch->class == 0 || (!IS_NPC(vch) && vch->level < 3)) continue;
	    if ( IS_SET(vch->in_room->room_flags,ROOM_SAFE) )
	    {
		stc("You are unaffected by the blast.\n\r",vch);
		continue;
	    }
	    wdam = obj->level + dice(12,50);
            damage(vch,vch,obj->level+ dice(12, 50),gsn_inferno); 
		send_to_char(buf, vch);
	    sprintf(buf,"The flames strike you incredibly hard![%d]\n\r",wdam);
		stc(buf,vch);
 	    }
	}

	if (obj != NULL) extract_obj( obj );
    }

    return;
}



/*
 * Aggress.
 *
 * for each mortal PC
 *     for each mob in room
 *         aggress on some random PC
 *
 * This function takes 25% to 35% of ALL Merc cpu time.
 * Unfortunately, checking on each PC move is too tricky,
 *   because we don't want the mob to just attack the first PC
 *   who leads the party into the room.
 *
 * -- Furey
 */
void aggr_update( void )
{
    CHAR_DATA *wch;
    CHAR_DATA *wch_next;
    CHAR_DATA *ch;
    CHAR_DATA *ch_next;
    CHAR_DATA *vch;
    CHAR_DATA *vch_next;
    CHAR_DATA *victim = NULL;

    OBJ_DATA *obj = NULL;
    OBJ_DATA *chobj = NULL;
    ROOM_INDEX_DATA *objroom = NULL;
    DESCRIPTOR_DATA *d;

    for ( d = descriptor_list; d != NULL; d = d->next )
    {
/*
	if ( d->connected == CON_PLAYING
	&& ( ch = d->character ) != NULL
	&&   !IS_NPC(ch)
	&&   ch->pcdata->stage[1] > 0
	&& ( victim = ch->pcdata->partner ) != NULL
	&&   !IS_NPC(victim)
	&&   ch->in_room != NULL
	&&   victim->in_room != NULL
	&&   victim->in_room != ch->in_room )
	{
	    ch->pcdata->stage[1] = 0;
	    victim->pcdata->stage[1] = 0;
	}
*/
	if (( d->connected == CON_PLAYING
	||    d->connected == CON_EDITING )
	&& ( ch = d->character ) != NULL
	&&   !IS_NPC(ch)
	&&   ch->pcdata != NULL
	&& ( obj = ch->pcdata->chobj ) != NULL )
	{
	    if (obj->in_room != NULL)
	    	objroom = obj->in_room;
	    else if (obj->in_obj != NULL)
	    	objroom = get_room_index(ROOM_VNUM_IN_OBJECT);
	    else if (obj->carried_by != NULL)
	    {
		if (obj->carried_by != ch && obj->carried_by->in_room != NULL)
		    objroom = obj->carried_by->in_room;
		else continue;
	    }
	    else continue;
	    if (ch->in_room != objroom && objroom != NULL)
	    {
	    	char_from_room(ch);
	    	char_to_room(ch,objroom);
		do_look(ch,"auto");
	    }
	}
	else if (( d->connected == CON_PLAYING
	||         d->connected == CON_EDITING )
	&& ( ch = d->character ) != NULL
	&&   !IS_NPC(ch)
	&&   ch->pcdata != NULL
	&&   (IS_HEAD(ch,LOST_HEAD) || IS_EXTRA(ch,EXTRA_OSWITCH) || ch->pcdata->obj_vnum != 0) )
	{
	    if (ch->pcdata->obj_vnum != 0)
	    {
		bind_char(ch);
		continue;
	    }
	    if (IS_HEAD(ch,LOST_HEAD))
	    {
	    	REMOVE_BIT(ch->loc_hp[0],LOST_HEAD);
	    	send_to_char("You are able to regain a body.\n\r",ch);
	    	ch->position = POS_RESTING;
	    	ch->hit = 1;
	    } else {
	    	send_to_char("You return to your body.\n\r",ch);
		REMOVE_BIT(ch->extra,EXTRA_OSWITCH);}
	    REMOVE_BIT(ch->affected_by,AFF_POLYMORPH);
	    free_string(ch->morph);
	    ch->morph = str_dup("");
	    char_from_room(ch);
	    char_to_room(ch,get_room_index(ROOM_VNUM_ALTAR));
	    if ( ( chobj = ch->pcdata->chobj ) != NULL )
		chobj->chobj = NULL;
	    ch->pcdata->chobj = NULL;
	    do_look(ch,"auto");
	}
	continue;
    }

    for ( wch = char_list; wch != NULL; wch = wch_next )
    {
	wch_next = wch->next;
	if ( IS_NPC(wch)
	|| ( wch->desc != NULL && wch->desc->connected != CON_PLAYING && wch->desc->connected != CON_EDITING )
	||   wch->position <= POS_STUNNED
	||   wch->level >= LEVEL_IMMORTAL
	||   wch->pcdata == NULL
	|| ( ( chobj = wch->pcdata->chobj ) != NULL )
	||   wch->in_room == NULL )
	    continue;

	if ( (IS_CLASS(wch, CLASS_WEREWOLF) && 
wch->power[DISC_WERE_LYNX] > 1 &&IS_HERO(wch)) ||
	    IS_ITEMAFF(wch, ITEMA_STALKER) || (IS_CLASS(wch, CLASS_NINJA) &&
wch->pcdata->powers[NPOWER_CHIKYU] >= 4))
	{
	    if ( wch->hunting != NULL && wch->hunting != '\0' && 
		strlen(wch->hunting) > 1 )
	    {
		ROOM_INDEX_DATA *old_room = wch->in_room;
		check_hunt( wch );
		if (wch->in_room == old_room)
		{
		    free_string(wch->hunting);
		    wch->hunting = str_dup( "" );
		    continue;
		}
		check_hunt( wch );
		if (wch->in_room == old_room)
		{
		    free_string(wch->hunting);
		    wch->hunting = str_dup( "" );
		}
		continue;
	    }
	}

	for ( ch = wch->in_room->people; ch != NULL; ch = ch_next )
	{
	    int count;

	    ch_next	= ch->next_in_room;

	    if ( !IS_NPC(ch)
	    ||   !IS_SET(ch->act, ACT_AGGRESSIVE)
	    ||   no_attack(ch, wch)
	    ||   ch->fighting != NULL
	    ||   IS_AFFECTED(ch, AFF_CHARM)
	    ||   !IS_AWAKE(ch)
	    ||   ( IS_SET(ch->act, ACT_WIMPY) && IS_AWAKE(wch) )
	    ||   !can_see( ch, wch ) )
		continue;

	    /*
	     * Ok we have a 'wch' player character and a 'ch' npc aggressor.
	     * Now make the aggressor fight a RANDOM pc victim in the room,
	     *   giving each 'vch' an equal chance of selection.
	     */
	    count	= 0;
	    victim	= NULL;
	    for ( vch = wch->in_room->people; vch != NULL; vch = vch_next )
	    {
		vch_next = vch->next_in_room;

		if ( !IS_NPC(vch)
		&&   !no_attack(ch, vch)
		&&   vch->pcdata != NULL
		&& ( ( chobj = vch->pcdata->chobj ) == NULL )
		&&   vch->level < LEVEL_IMMORTAL
		&&   vch->position > POS_STUNNED
		&&   ( !IS_SET(ch->act, ACT_WIMPY) || !IS_AWAKE(vch) )
		&&   can_see( ch, vch ) )
		{
		    if ( number_range( 0, count ) == 0 )
			victim = vch;
		    count++;
		}
	    }

	    if ( victim == NULL )
	    {
/*
		bug( "Aggr_update: null victim attempt by mob %d.", ch->pIndexData->vnum );
*/
		continue;
	    }

	    multi_hit( ch, victim, TYPE_UNDEFINED );
	}
    }

    return;
}


 
void embrace_update( void )
{
    DESCRIPTOR_DATA *d;
    CHAR_DATA       *ch;
    CHAR_DATA       *victim;
    int blpr;  /* variable to check for amout of blood sucked. Shakti */
    char buf[MAX_STRING_LENGTH];

    for ( d = descriptor_list; d != NULL; d = d->next )
    {
      
      if ( ( ch = d->character) == NULL )
	continue;

// Too lazy to make another update for monk stuff
// So I'm cheating and using embrace for monks. flaf.

      if ( IS_CLASS(ch, CLASS_MONK) && ch->fighting == NULL )
	ch->monkblock = 0;

      if ( !IS_NPC(ch) && IS_CLASS(ch, CLASS_MONK)
          && ch->focus[MAXIMUM] > 0 && ch->focus[MAXIMUM]
           > ch->focus[CURRENT] )
        {
          if ( ch->position == POS_SLEEPING )
            ch->focus[CURRENT] += number_range(2,3);
          else if ( ch->position == POS_MEDITATING )
            ch->focus[CURRENT] += number_range( 4, 5 );
          else if ( ch->position == POS_RESTING )
            ch->focus[CURRENT] += number_range(1,2);
          else if ( ch->position == POS_FIGHTING )
            ch->focus[CURRENT] += 0;
          else
            ch->focus[CURRENT] += number_range( 1, 2 );
        }

      if ( IS_NPC(ch) || ch->embracing == NULL )
        continue;

	if (!IS_CLASS(ch,CLASS_VAMPIRE))
	  stop_embrace(ch,NULL);

	victim=ch->embracing;

/* Fix for embracing mobs by Shakti.					*/

	if (IS_NPC(victim) )
	{
		if (victim->level > 75 )
		{
			stop_embrace(ch,victim);
			send_to_char("You cannot embrace someone so powerful!\n\r",ch);
			return;
		}
		
	/* To keep how much blood was sucked, and how much gained the same. Shakti */
	
		(blpr =number_range(30,40));
		victim->practice -=blpr;
		ch->pcdata->condition[COND_THIRST] +=blpr;
		
		sprintf(buf, "%s shudders in ecstacy as he drinks blood from %s's neck.\n\r", ch->name,victim->short_descr);
	    act(buf,ch,NULL,NULL,TO_ROOM);
	    sprintf(buf, "You shudder in ecstacy as you drink blood from %s's neck.\n\r",victim->short_descr);
	    send_to_char(buf,ch);
	    
		if (victim->practice < 0)
		{
			victim->practice = 0;
		}

		if (victim->practice == 0)
		
		{
	     raw_kill(victim);
	     sprintf(buf,"%s's body falls lifless to the ground!.\n\r",victim->short_descr);
	     act(buf,ch,NULL,NULL,TO_ROOM);
	     send_to_char(buf,ch);
	     stop_embrace(ch,victim);
		 return;
		}

		if ( ch->pcdata->condition[COND_THIRST] > (3000 /
ch->generation))
		{
	 	  ch->pcdata->condition[COND_THIRST] = (3000 /
ch->generation);
		  stc("Your bloodlust is sated.\n\r",ch);
		}

		continue;
	}



	if (get_char_world(ch,victim->name) == NULL)
	  {stop_embrace(ch,NULL);continue;}
	if (ch->in_room != victim->in_room)
	  stop_embrace(ch,victim);
	if (victim->pcdata->condition[COND_THIRST] < 0)
	  victim->pcdata->condition[COND_THIRST] = 0;
       
	ch->pcdata->condition[COND_THIRST] += number_range(30,40);
    sprintf(buf, "%s shudders in ecstacy as he drinks blood from %s's neck.\n\r", ch->name,victim->name);
	act(buf,ch,NULL,NULL,TO_ROOM);
	sprintf(buf, "You shudder in ecstacy as you drink blood from %s's neck.\n\r",victim->name);
	send_to_char(buf,ch);
	sprintf(buf, "You feel some of your life slip away as %s drinks from your neck.\n\r", ch->name);
	send_to_char(buf,victim);
	ch->pcdata->condition[COND_THIRST] += number_range(35,40);
	victim->pcdata->condition[COND_THIRST] -= number_range(40,42);
	if (ch->pcdata->condition[COND_THIRST] > 3000/ch->generation)
	{ch->pcdata->condition[COND_THIRST]=3000/ch->generation;
	send_to_char("Your bloodlust is sated.\n\r",ch);}
	if (victim->pcdata->condition[COND_THIRST] < 0)
	  victim->pcdata->condition[COND_THIRST]=0;
	if (victim->pcdata->condition[COND_THIRST] ==0)
	{
	  sprintf(buf,"You have been diablerized!\n\r");
	  send_to_char(buf,victim);
	  raw_kill(victim);
	  sprintf(buf,"%s's body falls lifeless to the ground.\n\r",victim->name);
	  act(buf,ch,NULL,NULL,TO_ROOM);
	  send_to_char(buf,ch);
	  stop_embrace(ch,victim);
     	  if (victim->generation < ch->generation && ch->generation > 3)
  	  {
	    sprintf(buf,"%s has been diablerized by %s.",victim->name,ch->name);
	    ch->generation -= 1;
	    victim->generation += 1;
	    victim->pcdata->condition[COND_THIRST] = 0;
	    do_info(ch,buf);
	  }
	  else
  	  {
	    sprintf(buf,"%s has been diablerized by %s for no generation.", victim->name,ch->name);
	    victim->pcdata->condition[COND_THIRST] = 0;
	    do_info(ch,buf);
	  }
    }
    continue; 
  }
  return;
}

void ww_update( void )
{
    DESCRIPTOR_DATA *d;
    CHAR_DATA       *victim;
    float            dam = 0;

    for ( d = descriptor_list; d != NULL; d = d->next )
      {
      if (!IS_PLAYING(d) || (victim = d->character) == NULL
        || IS_NPC(victim) || IS_IMMORTAL(victim)
	|| victim->in_room == NULL || victim->pcdata->chobj != NULL
        || IS_CLASS(victim,CLASS_WEREWOLF))
	{
            continue;
        }
      if ( !IS_SET( d->character->in_room->room_flags, ROOM_BLADE_BARRIER ) )
        continue;

      act( "The scattered blades on the ground fly up into the air ripping into you.", d->character, NULL, NULL, TO_CHAR );
      act( "The scattered blades on the ground fly up into the air ripping into $n.", d->character, NULL, NULL, TO_ROOM );

      act( "The blades drop to the ground inert.", d->character, NULL, NULL, TO_CHAR );
      act( "The blades drop to the ground inert.", d->character, NULL, NULL, TO_ROOM );

      dam = number_range( 7, 14 );
      dam = dam / 100;
      dam = d->character->hit * dam;
      if ( dam < 100 ) dam = 100;
      d->character->hit = d->character->hit - dam;
      if ( d->character->hit < -10 ) d->character->hit = -10;
      update_pos( victim );
      }

    return;
}


/*
 * Handle all kinds of updates.
 * Called once per pulse from game loop.
 * Random times to defeat tick-timing clients and players.
 */
void update_handler( void )
{
    static  int     pulse_area;
    static  int     pulse_mobile;
    static  int     pulse_violence;
    static  int     pulse_point;
    static  int     pulse_ww;
    static  int     pulse_embrace;
    static int pulse_db_dump;   /* OLC 1.1b */

    /* OLC 1.1b */
    if ( --pulse_db_dump  <= 0 )
    {
        pulse_db_dump   = PULSE_DB_DUMP;
        do_asave( NULL, "" );
    }

    if ( --pulse_ww       <= 0 )
    {
        pulse_ww        = PULSE_WW;
        ww_update       ( );
    }

    if ( --pulse_area     <= 0 )
    {
	pulse_area	= number_range( PULSE_AREA / 2, 3 * PULSE_AREA / 2 );
	area_update	( );
    }

    if ( --pulse_mobile   <= 0 )
    {
	pulse_mobile	= PULSE_MOBILE;
	mobile_update	( );
    }

    if ( --pulse_violence <= 0 )
    {
	pulse_violence	= PULSE_VIOLENCE;
	violence_update	( );
    }
    if ( --pulse_embrace <= 0)
    {
        pulse_embrace = PULSE_EMBRACE;
        embrace_update ( ); 
    }
    if ( --pulse_point    <= 0 )
    {
	pulse_point     = number_range( PULSE_TICK / 2, 3 * PULSE_TICK / 2 );
	weather_update	( );
	char_update	( );
	obj_update	( );
        room_update	( );
    }

    aggr_update( );
    tail_chain( );
    return;
}



#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"

void do_setgentick(CHAR_DATA *ch,char *argument)
{
char arg[MAX_INPUT_LENGTH];
int value;
one_argument(argument,arg);
value=is_number(arg) ? atoi(arg):-1;
ch->pcdata->gentick=value;
send_to_char("Ok.\n\r",ch);

return;
}
void do_testemb(CHAR_DATA *ch, char *argument  )
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    char buf[MAX_STRING_LENGTH];
    one_argument( argument,arg);
 
    if (IS_NPC(ch)) return;
    if (!IS_CLASS(ch,CLASS_VAMPIRE))
    {
    send_to_char("Huh?\n\r",ch);
    return;
    }
    if ( arg[0] == '\0' && ch->embracing==NULL)
    {
        send_to_char( "Who do you wish to embrace?\n\r", ch );
	return;
    }
if (ch->embracing != NULL)
{
    if ((victim=ch->embracing) != NULL)
    {
    send_to_char("You retract your fangs.",ch);
    act("$N retracts his fangs.",ch,NULL,NULL,TO_ROOM);
    stop_embrace(ch,victim);
    return;
    }
}
    if ((victim = get_char_room( ch, arg)) == NULL && ch->embracing==NULL)
    {
    send_to_char("They arent here.\n\r",ch);
    return;
    }
    if (IS_NPC(victim) || !IS_CLASS(ch,CLASS_VAMPIRE))
    {
    send_to_char("You can only embrace vampires.\n\r",ch);
    return;
    }
  
    if (victim->position != POS_MORTAL)
    {
    send_to_char("You can only embrace mortally wounded vampires.\n\r",ch);
    return;
    }
    sprintf(buf,
    "%s leaps toward %s baring his fangs.",ch->name,victim->name);
    act(buf,ch,NULL,NULL,TO_ROOM);
    sprintf(buf,
    "You leap toward %s baring your fangs.\n\r",victim->name);
    send_to_char(buf,ch);
    WAIT_STATE(ch, 15);
    
    sprintf(buf,
    "You sink your teeth into their throat.\n\r");
    send_to_char(buf,ch);
    sprintf(buf,
    "%s sinks their teeth into %s's throat."
    ,ch->name,victim->name);
    act(buf,ch,NULL,NULL,TO_ROOM);
    sprintf(buf,
    "%s sinks their teeth into your throat.\n\r",ch->name);
    send_to_char(buf,victim);
    victim->embraced=ch;
    ch->embracing=victim;
 
 
    return;
 
}

void do_conceal(CHAR_DATA *ch, char *argument)
{
char arg[MAX_STRING_LENGTH];
char buf[MAX_STRING_LENGTH];
OBJ_DATA *obj; 
one_argument(argument,arg);
if (IS_NPC(ch)) return;
if (!IS_CLASS(ch,CLASS_VAMPIRE))
{send_to_char("Huh?\n\r",ch);return;}
if (ch->power[DISC_VAMP_OBFU] < 5)
{send_to_char("You need obfuscate 5 to conceal items.\n\r",ch);return;}
if (arg[0]== '\0')
{send_to_char("Syntax: Conceal (item).\n\r",ch);return;}
if ((obj=get_obj_carry(ch,arg)) == NULL)
{send_to_char("You dont have that item.\n\r",ch);return;}
if (IS_SET(obj->extra_flags, ITEM_INVIS))
{
sprintf(buf,"%s fades into existance.",obj->short_descr);
send_to_char(buf,ch);act(buf,ch,NULL,NULL,TO_ROOM);
REMOVE_BIT(obj->extra_flags, ITEM_INVIS);
return;
}
if (!IS_SET(obj->extra_flags, ITEM_INVIS))
{
sprintf(buf,"%s fades out of existance.",obj->short_descr);
send_to_char(buf,ch);act(buf,ch,NULL,NULL,TO_ROOM);
SET_BIT(obj->extra_flags, ITEM_INVIS);
return;
}
 
return;
}

void do_fear( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char arg[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];

    argument = one_argument( argument, arg );

    if ( IS_NPC(ch) ) return;

    if ( !IS_CLASS(ch, CLASS_VAMPIRE) )
    {
	stc("Huh?\n\r",ch);
	return;
    }

    if ( ch->power[DISC_VAMP_DAIM] < 2 )
    {
      stc("You must obtain level 2 Daimoinon to use Fear.\n\r",ch);
      return;
    }

    if ( ( victim = get_char_room( ch, arg) ) == NULL )
    {
      stc("They aren't here.\n\r",ch);
      return;
    }

    arg[0] = UPPER(arg[0]);    

    if ( ch->fighting == NULL )
    {
      stc("You must be fighting to use Fear.\n\r",ch);
      return;
    }

    if ( victim->fighting == NULL )
    {
      sprintf(buf, "%s is not fighting anyone.", arg);
      stc(buf, ch);
      return;
    }  

    WAIT_STATE( ch, 16 );

    if ( IS_NPC(victim) )
    {
      act("You bare your fangs and growl at $N.",ch,NULL,victim,TO_CHAR);
      act("$n bares $s fangs and growls at you.",ch,NULL,victim,TO_VICT);
      act("$n bares $s fangs and growls at $N, and $N flees in terror.",ch,NULL,victim,TO_NOTVICT);
      do_flee( victim, "" );
      return;
    }

    if ( !IS_NPC(victim) )
    {
      if ( ch->power[DISC_VAMP_DAIM] < 5 )
      {
        if ( number_range( 1, 4 ) != 2 )
        {
          act("You bare your fangs and growl at $N, but nothing happens.",ch,NULL,victim,TO_CHAR);
          act("$n bares $s fangs and growls at you.",ch,NULL,victim,TO_VICT);
          act("$n bares $s fangs and growls at $N, but nothing happens.",ch,NULL,victim,TO_NOTVICT);
	  return;
        }
      }

      act("You bare your fangs and growl at $N.",ch,NULL,victim,TO_CHAR);
      act("$n bares $s fangs and growls at you.",ch,NULL,victim,TO_VICT);
      act("$n bares $s fangs and growls at $N, and $N flees in terror.",ch,NULL,victim,TO_NOTVICT);
      do_flee( victim, "" );
      return;
    }

  return;

}

void do_vtwist(CHAR_DATA *ch, char *argument)
{
  char arg1[MAX_STRING_LENGTH];
  char arg2[MAX_STRING_LENGTH];
  OBJ_DATA *obj; 
 
  argument=one_argument(argument,arg1);
  strcpy(arg2,argument);

  if (IS_NPC(ch)) return;

  if (!IS_CLASS(ch,CLASS_VAMPIRE))
  {
    send_to_char("Huh?\n\r",ch);
    return;
  }

  if (ch->power[DISC_VAMP_DAIM] < 5)
  {
    send_to_char("You must obtain level 5 Daimoinon to use Twist.\n\r",ch);
    return;
  }

  if (arg1 == NULL || arg2 == NULL)
  {
    send_to_char("Syntax: Dub (item) (description)?\n\r",ch);
    return;
  }

  if ((obj=get_obj_carry(ch,arg1)) == NULL)
  {
    send_to_char("You dont have that item.\n\r",ch);
    return;
  }

  if (strlen(arg2) > 40 || strlen(arg2) < 3)
  {
    send_to_char("From 3 to 40 characters please.\n\r",ch);
    return;
  }

  free_string(obj->name);
  obj->name = str_dup(arg2);
  free_string(obj->short_descr);
  obj->short_descr=str_dup(arg2);
  send_to_char("Ok.\n\r",ch);
  return;

}

void do_dub(CHAR_DATA *ch, char *argument)
{
char arg1[MAX_STRING_LENGTH];
char arg2[MAX_STRING_LENGTH];
OBJ_DATA *obj; 
 
argument=one_argument(argument,arg1);
strcpy(arg2,argument);
if (IS_NPC(ch)) return;
if (!IS_CLASS(ch,CLASS_VAMPIRE))
{send_to_char("Huh?\n\r",ch);return;}
if (ch->power[DISC_VAMP_OBFU] < 4)
{send_to_char("You need obfuscate 4 to dub items.\n\r",ch);return;}
if (arg1 == NULL || arg2 == NULL)
{send_to_char("Syntax: Dub (item) (description)?\n\r",ch);return;}
if ((obj=get_obj_carry(ch,arg1)) == NULL)
{send_to_char("You dont have that item.\n\r",ch);return;}
if (strlen(arg2) > 40 || strlen(arg2) < 3)
{send_to_char("From 3 to 40 characters please.\n\r",ch);return;}
free_string(obj->name);
obj->name = str_dup(arg2);
free_string(obj->short_descr);
obj->short_descr=str_dup(arg2);
send_to_char("Ok.\n\r",ch);
return;
}

void do_sharpen(CHAR_DATA *ch, char *argument)
{
  char arg[MAX_STRING_LENGTH];
  OBJ_DATA *obj;
  argument=one_argument(argument,arg);
  if (IS_NPC(ch)) return;
 
  if (!IS_CLASS(ch,CLASS_VAMPIRE))
  {
     send_to_char("Huh?\n\r",ch);
     return;
  }

  if (ch->power[DISC_VAMP_QUIE] < 7)
  {
     send_to_char("You need Quetius 7 to sharpen.\n\r",ch);
     return;
  }

  if (arg[0] == '\0')
  {
     send_to_char("What do you wish to sharpen?\n\r",ch);
     return;
  }

  if ( ( obj = get_obj_carry(ch,arg) ) == NULL )
  {
     send_to_char("You dont have that weapon.\n\r",ch);
     return;
  }

  if (IS_SET(obj->quest, QUEST_ARTIFACT) || obj->item_type != ITEM_WEAPON)
  {
     send_to_char("You cant sharpen that item.\n\r",ch);
     return;
  }

  if (obj->value[0] == 18000)
  {
     send_to_char("This item is already Sharp!\n\r",ch);
     return;
  }

  if (obj->value[0] != 0)
  {
     send_to_char(" This weapon already has a power.\n\r",ch);
     return;
  }

  obj->value[0] = 18000;
  obj->value[1] = 20;
  obj->value[2] = 30;

  /*mite as well recycle the arg string*/
  sprintf(arg, "You grind away at %s until it is razor sharp!", obj->short_descr);
  send_to_char(arg,ch);
  sprintf(arg, "%s grinds away at %s until it is razor sharp!", ch->name,obj->short_descr);
  act(arg,ch,NULL,NULL,TO_ROOM);
  return;
}
 
 

/*gourge*/
void do_gourge(CHAR_DATA *ch, char *argument  )
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    char buf[MAX_STRING_LENGTH];
   one_argument( argument,arg);
 
    if (IS_NPC(ch)) return;
    if (!IS_CLASS(ch,CLASS_VAMPIRE))
    {
    send_to_char("Huh?\n\r",ch);
    return;
    }
   if (ch->power[DISC_VAMP_THAU] < 8)
   {
   send_to_char("You need Thaumaturgy 8 to Gourge.\n\r",ch);
   return;
   }
    if ( arg[0] == '\0' )
    {
        send_to_char( "Who do you wish to gourge?\n\r", ch );
	return;
    }
    if ((victim = get_char_room( ch, arg)) == NULL)
    {
    send_to_char("They arent here.\n\r",ch);
    return;
    }
	if (IS_NPC(victim) && IS_SET(victim->act, ACT_NOAUTOKILL)) {
	send_to_char("You can't do that to them.\n\r",  ch);
	return;}

    if (!IS_NPC(victim))
    {
    send_to_char("You cannot gourge a person.\n\r",ch);
    return;
    }
    if (victim->level > 30)
    {
    send_to_char(
    "Only small creatures are defenceless enough to be gourged on.\n\r",ch);
    return;
    }
    sprintf(buf,
    "%s leaps toward %s baring his fangs.",ch->name,victim->name);
    act(buf,ch,NULL,NULL,TO_ROOM);
    sprintf(buf,
    "You leap toward %s baring your fangs.\n\r",victim->name);
    send_to_char(buf,ch);
    WAIT_STATE(ch, 15);
    
    send_to_char(
    "You rip their throat out and gourge on the blood.\n\r",ch);
    sprintf(buf,
    "%s rips %s's throat out, gourging on all of their blood."
    ,ch->name,victim->name);
    act(buf,ch,NULL,NULL,TO_ROOM);
    ch->pcdata->condition[COND_THIRST] += number_range(100,200);
    if (ch->pcdata->condition[COND_THIRST] >= 1000 /
ch->generation)
    {
    send_to_char("Your bloodlust is sated.\n\r",ch);
    ch->pcdata->condition[COND_THIRST] = 1000/ch->generation;
    }
    sprintf(buf,
    "%s body falls to the ground lifeless.",victim->name);
    send_to_char(buf,ch);
    act(buf,ch,NULL,NULL,TO_ROOM);
    raw_kill( victim );
    return;
}

/*bloodwater*/
 
void do_bloodwater( CHAR_DATA *ch, char *argument )
{
CHAR_DATA *victim;
char arg1 [MAX_INPUT_LENGTH];
int dam;
 
argument = one_argument( argument, arg1 );
 
 
if ( IS_NPC(ch) )
    return;
 
 
if (!IS_CLASS(ch, CLASS_VAMPIRE))
     {
          send_to_char("Huh?\n\r",ch);
      return;
 }
 
if (ch->power[DISC_VAMP_NECR] < 5)
 {
send_to_char(
"You need at least level 5 Necromancy to use Blood Water.\n\r",ch);
    return;
 }
 
 
if ( arg1[0] == '\0' )
{
send_to_char( "Whose blood do you wish to turn to water?\n\r", ch );
   return;
}
 if ( ( victim = get_char_room( ch, arg1 ) ) == NULL )
{
    send_to_char( "They aren't here.\n\r", ch );
   return;
}
 
 
if (is_safe(ch,victim) == TRUE) return;
if (IS_NPC(victim)) dam=2000;
if (!IS_NPC(victim)) dam=1000;
if (!IS_CLASS(victim,CLASS_VAMPIRE)) victim->hit -= dam;
    act(
    "$N screams in agony as you turn his blood to water.",
   ch, NULL, victim,TO_CHAR);
act("$N screams in agony as $n turns his blood to water.",
 ch, NULL, victim,TO_NOTVICT);
act("You scream in agony as $n turns your blood to water.",
ch, NULL, victim,TO_VICT);
if (!IS_CLASS(victim,CLASS_VAMPIRE))    WAIT_STATE(ch,12);
if (IS_CLASS(victim,CLASS_VAMPIRE))
{
WAIT_STATE(ch,6);
victim->pcdata->condition[COND_THIRST] -= 150;
}
return;
}
/*spew*/
void do_spew( CHAR_DATA *ch, char *argument )
{
char  buf[MAX_INPUT_LENGTH];
int   sn;  
int   level;
int   spelltype;
 
 
    if ( IS_NPC(ch) )return;
 
if (!IS_CLASS(ch, CLASS_VAMPIRE))
        {
        send_to_char("Huh?\n\r", ch);
        return;
    }
    if ( IS_CLASS(ch, CLASS_VAMPIRE) &&
    ch->power[DISC_VAMP_THAU] < 6)
    {
    send_to_char(
    "You need level 6 Thaumaturgy to use this power.\n\r",ch);
    return; 
    }
if (ch->pcdata->condition[COND_THIRST] < 20)
{send_to_char("You need 20 blood to spew.\n\r",ch);return;}
ch->pcdata->condition[COND_THIRST] -= number_range(18,22);
 
if (IS_SET(ch->in_room->room_flags, ROOM_SAFE))
{
send_to_char("You cannot do that here.\n\r",ch);
return;
}
if ( ( sn = skill_lookup( "spew" ) ) < 0 )
{
sprintf(buf,"Yep, sn is bieng set to %d.",sn);
send_to_char(buf,ch);
return;
 
}
 
spelltype = skill_table[sn].target;
level = ch->power[DISC_VAMP_THAU];
(*skill_table[sn].spell_fun) ( sn, level, ch, NULL);
WAIT_STATE( ch, 12 );
return;
}

/*vampdarkness*/
void do_vampdarkness( CHAR_DATA *ch, char *argument )
{
char buf[MAX_STRING_LENGTH];
ROOM_INDEX_DATA *inroom;   
inroom= ch->in_room;
 
if (IS_NPC(ch)) return;
if (!IS_CLASS(ch, CLASS_VAMPIRE))
{
  send_to_char("Huh?\n\r", ch);
  return;
}
if (ch->power[DISC_VAMP_QUIE] < 6)
{
      send_to_char("You require level 6 Quietus to use Darkness of Death.\n\r",ch);
return;
    }
 
if (ch->pcdata->condition[COND_THIRST] < 300)
{
send_to_char("You have insufficient blood.\n\r", ch);
 return;
}
ch->pcdata->condition[COND_THIRST] -= 300;
SET_BIT(inroom->room_flags, ROOM_DARK);
sprintf(buf,"A look of concentration passes over %s's face.",
ch->name);
act(buf,ch,NULL,NULL,TO_ROOM);
send_to_char("A look of concentration passes over your face.\n\r",ch);
sprintf(buf,"A complete darkness fills the room.\n\r");
act(buf,ch,NULL,NULL,TO_ROOM);
send_to_char(buf,ch);
return;
}
 

/*dragon*/
void do_dragonform( CHAR_DATA *ch, char *argument )
{
char arg [MAX_INPUT_LENGTH];
char buf [MAX_STRING_LENGTH];
argument = one_argument( argument, arg );
 
if (IS_NPC(ch)) return;
 
if (!IS_CLASS(ch, CLASS_VAMPIRE))
    {
     send_to_char("Huh?\n\r",ch);
        return;
}
if (ch->power[DISC_VAMP_VICI] < 4)
{
send_to_char("You must obtain at least level 4 in Vicissitude to use Dragonform\n\r",ch);
return;
}
 
 
if (!IS_POLYAFF(ch, POLY_ZULOFORM))
{
send_to_char("You can only Dragonform while in Zuloform.\n\r",ch);
return;
}
 
if (IS_EXTRA(ch, EXTRA_DRAGON))
{
REMOVE_BIT(ch->extra,EXTRA_DRAGON);
act( "You transform back into zuloform.", ch, NULL, NULL, TO_CHAR );
    act( "$n shrinks back into a big black monster.", ch, NULL, NULL,
TO_ROOM );
    ch->max_hit = ch->max_hit - 500;
ch->hit = ch->hit - 500;
 
if (ch->hit < 1) ch->hit = 1;
    ch->damroll = ch->damroll / 1.2;
ch->hitroll = ch->hitroll / 1.2;
    free_string( ch->morph );
    ch->morph = str_dup( "A big black monster" );
return;
}
 
 
if ( ch->pcdata->condition[COND_THIRST] < 100 )
{
    send_to_char("You have insufficient blood.\n\r",ch);
    return;
}
 
if (ch->mounted == IS_RIDING) do_dismount(ch,"");
ch->pcdata->condition[COND_THIRST] -= number_range(200,400);
    act( "You transform into a large dragon.", ch, NULL, NULL, TO_CHAR );
    act( "$n's body grows and distorts into a large dragon.", ch, NULL,
NULL,TO_ROOM);
SET_BIT(ch->extra,EXTRA_DRAGON);
sprintf(buf, "%s, the huge rabid dragon", ch->name);
free_string( ch->morph );
ch->morph = str_dup( buf );
ch->max_hit = ch->max_hit + 500;
ch->hit = ch->hit + 500;
ch->damroll = ch->damroll * 1.2;
ch->hitroll = ch->hitroll * 1.2;
return;
}

/*obj*/
void do_obj( CHAR_DATA *ch, char *argument )
{
    OBJ_DATA *obj;                              
    OBJ_DATA *obji;
    char buf[MAX_STRING_LENGTH];
    char arg[MAX_STRING_LENGTH];
    argument=one_argument(argument,arg);
    if (IS_NPC(ch)) return;
    if (!IS_CLASS(ch, CLASS_VAMPIRE))
    {
	send_to_char( "Huh?\n\r", ch);
	return;
    }
    if (ch->power[DISC_VAMP_VICI] < 10)
    {
    send_to_char("You require Vicissitude 10 to Object.\n\r",ch);
    return;
    }
    if (IS_AFFECTED(ch,AFF_POLYMORPH) && ch->pcdata->chobj == NULL)
    {
	send_to_char( "You cannot do this while polymorphed.\n\r", ch);
	return;
    }
 
   if (ch->pcdata->obj_vnum != 0)
   {
   do_humanform(ch,"");
   return;
   }
 
   if (arg[0] == '\0')
   {
    send_to_char("Which object in the game do you want to become?\n\r",ch); 
    return;
   }
   if ((obji = get_obj_world(ch,arg)) == NULL)
    {
        send_to_char( "Nothing like that is in the game.\n\r", ch);
	return;
    }
    if (IS_AFFECTED(ch,AFF_WEBBED))
    {
	send_to_char( "Not with all this sticky webbing on.\n\r", ch);
	return;
    }
if (obji->item_type == ITEM_GEMSTONE ||
    obji->item_type == ITEM_HILT     ||
    obji->item_type == ITEM_COPPER   ||
    obji->item_type == ITEM_IRON     ||
    obji->item_type == ITEM_STEEL    ||
    obji->item_type == ITEM_ADAMANTITE||
    obji->item_type == ITEM_QUEST ||
    IS_SET(obji->quest,QUEST_ARTIFACT)
    || IS_SET(obji->quest, QUEST_RELIC))

{send_to_char("You are unable to take the form of that.\n\r",ch);return;}
 
    
   

    obj=create_object(get_obj_index(obji->pIndexData->vnum),60);
    obj_to_room(obj,ch->in_room);
    send_to_char("You concentrate deeply and transform into the basics of the item.\n\r",ch);
    act("$n's form shrinks and distorts into $p.",ch,obj,NULL,TO_ROOM);
    act("Your form shrinks and distorts into $p.",ch,obj,NULL,TO_CHAR);
    ch->pcdata->obj_vnum = obj->pIndexData->vnum;
    sprintf(buf,"%d",ch->pcdata->obj_vnum);
    send_to_char(buf,ch);
    obj->chobj = ch;
    ch->pcdata->chobj = obj;
    SET_BIT(ch->affected_by, AFF_POLYMORPH);
    SET_BIT(ch->extra, EXTRA_OSWITCH);
    free_string(ch->morph);
    ch->morph = str_dup(obj->short_descr);
    return;
}
 
 

/*baal*/
void do_baal(CHAR_DATA *ch, char *argument)
{
    int bloodpool;

    if (ch->generation <= 0)
        ch->generation = 13;

    {
    if (IS_SET(ch->newbits, NEW_TIDE))
    bloodpool = (3000 / ch->generation);
    else bloodpool = (2000 / ch->generation);
    } 

if (IS_NPC(ch)) return;
if (!IS_CLASS(ch,CLASS_VAMPIRE))
{
send_to_char("Huh?\n\r",ch);
return;
}
if (ch->power[DISC_VAMP_DOMI] < 5)
{
send_to_char("You need Dominate 5 to summon the spirit of Baal.\n\r",ch);
return;
}
if (IS_SET(ch->extra, EXTRA_BAAL))
{
send_to_char("You already have the spirit of Baal with you!\n\r",ch);
return;
}
if (ch->pcdata->condition[COND_THIRST] < bloodpool)
{
send_to_char("You need maximum blood to use Baal.\n\r",ch);
return;
}

ch->pcdata->condition[COND_THIRST] = 0;

WAIT_STATE(ch,20);

SET_BIT(ch->extra, EXTRA_BAAL);
ch->power[DISC_VAMP_POTE] += 2;
ch->power[DISC_VAMP_CELE] += 2;
ch->power[DISC_VAMP_FORT] += 2;
send_to_char("You now carry the spirit of Baal.\n\r",ch);
return;
}
 

/*facade*/
void do_facade( CHAR_DATA *ch, char *argument )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    int value;
 
    smash_tilde( argument );
    argument = one_argument( argument, arg1 );
    strcpy( arg2, argument );
 
    if ( IS_NPC(ch) )
	return;
 
    if (!IS_CLASS(ch, CLASS_VAMPIRE) )
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }
    if (ch->power[DISC_VAMP_PRES] < 6 )
    {
        send_to_char("You need presence 6 to facade.\n\r",ch);
	return;
    }
 
    if (arg1[0] != '\0' && !str_cmp(arg1,"on"))
    {
	if (IS_EXTRA(ch, EXTRA_FAKE_CON))
        {send_to_char("You already have Facade on.\n\r",ch); return;}
	SET_BIT(ch->extra, EXTRA_FAKE_CON);
        send_to_char("Your Facade is now ON.\n\r",ch);
	return;
    }
    if (arg1[0] != '\0' && !str_cmp(arg1,"off"))
    {
	if (!IS_EXTRA(ch, EXTRA_FAKE_CON))
        {send_to_char("You already have Facade off.\n\r",ch); return;}
	REMOVE_BIT(ch->extra, EXTRA_FAKE_CON);
        send_to_char("Your Facade is now OFF.\n\r",ch);
	return;
    }
    if ( arg1[0] == '\0' || arg2[0] == '\0' )
    {
	send_to_char("You have the following stats:\n\r",ch);
	sprintf(buf,"Hitroll: %d, Actual: %d.\n\r",
		ch->pcdata->fake_hit, char_hitroll(ch));
	send_to_char(buf, ch);
	sprintf(buf,"Damroll: %d, Actual: %d.\n\r",
		ch->pcdata->fake_dam, char_damroll(ch));
	send_to_char(buf, ch);
	sprintf(buf,"Armour: %d, Actual: %d.\n\r",
		ch->pcdata->fake_ac, char_ac(ch));
	send_to_char(buf, ch);
	sprintf(buf,"Hp: %d, Actual: %d.\n\r",
		ch->pcdata->fake_hp, ch->hit);
	send_to_char(buf, ch);
	sprintf(buf,"Mana: %d, Actual: %d.\n\r",
		ch->pcdata->fake_mana, ch->mana);
	send_to_char(buf, ch);
	sprintf(buf,"Move: %d, Actual: %d.\n\r",
		ch->pcdata->fake_move, ch->move);
	send_to_char(buf, ch);
	return;
    }
    value = is_number( arg2 ) ? atoi( arg2 ) : -10000;
    if (!str_cmp(arg1,"hit") || !str_cmp(arg1,"hitroll"))
    {
	if (value < 0 || value > 1000)
	{
	    send_to_char("Please enter a value between 0 and 1000.\n\r",ch);
	    return;
	}
	ch->pcdata->fake_hit = value;
	send_to_char("Ok.\n\r",ch);
	return;
    }
    if (!str_cmp(arg1,"dam") || !str_cmp(arg1,"damroll"))
    {
	if (value < 0 || value > 1000)
	{
	    send_to_char("Please enter a value between 0 and 1000.\n\r",ch);
	    return;
	}
	ch->pcdata->fake_dam = value;
	send_to_char("Ok.\n\r",ch);
	return;
    }
    if (!str_cmp(arg1,"ac") || !str_cmp(arg1,"armour") ||
!str_cmp(arg1,"armor"))
    {
	if (value < -1000 || value > 100)
	{
	    send_to_char("Please enter a value between -1000 and 100.\n\r",ch);
	    return;
	}
	ch->pcdata->fake_ac = value;
	send_to_char("Ok.\n\r",ch);
	return;
    }
    if (!str_cmp(arg1,"hp") || !str_cmp(arg1,"hitpoints"))
    {
	if (value < 1 || value > 30000)
	{
	    send_to_char("Please enter a value between 1 and 30000.\n\r",ch);
	    return;
	}
	ch->pcdata->fake_hp = value;
	send_to_char("Ok.\n\r",ch);
	return;
    }
    if (!str_cmp(arg1,"mana"))
    {
	if (value < 1 || value > 30000)
	{
	    send_to_char("Please enter a value between 1 and 30000.\n\r",ch);
	    return;
	}
	ch->pcdata->fake_mana = value;
	send_to_char("Ok.\n\r",ch);
	return;
    }
    if (!str_cmp(arg1,"move"))
    {
	if (value < 1 || value > 30000)
	{
	    send_to_char("Please enter a value between 1 and 30000.\n\r",ch);
	    return;
	}
	ch->pcdata->fake_move = value;
	send_to_char("Ok.\n\r",ch);
	return;
    }
    send_to_char("You can set: Hit, Dam, Ac, Hp, Mana, Move.\n\r",ch);
    return;
}

/*wall*/
void do_wall(CHAR_DATA *ch, char *argument)
{
OBJ_DATA *obj = NULL;
OBJ_DATA *objc;
char arg[MAX_STRING_LENGTH];
char wall[MAX_STRING_LENGTH];
char buf[MAX_STRING_LENGTH];
argument=one_argument(argument,arg);
if (IS_NPC(ch)) return;
if (!IS_CLASS(ch,CLASS_VAMPIRE))
{
send_to_char("Huh?\n\r",ch);
return;
}
if (ch->power[DISC_VAMP_DAIM] < 7)
{
send_to_char("You need Daimionon 7 to call Walls of Water.\n\r",ch);
return;
}
if (ch->pcdata->condition[COND_THIRST] < 50)
{
send_to_char("You dont have enough blood.\n\r",ch);
return;
}
if (arg[0] == '\0' || (str_cmp(arg,"n")
                   && str_cmp(arg,"s")
                   && str_cmp(arg,"e")
                   && str_cmp(arg,"w")
                   && str_cmp(arg,"u")
                   && str_cmp(arg,"d")))
{
send_to_char("You may wall n, w, s, e, d or u.\n\r",ch);
return;
}
ch->pcdata->condition[COND_THIRST] -= 50;
sprintf(buf,"A look of concentration passes over %s's face.",ch->name);
act(buf,ch,NULL,NULL,TO_ROOM);
send_to_char("A look of concentration passes over your face.\n\r",ch);
if (!str_cmp(arg,"n")) sprintf(wall,"walln");
if (!str_cmp(arg,"w")) sprintf(wall,"wallw");
if (!str_cmp(arg,"s")) sprintf(wall,"walls");
if (!str_cmp(arg,"e")) sprintf(wall,"walle");
if (!str_cmp(arg,"d")) sprintf(wall,"walld");
if (!str_cmp(arg,"u")) sprintf(wall,"wallu");
objc = get_obj_list(ch,wall,ch->in_room->contents);
if ( objc != NULL)
{
send_to_char("There is already a wall blocking that direction.\n\r",ch);
return;
}
WAIT_STATE(ch,25);
sprintf(buf,"A wall of water pours out of the ground.");
act(buf,ch,NULL,NULL,TO_ROOM);
send_to_char(buf,ch);
if (!str_cmp(arg,"n")) obj=create_object(get_obj_index(30043),0);
if (!str_cmp(arg,"s")) obj=create_object(get_obj_index(30044),0);
if (!str_cmp(arg,"e")) obj=create_object(get_obj_index(30045),0);
if (!str_cmp(arg,"w")) obj=create_object(get_obj_index(30046),0);
if (!str_cmp(arg,"d")) obj=create_object(get_obj_index(30047),0);
if (!str_cmp(arg,"u")) obj=create_object(get_obj_index(30048),0);
obj_to_room(obj,ch->in_room);
obj->timer=3;
obj->item_type = ITEM_WALL; 
return;
}
 
 
 

/*inferno*/
void do_inferno(CHAR_DATA *ch, char *argument)
{
char buf[MAX_STRING_LENGTH];
ROOM_INDEX_DATA *inroom;
 if (IS_NPC(ch)) return;
 inroom= ch->in_room;
 if (!IS_CLASS(ch,CLASS_VAMPIRE))
  {
  send_to_char("Huh?\n\r",ch);
  return;
  }
 if (ch->power[DISC_VAMP_DAIM] < 6)
  {
  send_to_char("You need Daimionon 6 to use Inferno.\n\r",ch);
  return;
  }
 if (IS_SET(ch->in_room->room_flags,ROOM_FLAMING))
  {
  send_to_char("This room is already engulfed in flames!\n\r",ch);
  return;
  }
 if (ch->pcdata->condition[COND_THIRST] < 100)
  {
  send_to_char("You dont have enough blood.\n\r",ch);
  return;
  }
if (IS_SET(ch->in_room->room_flags, ROOM_SAFE))
{
send_to_char("Somthing prevents you from torching this room.\n\r",ch);
return;
}

ch->pcdata->condition[COND_THIRST] -= 100;
SET_BIT(inroom->room_flags,ROOM_FLAMING);
sprintf(buf,"A look of concentration passes over %s's face.\n\r",ch->name);
act(buf,ch,NULL,NULL,TO_ROOM);
send_to_char("A look of concentration passes over your face.\n\r",ch);
sprintf(buf,"This room is engulfed in flames!");
send_to_char(buf,ch);
act(buf,ch,NULL,NULL,TO_ROOM);
return;
}
 
 
 
 

/*zombie*/
void do_zombie(CHAR_DATA *ch, char *argument )
{

    char buf2[MAX_STRING_LENGTH]; 
    char buf [MAX_INPUT_LENGTH];
    char arg [MAX_STRING_LENGTH];
    CHAR_DATA *victim;
    AFFECT_DATA af;
    OBJ_DATA *obj;
    one_argument(argument,arg);
    if (IS_NPC(ch)) return;
    if (!IS_CLASS(ch, CLASS_VAMPIRE))
     {
     send_to_char("Huh?\n\r",ch);
     return;
     }
    if (arg[0] == '\0')
    {
    send_to_char("Zombie what corpse?\n\r",ch);
    return;
    }
    if (ch->power[DISC_VAMP_NECR] < 5)
    {
    send_to_char("You require level 5 Necromancy to create a zombie.\n\r",ch);
    return;
    }
 
    if (ch->pcdata->followers > 5)
    {
	send_to_char("Nothing happens.\n\r",ch);
	return;
    }
    if ((obj = get_obj_carry(ch,arg)) == NULL)
    {
    send_to_char("You dont have that corpse.",ch);
    return;
    }
    if (obj->item_type != ITEM_CORPSE_NPC || IS_SET(obj->quest,
QUEST_ZOMBIE))
    {
    send_to_char("You can only Zombie original corpses.\n\r",ch);
    return;
    }
 
 
    ch->pcdata->followers++;
 
    
    victim=create_mobile( get_mob_index( obj->value[2] ) );
    sprintf(buf,"the zombie of %s",victim->short_descr);
    sprintf(buf2,"the zombie of %s is here.\n\r",victim->short_descr);
    free_string(victim->short_descr);
    victim->short_descr = str_dup(buf);
    free_string(victim->name);
    victim->name = str_dup(buf);
    free_string(victim->long_descr);
    victim->long_descr= str_dup(buf2);
    SET_BIT(victim->extra, EXTRA_ZOMBIE);
 	victim->spec_fun = NULL;
    strcpy(buf,"Rise corpse, and bow before me!");
    do_say( ch, buf );
    sprintf(buf, "%s clambers back up to its feet.\n\r",obj->short_descr
);
    act(buf,ch,NULL,NULL,TO_ROOM);
    send_to_char(buf,ch);
 
 
    char_to_room( victim, ch->in_room );
 
 if (victim->level < 100)
{
    add_follower( victim, ch );
    af.duration  = 666;
    af.location  = APPLY_NONE;
    af.modifier  = 0;
    af.bitvector = AFF_CHARM;
    affect_to_char( victim, &af );
}
WAIT_STATE(ch,10);
extract_obj(obj);
    return;
}

/*fleshcraft*/
void do_fleshcraft( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char      arg [MAX_INPUT_LENGTH];
    char      buf [MAX_INPUT_LENGTH];
 
    argument = one_argument( argument, arg );
 
    if (IS_NPC(ch)) return;
 
    if (!IS_CLASS(ch, CLASS_VAMPIRE))
    {
	send_to_char( "Huh?\n\r", ch );
	return;
    }
 
    if (ch->power[DISC_VAMP_VICI] < 2)
    {
	send_to_char("You need Vicissitude 2 to fleshcraft.\n\r",ch);
	return;
    }
 
    if ( arg[0] == '\0' )
    {
	send_to_char( "Change to look like whom?\n\r", ch );
	return;
    }
 
    if (IS_AFFECTED(ch,AFF_POLYMORPH) && !IS_VAMPAFF(ch,VAM_DISGUISED))
    {
	send_to_char( "Not while polymorphed.\n\r", ch );
	return;
    }
 
    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }
 
    if ( !IS_NPC(victim) && ch != victim)
    {
	send_to_char( "Not on Players.\n\r", ch );
	return;
    }
 
 
    if ( ch->pcdata->condition[COND_THIRST] < 40 )
    {
	send_to_char("You have insufficient blood.\n\r",ch);
	return;
    }
    ch->pcdata->condition[COND_THIRST] -= number_range(30,40);
 
    if ( ch == victim )
    {
	if (!IS_AFFECTED(ch,AFF_POLYMORPH) &&
!IS_VAMPAFF(ch,VAM_DISGUISED))
	{
	    send_to_char( "You already look like yourself!\n\r", ch );
	    return;
	}
        sprintf(buf,"Your flesh molds and transforms into %s.",ch->name);
	act(buf,ch,NULL,victim,TO_CHAR);
        sprintf(buf,"%s's flesh molds and transforms into %s.",ch->morph,ch->name);
	act(buf,ch,NULL,victim,TO_ROOM);
	REMOVE_BIT(ch->affected_by, AFF_POLYMORPH);
	REMOVE_BIT(ch->pcdata->stats[UNI_AFF], VAM_DISGUISED);
    	free_string( ch->morph );
    	ch->morph = str_dup( "" );
	return;
    }
    if (IS_VAMPAFF(ch,VAM_DISGUISED))
    {
        sprintf(buf,"Your flesh molds and transforms into a clone of %s.",victim->short_descr);
    	act(buf,ch,NULL,victim,TO_CHAR);
        sprintf(buf,"%s's flesh molds and transforms into a clone of %s.",ch->morph,victim->short_descr);
    	act(buf,ch,NULL,victim,TO_NOTVICT);
        sprintf(buf,"%s's flesh mols and transforms into a clone of you!",ch->morph);
    	act(buf,ch,NULL,victim,TO_VICT);
    	free_string( ch->morph );
        ch->morph = str_dup( victim->short_descr );
	return;
    }
    sprintf(buf,"Your flesh molds and transforms into a clone of %s.",victim->short_descr);
    act(buf,ch,NULL,victim,TO_CHAR);
    sprintf(buf,"%s's flesh molds and transforms into a clone of %s.",ch->name,victim->short_descr);
    act(buf,ch,NULL,victim,TO_NOTVICT);
    sprintf(buf,"%s's flesh molds and transforms into a clone of you!",ch->name);
    act(buf,ch,NULL,victim,TO_VICT);
    SET_BIT(ch->affected_by, AFF_POLYMORPH);
    SET_BIT(ch->pcdata->stats[UNI_AFF], VAM_DISGUISED);
    free_string( ch->morph );
    ch->morph = str_dup( victim->short_descr );
    return;
}

/*entrance*/
void do_entrance( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char arg [MAX_INPUT_LENGTH];
    int sn;
    int level;
    int spelltype;
    char buf[MAX_STRING_LENGTH];
    argument = one_argument( argument, arg );
 
    if (IS_NPC(ch)) return;
 
    if (!IS_CLASS(ch, CLASS_VAMPIRE)) 
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }
    if (ch->power[DISC_VAMP_PRES] < 3)
    {
 send_to_char("You need presence 3 to entrance.\n\r",ch);
 return;
 }
 
    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }
 
    if ( ch == victim )
    {
  send_to_char( "You cannot entrance yourself.\n\r", ch );
	return;
    }
 
    if ( IS_AFFECTED(victim, AFF_ETHEREAL) )
    {
   send_to_char( "You cannot entrance an ethereal person.\n\r", ch );
	return;
    }
if (is_safe(ch,victim) == TRUE) return;
sprintf(buf,"A look of concentration crosses your face.");
act(buf,ch,NULL,NULL,TO_CHAR);
sprintf(buf,"A look of concentration crosses over $n's face.\n\r");
act(buf,ch,NULL,victim,TO_ROOM);
 
    if ( ( sn = skill_lookup( "charm" ) ) < 0 ) return;
    spelltype = skill_table[sn].target;
    level = ch->power[DISC_VAMP_PRES] * 40;
    (*skill_table[sn].spell_fun) ( sn, level, ch, victim );
    WAIT_STATE( ch, 12 );
    return;
}

/*tendrils*/
void do_tendrils( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char arg [MAX_INPUT_LENGTH];
    int sn;
    int level;
    int spelltype;
 
    argument = one_argument( argument, arg );
 
    if (IS_NPC(ch)) return;
 
    if (!IS_CLASS(ch, CLASS_VAMPIRE)) 
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }
    if (ch->power[DISC_VAMP_SERP] < 4)
    {
 send_to_char("you need level 4 serpentis to use Arms of the
Abyss.\n\r",ch);
 return;
 }
 
    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }
 
    if ( ch == victim )
    {
  send_to_char( "You cannot use Arms of the Abyss on yourself.\n\r", ch );
	return;
    }
 
    if ( IS_AFFECTED(victim, AFF_ETHEREAL) )
    {
   send_to_char( "You cannot Arms of Abyss an ethereal person.\n\r", ch );
	return;
    }
 if (is_safe(ch,victim) == TRUE) return;
    if ( ( sn = skill_lookup( "tendrils" ) ) < 0 ) return;
    spelltype = skill_table[sn].target;
    level = ch->spl[spelltype] * 0.25;
    (*skill_table[sn].spell_fun) ( sn, level, ch, victim );
    WAIT_STATE( ch, 12 );
    return;
}

/*lamprey*/
void do_lamprey( CHAR_DATA *ch, char *argument )
{
CHAR_DATA *victim;
 
char buf[MAX_STRING_LENGTH];
 
int dam;
int bloodpool;

    if (ch->generation <= 0)
        ch->generation = 4;

    {
    if (IS_SET(ch->newbits, NEW_TIDE))
    bloodpool = (3000 / ch->generation);
    else bloodpool = (2000 / ch->generation);
    } 
if (IS_NPC(ch)) return;
if (!IS_CLASS(ch,CLASS_VAMPIRE))
{
send_to_char("Huh?\n\r",ch);
return;
}
if (ch->power[DISC_VAMP_OBTE] < 5)
{
send_to_char("You need level 5 Obtenebration to Lamprey.\n\r",ch);
    return;
 
send_to_char("You need level 5 Obtenebration to Lamprey.\n\r",ch);
    return;
    }
 
 
if ( ( victim = ch->fighting ) == NULL )
{
send_to_char( "You aren't fighting anyone.\n\r", ch );
      return;
 
}
WAIT_STATE( ch, 5 );
 
 
if (!IS_NPC(victim))
{
dam = ch->power[DISC_VAMP_OBTE] * 20;
}
else if (IS_NPC(victim))
{
dam = ch->power[DISC_VAMP_OBTE] * 100;
}
if ( !IS_NPC(victim) && IS_CLASS(victim, CLASS_WEREWOLF) )
{
    if (victim->power[DISC_WERE_BOAR] > 2 ) dam *= 0.5;
}
if (is_safe(ch,victim) == TRUE) return; 
dam += number_range(1,30);
if ( dam <= 0 )
   dam = 1;
 

sprintf(buf,"Your tendrils of darkness hits $N incredibly hard! [%d]\n\r",dam);
act(buf,ch,NULL,victim,TO_CHAR);
sprintf(buf,"$n's tendrils of darkness hits you incredibly hard! [%d]\n\r",dam);
act(buf,ch,NULL,victim,TO_VICT);
sprintf(buf,"$n's tendrils of darkness hits $N incredibly hard! [%d]\n\r",dam);
act(buf,ch,NULL,victim,TO_NOTVICT);
 
 

send_to_char("\n\r",ch);
victim->hit -= dam;
ch->pcdata->condition[COND_THIRST] += number_range(40,50);
if (ch->pcdata->condition[COND_THIRST]>bloodpool)
{
send_to_char("Your bloodlust is sated.\n\r",ch);
ch->pcdata->condition[COND_THIRST] = bloodpool;
}
return;
}
 
 
 
 
 
 

/*clone*/
void do_clone( CHAR_DATA *ch, char *argument )
{
    char arg1[MAX_INPUT_LENGTH];
    OBJ_INDEX_DATA *pObjIndex;
    OBJ_DATA *obj;
    OBJ_DATA *obj2;
    AFFECT_DATA *paf;
    AFFECT_DATA *paf2;
 
    argument = one_argument( argument, arg1 );
    if (IS_NPC(ch)) return;
    if (!IS_CLASS(ch, CLASS_VAMPIRE))
    {
    send_to_char("Huh?\n\r",ch);
    return;
    }
    if (ch->power[DISC_VAMP_CHIM] < 3)
    {
    send_to_char("You need Chimeristry 3 to clone objects.\n\r",ch);
    return;
    }
 
 
    if ( arg1[0] == '\0' )
    {
        send_to_char( "Make a clone of what object?\n\r", ch );
        return;
    }
 
    if ( ( obj = get_obj_carry( ch, arg1 ) ) == NULL )
    {
        send_to_char( "You dont have that item.\n\r", ch );
	return;
    }
 
   if (obj->points > 0
   || IS_SET(obj->quest, QUEST_ARTIFACT)
   || IS_SET(obj->quest, QUEST_RELIC)
   || (obj->chobj) != NULL
||    obj->item_type == ITEM_GEMSTONE 
||    obj->item_type == ITEM_HILT     
||    obj->item_type == ITEM_COPPER   
||    obj->item_type == ITEM_IRON     
||    obj->item_type == ITEM_STEEL    
||    obj->item_type == ITEM_ADAMANTITE
||    obj->item_type == ITEM_QUEST 
||    obj->item_type == ITEM_QUESTCARD    
||    obj->item_type == ITEM_DTOKEN)   

   {

   send_to_char("You cant clone that object.\n\r",ch);
   return;
   }
 
 
    pObjIndex = get_obj_index( obj->pIndexData->vnum);
    obj2 = create_object( pObjIndex, obj->level );
    /* Copy any changed parts of the object. */
    free_string(obj2->name);
    obj2->name=str_dup(obj->name);
    free_string(obj2->short_descr);
    obj2->short_descr=str_dup(obj->short_descr);
    free_string(obj2->description);
    obj2->description=str_dup(obj->description);
 
    if (obj->questmaker != NULL && strlen(obj->questmaker) > 1)
    {
	free_string(obj2->questmaker);
	obj2->questmaker=str_dup(obj->questmaker);
    }
 
    if (obj->chpoweron != NULL)
    {
    	free_string(obj2->chpoweron);
    	obj2->chpoweron=str_dup(obj->chpoweron);
    }
    if (obj->chpoweroff != NULL)
    {
    	free_string(obj2->chpoweroff);
    	obj2->chpoweroff=str_dup(obj->chpoweroff);
    }
    if (obj->chpoweruse != NULL)
    {
    	free_string(obj2->chpoweruse);
    	obj2->chpoweruse=str_dup(obj->chpoweruse);
    }
    if (obj->victpoweron != NULL)
    {
    	free_string(obj2->victpoweron);
    	obj2->victpoweron=str_dup(obj->victpoweron);
    }
    if (obj->victpoweroff != NULL)
    {
    	free_string(obj2->victpoweroff);
    	obj2->victpoweroff=str_dup(obj->victpoweroff);
    }
    if (obj->victpoweruse != NULL)
    {
    	free_string(obj2->victpoweruse);
    	obj2->victpoweruse=str_dup(obj->victpoweruse);
    }
    obj2->item_type 	= obj->item_type;
    obj2->extra_flags 	= obj->extra_flags;
    obj2->wear_flags 	= obj->wear_flags;
    obj2->weight 	= obj->weight;
    obj2->spectype 	= obj->spectype;
    obj2->specpower 	= obj->specpower;
    obj2->condition 	= obj->condition;
    obj2->toughness 	= obj->toughness;
    obj2->resistance 	= obj->resistance;
    obj2->quest 	= obj->quest;
    obj2->points 	= obj->points;
    obj2->cost 		= obj->cost;
    obj2->value[0] 	= obj->value[0];
    obj2->value[1] 	= obj->value[1];
    obj2->value[2] 	= obj->value[2];
    obj2->value[3] 	= obj->value[3];
    /*****************************************/
    obj_to_char(obj2,ch);
 
    if (obj->affected != NULL)
    {
    	for ( paf = obj->affected; paf != NULL; paf = paf->next )
    	{
	    if (affect_free == NULL)
	        paf2 = alloc_perm( sizeof(*paf) );
	    else
	    {
		paf2 = affect_free;
		affect_free = affect_free->next;
	    }
	    paf2->type  	= 0;
	    paf2->duration	= paf->duration;
	    paf2->location	= paf->location;
	    paf2->modifier	= paf->modifier;
	    paf2->bitvector	= 0;
	    paf2->next  	= obj2->affected;
	    obj2->affected	= paf2;
    	}
    }
    obj2->timer = ch->power[DISC_VAMP_CHIM] * 2;
SET_BIT(obj2->quest, QUEST_CLONED);    
act( "A clone of $p appears in your hands in a flash of light.", ch, obj, NULL, TO_CHAR );
    act( "A clone of $p appears in $n's hands in a flash of light.", ch, obj, NULL, TO_ROOM );
 if (obj->questmaker != NULL) free_string(obj->questmaker);
    obj->questmaker = str_dup(ch->name);	
   WAIT_STATE(ch, 16);
    return;
}

/*assassinate*/
void do_assassinate( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    char buf[MAX_STRING_LENGTH];
    int dam;
    argument = one_argument( argument, arg );
 
 
    if(!IS_CLASS(ch,CLASS_VAMPIRE))
    {
    send_to_char("Huh?\n\r",ch);
    return;
    }
    if (ch->power[DISC_VAMP_QUIE] < 4)
    {
    send_to_char("You need Quietus level 4 to Assassinate.\n\r",ch);
    return;
    }
 
    if ( arg[0] == '\0' )
    {
        send_to_char( "Assassinate whom?\n\r", ch );
	return;
    }
 
 
    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }
 
    if ( victim == ch )
    {
        send_to_char( "How can you assassinate yourself?\n\r", ch );
	return;
    }
 
	if (!IS_NPC(victim) && !str_cmp(victim->pcdata->switchname, "SirMog")) 
	return;

    if (is_safe(ch,victim) == TRUE) return;
 
    if ( victim->fighting != NULL )
    {
        send_to_char( "You can't assassinate a fighting person.\n\r", ch
);
	return;
    }
 
    if ( victim->hit < victim->max_hit )
    {
	act( "$N is hurt and suspicious ... you can't sneak up.",
	    ch, NULL, victim, TO_CHAR );
	return;
    }
    if (!IS_AFFECTED(ch, AFF_HIDE))
    {
    send_to_char("You must be hidden to assassinate!\n\r",ch);
    return;
    }
WAIT_STATE(ch,15);
    if (number_percent( ) < 5)
    {
    sprintf(buf,"%s has been assassinated by %s.",victim->name,ch->name);
    do_info(ch,buf);
    victim->hit = 1;
    ch->fighting = victim;
    send_to_char("You spin around and throw a headbutt to finish him.\n\r",ch);
    damage(ch,victim,11,gsn_headbutt);
    return;
    }

    if (!IS_NPC(victim)) dam = ch->power[DISC_VAMP_QUIE] * 200;
    if (IS_NPC(victim)) dam = ch->power[DISC_VAMP_QUIE] * 400;
dam += number_range(1,20);
sprintf(buf,"Your assassination hits $N incredibly hard! [%d]",dam);
act(buf,ch,NULL,victim,TO_CHAR);
sprintf(buf,"$n's assassination hits you incredibly hard! [%d]\n\r",dam);
act(buf,ch,NULL,victim,TO_VICT);
sprintf(buf,"$n's assassination hits $N incredibly hard! [%d]\n\r",dam);
act(buf,ch,NULL,victim,TO_NOTVICT);
 
if (dam > victim->hit) dam = victim->hit-1;
victim->hit -= dam;
ch->fighting = victim;
victim->fighting = ch;
if (victim->hit <= 1)
{
victim->hit = 1;
send_to_char("You spin around and throw a headbutt to finish him.\n\r",ch);
ch->fighting=victim;
damage(ch,victim,11,gsn_headbutt);

}

   return;
}

/*mindblast*/
void do_mindblast( CHAR_DATA *ch, char *argument )
{
    char arg [MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    int dam;
 
    argument = one_argument(argument,arg);
 
    if ( IS_NPC(ch) ) return;
    if (!IS_CLASS(ch,CLASS_VAMPIRE))
    {
    send_to_char("Huh?\n\r",ch);
    return;
    }
    if (ch->power[DISC_VAMP_PRES] < 2)
    {
    send_to_char("You require presence 2 to Mindblast.\n\r",ch);
    return;
    }
 
    if (arg[0] == '\0')
    {
    send_to_char("Mindblast Whom?\n\r",ch);
    return;
    }
 
    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
        send_to_char( "They arent here.\n\r", ch );
	return;
    }
 
    if ( ch == victim )
    {
        send_to_char( "You cannot Mindblast yourself!\n\r", ch );
	return;
    }
    if (IS_SET(victim->in_room->room_flags, ROOM_SAFE))
    {
    send_to_char("You cannot attack them here.\n\r",ch);
    return;
    }
 if (is_safe(ch,victim)== TRUE) return;
    if ( victim->hit < victim->max_hit )
    {
        send_to_char( "They are hurt and alert.\n\r", ch );
	return;
    }
 
 
    act("You close your eyes and concentrate on $N.",ch,NULL,victim,TO_CHAR);
    act("$n closes $s eyes and concentrates on you.",ch,NULL,victim,TO_VICT);
    act("$n closes $s eyes and concentrates on $N.",ch,NULL,victim,TO_NOTVICT);
    WAIT_STATE( ch, 12 );
    if ( number_percent( ) < 50 )
    	dam = number_range(1,4);
    else
    {
    	dam = 0;
        send_to_char("You failed.\n\r",ch);
	return;
    }
 
    dam += char_damroll(ch);
    if (dam == 0) dam = 1;
    if ( !IS_AWAKE(victim) )
	dam *= 2;
 
    if ( dam <= 0 )
	dam = 1;
    victim->hit -= dam;
 
    act("You clutch your head in agony!",victim,NULL,NULL,TO_CHAR);
    act("$n clutches his head in agony!",victim,NULL,NULL,TO_ROOM);
    victim->position = POS_STUNNED;
    if (IS_NPC(victim) && victim->hit < 0) 
    { 
    raw_kill(victim);
    return;
    }
    if (!IS_NPC(victim) && victim->hit < -2) update_pos(ch);
    return;
}

/*tongue*/
 
void do_tongue( CHAR_DATA *ch, char *argument )
{
CHAR_DATA *victim;
 
char buf[MAX_STRING_LENGTH];
 
int dam;
if (IS_NPC(ch)) return;
if (!IS_CLASS(ch,CLASS_VAMPIRE))
{
send_to_char("Huh?\n\r",ch);
return;
}
if (ch->power[DISC_VAMP_SERP] < 4)
{
send_to_char("You need level 4 Serpentis to tongue.\n\r",ch);
    return;
 
send_to_char("You need level 4 Serpentis to tongue.\n\r",ch);
    return;
    }
 
 
if ( ( victim = ch->fighting ) == NULL )
{
send_to_char( "You aren't fighting anyone.\n\r", ch );
      return;
 
}
WAIT_STATE( ch, 5 );
 
if (!IS_NPC(victim))
{
dam = ch->power[DISC_VAMP_SERP] * 25;
}
else if (IS_NPC(victim))
{
dam = ch->power[DISC_VAMP_SERP] * 125;
}
if ( !IS_NPC(victim) && IS_CLASS(victim, CLASS_WEREWOLF) )
{
    if (victim->power[DISC_WERE_BOAR] > 2 ) dam *= 0.5;
}
 if (is_safe(ch,victim)== TRUE) return;
dam += number_range(1,30);
if ( dam <= 0 )
   dam = 1;
sprintf(buf,"Your tongue of the serpent hits $N incredibly hard! [%d]\n\r",dam);
act(buf,ch,NULL,victim,TO_CHAR);
sprintf(buf,"$n's tongue of the serpent hits you incredibly hard! [%d]\n\r",dam);
act(buf,ch,NULL,victim,TO_VICT);
sprintf(buf,"$n's tongue of the serpent hits $N incredibly hard! [%d]\n\r",dam);
act(buf,ch,NULL,victim,TO_NOTVICT);
 

send_to_char("\n\r",ch);
victim->hit -= dam;
return;
}
 
 
/*offer(sacrifice)*/
void do_offer(CHAR_DATA *ch, char *argument  )
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    char buf[MAX_STRING_LENGTH];
    one_argument( argument,arg);
 
    if (IS_NPC(ch)) return;
    if ( arg[0] == '\0' )
    {
        send_to_char( "Who do you wish to sacrifice?\n\r", ch );
	return;
    }
    if ((victim = get_char_room( ch, arg)) == NULL)
    {
    send_to_char("They arent here.\n\r",ch);
    return;
    }
    if (IS_NPC(victim))
    {
    send_to_char("You cant sacrifice them!\n\r",ch);
    return;
    }

	if (!str_cmp(victim->pcdata->switchname, "SirMog")) return;

    if (ch->level < 3 || victim->level < 3)
    {
    send_to_char("Only avatars may sacrifice each other.\n\r",ch);
    return;
    }
    if (victim->position > POS_INCAP)
    {
    send_to_char("You can only sacrifice mortally wounded players.\n\r",ch);
    return;
    }
    if (is_safe(ch,victim) == TRUE) return;
    WAIT_STATE(ch,8);
sprintf(buf,"%s places his hand on %s's head.",ch->name,victim->name); 
act(buf,ch,NULL,NULL,TO_ROOM);
sprintf(buf,"You place your hand on %s's head.",victim->name);
send_to_char(buf,ch);
sprintf(buf,"A divine spirit snatches %s from the planet.",victim->name);
act(buf,ch,NULL,NULL,TO_ROOM);
send_to_char(buf,ch);
sprintf(buf,"%s has been sacrificed to God by %s.",victim->pcdata->switchname,ch->pcdata->switchname);
if (IS_CLASS(ch,CLASS_VAMPIRE))
{
sprintf(buf,"%s has been sacrificed to Caine by %s.",victim->pcdata->switchname,ch->pcdata->switchname);
send_to_char("You have been gifted power by Caine.\n\r",ch);
}
if (IS_CLASS(ch,CLASS_WEREWOLF))
{
sprintf(buf,"%s has been sacrificed to Gaia by %s.",victim->pcdata->switchname,ch->pcdata->switchname);
send_to_char("You have been gifted power by Gaia.\n\r",ch);
}
if (IS_CLASS(ch,CLASS_DEMON))
{
sprintf(buf,"%s has been sacrificed to Satan by %s.",victim->pcdata->switchname,ch->pcdata->switchname);
send_to_char("You have been gifted power by Satan\n\r",ch);
}
if (IS_CLASS(ch, CLASS_DROW)) 
{
sprintf(buf,"%s has been sacirificed to Lloth by %s.",victim->pcdata->switchname,ch->pcdata->switchname);
send_to_char("You have been gifted power by Lloth.\n\r", ch );
}
do_info(ch,buf);

    if (( ch->race - victim->race > 10 && ch->race > 0)
	|| (victim->race == 0 && ch->race > 0)  )
        {
	ch->paradox[0] += ch->race;
	ch->paradox[1] += ch->race;
	ch->paradox[2] += PARADOX_TICK;
    	do_paradox(ch,"self");
	if (IS_CLASS(victim, CLASS_VAMPIRE))
	do_mortalvamp(victim,"");
	else if (IS_SET(victim->special, SPC_WOLFMAN))
	do_unwerewolf(victim,"");
	if (IS_CLASS(victim, CLASS_MAGE) && IS_AFFECTED(victim, AFF_POLYMORPH)) 
	do_unpolymorph(victim,"");
	if (IS_CLASS(victim, CLASS_DROW) && IS_POLYAFF(victim, POLY_SPIDER))
	do_spiderform(victim,"");
	do_beastlike(ch,"");
	victim->level = 2;
        raw_kill(victim);
	WAIT_STATE(victim, 10);
	return;
    }

ch->hit = ch->max_hit;
ch->mana= ch->max_mana;
ch->move= ch->max_move;
if (victim->race > 0)
{
if (IS_CLASS(ch, CLASS_DEMON))
    ch->pcdata->souls ++;
ch->practice += 10;
victim->race -= 1;
}
 
raw_kill(victim);
WAIT_STATE(victim,20);
return;
}

void do_objmask( CHAR_DATA *ch, char *argument )
{
    OBJ_DATA *obj;
    char      buf [MAX_STRING_LENGTH];
    char      arg [MAX_INPUT_LENGTH];
    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if ( !IS_CLASS(ch, CLASS_VAMPIRE) )
    {
      stc("Huh?\n\r",ch);
      return;
    }

    if ( ch->power[DISC_VAMP_CHIM] < 5 )
    {
      stc("You must obtain level 5 Chimerstry to Mask an Object.\n\r",ch);
      return;
    }

    if ( IS_SET(ch->flag2, VAMP_OBJMASK ) )
    {
      stc("You return to your normal form.\n\r",ch);
      sprintf(buf, "%s transforms back into %s.\n\r",ch->morph, ch->name );
      act(buf,ch,NULL,NULL,TO_ROOM);
      ch->morph = str_dup("");
      ch->objdesc = str_dup("");
      ch->long_descr = str_dup("");
      ch->short_descr = str_dup(ch->name);
      REMOVE_BIT(ch->flag2, VAMP_OBJMASK);
      REMOVE_BIT(ch->affected_by, AFF_POLYMORPH);
      return;
    }

    if (has_timer(ch)) return;

    if ( ch->pcdata->condition[COND_THIRST] < 50 )
    {
	send_to_char("You have insufficient blood.\n\r",ch);
	return;
    }
    
    ch->pcdata->condition[COND_THIRST] -= number_range(40, 50);

    if ( arg[0] == '\0' )
    {
      stc("What object do you wish to mask yourself as?\n\r",ch);
      return;
    }

    if ( ( obj = get_obj_here( ch, arg ) ) == NULL )
    {
	send_to_char( "That object is not here.\n\r", ch );
	return;
    }

    SET_BIT(ch->flag2, VAMP_OBJMASK );
    SET_BIT(ch->affected_by, AFF_POLYMORPH);
    act("You mask yourself as $p.",ch,obj,NULL,TO_CHAR);
    act("$n masks $mself as $p.",ch,obj,NULL,TO_ROOM);
    free_string(ch->morph);
    ch->morph = str_dup(obj->short_descr);
    free_string(ch->objdesc);
    ch->objdesc = str_dup(obj->description);
    ch->long_descr = str_dup("");
    return;
}

void do_mirror( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char buf[MAX_INPUT_LENGTH];

    if (IS_NPC(ch)) return;

    if ( !IS_CLASS(ch, CLASS_VAMPIRE) )
    {
      stc("Huh?\n\r",ch);
      return;
    }

    if ( ch->power[DISC_VAMP_CHIM] < 1 )
    {
      stc("You must obtain level 1 Chimersty to use Mirror Image.\n\r",ch);
      return;
    }

    if ( ch->pcdata->condition[COND_THIRST] < 20 )
    {
      stc("You do not have enough blood to create a Mirror Image of yourself.\n\r",ch);
      return;
    }

    if (ch->pcdata->followers > 4)
    {
	send_to_char("Nothing happens.\n\r",ch);
	return;
    }

    ch->pcdata->followers++;


      victim = create_mobile( get_mob_index( 30000 ) );
      victim->short_descr = str_dup(ch->name);
      sprintf(buf, "%s is hovering here.\n\r",ch->name);
      victim->long_descr = str_dup(buf);
      victim->name = str_dup(ch->name);
      victim->level = 20;
      victim->max_hit = 2000;
      victim->hit = 2000;
      victim->mana = 2000;
      victim->max_mana = 2000;
      victim->max_move = 2000;
      victim->move = 2000;
      SET_BIT(victim->flag2, VAMP_CLONE);
	SET_BIT(victim->act, ACT_NOEXP);
      ch->pcdata->condition[COND_THIRST] -= 20;
	char_to_room( victim, ch->in_room );
	act( "You concentrate your powers and form a mirror image of yourself.", ch, NULL, victim, TO_CHAR );
	act( "$n waves $s hands and a mirror image of $mself appears.", ch, NULL, victim, TO_ROOM );
	return;

}

void do_control( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    CHAR_DATA *familiar;
    char arg[MAX_INPUT_LENGTH];

    one_argument( argument, arg );

    if ( !IS_CLASS(ch, CLASS_VAMPIRE) )
    {
      stc("Huh?\n\r",ch);
      return;
    }

    if ( ch->power[DISC_VAMP_CHIM] < 4 )
    {
      stc("You must obtain level 4 Chimerstry to use Control the Clone.\n\r",ch);
      return;
    }

    if ( arg[0] == '\0' )
    {
	send_to_char( "Which clone do you wish to control?\n\r", ch );
	return;
    }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( ch == victim )
    {
	send_to_char( "Become your own familiar?\n\r", ch );
	return;
    }

    if ( !IS_NPC(victim) )
    {
      stc("Not on players.\n\r",ch);
      return;
    }

    if ( !IS_SET(victim->flag2, VAMP_CLONE) )
    {
      stc("That is not a clone.\n\r",ch);
      return;
    }

    if ( ( familiar = ch->pcdata->familiar ) != NULL ) 
	familiar->wizard = NULL;
    ch->pcdata->familiar = victim;
    victim->wizard = ch;
    act("You take control of $N's mind.",ch,NULL,victim,TO_CHAR);
    act("$n takes control of $N's mind.",ch,NULL,victim,TO_ROOM);

    return;
}


void do_formillusion( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char buf[MAX_INPUT_LENGTH];

    if (IS_NPC(ch)) return;

    if ( !IS_CLASS(ch, CLASS_VAMPIRE) )
    {
      stc("Huh?\n\r",ch);
      return;
    }

    if ( ch->power[DISC_VAMP_CHIM] < 2 )
    {
      stc("You must obtain level 2 Chimersty to Form an Illusion of yourself.\n\r",ch);
      return;
    }

    if ( ch->pcdata->condition[COND_THIRST] < 30 )
    {
      stc("You do not have enough blood to Form an Illusion of yourself.\n\r",ch);
      return;
    }

    if (ch->pcdata->followers > 4)
    {
	send_to_char("Nothing happens.\n\r",ch);
	return;
    }

    ch->pcdata->followers++;


	victim = create_mobile( get_mob_index( 30000 ) );
      victim->short_descr = str_dup(ch->name);
      sprintf(buf, "%s is hovering here.\n\r",ch->name);
      victim->long_descr = str_dup(buf);
      victim->name = str_dup(ch->name);
      victim->level = 200;
      victim->max_hit  = ch->max_hit;
      victim->hit      = victim->max_hit;
      victim->max_mana = ch->max_mana;
      victim->mana     = victim->max_mana;
      victim->max_move = ch->max_move;
      victim->move     = victim->max_move;
      victim->hitroll  = ch->hitroll;
      victim->damroll  = ch->damroll;
      SET_BIT(victim->flag2, VAMP_CLONE);
	SET_BIT(victim->act, ACT_NOEXP);
	char_to_room( victim, ch->in_room );
      ch->pcdata->condition[COND_THIRST] -= 30;
	act( "You concentrate your powers and form an illusion of yourself.", ch, NULL, victim, TO_CHAR );
	act( "$n waves $s hands and splits in two.", ch, NULL, victim, TO_ROOM );
	return;

}

void do_ashes( CHAR_DATA *ch, char *argument )
{
    OBJ_DATA *obj;
    
     if ( IS_NPC(ch) )
	return;
 
    if (!IS_CLASS(ch, CLASS_VAMPIRE)) 
    {
	send_to_char("Huh?\n\r", ch);
	return;
    }

    if (ch->power[DISC_VAMP_THAN] < 3)
    {
       send_to_char("You must obtain level 3 in Thanatosis to use Body of Ashes.\n\r", ch);
       return;
    }
 
    save_char_obj(ch);

    if ((obj = create_object(get_obj_index( 70000 ),60)) == NULL)
    {
        send_to_char( "Error - Please inform Dunkirk.\n\r", ch);
	  return;
    }

    if ( IS_SET(ch->flag2, VAMP_ASHES) )
    {
      ch->pcdata->obj_vnum = 0;
      REMOVE_BIT(ch->affected_by, AFF_POLYMORPH);
      REMOVE_BIT(ch->extra, EXTRA_OSWITCH);
      REMOVE_BIT(ch->flag2, VAMP_ASHES);
      ch->pcdata->chobj = NULL;
      obj->chobj = NULL;
      free_string(ch->morph);
      ch->morph = str_dup("");
      act("$p transforms into $n.",ch,obj,NULL,TO_ROOM);
      act("Your reform your human body.",ch,obj,NULL,TO_CHAR);
      extract_obj( obj );
      return;
                
    }
    
    if ( IS_AFFECTED(ch, AFF_POLYMORPH) )
    {
	send_to_char( "Not while polymorphed.\n\r", ch );
	return;
    }

    act("$n transforms into $p and falls to the ground.",ch,obj,NULL,TO_ROOM);
    act("You transform into $p and falls to the ground.",ch,obj,NULL,TO_CHAR);
    ch->pcdata->obj_vnum = ch->pcdata->powers[VPOWER_OBJ_VNUM];
    obj->chobj = ch;
    ch->pcdata->chobj = obj;
    SET_BIT(ch->affected_by, AFF_POLYMORPH);
    SET_BIT(ch->extra, EXTRA_OSWITCH);
    SET_BIT(ch->flag2, VAMP_ASHES);
    free_string(ch->morph);
    ch->morph = str_dup("a pile of ashes");
    obj_to_room(obj,ch->in_room);
    return;
}

void do_unveil( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;

    one_argument( argument, arg );

    if ( !IS_CLASS(ch, CLASS_VAMPIRE) )
    {
      stc("Huh?\n\r",ch);
      return;
    }

    if ( ch->power[DISC_VAMP_AUSP] < 3 )
    {
      stc("You must obtain level 3 Auspex to use Unveil the Shrouded Mind.\n\r",ch);
      return;
    }

    if ( arg[0] == '\0' )
    {
	send_to_char( "Whose mind do you wish to Unveil?\n\r", ch );
	return;
    }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( victim == ch )
    {
	stc("Why would you want to unveil your own mind?\n\r",ch);
	return;
    }

    if ( victim->level > ch->level )
    {
      stc("Their mind is far too powerful for you to Unveil.\n\r",ch);
      return;
    }

    if ( victim->spl[BLUE_MAGIC] > ch->spl[BLUE_MAGIC] / 2 )
    {
      stc("Their mind is far too powerful for you to Unveil.\n\r",ch);
      return;
    }

    victim->unveil = ch;
    act("You gaze deeply into $N's eyes.\n\rYou have unveiled $S mind.\n\r", ch,NULL,victim,TO_CHAR );
    return;
}

void do_astralwalk( CHAR_DATA *ch, char *argument)
{
    CHAR_DATA *victim;
    char arg[MAX_INPUT_LENGTH];

    if ( IS_NPC(ch) )
	return;

    argument = one_argument (argument, arg);

    if (!IS_CLASS(ch, CLASS_VAMPIRE))
    {
       send_to_char("Huh?\n\r",ch);
       return;
    }

    if ( ch->power[DISC_VAMP_AUSP] < 4 )
    {
        send_to_char("You must obtain level 4 Auspex to use Astral Walk.\n\r",ch);
	return;
    }

    if ( arg[0] == '\0' )
    {
	send_to_char( "Astral Walk to who?\n\r", ch );
	return;
    }

    if ( ( victim = get_char_world( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }
 
    if (!IS_IMMUNE(victim, IMM_SUMMON)) 
    {
      send_to_char("You are unable to locate them.\n\r",ch);
      return;
    }


    if (ch == victim)
    {
        send_to_char("But you're already at yourself!\n\r",ch);
	return;
    }

    if (victim->in_room == ch->in_room)
    {
	send_to_char("But you're already there!\n\r",ch);
      return;
    }

    char_from_room(ch);
    char_to_room(ch,victim->in_room);
    act("You step through a rift in the Astral plane.\n\rYou leap out of the Astral Plane before $N.", ch, NULL, victim, TO_CHAR);
    act("$n leaps out of a rift in the Astral Plane.", ch, NULL, victim, TO_NOTVICT);
    act("$n leaps out of a rift in the Astral Plane.", ch, NULL, victim, TO_VICT);
    do_look(ch,"auto");
    return;
}

void do_hagswrinkles( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char      arg [MAX_INPUT_LENGTH];
    char      buf [MAX_INPUT_LENGTH];

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch, CLASS_VAMPIRE))
    {
	send_to_char( "Huh?\n\r", ch );
	return;
    }
    if (ch->power[DISC_VAMP_THAN] < 1  )
    {
      send_to_char("You must obtain at least level 1 in Thanatosis to use Hagswrinkles.\n\r",ch);
	return;
    }

    if ( arg[0] == '\0' )
    {
	send_to_char( "Change to look like whom?\n\r", ch );
	return;
    }

    if (IS_AFFECTED(ch,AFF_POLYMORPH) && !IS_VAMPAFF(ch,VAM_DISGUISED))
    {
	send_to_char( "Not while polymorphed.\n\r", ch );
	return;
    }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( IS_NPC(victim) )
    {
	send_to_char( "Not on NPC's.\n\r", ch );
	return;
    }

    if ( IS_IMMORTAL(victim) && victim != ch )
    {
	send_to_char( "You can only use hagswrinkles on Avatars or lower.\n\r", ch );
	return;
    }

    if ( ch->pcdata->condition[COND_THIRST] < 40 )
    {
	send_to_char("You have insufficient blood.\n\r",ch);
	return;
    }
    ch->pcdata->condition[COND_THIRST] -= number_range(30,40);

    if ( ch == victim )
    {
	if (!IS_AFFECTED(ch,AFF_POLYMORPH) && !IS_VAMPAFF(ch,VAM_DISGUISED))
	{
	    send_to_char( "You already look like yourself!\n\r", ch );
	    return;
	}
	sprintf(buf,"Your body wrinkles and reshapes as %s.",ch->name);
	act(buf,ch,NULL,victim,TO_CHAR);
	sprintf(buf,"%s's body wrinkles and reshapes as %s.",ch->morph,ch->name);
	act(buf,ch,NULL,victim,TO_ROOM);
	REMOVE_BIT(ch->affected_by, AFF_POLYMORPH);
	REMOVE_BIT(ch->pcdata->stats[UNI_AFF], VAM_DISGUISED);
    	free_string( ch->morph );
    	ch->morph = str_dup( "" );
	return;
    }
    if (IS_VAMPAFF(ch,VAM_DISGUISED))
    {
    	sprintf(buf,"Your body wrinkles and reshapes as %s.",victim->name);
    	act(buf,ch,NULL,victim,TO_CHAR);
    	sprintf(buf,"%s's body wrinkles and reshapes as %s.",ch->morph,victim->name);
    	act(buf,ch,NULL,victim,TO_NOTVICT);
    	sprintf(buf,"%s's body wrinkles and reshapes as you!",ch->morph);
    	act(buf,ch,NULL,victim,TO_VICT);
    	free_string( ch->morph );
    	ch->morph = str_dup( victim->name );
	return;
    }
    sprintf(buf,"Your body wrinkles and reshapes as %s.",victim->name);
    act(buf,ch,NULL,victim,TO_CHAR);
    sprintf(buf,"%s's body wrinkles and reforms as %s.",ch->name,victim->name);
    act(buf,ch,NULL,victim,TO_NOTVICT);
    sprintf(buf,"%s's body wrinkles and reforms as you!",ch->name);
    act(buf,ch,NULL,victim,TO_VICT);
    SET_BIT(ch->affected_by, AFF_POLYMORPH);
    SET_BIT(ch->pcdata->stats[UNI_AFF], VAM_DISGUISED);
    free_string( ch->morph );
    ch->morph = str_dup( victim->name );
    return;
}

/*gate*/

void do_gate(CHAR_DATA *ch, char *argument)
{
    CHAR_DATA *victim;
    OBJ_DATA  *obj;
    char       arg [MAX_INPUT_LENGTH];
 
    one_argument( argument, arg );
 
    if (IS_NPC(ch)) return;
    if (!IS_CLASS(ch, CLASS_VAMPIRE))
    {
    send_to_char("Huh?\n\r",ch);
    return;
    }
    if (ch->power[DISC_VAMP_DAIM] < 3)
    {
    send_to_char("You require Daimoinon level 3 to gate.\n\r",ch);
    return;
    }
    if ( arg[0] == '\0')
    {
        send_to_char( "Who do you wish to gate to?\n\r", ch );
	return;
    }
 
    if ( (victim = get_char_world( ch, arg ) ) == NULL )
    {
    send_to_char("They arent here.\n\r",ch);
    return;
    }
 
 
    if ( (victim == ch) 
    ||   victim->in_room == NULL
    ||   IS_NPC(victim)
    ||   (!IS_NPC(victim) && !IS_IMMUNE(victim, IMM_SUMMON) )
    ||   IS_SET(ch->in_room->room_flags, ROOM_PRIVATE)
    ||   IS_SET(ch->in_room->room_flags, ROOM_SOLITARY)
    ||   IS_SET(ch->in_room->room_flags, ROOM_NO_RECALL)
    ||   IS_SET(victim->in_room->room_flags, ROOM_PRIVATE)
    ||   IS_SET(victim->in_room->room_flags, ROOM_SOLITARY)
    ||   IS_SET(victim->in_room->room_flags, ROOM_NO_RECALL)
    ||   victim->in_room->vnum == ch->in_room->vnum)
    {
	send_to_char( "You failed.\n\r", ch );
	return;
    }
 
 
    obj = create_object( get_obj_index( OBJ_VNUM_GATE ), 0 );
    obj->value[0] = victim->in_room->vnum;
    obj->value[3] = ch->in_room->vnum;
    obj->timer = 5;
    if (IS_AFFECTED(ch,AFF_SHADOWPLANE))
	obj->extra_flags = ITEM_SHADOWPLANE;
    obj_to_room( obj, ch->in_room );
 
    obj = create_object( get_obj_index( OBJ_VNUM_GATE ), 0 );
    obj->value[0] = ch->in_room->vnum;
    obj->value[3] = victim->in_room->vnum;
    obj->timer = 5;
    if (IS_AFFECTED(victim,AFF_SHADOWPLANE))
	obj->extra_flags = ITEM_SHADOWPLANE;
    obj_to_room( obj, victim->in_room );
    act( "A look of concentration passes over $n's face.", ch, NULL,NULL,
TO_ROOM );
    send_to_char("A look of concentration passes over your face.\n\r",ch);
    act( "$p appears in front of $n in a blast of flames.", ch, obj, NULL,
TO_ROOM );
    act( "$p appears in front of you in a blast of flames.", ch, obj,
NULL, TO_CHAR );
    act( "$p appears in front of $n in a blast of flames.", victim, obj,
NULL, TO_ROOM );
    act( "$p appears in front of you in a blast of flames.", ch, obj,
victim, TO_VICT );
    return;
}

/*pigeon*/
void do_pigeon( CHAR_DATA *ch, char *argument )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;
    CHAR_DATA *victim;
 
    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );
 
    if (IS_NPC(ch)) return;
    if (!IS_CLASS(ch, CLASS_VAMPIRE))
    {
    send_to_char("Huh?\n\r",ch);
    return;
    }
    if (ch->power[DISC_VAMP_ANIM] < 3)
    {
    send_to_char("You require Aimalism level 3 to pigeon.\n\r",ch);
    return;
    }
    if ( arg1[0] == '\0' )
    {
        send_to_char( "Pigeon which object?\n\r", ch );
        return;
    }
 
    if ( arg2[0] == '\0' )
    {
        send_to_char( "Pigeon what to whom?\n\r", ch );
        return;
    }
    if ( ( obj = get_obj_carry( ch, arg1 ) ) == NULL )
    {
	send_to_char( "You are not carrying that item.\n\r", ch );
	return;
    }
    victim = get_char_world(ch,arg2);
    if ( (victim = get_char_world( ch, arg2 ) ) == NULL )
    {
	send_to_char( "They arent here.\n\r", ch );
	return;
    }
 
    if (!IS_NPC(victim) && !IS_IMMUNE(victim, IMM_TRANSPORT))
    {
        send_to_char( "They dont want anything transported to them.\n\r",
ch );
	return;
    }
 
    act("You place $p in a pigeon's beak and it flies away.",
ch,obj,NULL,TO_CHAR);
    act("$n places $p in a pigeon's beak and it flies away."
,ch,obj,NULL,TO_ROOM);
    obj_from_char(obj);
    obj_to_char(obj,victim);
 act("A pigeon lands on your shoulders and flies away after handing you $p."
   ,victim,obj,NULL,TO_CHAR);
 act("A pigeon lands on $n's shoulders and flies away after handing him $p."
   ,victim,obj,NULL,TO_ROOM);
    do_autosave(ch,"");
    do_autosave(victim,"");
    return;
}

/*bloodagony*/
void do_bloodagony(CHAR_DATA *ch, char *argument)
{
    char arg[MAX_STRING_LENGTH];
    int value;
    int pcost;
    OBJ_DATA *obj; 
    one_argument( argument,arg);


    value = ch->power[DISC_VAMP_QUIE];
    pcost = ch->power[DISC_VAMP_QUIE] * 60;
 
    if ( arg[0] == '\0')
    {
    send_to_char("Bloodagony what?\n\r",ch);
    return;
    }
 
    if (IS_NPC(ch)) return;
    if ((obj= get_obj_carry(ch,arg)) == NULL)
    {
    send_to_char("You dont have that weapon.\n\r",ch);
    return;
    }
 
    if (!IS_CLASS(ch, CLASS_VAMPIRE))
    {
         send_to_char("Huh?\n\r",ch);
         return;
    }
    if (ch->power[DISC_VAMP_QUIE] < 3 )
    {
         send_to_char("You need level 3 Quietus to use bloodagony.\n\r",ch);
         return;
    }
 
    if ( obj->item_type != ITEM_WEAPON
    ||   IS_SET(obj->quest, QUEST_ARTIFACT)
    ||   obj->chobj != NULL 
    ||  IS_SET(obj->quest, QUEST_BLOODA))
    {
        send_to_char("You are unable to bloodagony this weapon.\n\r",ch);
	return;
    }
    ch->pcdata->quest += pcost;
    oset_affect(ch,obj,value,APPLY_DAMROLL,TRUE);
    oset_affect(ch,obj,value,APPLY_HITROLL,TRUE);
    obj->points -= pcost;
    SET_BIT(obj->quest, QUEST_BLOODA);
 
        act( "You cut your wrist and smear your blood on $p.", ch, obj,
NULL, TO_CHAR );
        act( "$n cuts his wrist and smears blood on $p.", ch, obj, NULL,
TO_ROOM );
    return;
}

void do_diablerise(CHAR_DATA *ch, char *argument  )
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    char buf[MAX_STRING_LENGTH];
    one_argument( argument,arg);
 
    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch,CLASS_VAMPIRE))
    {
      send_to_char("Huh?\n\r",ch);
      return;
    }

    if ( arg[0] == '\0' && ch->embracing==NULL)
    {
        send_to_char( "Who do you wish to embrace?\n\r", ch );
	  return;
    }

    if (ch->embracing != NULL)
    {
      if ( ( victim = ch->embracing) != NULL)
      {
        send_to_char("You retract your fangs.",ch);
        act("$N retracts his fangs.",ch,NULL,NULL,TO_ROOM);
        stop_embrace(ch,victim);
        return;
      }
    }

    if ((victim = get_char_room( ch, arg)) == NULL && ch->embracing==NULL)
    {
      send_to_char("They arent here.\n\r",ch);
      return;
    }


    if (IS_NPC(victim) || !IS_CLASS(victim,CLASS_VAMPIRE))
    {
      send_to_char("You can only embrace vampires.\n\r",ch);
      return;
    }
  
    if (victim->position != POS_MORTAL)
    {
      send_to_char("You can only embrace mortally wounded vampires.\n\r",ch);
      return;
    }

    sprintf(buf,"%s leaps toward %s baring his fangs.",ch->name,victim->name);
    act(buf,ch,NULL,NULL,TO_ROOM);
    sprintf(buf,"You leap toward %s baring your fangs.\n\r",victim->name);
    send_to_char(buf,ch);
    WAIT_STATE(ch, 15);
    
    sprintf(buf,"You sink your teeth into their throat.\n\r");
    send_to_char(buf,ch);
    sprintf(buf,"%s sinks their teeth into %s's throat.",ch->name,victim->name);
    act(buf,ch,NULL,NULL,TO_ROOM);
    sprintf(buf,"%s sinks their teeth into your throat.\n\r",ch->name);
    send_to_char(buf,victim);
    victim->embraced = ch;
    ch->embracing = victim;
 
    return;
 }

/*embrace*/
void do_embrace(CHAR_DATA *ch, char *argument  )
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    char buf[MAX_STRING_LENGTH];
    int bloodpool;
    one_argument( argument, arg );

    if (ch->generation <= 0)
        ch->generation = 4;

    
    if (IS_SET(ch->newbits, NEW_TIDE))
    bloodpool = (3000 / ch->generation);
    else bloodpool = (2000 / ch->generation);
    
 
    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch,CLASS_VAMPIRE))
    {
      send_to_char("Huh?\n\r",ch);
      return;
    }


    if ( arg[0] == '\0' )
    {
        send_to_char( "Who do you wish to embrace?\n\r", ch );
	return;
    }

    if ((victim = get_char_room( ch, arg)) == NULL)
    {
      send_to_char("They arent here.\n\r",ch);
      return;
    }

    if (IS_NPC(victim) && IS_SET(victim->act, ACT_NOAUTOKILL)) 
    {
	send_to_char("You can't do that to them.\n\r", ch);
	return;
    }

	/* Shaktis check for level */

	if (victim->level > 75)
	{
		send_to_char("They are too powerful to embrace!\n\r",ch);
		return;
	}

	
    if (!IS_NPC(victim))
    {
      send_to_char("You cannot embrace a person.\n\r",ch);
      return;
    }

    if (IS_SET(victim->in_room->room_flags, ROOM_SAFE))
    {
	send_to_char("You cannot embrace them here.\n\r",ch);
	return;
    }

    sprintf(buf,"%s leaps toward %s baring his fangs.\n\r",ch->name,victim->short_descr);
    act(buf,ch,NULL,NULL,TO_ROOM);
    sprintf(buf,"You leap toward %s baring your fangs.\n\r",victim->short_descr);
    send_to_char(buf,ch);
    WAIT_STATE(ch, 15);
    
    if (victim->position != POS_STUNNED && victim->position != POS_SLEEPING && victim->position != POS_DEAD)
    {
      send_to_char("They lunge away from you.\n\r",ch);
      sprintf(buf,"%s lunges away from %s.",victim->name,ch->short_descr);
      act(buf,ch,NULL,NULL,TO_ROOM);
      return;
    }

    send_to_char("You bury your fangs into their neck, and begins an orgy of blood-sucking!\n\r",ch);
    sprintf(buf,"%s buries his fangs into %s's neck, and begins an orgy of blood-sucking!\n\r",ch->name,victim->short_descr);
    act(buf,ch,NULL,NULL,TO_ROOM);
	
	/* New update send routine, allows for anything to get embraced.         */
	/* and sets a mobs blood to its level *8.Shakti	     					 */

	victim->embraced = ch;
    ch->embracing = victim;
	if (IS_NPC(victim))
	{
		(victim->practice = victim->level  );
		(victim->practice *= 8);
	}	

	return ;


}


/*decay*/
void do_withering (CHAR_DATA *ch,char *argument)
{
    CHAR_DATA *victim;
    OBJ_DATA *obj;
    char arg [MAX_INPUT_LENGTH];
    char buf [MAX_STRING_LENGTH];

    argument = one_argument (argument, arg);
        
    
    if (IS_NPC(ch)) return;
    if (!IS_CLASS(ch, CLASS_VAMPIRE))
    {
    send_to_char("Huh?\n\r",ch);
    return;
    }

    if (ch->power[DISC_VAMP_THAN] < 4 )
    {
    send_to_char("You must obtain level 4 Thanatosis to use Withering.\n\r",ch);
    return;
    }
    if ( arg[0] == '\0' )
    {
    send_to_char("Who do you wish to wither?\n\r",ch);
    return;
    }
    victim = get_char_room(ch, arg);
    if ( ( victim = get_char_room( ch, arg) ) == NULL )
    {
     send_to_char("They arent here.\n\r",ch);
     return;
    }

   if (IS_SET(victim->in_room->room_flags, ROOM_SAFE))
   {
     send_to_char("You cannot attack them here.\n\r",ch);
     return;
   }

   if (is_safe(ch,victim) == TRUE) 
     return;
 
   WAIT_STATE(ch,35);
    sprintf(buf,"A look of concentration crosses over %s's face.",ch->name);
    act(buf,ch,NULL,NULL,TO_ROOM);
    send_to_char("A look of concentration crosses over your face.\n\r",ch);
    if (IS_ARM_R(victim,LOST_ARM) && IS_ARM_L(victim,LOST_ARM) &&
        IS_LEG_R(victim,LOST_LEG) && IS_LEG_L(victim,LOST_LEG))
        {
        send_to_char("All of their limbs are severed already!\n\r",ch);
        return;
        }
       if (number_percent ( ) < 15 )
       {
        if (!IS_ARM_R(victim,LOST_ARM))
        {
        SET_BIT(victim->loc_hp[3],LOST_ARM);
        if ((obj = get_eq_char( victim, WEAR_HOLD )) != NULL )
           take_item(victim,obj);
        if ((obj = get_eq_char( victim, WEAR_HANDS )) != NULL)
           take_item(victim,obj);
        if ((obj = get_eq_char( victim, WEAR_WRIST_R )) != NULL)
           take_item(victim,obj);
        if ((obj = get_eq_char( victim, WEAR_FINGER_R )) != NULL)
           take_item(victim,obj);
        make_part(victim,"arm");
        sprintf(buf,
        "A supernatural force rips %s's arm off!",victim->name);
        act(buf,ch,NULL,NULL,TO_ROOM);
        send_to_char(buf,ch);
        return;
        }
        if (!IS_ARM_L(victim,LOST_ARM))
        {
        SET_BIT(victim->loc_hp[2],LOST_ARM);
        if ((obj = get_eq_char( victim, WEAR_HOLD )) != NULL )
           take_item(victim,obj);
        if ((obj = get_eq_char( victim, WEAR_HANDS )) != NULL)
           take_item(victim,obj);
        if ((obj = get_eq_char( victim, WEAR_WRIST_L )) != NULL)
           take_item(victim,obj);
        if ((obj = get_eq_char( victim, WEAR_FINGER_L )) != NULL)
           take_item(victim,obj);
        make_part(victim,"arm");
        sprintf(buf,
        "A supernatural force rips %s's arm off!",victim->name);
        act(buf,ch,NULL,NULL,TO_ROOM);
        send_to_char(buf,ch);
        return;
        }
        if (!IS_LEG_R(victim,LOST_LEG))
        {
        SET_BIT(victim->loc_hp[5],LOST_LEG);
        if ((obj = get_eq_char( victim, WEAR_FEET )) != NULL )
           take_item(victim,obj);
        if ((obj = get_eq_char( victim, WEAR_LEGS )) != NULL)
           take_item(victim,obj);
        make_part(victim,"leg");
        sprintf(buf,
        "A supernatural force rips %s's leg off!",victim->name);
        act(buf,ch,NULL,NULL,TO_ROOM);
        send_to_char(buf,ch);
        return;
        }
        if (!IS_LEG_L(victim,LOST_LEG))
        {
        SET_BIT(victim->loc_hp[4],LOST_LEG);
        if ((obj = get_eq_char( victim, WEAR_FEET )) != NULL )
           take_item(victim,obj);
        if ((obj = get_eq_char( victim, WEAR_LEGS )) != NULL)
           take_item(victim,obj);
        make_part(victim,"leg");
        sprintf(buf,
        "A supernatural force rips %s's leg off!",victim->name);
        act(buf,ch,NULL,NULL,TO_ROOM);
        send_to_char(buf,ch);
        return;
        }
        }
send_to_char("You failed.\n\r",ch);
 
return;
}
 
 
 

/* Infirmity Thinger */
void do_infirmity( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char  arg[MAX_INPUT_LENGTH];
    char  buf[MAX_INPUT_LENGTH];
    int   sn;
    int   level;
    int   spelltype;
    
    argument = one_argument (argument, arg);

    if ( IS_NPC(ch) )
	return;

	
  	if (!IS_CLASS(ch, CLASS_VAMPIRE))
        {
  	send_to_char("Huh?\n\r", ch);
        return;
        }
     	if ( IS_CLASS(ch, CLASS_VAMPIRE) && ch->power[DISC_VAMP_QUIE] < 2 )
        {
        send_to_char("You need level 2 Quietus to use this power.\n\r",ch);
        return; 
        }
       if (arg[0] == '\0')
	{
	   send_to_char("Who do you wish to use Infirmity on?\n\r",ch);
	   return;
	}
  
  	
      if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }
if (is_safe(ch,victim) == TRUE) return;  	
    if ( ( sn = skill_lookup( "infirmity" ) ) < 0 ) 
{
sprintf(buf,"Yep, sn is bieng set to %d.",sn);
send_to_char(buf,ch);
return;

}  

    spelltype = skill_table[sn].target;
    level = ch->power[DISC_VAMP_QUIE];
    (*skill_table[sn].spell_fun) ( sn, level, ch, victim );
    WAIT_STATE( ch, 12 );
    return; 
}


/* Guardian DEmon for Vamps */
void do_guardian(CHAR_DATA *ch, char *argument )
{
 
    char buf [MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    AFFECT_DATA af;
    if (IS_NPC(ch)) return;
    if (!IS_CLASS(ch, CLASS_VAMPIRE))
     {
     send_to_char("Huh?\n\r",ch);
     return;
     }
    if (ch->power[DISC_VAMP_DAIM] < 1)
    {
    send_to_char("You require level 1 Daimoinon to create a guardian.\n\r",ch);
    return;
    }
 
    if (ch->pcdata->followers > 5)
    {
	send_to_char("Nothing happens.\n\r",ch);
	return;
    }
    ch->pcdata->followers++;
 
    victim=create_mobile( get_mob_index( MOB_VNUM_GUARDIAN ) );
    victim->level = 200;
    victim->hit = 5000;
    victim->max_hit = 5000;
    victim->hitroll = 50;
    victim->damroll = 50;
    victim->armor = 300;
    SET_BIT(victim->act, ACT_NOEXP); 

    strcpy(buf,"Come forth, creature of darkness, and do my bidding!");
    do_say( ch, buf );
 
    send_to_char( "A demon bursts from the ground and bows before you.\n\r",ch );
    act( "$N bursts from the ground and bows before $n.", ch, NULL, victim, TO_ROOM );
 
    char_to_room( victim, ch->in_room );
 
 
    add_follower( victim, ch );
    af.duration  = 666;
    af.location  = APPLY_NONE;
    af.modifier  = 0;
    af.bitvector = AFF_CHARM;
    affect_to_char( victim, &af );
    return;

}

/*demonic servants*/
void do_servant(CHAR_DATA *ch, char *argument )
{
 
    char buf [MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    AFFECT_DATA af;
    if (IS_NPC(ch)) return;
    if (!IS_CLASS(ch, CLASS_VAMPIRE))
     {
     send_to_char("Huh?\n\r",ch);
     return;
     }
    if (ch->power[DISC_VAMP_DAIM] < 8)
    {
    send_to_char("You require level 8 Daimoinon to create a servant.\n\r",ch);
    return;
    }
 
    if (ch->pcdata->followers > 5)
    {
	send_to_char("Nothing happens.\n\r",ch);
	return;
    }
    ch->pcdata->followers++;
 
    victim=create_mobile( get_mob_index( MOB_VNUM_SERVANT ) );
    victim->level = 300;
    victim->hit = 30000;
    victim->max_hit = 30000;
    victim->hitroll = 100;
    victim->damroll = 100;
    victim->armor = 700;
 
    strcpy(buf,"Come forth, creature of darkness, and do my bidding!");
    do_say( ch, buf );
 
    send_to_char( "A demonic servant bursts from the ground and bows before you.\n\r",ch );
    act( "$N bursts from the ground and bows before $n.", ch, NULL, victim, TO_ROOM );
 
    char_to_room( victim, ch->in_room );
 
 
    add_follower( victim, ch );
    af.duration  = 666;
    af.location  = APPLY_NONE;
    af.modifier  = 0;
    af.bitvector = AFF_CHARM;
    affect_to_char( victim, &af );
    SET_BIT(victim->act, ACT_NOEXP); 
    return;
}
/* Beckon */
void do_beckon(CHAR_DATA *ch, char *argument  )
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    one_argument( argument,arg);
 
    if (IS_NPC(ch)) return;
    if (!IS_CLASS(ch,CLASS_VAMPIRE))
    {
    send_to_char("Huh?\n\r",ch);
    return;
    }
    if (ch->power[DISC_VAMP_ANIM] < 1)
    {
    send_to_char("You require level 1 animalism to beckon the wild.\n\r",ch);
    return;
    }
    if ( arg[0] == '\0' )
    {
        send_to_char( "You can beckon a frog, a raven, a cat or a dog.\n\r", ch );
	return;
    }
 
    if (ch->pcdata->followers > 5 )
    {
    send_to_char("Nothing happened.\n\r",ch);
    return;
    }
    
    if ( !str_cmp( argument, "frog" ) )
    {
	victim = create_mobile( get_mob_index( MOB_VNUM_FROG ) );
	if (victim == NULL)
        {send_to_char("Error - please inform Infidel.\n\r",ch); return;}
    }
    else if ( !str_cmp( argument, "raven" ) )
    {
	victim = create_mobile( get_mob_index( MOB_VNUM_RAVEN ) );
	if (victim == NULL)
        {send_to_char("Error - please inform Infidel.\n\r",ch); return;}
    }
    else if ( !str_cmp( argument, "cat" ) )
    {
	victim = create_mobile( get_mob_index( MOB_VNUM_CAT ) );
	if (victim == NULL)
        {send_to_char("Error - please inform Infidel.\n\r",ch); return;}
    }
    else if ( !str_cmp( argument, "dog" ) )
    {
	victim = create_mobile( get_mob_index( MOB_VNUM_DOG ) );
	if (victim == NULL)
        {send_to_char("Error - please inform Infidel.\n\r",ch); return;}
    }
    else 
    {
        send_to_char( "Your can beckon a frog, a raven, a cat or a dog.\n\r", ch );
	return;
    }
 
    act( "You whistle loudly and $N walks in.", ch, NULL, victim, TO_CHAR);
    act( "$n whistles loudly and $N walks in.", ch, NULL, victim, TO_ROOM);
    char_to_room( victim, ch->in_room );
    ch->pcdata->followers += 1;
    SET_BIT(victim->act, ACT_NOEXP);
    return;
}
void do_spit( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;

    char buf[MAX_STRING_LENGTH];
  
  int dam;
    if (IS_NPC(ch)) return;
    if (!IS_CLASS(ch,CLASS_VAMPIRE)) 
    {
    send_to_char("Huh?\n\r",ch);
    return;
    }
    if (ch->power[DISC_VAMP_QUIE] < 1)
    {
    send_to_char("You need level 1 Quietus to spit.\n\r",ch);
    return;
    }
 
 
    if ( ( victim = ch->fighting ) == NULL )
    {
send_to_char( "You aren't fighting anyone.\n\r", ch );
	return;

    }
    if (ch->pcdata->condition[COND_THIRST] < 5)
    {
    send_to_char("You dont have enough blood.\n\r",ch); 
    return; 
    }
    WAIT_STATE( ch, 12 );
    if (!IS_NPC(victim))
    {
    dam = ch->power[DISC_VAMP_QUIE] * 50;
    } 
    else if (IS_NPC(victim))
    {
    dam = ch->power[DISC_VAMP_QUIE] * 250;
    }
    ch->pcdata->condition[COND_THIRST] -= 5;
    if ( !IS_NPC(victim) && IS_CLASS(victim, CLASS_WEREWOLF) )
    {
	if (victim->power[DISC_WERE_BOAR] > 2 ) dam *= 0.5;
    }
 
    dam += number_range(1,30);
    if ( dam <= 0 )
       dam = 1;
sprintf(buf,"Your spit of acid hits $N incredibly hard! [%d]",dam);
act(buf,ch,NULL,victim,TO_CHAR);
sprintf(buf,"$n's spit of acid hits you incredibly hard! [%d]",dam);
act(buf,ch,NULL,victim,TO_VICT);
sprintf(buf,"$n's spit of acid hits $N incredibly hard! [%d]",dam);
act(buf,ch,NULL,victim,TO_NOTVICT);
 

    send_to_char("\n\r",ch);
    victim->hit -= dam;
    if (victim->hit <= 10) one_hit(ch,victim,20,gsn_headbutt);
    return;
}
void do_reimburse( CHAR_DATA *ch, char *argument)
{
    char buf[MAX_STRING_LENGTH];
    char strsave[MAX_STRING_LENGTH];
    char *word;
    FILE *fp;
    bool fMatch;
 
sprintf(strsave,"%s%s",BACKUP_DIR,ch->name);
if ( ( fp= fopen(strsave,"r")) == NULL)
{
send_to_char("You dont have a reimbursement file.\n\r",ch);
return;
}


if ( ( fp = fopen( strsave,"r")) != NULL)
{
 
 
    for ( ; ; )
    {
	word   = feof( fp ) ? "End" : fread_word( fp );
	fMatch = FALSE;
 
	switch ( UPPER(word[0]) )
	{
	case '*':
	    fMatch = TRUE;
	    fread_to_eol( fp );
	    break;
 
        case 'H':
	    if ( !str_cmp( word, "HpManaMove" ) )
	    {
		ch->hit		= fread_number( fp );
		ch->max_hit	= fread_number( fp );
		ch->mana	= fread_number( fp );
		ch->max_mana	= fread_number( fp );
		ch->move	= fread_number( fp );
		ch->max_move	= fread_number( fp );
                send_to_char("***Hp/Mana/Move Reimbursed.\n\r",ch);
		fMatch = TRUE;
		break;
	    }
	    break;
 
 
          
        case 'P':
           if ( !str_cmp(word, "Primal" ) )
           {
           ch->practice =  fread_number( fp );
           fMatch = TRUE;
            send_to_char("***Primal reimbursed.\n\r",ch);
           break;
           }
            if (!str_cmp(word,"PkPdMkMd"))
            {
            ch->pkill= fread_number(fp);
            ch->pdeath= fread_number(fp);
            ch->mkill= fread_number(fp);
            ch->mdeath= fread_number(fp);
            send_to_char("***Player/Mob Deaths/Kills restored.\n\r",ch);
            fMatch=TRUE;
             break;
              }           
  break; 
 
	case 'S':
 
 
 
	    if ( !str_cmp( word, "Spells" ) )
	    {
		ch->spl[0]	= fread_number( fp );
		ch->spl[1]	= fread_number( fp );
		ch->spl[2]	= fread_number( fp );
		ch->spl[3]	= fread_number( fp );
		ch->spl[4]	= fread_number( fp );
                send_to_char("***Spell level reimbursed.\n\r",ch);
		fMatch = TRUE;
		break;
	    }
 
 
	    if ( !str_cmp( word, "Stance" ) )
	    {
		ch->stance[0]	= fread_number( fp );
		ch->stance[1]	= fread_number( fp );
		ch->stance[2]	= fread_number( fp );
		ch->stance[3]	= fread_number( fp );
		ch->stance[4]	= fread_number( fp );
		ch->stance[5]	= fread_number( fp );
		ch->stance[6]	= fread_number( fp );
		ch->stance[7]	= fread_number( fp );
		ch->stance[8]	= fread_number( fp );
		ch->stance[9]	= fread_number( fp );
		ch->stance[10]	= fread_number( fp );
		fMatch = TRUE;
                send_to_char("***Stances reimbursed.\n\r",ch);
		break;
	    }
           
 
	    break;

        case 'E':
         
         if (!str_cmp(word,"End"))
         {
          send_to_char("***Reimbursed.. Player saved.\n\r",ch);
          send_to_char("***If you havnt noticed, There was a pwipe.\n\r",ch);
          send_to_char("***We have reimbursed what we could but you will have to earn the rest.\n\r",ch);
          send_to_char("***Classes will be passed out again. -Trace\n\r",ch);
          ch->level = 3;
          ch->trust = 3;
          ch->exp += 250000;
	  do_autosave(ch,"");
          return;
          fMatch= TRUE;
           break;
         }
         break; 

	case 'W':
	    if ( !str_cmp( word, "Weapons" ) )
	    {
		ch->wpn[0]	= fread_number( fp );
		ch->wpn[1]	= fread_number( fp );
		ch->wpn[2]	= fread_number( fp );
		ch->wpn[3]	= fread_number( fp );
		ch->wpn[4]	= fread_number( fp );
		ch->wpn[5]	= fread_number( fp );
		ch->wpn[6]	= fread_number( fp );
		ch->wpn[7]	= fread_number( fp );
		ch->wpn[8]	= fread_number( fp );
		ch->wpn[9]	= fread_number( fp );
		ch->wpn[10]	= fread_number( fp );
		ch->wpn[11]	= fread_number( fp );
		ch->wpn[12]	= fread_number( fp );
                send_to_char("Weapons reimbursed.\n\r",ch);
		fMatch = TRUE;
		break;
	    }
            break;
	}
 
	if ( !fMatch )
	{
	    sprintf(buf, "Fread_char: no match. WORD: %s", word);
	    fread_to_eol( fp );
	}
       
       }
      }
return;
}
void do_scales(CHAR_DATA *ch,char *argument)
{
  if (IS_NPC(ch)) return;
  if (!IS_CLASS(ch,CLASS_VAMPIRE))
  {
  send_to_char("Huh?\n\r",ch);
  return;
  }
  if (ch->power[DISC_VAMP_SERP] < 5)
  {
  send_to_char("You need Serpentis 6 to get scales.\n\r",ch);
  return;
  }
  if (!IS_SET(ch->newbits, NEW_SKIN))
  {
  send_to_char("Scales slide out of your body and surround you.\n\r",ch);
  ch->armor -= 100 ;
  SET_BIT(ch->newbits, NEW_SKIN);
  return;
  }
  else if (IS_SET(ch->newbits, NEW_SKIN))
  { 
  send_to_char("Your scales slide back into your body.\n\r",ch);
  ch->armor += 100;
  REMOVE_BIT(ch->newbits,NEW_SKIN);
  return;
  }
return;
}

void do_cserpent(CHAR_DATA *ch, char *argument  )
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    one_argument( argument,arg);
 
    if (IS_NPC(ch)) return;
    if (!IS_CLASS(ch,CLASS_VAMPIRE))
    {
    send_to_char("Huh?\n\r",ch);
    return;
    }
    if (ch->power[DISC_VAMP_SERP] < 4)
    {
    send_to_char("You require level 5 serpentis to call a serpent.\n\r",ch);
    return;
    }
/*
    if ( arg[0] == '\0' )
    {
        send_to_char( "You can beckon a serpent at anytime.\n\r", ch );
	return;
    }
*/ 

    if (ch->pcdata->followers > 5 )
    {
    send_to_char("Nothing happened.\n\r",ch);
    return;
    }
    
	victim = create_mobile( get_mob_index( MOB_VNUM_SERPENT ) );
	if (victim == NULL)
        {send_to_char("Error - please inform Trace.\n\r",ch); return;}
 
    act( "You close your eyes and concentrate a huge serpent walks in.", ch, NULL, victim, TO_CHAR);
    act( "$n closes his eyes and concentrates a huge $N walks in.", ch, NULL, victim, TO_ROOM);
    char_to_room( victim, ch->in_room );
    ch->pcdata->followers += 1;
    SET_BIT(victim->act, ACT_NOEXP);
    SET_BIT(victim->act, ACT_MOUNT);
    return;
}

void do_illusion(CHAR_DATA *ch, char *argument  )
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    one_argument( argument,arg);
 
    if (IS_NPC(ch)) return;
    if (!IS_CLASS(ch,CLASS_VAMPIRE))
    {
    send_to_char("Huh?\n\r",ch);
    return;
    }
    if (ch->power[DISC_VAMP_CHIM] < 1)
    {
    send_to_char("You require level 1 chim to make an illusion.\n\r",ch);
    return;
    } 

    if (ch->pcdata->followers > 5 )
    {
    send_to_char("Nothing happened.\n\r",ch);
    return;
    }
    
	victim = create_mobile( get_mob_index( MOB_VNUM_ILLUSION ) );
	if (victim == NULL)
        {send_to_char("Error - please inform Trace.\n\r",ch); return;}
 
    act( "You close your eyes and concentrate an illusion appears in the
room.", ch, NULL, victim, TO_CHAR);
    act( "$n closes his eyes and concentrates an $N appears in the room.",
ch, NULL, victim, TO_ROOM);
    char_to_room( victim, ch->in_room );
    ch->pcdata->followers += 1;
    SET_BIT(victim->act, ACT_NOEXP);
    do_form(victim,"justtesting");
    return;
}





#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include "merc.h"

// Necromancy, Melpominee, Obeah

void do_preserve( CHAR_DATA *ch, char *argument )
{
    OBJ_DATA *obj;
    char arg [MAX_INPUT_LENGTH];
    
    argument = one_argument( argument, arg );

    if ( IS_NPC(ch) ) return;

    if ( !IS_CLASS(ch, CLASS_VAMPIRE) )
    {
      stc("Huh?\n\r",ch);
      return;
    }

    if ( ch->power[DISC_VAMP_NECR] < 2 )
    {
      stc("You must obtain level 2 Necromancy to use Preserve.\n\r",ch);
      return;
    }

    if ( ( obj = get_obj_carry(ch, arg) ) == NULL )
    {
      stc("You do not have that item.\n\r",ch);
      return;
    }

    if ( obj->item_type == ITEM_HEAD )
    {
      stc("You cannot preserve that item.\n\r",ch);
      return;
    }

    if ( obj->timer <= 0 )
    {
      stc("That object has no timer.\n\r",ch);
      return;
    }

    obj->timer = -1;
    act("You place your hands on $p and concentrate on it.",ch,obj,NULL,TO_CHAR);
    act("$n places $s hands on $p and it glows brightly.",ch,obj,NULL,TO_ROOM);
    return;
}

void do_spiritguard( CHAR_DATA *ch, char *argument )
{
   
    if (IS_NPC(ch) ) return;

    if (!IS_CLASS(ch, CLASS_VAMPIRE) )
    {
      stc("Huh?\n\r",ch);
      return;
    }

    if ( ch->power[DISC_VAMP_NECR] < 4 )
    {
      stc("You must obtain level 4 Necromancy to use Spirit Guardian.\n\r",ch);
      return;
    }

    if ( !IS_SET(ch->flag2, AFF_SPIRITGUARD) )
    {
      stc("You awaken your spirit guardian.\n\r",ch);
      SET_BIT(ch->flag2, AFF_SPIRITGUARD);
      return;
    }

    else
    {
      stc("You dismiss your spirit guardian.\n\r",ch);
      REMOVE_BIT(ch->flag2, AFF_SPIRITGUARD);
      return;
    }
  return;
}

void do_spiritgate( CHAR_DATA *ch, char *argument )
{
    OBJ_DATA *obj;
    char arg[MAX_INPUT_LENGTH];
   
    argument = one_argument( argument, arg );
   
    if ( IS_NPC(ch) ) return;
  
    if ( !IS_CLASS(ch, CLASS_VAMPIRE) )
    {
      stc("Huh?\n\r",ch);
      return;
    }

    if ( ch->power[DISC_VAMP_NECR] < 3 )
    {
      stc("You must obtain level 3 Necromancy to use SpiritGate.\n\r",ch);
      return;
    }

    if ( ( obj = get_obj_world( ch, arg ) ) == NULL )
    {
      stc("You cannot find that object.\n\r",ch);
      return;
    }

    if ( ch->pcdata->condition[COND_THIRST] < 66 )
    {
      stc("You do not have enough blood.\n\r",ch);
      return;
    }

    if ( obj->in_room == NULL )
    {
      stc("You cannot locate that object.\n\r",ch);
      return;
    }

    if ( obj->carried_by != NULL )
    {
      stc("That corpse is being carried by someone!\n\r",ch);
      return;
    }

    if ( obj->item_type != ITEM_CORPSE_PC && obj->item_type != ITEM_CORPSE_NPC )
    {
      stc("That's not even a corpse!\n\r",ch);
      return;
    }

    if ( obj->in_room->vnum == ch->in_room->vnum )
    {
      stc("You're already there!\n\r",ch);
      return;
    }

    act("$n steps into a spirit gate and vanishes.",ch,NULL,NULL,TO_ROOM);
    char_from_room(ch);
    char_to_room(ch, get_room_index( obj->in_room->vnum ));
    act("You step through a spirit gate and appear before $p.",ch,obj,NULL,TO_CHAR);
    act("$n steps out of a spirit gate in front of $p.",ch,obj,NULL,TO_ROOM);
    ch->pcdata->condition[COND_THIRST] -= 65;
    return;
}

void do_scream( CHAR_DATA *ch, char *argument )
{
   CHAR_DATA *vch;
   CHAR_DATA *vch_next;
   CHAR_DATA *mount;
   char arg[MAX_INPUT_LENGTH];

   argument = one_argument( argument, arg );

   if ( IS_NPC(ch) ) return;
 
   if ( !IS_CLASS(ch, CLASS_VAMPIRE) )
   {
     stc("Huh?\n\r",ch);
     return;
   }

   if ( ch->power[DISC_VAMP_MELP] < 1 )
   {
     stc("You must obtain level 1 Melpominee to use Scream.\n\r",ch);
     return;
   }

   if ( IS_SET(ch->in_room->room_flags, ROOM_SAFE) )
   {
     stc("Your screams will have no effect here.\n\r",ch);
     return;
   }

   if ( ch->pcdata->condition[COND_THIRST] < 50 )
   {
     stc("You have insufficient blood.\n\r",ch);
     return;
   }

    for ( vch = char_list; vch != NULL; vch = vch_next )
    {
        vch_next        = vch->next;

        if ( vch->in_room == NULL )
            continue;
        if ( !IS_NPC(vch) && vch->pcdata->chobj != NULL )
            continue;
        if ( ch == vch )
              continue;
        if ( vch->in_room == ch->in_room )
        {
            if ( ( mount = ch->mount ) != NULL )
            {
                if ( mount == vch )
                continue;
            }
            if (can_see(ch,vch))
            {
              if ( number_range( 1, (7 - ch->power[DISC_VAMP_MELP])) == 2 )
              {
                act("$n lets out an ear-popping scream!",ch,NULL,vch,TO_ROOM);
                stc("You fall to the ground, clutching your ears.\n\r",vch);
                vch->position = POS_STUNNED;
                act("$n falls to the ground, stunned.",vch,NULL,vch,TO_NOTVICT);
                return;
              }
	      else
	      {
                act("$n lets out an ear-popping scream!",ch,NULL,vch,TO_ROOM);
	        return;
	      }
	    }
	    else continue;

	    return;
        }
    }

  return;
}




#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"


void do_bloodwall(CHAR_DATA *ch, char *argument)
{
OBJ_DATA *obj = NULL;
OBJ_DATA *objc;
char arg[MAX_STRING_LENGTH];
char arg2[MAX_STRING_LENGTH];
char wall[MAX_STRING_LENGTH];
char buf[MAX_STRING_LENGTH];
int value;

argument=one_argument(argument,arg);
argument=one_argument(argument,arg2);

if (IS_NPC(ch)) return;

if (!IS_CLASS(ch,CLASS_VAMPIRE))
{
send_to_char("Huh?\n\r",ch);
return;
}
if (ch->power[DISC_VAMP_DAIM] < 2)
{
send_to_char("You need Daiminion 2 to call Blood Walls.\n\r",ch);
return;
}

if (arg[0] == '\0' || (str_cmp(arg,"n")
                   && str_cmp(arg,"s")
                   && str_cmp(arg,"e")
                   && str_cmp(arg,"w")
                   && str_cmp(arg,"u")
                   && str_cmp(arg,"d")))
{
send_to_char("You may wall n, w, s, e, d or u.\n\r",ch);
return;
}

if (arg2[0] == '\0')
{
send_to_char("Please supply the amount of blood to expend.\n\r",ch);
return;
}

value = is_number( arg2 ) ? atoi( arg2 ) : -1;

if (value > 200 || value < 1)
{
send_to_char("Please select a value between 1 and 200.\n\r",ch);
return;
}

ch->pcdata->condition[COND_THIRST] -= value;
sprintf(buf,"A look of concentration passes over %s's face.",ch->name);
act(buf,ch,NULL,NULL,TO_ROOM);
send_to_char("A look of concentration passes over your face.\n\r",ch);
if (!str_cmp(arg,"n")) sprintf(wall,"walln");
if (!str_cmp(arg,"w")) sprintf(wall,"wallw");
if (!str_cmp(arg,"s")) sprintf(wall,"walls");
if (!str_cmp(arg,"e")) sprintf(wall,"walle");
if (!str_cmp(arg,"d")) sprintf(wall,"walld");
if (!str_cmp(arg,"u")) sprintf(wall,"wallu");
objc = get_obj_list(ch,wall,ch->in_room->contents);
if ( objc != NULL)
{
send_to_char("There is already a wall blocking that direction.\n\r",ch);
return;
}
WAIT_STATE(ch,25);
sprintf(buf,"A wall of blood pours out of the ground.");
act(buf,ch,NULL,NULL,TO_ROOM);
send_to_char(buf,ch);
if (!str_cmp(arg,"n")) 
{
obj=create_object(get_obj_index(30043),0);
sprintf(buf,"A wall of blood is here, blocking your exit north.");
obj->short_descr = str_dup(buf);
}
if (!str_cmp(arg,"s")) 
{
obj=create_object(get_obj_index(30044),0);
sprintf(buf,"A wall of blood is here, blocking your exit south.");
obj->short_descr = str_dup(buf);
}
if (!str_cmp(arg,"e")) 
{
obj=create_object(get_obj_index(30045),0);
sprintf(buf,"A wall of blood is here, blocking your exit east");
obj->short_descr = str_dup(buf);
}
if (!str_cmp(arg,"w")) 
{
obj=create_object(get_obj_index(30046),0);
sprintf(buf,"A wall of blood is here, blocking your exit west");
obj->short_descr = str_dup(buf);
}
if (!str_cmp(arg,"d")) 
{
obj=create_object(get_obj_index(30047),0);
sprintf(buf,"A wall of blood is here, blocking your exit down");
obj->short_descr = str_dup(buf);
}
if (!str_cmp(arg,"u")) 
{
obj=create_object(get_obj_index(30048),0);
sprintf(buf,"A wall of blood is here, blocking your exit up.");
obj->short_descr = str_dup(buf);
}
obj_to_room(obj,ch->in_room);
obj->timer=(value/4);
obj->item_type = ITEM_WALL; 
return;
}

void do_bloodrod( CHAR_DATA *ch, char *argument )
{
    OBJ_DATA *obj;
 
    if (IS_NPC(ch)) return;
 
    if (!IS_CLASS(ch, CLASS_VAMPIRE))
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }
 
    if (ch->power[DISC_VAMP_THAU] < 2)
    {
	send_to_char("You need to obtain level 2 Thaumaturgy to create a Blood Rod.\n\r",ch);
	return;
    }

    if ( 10 > ch->practice)
    {
	send_to_char("It costs 10 points of primal to create a Blood Rod.\n\r",ch);
	return;
    }
	ch->practice   -= 10;
	obj = create_object(get_obj_index(OBJ_VNUM_BROD)  ,0 );
    	obj_to_char(obj, ch);
	act("A Rod of Blood appears in your hands.",ch,NULL,NULL,TO_CHAR);
	act("A Rod of blood appears in $n's hands.",ch,NULL,NULL,TO_ROOM);
	return;
}

void do_shadowgaze(CHAR_DATA *ch, char *argument  )
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    char buf[MAX_STRING_LENGTH];
   one_argument( argument,arg);
 
    if (IS_NPC(ch)) return;
    if (!IS_CLASS(ch,CLASS_VAMPIRE))
    {
    send_to_char("Huh?\n\r",ch);
    return;
    }
   if (ch->power[DISC_VAMP_OBTE] < 10)
   {
   send_to_char("You need level 10 Obtenebration to use Shadow Gaze.\n\r",ch);
   return;
   }

   if (!IS_AFFECTED(ch, AFF_SHADOWPLANE))
   {
	send_to_char("You need to be in the Shadowplane, first!\n\r",ch);
	return;
   }


    if ( arg[0] == '\0' )
    {
        send_to_char( "Who do you wish to use Shadow Gaze on?\n\r", ch );
	return;
    }
    if ((victim = get_char_room( ch, arg)) == NULL)
    {
    send_to_char("They arent here.\n\r",ch);
    return;
    }
  
    if (IS_AFFECTED(victim, AFF_SHADOWPLANE))
   {
        send_to_char("They are already in the Shadowplane!\n\r",ch);
        return;
   } 

    if (!IS_NPC(victim))
    {
    send_to_char("You cannot Shadow Gaze a person.\n\r",ch);
    return;
    }
    sprintf(buf,
    "%s gazes intently at %s.",ch->name,victim->short_descr);
    act(buf,ch,NULL,NULL,TO_ROOM);
    sprintf(buf,
    "You gaze deeply into %s's eyes.\n\r",victim->short_descr);
    send_to_char(buf,ch);
    WAIT_STATE(ch, 8);   
    sprintf(buf,
    "You pull %s into the Shadowplane!",victim->short_descr);
    act(buf,ch,NULL,NULL,TO_CHAR);
    sprintf(buf,
    "%s rips %s into the Shadowplane!"
    ,ch->name,victim->short_descr);
    act(buf,ch,NULL,NULL,TO_ROOM);
    SET_BIT(victim->affected_by, AFF_SHADOWPLANE);
    return;
}


void do_grab(CHAR_DATA *ch, char *argument  )
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    char buf[MAX_STRING_LENGTH];
   one_argument( argument,arg);
 
    if (IS_NPC(ch)) return;
    if (!IS_CLASS(ch,CLASS_VAMPIRE))
    {
    send_to_char("Huh?\n\r",ch);
    return;
    }
   if (ch->power[DISC_VAMP_OBTE] < 8)
   {
   send_to_char("You need level 8 Obtenebration to use Grab.\n\r",ch);
   return;
   }

   if (!IS_AFFECTED(ch, AFF_SHADOWPLANE))
   {
	send_to_char("You need to be in the Shadowplane, first!\n\r",ch);
	return;
   }


    if ( arg[0] == '\0' )
    {
        send_to_char( "Who do you wish to Grab?\n\r", ch );
	return;
    }
    if ((victim = get_char_room( ch, arg)) == NULL)
    {
    send_to_char("They arent here.\n\r",ch);
    return;
    }

     if (IS_AFFECTED(victim, AFF_SHADOWPLANE))
   {
        send_to_char("They are already in the Shadowplane!\n\r",ch);
        return;
   }

    if (IS_NPC(victim))
    {
    send_to_char("You cannot Grab a mobile!\n\r",ch);
    return;
    }
    sprintf(buf,
    "%s pulls %s into the Shadowplane.",ch->name,victim->name);
    act(buf,ch,NULL,NULL,TO_ROOM);
    sprintf(buf,
    "You pull %s into the Shadowplane!\n\r",victim->name);
    send_to_char(buf,ch);
    sprintf(buf,
    "%s pulls you into the Shadowplane!\n\r",ch->name);
    act(buf,ch,NULL,victim,TO_VICT);
    WAIT_STATE(ch, 8);     
    SET_BIT(victim->affected_by, AFF_SHADOWPLANE);
    return;
}


void do_share( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    CHAR_DATA *familiar;
    char arg[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];

    one_argument( argument, arg );

    if ( IS_NPC(ch) )
	return;

    if (!IS_CLASS(ch, CLASS_VAMPIRE) )
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }

    if (ch->power[DISC_VAMP_ANIM] < 4)
    {
        send_to_char("You must obtain at least level 4 in Animalism to use Share Spirits.\n\r",ch);
	return;
    }

    if ( ( familiar = ch->pcdata->familiar ) != NULL)
    {
	sprintf(buf,"You release %s.\n\r",familiar->short_descr);
	send_to_char( buf, ch );
	familiar->wizard = NULL;
	ch->pcdata->familiar = NULL;
	return;
    }

    if ( arg[0] == '\0' )
    {
	send_to_char( "What do you wish to Share spirits with?\n\r", ch );
	return;
    }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( ch == victim )
    {
	send_to_char( "What an intelligent idea!\n\r", ch );
	return;
    }

    if ( !IS_NPC(victim) )
    {
	send_to_char( "Not on players.\n\r", ch );
	return;
    }

    if (victim->wizard != NULL)
    {
	send_to_char( "You are unable to Share Spirits them.\n\r", ch );
	return;
    }

    if (victim->level > (ch->spl[RED_MAGIC] * 0.25))
    {
	send_to_char( "They are too powerful.\n\r", ch );
	return;
    }

    if ( ch->pcdata->condition[COND_THIRST] < 25 )
    {
	send_to_char("You have insufficient blood.\n\r",ch);
	return;
    }

    ch->pcdata->condition[COND_THIRST] -= 25;
    ch->pcdata->familiar = victim;
    victim->wizard = ch;
    act("You share your being with $N.",ch,NULL,victim,TO_CHAR);
    act("$n is staring at you!",ch,NULL,victim,TO_VICT);
    act("$n starts staring at $N",ch,NULL,victim,TO_NOTVICT);
    return;
}

void do_frenzy( CHAR_DATA *ch, char *argument )
{
/*
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;

    argument = one_argument (argument, arg);
*/

    if ( IS_NPC(ch) )
	return;


    if ( ch->power[DISC_VAMP_ANIM] < 5 )
    {
	send_to_char("You need level 5 Animalism to use Frenzy.\n\r",ch);
	return;
    }
/*
    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
        send_to_char( "They aren't here.\n\r", ch );
        return;
    }    

    if ( IS_NPC(victim) )
	{
	  send_to_char("Not on NPC's!\n\r",ch);
	  return;
	}



    if (IS_CLASS(victim, CLASS_VAMPIRE) && arg[0] != '\0')
    {
	if ( victim->rage >= 25 )
	{
	    send_to_char("Their beast is already controlling them!\n\r",ch);
	    return;
	}

      if (number_percent ( )  <= 50)
	{
	    send_to_char("They shake off your attempt.\n\r",ch);
	    act("You shake off $n's attempt to frenzy you.\n\r",ch,NULL,victim,TO_VICT);
	    act("$N shakes off $n's attempt to frenzy $m.\n\r",ch,NULL,victim,TO_ROOM);
          return;
      }

      if (victim->beast == 0 )
	{
	  send_to_char("They are too calm to frenzy!\n\r",ch);
	  return;
	}

	if (!IS_VAMPAFF(victim, VAM_NIGHTSIGHT)) do_nightsight(victim,"");
	if (!IS_VAMPAFF(victim, VAM_FANGS)) do_fangs(victim,"");
	if (!IS_VAMPAFF(victim, VAM_CLAWS)) do_claws(victim,"");
      act("$n sends you into a frenzied rage!",ch,NULL,victim,TO_VICT);
	act("You excite the beast within $n!",victim,NULL,NULL,TO_CHAR);
	act("$n bares $s fangs and growls as $s inner beast consumes $m.",ch,NULL,NULL,TO_ROOM);
	ch->rage += number_range(10,20);
	if (victim->beast > 0) do_beastlike(victim,"");
	WAIT_STATE(ch,12);
	return;
    }
   
    send_to_char("But they are already in a rage!\n\r",ch);
    return;
*/

    if (IS_CLASS(ch, CLASS_VAMPIRE))
    {
      if (ch->beast >= 20)
      {
	if ( ch->rage >= ch->beast )
	{
	    send_to_char("Your beast is already controlling you.\n\r",ch);
	    return;
	}
      }
      if (ch->beast <= 19)
      {
        if ( ch->rage >= 20 )
        {
            send_to_char("Your beast is already controlling you.\n\r",ch);
            return;
        }
      } 

/*
        if (ch->beast == 0)
	{
	   send_to_char("You are too calm to use frenzy.\n\r",ch);
	   return;
	}

*/

	if (!IS_VAMPAFF(ch, VAM_NIGHTSIGHT)) do_nightsight(ch,"");
	if (!IS_VAMPAFF(ch, VAM_FANGS)) do_fangs(ch,"");
	if (!IS_VAMPAFF(ch, VAM_CLAWS)) do_claws(ch,"");
	send_to_char("You bare your fangs and growl as your inner beast consumes you.\n\r",ch);
	act("$n bares $s fangs and growls as $s inner beast consumes $m.",ch,NULL,NULL,TO_ROOM);
	ch->rage += number_range(20,30);
	if (ch->beast > 0) do_beastlike(ch,"");
	WAIT_STATE(ch,12);
	return;
    }
 
    send_to_char("But you are already in a rage!\n\r",ch);
    return;
}

void do_shroud( CHAR_DATA *ch, char *argument )
{
    if ( IS_NPC(ch) )
	return;

    if (!IS_CLASS(ch, CLASS_VAMPIRE) || (ch->power[DISC_VAMP_OBTE] < 1))
     {
	  send_to_char("You need level 1 Obtenebration to use this power.\n\r",ch);
	  return;
     }

    if ( IS_SET(ch->act, PLR_WIZINVIS) )
    {
	REMOVE_BIT(ch->act, PLR_WIZINVIS);
	send_to_char( "You step out from the shadows.\n\r", ch );
	act("$n emerges from the shadows.",ch,NULL,NULL,TO_ROOM);
    }
    else
    {
	send_to_char( "You slowly blend with the shadows.\n\r", ch );
	act("$n blends in with the shadows and disappears.",ch,NULL,NULL,TO_ROOM);
	SET_BIT(ch->act, PLR_WIZINVIS);
    }
    return;
}

void do_summon(CHAR_DATA *ch, char *argument)
{
    CHAR_DATA *victim;
    CHAR_DATA *mount;
    char arg [MAX_INPUT_LENGTH];

    argument = one_argument (argument,arg);


    if ( !IS_CLASS(ch, CLASS_VAMPIRE) )
    {
      do_nosummon(ch,"");
      return;
    }

    if (arg[0] == '\0')
    {
	send_to_char("Summon whom?\n\r",ch);
	return;
    }  

    if ( ( victim = get_char_world( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }


    if   (victim == ch
    ||   victim->in_room == NULL
    ||   IS_SET(victim->in_room->room_flags, ROOM_SAFE)
    ||   IS_SET(victim->in_room->room_flags, ROOM_PRIVATE)
    ||   IS_SET(victim->in_room->room_flags, ROOM_SOLITARY)
    ||   IS_SET(victim->in_room->room_flags, ROOM_NO_RECALL)
    ||   victim->level >= ch->level + 5
    ||   victim->fighting != NULL
    ||   (!IS_NPC(victim) && !IS_IMMUNE(victim, IMM_SUMMON) ))
    
    {
	send_to_char( "You cannot locate them.\n\r", ch );
	return;
    }

    if (ch->power[DISC_VAMP_PRES] < 4)
    {
	send_to_char("You need level 4 in Presence to use this.\n\r",ch);
	return;
    }
    WAIT_STATE(ch,10);
    act( "$n disappears suddenly.", victim, NULL, NULL, TO_ROOM );
    char_from_room( victim );
    char_to_room( victim, ch->in_room );
    act( "$n arrives suddenly.", victim, NULL, NULL, TO_ROOM );
    act( "$N has summoned you!", victim, NULL, ch,   TO_CHAR );
    do_look( victim, "auto" );
    if ( (mount = victim->mount) == NULL ) return;
    char_from_room( mount );
    char_to_room( mount, get_room_index(victim->in_room->vnum) );
    do_look( mount, "auto" );
    return;
}


void do_drain( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char arg [MAX_INPUT_LENGTH];
    int dam;

    argument = one_argument( argument, arg );

    if ( IS_NPC(ch) )
	return;

    if (!IS_CLASS(ch, CLASS_VAMPIRE))
     {
	  send_to_char("Huh?\n\r",ch);
	  return;
     }

    if (ch->power[DISC_VAMP_THAN] < 5 )
     {
	send_to_char("You must obtain level 5 Thanatosis to use Drain Life.\n\r",ch);
	return;
     }
     
  
   if ( ( victim = get_char_room( ch, arg ) ) == NULL && (ch->fighting) == NULL)
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }
   if ((ch->fighting) != NULL)
   {
   victim = ch->fighting;
   }
    
   if ( arg[0] == '\0' && (ch->fighting) == NULL)
    {
	send_to_char( "Whose life do you wish to drain?\n\r", ch );
	return;
    }

    if (victim->hit < 500)
	{
	   send_to_char("They are far to hurt to do that!\n\r",ch);
	   return;
	}

	 if (is_safe(ch, victim))
	 {
       send_to_char("Not while in a safe room!\n\r", ch);
       return;
    }

    if (IS_NPC(victim))
	{
	  dam = ch->power[DISC_VAMP_THAN] * 10;
        victim->hit = (victim->hit - dam);
        if (dam > 500) dam = number_range( 450, 550 );
        ch->hit = (ch->hit + dam);
	if (ch->hit > ch->max_hit + 1000)
	ch->hit = ch->max_hit + 1000;
        act("You drain the lifeforce out of $N.", ch, NULL, victim, TO_CHAR);
        act("$n drains the lifeforce out of $N.", ch, NULL, victim, TO_NOTVICT);
        act("You feel $n draining your lifeforce.", ch, NULL, victim, TO_VICT);
        WAIT_STATE(ch,12);
	  return;
      }

    if (!IS_NPC(victim))
	{
	  dam = ch->power[DISC_VAMP_THAN] * 50;
        victim->hit = (victim->hit - dam);
        if (dam > 400) dam = number_range( 350, 450 );
        ch->hit = (ch->hit + dam);
        if (ch->hit > ch->max_hit + 1000)
        ch->hit = ch->max_hit + 1000;      
        act("You drain the lifeforce out of $N.", ch, NULL, victim, TO_CHAR);
        act("$n drains the lifeforce out of $N.", ch, NULL, victim, TO_NOTVICT);
        act("You feel $n draining your lifeforce.", ch, NULL, victim, TO_VICT);
        WAIT_STATE(ch,12);
	  return;
      }


}

void do_flamehands( CHAR_DATA *ch, char *argument)
{
    if ( IS_NPC(ch) )
     return;

    if (!IS_CLASS(ch, CLASS_VAMPIRE))
    {
	  send_to_char("Huh?\n\r",ch);
	  return;
    }

    if (ch->power[DISC_VAMP_PROT] < 5)
    {
	  send_to_char("You need level 5 Protean to use flaming hands.\n\r",ch);
	  return;
    }

    if (IS_SET(ch->newbits, NEW_MONKFLAME))
    {
	  REMOVE_BIT(ch->newbits, NEW_MONKFLAME);
        send_to_char("Your hands are no longer engulfed by flames.\n\r",ch);
	  act("$n's hands are no longer engulfed by flames.\n\r",ch,NULL,NULL,TO_ROOM);
	  return;
    }
    if (!IS_SET(ch->newbits, NEW_MONKFLAME))
    {
	  SET_BIT(ch->newbits, NEW_MONKFLAME);
	  send_to_char("Your hands are engulfed by flames!\n\r",ch);
	  act("$n's hands are engulfed by flames!\n\r",ch,NULL,NULL,TO_ROOM);
	  return;
    }
}

void do_cauldron( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char arg1 [MAX_INPUT_LENGTH];
    char arg2 [MAX_INPUT_LENGTH];
    int value;
    int dam;

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    value = is_number( arg2 ) ? atoi( arg2 ) : -1;

    if ( IS_NPC(ch) )
	return;

    if (!IS_CLASS(ch, CLASS_VAMPIRE))
     {
	  send_to_char("Huh?\n\r",ch);
	  return;
     }

    if (ch->power[DISC_VAMP_THAU] < 2)
     {
	send_to_char("You need at least level 2 Thaumaturgy to use this power.\n\r",ch);
	return;
     }


    if ( arg1[0] == '\0' )
    {
	send_to_char( "Whose blood do you wish to boil?\n\r", ch );
	return;
    }
     if ( ( victim = get_char_room( ch, arg1 ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if (arg2[0] == '\0' )
    {
	send_to_char( "How much blood do you want to use?\n\r", ch );
	return;
    }

    if (value > 200)
    {
	stc("You can only use 200 blood on this power.\n\r",ch);
	return;
    }


    if (ch->pcdata->condition[COND_THIRST] < value )
	{
	   send_to_char("You don't have that much blood!\n\r",ch);
	   return;
	}

if (is_safe(ch,victim) == TRUE) return;

    if (IS_NPC(victim))
	{
	dam = (value * 4);
        victim->hit = (victim->hit - dam);
        ch->pcdata->condition[COND_THIRST] = ch->pcdata->condition[COND_THIRST] - value;
        act("$N screams in agony as $m blood begins to boil.", ch, NULL, victim, TO_CHAR);
        act("$N screams in agony as $n causes his blood to boil.", ch, NULL, victim, TO_NOTVICT);
        act("You scream in agony as $n causes your blood to boil.", ch, NULL, victim, TO_VICT);
        WAIT_STATE(ch,12);
	  return;
      }

    if (!IS_NPC(victim))
	{
	  dam = value * 1.5;
        victim->hit = (victim->hit - dam);
	if (victim->pcdata->condition[COND_THIRST] < value)
	victim->pcdata->condition[COND_THIRST] = 1;
        victim->pcdata->condition[COND_THIRST] = victim->pcdata->condition[COND_THIRST] - value;
	ch->pcdata->condition[COND_THIRST] = ch->pcdata->condition[COND_THIRST] - value;
        act("$N screams in agony as $m blood begins to boil.", ch, NULL, victim, TO_CHAR);
        act("$N screams in agony as $n causes his blood to boil.", ch, NULL, victim, TO_NOTVICT);
        act("You scream in agony as $n causes your blood to boil.", ch, NULL, victim, TO_VICT);
        WAIT_STATE(ch,12);
	  return;
      }


}
void do_vset( CHAR_DATA *ch, char *argument )
{
    char arg1 [MAX_INPUT_LENGTH];
    char arg2 [MAX_INPUT_LENGTH];
    char arg3 [MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    CHAR_DATA *victim;
    int value;
    
    sprintf(buf,"%s: Vset %s",ch->name,argument);
    if (ch->level < NO_WATCH) do_watching(ch,buf);
/*
    smash_tilde( argument );
  */
  argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );
argument=one_argument(argument,arg3);
  /*
   strcpy( arg3, argument );
  */
    if ( arg1[0] == '\0' || arg2[0] == '\0' || arg3[0] == '\0' )
    {
	send_to_char( "\n\r",ch);
	send_to_char( "Syntax:vset <victim> <field>  <value>\n\r", ch );
	send_to_char( "\n\r", ch );
	send_to_char( "Field being one of:\n\r", ch );
	send_to_char( "    Animal Obtenebration Thau    \n\r",   ch );
	send_to_char( "    Serpentis Celerity Daim      \n\r",       ch ); 
        send_to_char( "    Potence Viciss Fortitude     \n\r",       ch ); 
        send_to_char( "    Dominate Protean Quietus     \n\r",	     ch );
	send_to_char( "    Auspex Presence Obfuscate    \n\r",       ch );
	send_to_char( " --------------------------------\n\r",       ch );
        send_to_char( "    Clan  Lord  Generation  Age  \n\r",       ch );
	send_to_char( " --------------------------------\n\r",       ch );
	return;
    }
    if ((victim = get_char_room(ch, arg1)) == NULL)
     {
       
      send_to_char("They arent here.\n\r",ch);
    return;
}

    
    value = is_number( arg3 ) ? atoi( arg3 ) : -1;
    /*
     * Set something.
     */
    if ( !str_cmp( arg2, "animal" ) )
    {
	if ( IS_NPC(victim) )
	{
	    send_to_char( "Not on NPC's.\n\r", ch );
	    return;
	}

	if ( value < 0 || value > 10 )
	{
	    send_to_char( "Range is from 0 to 10.\n\r", ch );
	    return;
	}


	if (IS_CLASS(victim, CLASS_VAMPIRE))
	victim->power[DISC_VAMP_ANIM] = value;
	send_to_char("Ok. \n\r",ch);
	return;
    }

    if ( !str_cmp( arg2, "thau" ) )
    {
	if ( IS_NPC(victim) )
	{
	    send_to_char( "Not on NPC's.\n\r", ch );
	    return;
	}

	if ( value < 0 || value > 10 )
	{
	    send_to_char( "Range is from 0 to 10.\n\r", ch );
	    return;
	}

	if (IS_CLASS(victim, CLASS_VAMPIRE))
	victim->power[DISC_VAMP_THAU] = value;
	send_to_char("Ok. \n\r",ch);
	return;
    }

    if ( !str_cmp( arg2, "Obtenebration" ) )
    {
	if ( IS_NPC(victim) )
	{
	    send_to_char( "Not on NPC's.\n\r", ch );
	    return;
	}

	if ( value < 0 || value > 10 )
	{
	    send_to_char( "Range is from 0 to 10.\n\r", ch );
	    return;
	}

	if (IS_CLASS(victim, CLASS_VAMPIRE))
	victim->power[DISC_VAMP_OBTE] = value;
	send_to_char("Ok. \n\r",ch);
	return;
    }

    if ( !str_cmp( arg2, "serpentis" ) )
    {
	if ( IS_NPC(victim) )
	{
	    send_to_char( "Not on NPC's.\n\r", ch );
	    return;
	}

	if ( value < 0 || value > 10 )
	{
	    send_to_char( "Range is from 0 to 10.\n\r", ch );
	    return;
	}

	if (IS_CLASS(victim, CLASS_VAMPIRE))
	victim->power[DISC_VAMP_SERP] = value;
	send_to_char("Ok. \n\r",ch);
	return;
    }

  if ( !str_cmp( arg2, "celerity" ) )
{

    if ( IS_NPC(victim) )
	{
	    send_to_char( "Not on NPC's.\n\r", ch );
	    return;
	}

	if ( value < 0 || value > 10 )
	{
	    send_to_char( "Range is from 0 to 10.\n\r", ch );
	    return;
	}

	if (IS_CLASS(victim, CLASS_VAMPIRE))
	victim->power[DISC_VAMP_CELE] = value;
	send_to_char("Ok. \n\r",ch);
	return;
    }

    if ( !str_cmp( arg2, "presence" ) )
    {
	if ( IS_NPC(victim) )
	{
	    send_to_char( "Not on NPC's.\n\r", ch );
	    return;
	}

	if ( value < 0 || value > 10 )
	{
	    send_to_char( "Range is from 0 to 10.\n\r", ch );
	    return;
	}

	if (IS_CLASS(victim, CLASS_VAMPIRE))
	victim->power[DISC_VAMP_PRES] = value;
	send_to_char("Ok. \n\r",ch);
	return;
    }

    if ( !str_cmp( arg2, "auspex" ) )
    {
	if ( IS_NPC(victim) )
	{
	    send_to_char( "Not on NPC's.\n\r", ch );
	    return;
	}

	if ( value < 0 || value > 10 )
	{
	    send_to_char( "Range is from 0 to 10.\n\r", ch );
	    return;
	}

	if (IS_CLASS(victim, CLASS_VAMPIRE))
	victim->power[DISC_VAMP_AUSP] = value;
	send_to_char("Ok. \n\r",ch);
	return;
    }

  if ( !str_cmp( arg2, "potence" ) )
    {

    if ( IS_NPC(victim) )
	{
	    send_to_char( "Not on NPC's.\n\r", ch );
	    return;
	}

	if ( value < 0 || value > 10 )
	{
	    send_to_char( "Range is from 0 to 10.\n\r", ch );
	    return;
	}

	if (IS_CLASS(victim, CLASS_VAMPIRE))
	victim->power[DISC_VAMP_POTE] = value;
	send_to_char("Ok. \n\r",ch);
	return;
    }

    if ( !str_cmp( arg2, "viciss" ) )
    {
	if ( IS_NPC(victim) )
	{
	    send_to_char( "Not on NPC's.\n\r", ch );
	    return;
	}

	if ( value < 0 || value > 10 )
	{
	    send_to_char( "Range is from 0 to 10.\n\r", ch );
	    return;
	}

	if (IS_CLASS(victim, CLASS_VAMPIRE))
	victim->power[DISC_VAMP_VICI] = value;
	send_to_char("Ok. \n\r",ch);
	return;
    }

    if ( !str_cmp( arg2, "fortitude" ) )
    {
	if ( IS_NPC(victim) )
	{
	    send_to_char( "Not on NPC's.\n\r", ch );
	    return;
	}

	if ( value < 0 || value > 10 )
	{
	    send_to_char( "Range is from 0 to 10.\n\r", ch );
	    return;
	}

	if (IS_CLASS(victim, CLASS_VAMPIRE))
	victim->power[DISC_VAMP_FORT] = value;
	send_to_char("Ok. \n\r",ch);
	return;
    }

        if ( !str_cmp( arg2, "quietus" ) )
    {
	if ( IS_NPC(victim) )
	{
	    send_to_char( "Not on NPC's.\n\r", ch );
	    return;
	}

	if ( value < 0 || value > 10 )
	{
	    send_to_char( "Range is from 0 to 10.\n\r", ch );
	    return;
	}

	if (IS_CLASS(victim, CLASS_VAMPIRE))
	victim->power[DISC_VAMP_QUIE] = value;
	send_to_char("Ok. \n\r",ch);
	return;
    }

  if ( !str_cmp( arg2, "dominate" ) )
   { 

    if ( IS_NPC(victim) )
	{
	    send_to_char( "Not on NPC's.\n\r", ch );
	    return;
	}

	if ( value < 0 || value > 10 )
	{
	    send_to_char( "Range is from 0 to 10.\n\r", ch );
	    return;
	}

	if (IS_CLASS(victim, CLASS_VAMPIRE))
	victim->power[DISC_VAMP_DOMI] = value;
	send_to_char("Ok. \n\r",ch);
	return;
    }

    if ( !str_cmp( arg2, "protean" ) )
    {
	if ( IS_NPC(victim) )
	{
	    send_to_char( "Not on NPC's.\n\r", ch );
	    return;
	}

	if ( value < 0 || value > 10 )
	{
	    send_to_char( "Range is from 0 to 10.\n\r", ch );
	    return;
	}

	if (IS_CLASS(victim, CLASS_VAMPIRE))
	victim->power[DISC_VAMP_PROT] = value;
	send_to_char("Ok. \n\r",ch);
	return;
    }

    if ( !str_cmp( arg2, "daim" ) )
    {
	if ( IS_NPC(victim) )
	{
	    send_to_char( "Not on NPC's.\n\r", ch );
	    return;
	}

	if ( value < 0 || value > 10 )
	{
	    send_to_char( "Range is from 0 to 10.\n\r", ch );
	    return;
	}

	if (IS_CLASS(victim, CLASS_VAMPIRE))
	victim->power[DISC_VAMP_DAIM] = value;
	send_to_char("Ok. \n\r",ch);
	return;
    }

    if ( !str_cmp( arg2, "age" ) )
    {
	if ( IS_NPC(victim)) 
	{
	   send_to_char("Not on Mobiles.\n\r",ch);
	   return;
	}

	if (!IS_CLASS(ch,CLASS_VAMPIRE))
	{
	   send_to_char("Only on Vampires!\n\r",ch);
	   return;
	}

	     if ( !str_cmp( arg3, "childe"     ) )
{
 victim->pcdata->rank = AGE_CHILDE;
send_to_char("Ok.\n\r",ch);
return;
}
	else if ( !str_cmp( arg3, "ancilla"    ) )
{
 victim->pcdata->rank = AGE_ANCILLA;
send_to_char("Ok.\n\r",ch);
return;
}
	else if ( !str_cmp( arg3, "elder"      ) )
{
 victim->pcdata->rank = AGE_ELDER;
send_to_char("Ok.\n\r",ch);
return;
}
	else if ( !str_cmp( arg3, "methuselah" ) ) 
{
victim->pcdata->rank = AGE_METHUSELAH;
send_to_char("Ok.\n\r",ch);
return;
}
	else if (!IS_NPC(victim))
	{
	   
           send_to_char( "Age should be one of the following:\n\r Childe,
Ancilla, Elder, or Methuselah.\n\r", ch );
	    return;
	}

    }


    if ( !str_cmp( arg2, "blood" ) )
    {
	if ( IS_NPC(victim) )
	{
	    send_to_char( "Not on NPC's.\n\r", ch );
	    return;
	}

	if ( value < 0 || value > 1000 )
	{
	    send_to_char( "Blood range is 0 to 1000.\n\r", ch );
	    return;
	}

	victim->pcdata->condition[COND_THIRST] = value;
	send_to_char("Ok.\n\r",ch);
	return;
    }

    


    if ( !str_cmp( arg2, "lord" ) )
    {
	if ( IS_NPC(victim) )
	{
	    send_to_char( "Not on NPC's.\n\r", ch );
	    return;
	}

        smash_tilde(argument);
        capitalize(arg3);
	free_string( victim->lord );
	victim->lord = str_dup( arg3 );
	send_to_char("Ok.\n\r",ch);
	return;
    }

    if ( !str_cmp( arg2, "generation" ) )
    {
	if ( IS_NPC(victim) )
	{
	    send_to_char( "Not on NPC's.\n\r",ch );
	    return;
	}
	if (!IS_CLASS(ch, CLASS_VAMPIRE))
	{
	    send_to_char( "Only on Vampires!\n\r",ch);
	    return;
	}

	if ( value < 1 || value > 15 )
	{
	   send_to_char("Valid range is 1 - 15 \n\r",ch);
	   return;
	}

	victim->generation = value;
	send_to_char("Ok.\n\r",ch);
	return;
     }

   
    do_vset( ch, "" );
    return;
}


void do_bonemod( CHAR_DATA *ch, char *argument )
{
    char arg1 [MAX_INPUT_LENGTH];

    smash_tilde( argument );
    argument = one_argument( argument, arg1 );


	if (IS_NPC(ch)) return;

	if (!IS_CLASS(ch, CLASS_VAMPIRE))
	{
	   send_to_char("Huh?\n\r",ch);
	   return;
	}
	if (ch->power[DISC_VAMP_VICI] < 3)
	{
	   send_to_char("You need level 3 Vicissitude to use this power.\n\r",ch);
	   return;
	}

    if ( arg1[0] == '\0')
    {
	send_to_char( "Syntax: bonemod <modification>\n\r",	ch );
	send_to_char( "Horns, Wings, Head, Exoskeleton, Tail\n\r",ch);
        return;
    }


    /*
     * Set something.
     */
    if ( !str_cmp( arg1, "horns" ) )
    {
	
 	if (!IS_VAMPAFF(ch, VAM_HORNS))
	 {
	  SET_BIT(ch->pcdata->stats[UNI_AFF], VAM_HORNS);
	  send_to_char("You pull a set of horns out of your head.\n\r",ch);
	  act("$n pulls a set of horns from his head!\n\r",ch,NULL,NULL,TO_ROOM);
	  return;
       }
	
	if (IS_VAMPAFF(ch, VAM_HORNS))
	 {
	  REMOVE_BIT(ch->pcdata->stats[UNI_AFF], VAM_HORNS);
	  send_to_char("You push your horns back into your head.\n\r",ch);
	  act("$n pushes $n's horns back into $n head.\n\r",ch,NULL,NULL,TO_ROOM); 
	  return;

	 }
    }

    if ( !str_cmp( arg1, "wings" ) )
    {
	
 	if (!IS_VAMPAFF(ch, VAM_WINGS))
	 {
	  SET_BIT(ch->pcdata->stats[UNI_AFF], VAM_WINGS);
	  send_to_char("You pull a pair of leathery wings from your back.\n\r",ch);
	  act("$n pulls a pair of leathery wings from $s back!\n\r",ch,NULL,NULL,TO_ROOM);
	  return;
       }
	
	if (IS_VAMPAFF(ch, VAM_WINGS))
	 {
	  REMOVE_BIT(ch->pcdata->stats[UNI_AFF], VAM_WINGS);
	  send_to_char("You push your wings into your back.\n\r",ch);
	  act("$n pushes $s wings into $s back.\n\r",ch,NULL,NULL,TO_ROOM);
	  return;

	 }
    }    

     if ( !str_cmp( arg1, "exoskeleton" ) )
    {
	
 	if (!IS_VAMPAFF(ch, VAM_EXOSKELETON))
	 {
	  SET_BIT(ch->pcdata->stats[UNI_AFF], VAM_EXOSKELETON);
	  send_to_char("Your skin is covered by a hard exoskeleton.\n\r",ch);
	  act("$n's skin is covered by a hard exoskeleton!\n\r",ch,NULL,NULL,TO_ROOM);
	  return;
       }
	
	if (IS_VAMPAFF(ch, VAM_EXOSKELETON))
	 {
	  REMOVE_BIT(ch->pcdata->stats[UNI_AFF], VAM_EXOSKELETON);
	  send_to_char("Your exoskeleton slowly disappears under your skin.\n\r",ch);
	  act("$n's hard exoskeleton disappears under $s skin.\n\r",ch,NULL,NULL,TO_ROOM);
	  return;

	 }
    }    

     if ( !str_cmp( arg1, "tail" ) )
    {
	
 	if (!IS_VAMPAFF(ch, VAM_TAIL))
	 {
	  SET_BIT(ch->pcdata->stats[UNI_AFF], VAM_TAIL);
	  send_to_char("Your spine extends out into a long, pointed tail.\n\r",ch);
	  act("$n's spine extends to form a long pointed tail!\n\r",ch,NULL,NULL,TO_ROOM);
	  return;
       }
	
	if (IS_VAMPAFF(ch, VAM_TAIL))
	 {
	  REMOVE_BIT(ch->pcdata->stats[UNI_AFF], VAM_TAIL);
	  send_to_char("Your tail slowly retracts into your spine.\n\r",ch);
	  act("$n's tail shrinks and vanishes into $s spine.\n\r",ch,NULL,NULL,TO_ROOM);
	  return;

	 }
    }    

     if ( !str_cmp( arg1, "head" ) )
    {
	
 	if (!IS_VAMPAFF(ch, VAM_HEAD))
	 {
	  SET_BIT(ch->pcdata->stats[UNI_AFF], VAM_HEAD);
	  send_to_char("Your head transforms into that of a fierce lion.\n\r",ch);	  
	  act("$n's head transforms into that of a fierce lion!\n\r",ch,NULL,NULL,TO_ROOM);
	  return;
       }
	
	if (IS_VAMPAFF(ch, VAM_HEAD))
	 {
	  REMOVE_BIT(ch->pcdata->stats[UNI_AFF], VAM_HEAD);
	  send_to_char("Your head slowly resumes it's normal form.\n\r",ch);
	  act("$n's head resumes its normal form.\n\r",ch,NULL,NULL,TO_ROOM);
	  return;

	 }
    }    




    /*
     * Generate usage message.
     */
    do_bonemod( ch, "" );
    return;
}




*****************************************************


 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *


 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *


 *                                                                         *


 *  Merc Diku Mud improvements copyright (C) 1992, 1993 by Michael         *


 *  Chastain, Michael Quan, and Mitchell Tse.                              *


 *                                                                         *


 *  In order to use any part of this Merc Diku Mud, you must comply with   *


 *  both the original Diku license in 'license.doc' as well the Merc       *


 *  license in 'license.txt'.  In particular, you may not remove either of *


 *  these copyright notices.                                               *


 *                                                                         *


 *  Much time and thought has gone into this software and you are          *


 *  benefiting.  We hope that you share your changes too.  What goes       *


 *  around, comes around.                                                  *


 ***************************************************************************/





#if defined(macintosh)


#include <types.h>


#else


#include <sys/types.h>


#endif


#include <stdio.h>


#include <stdlib.h>


#include <string.h>


#include <time.h>


#include <assert.h>


#include <unistd.h>


#include <string.h>


#include "merc.h"





const char wizutil_id [] = "$Id: wizutil.c,v 1.6 1996/01/04 21:30:45 root Exp root $";



/*addlag, add lag to troublesome players -Trace- */
void do_addlag(CHAR_DATA *ch, char *argument)
{
        CHAR_DATA *victim;
        char arg1[MAX_STRING_LENGTH];
        int x;

        argument = one_argument(argument, arg1);

        if (arg1[0] == '\0')
        {
                send_to_char("Addlag to who?", ch);
                return;
        }

        if ((victim = get_char_world(ch, arg1)) == NULL)
        {
                send_to_char("They're not here.", ch);
                return;
        }

        if ((x = atoi(argument)) <= 0)
        {
                send_to_char("That makes a LOT of sense, ya lag yourself *DUH*.", ch);
                return;
        }

        if (x > 100)
        {
                send_to_char("There's a limit to cruel and unusual punishment", ch);
                return;
        }

        send_to_char("Somebody REALLY dosen't like you", victim);
        WAIT_STATE(victim, x);
        send_to_char("That ought to show that nerdy bitch...", ch);
        return;
}

/*secset, set security -Trace- */
void do_secset(CHAR_DATA *ch, char *argument)      
{	CHAR_DATA *victim;	
	char arg1[MAX_STRING_LENGTH];
	char arg2[MAX_STRING_LENGTH];	
	char buf[MAX_STRING_LENGTH];
	int seclevel;
	
	argument = one_argument(argument, arg1);
	
	if (arg1[0] =='\0')	
	{
	send_to_char("Set who's Security?\n\r", ch);
	return;	
	}
	
	if ((victim = get_char_world(ch, arg1)) == NULL)	
	{
	send_to_char("They're not here.\n\r", ch);
	return;	
	}

	if ( IS_NPC( victim ) )
    	{		
	send_to_char( "You may change an NPC's security.\n\r", ch);	return;
    	}
        
	if ( victim->level > ch->level )    
	{
    	send_to_char("You may not alter someones who is a higher level than you.\n\r", ch);		
	return;	
	}	

	argument = one_argument(argument, arg2);

	if (arg2[0] == '\0')	
	{
	send_to_char("Set their security to what level?\n\r", ch);
	return;	
	}

	seclevel = atoi(arg2);	

	if( (seclevel <= 0) || (seclevel > 9) )	
	{
	send_to_char("Security range is from 1 to 9.\n\r", ch);
	return;	
	}
	victim->pcdata->security = seclevel;
	send_to_char("Changed players security level.\n\r", ch);
	sprintf(buf, "%s just raised your security to level %d",ch->name,seclevel);
	send_to_char(buf, victim);	
	return;
}
/*


===========================================================================


This snippet was written by Erwin S. Andreasen, erwin@pip.dknet.dk. You may 


use this code freely, as long as you retain my name in all of the files. You


also have to mail me telling that you are using it. I am giving this,


hopefully useful, piece of source code to you for free, and all I require


from you is some feedback.





Please mail me if you find any bugs or have any new ideas or just comments.





All my snippets are publically available at:





http://pip.dknet.dk/~pip1773/





If you do not have WWW access, try ftp'ing to pip.dknet.dk and examine


the /pub/pip1773 directory.


===========================================================================





  Various administrative utility commands.


  Version: 3 - Last update: January 1996.





  To use these 2 commands you will have to add a filename field to AREA_DATA.


  This value can be found easily in load_area while booting - the filename


  of the current area boot_db is reading from is in the strArea global.





  Since version 2 following was added:





  A rename command which renames a player. Search for do_rename to see


  more info on it.





  A FOR command which executes a command at/on every player/mob/location.  





  Fixes since last release: None.


  


  


*/








/* To have VLIST show more than vnum 0 - 9900, change the number below: */ 





#define MAX_SHOW_VNUM   99 /* show only 1 - 100*100 */





#define NUL '\0'








extern ROOM_INDEX_DATA *       room_index_hash         [MAX_KEY_HASH];


/* db.c */





/* opposite directions */


const sh_int opposite_dir [6] = { DIR_SOUTH, DIR_WEST, DIR_NORTH, DIR_EAST, DIR_DOWN, DIR_UP };








/* get the 'short' name of an area (e.g. MIDGAARD, MIRROR etc. */


/* assumes that the filename saved in the AREA_DATA struct is something like midgaard.are */


char * area_name (AREA_DATA *pArea)


{


	static char buffer[64]; /* short filename */


	char  *period;





	assert (pArea != NULL);


	


	strncpy (buffer, pArea->filename, 64); /* copy the filename */	


	period = strchr (buffer, '.'); /* find the period (midgaard.are) */


	if (period) /* if there was one */


		*period = '\0'; /* terminate the string there (midgaard) */


		


	return buffer;	


}





typedef enum {exit_from, exit_to, exit_both} exit_status;





/* depending on status print > or < or <> between the 2 rooms */


void room_pair (ROOM_INDEX_DATA* left, ROOM_INDEX_DATA* right, exit_status ex, char *buffer)


{


	char *sExit;


	


	switch (ex)


	{


		default:


			sExit = "??"; break; /* invalid usage */


		case exit_from:


			sExit = "< "; break;


		case exit_to:


			sExit = " >"; break;


		case exit_both:


			sExit = "<>"; break;


	}


	


sprintf (buffer, "%5d %-26.26s %s%5d %-26.26s(%-8.8s)\n\r",


			  left->vnum, left->name, 


			  sExit,


			  right->vnum, right->name,


			  area_name(right->area)


	    );


}





/* for every exit in 'room' which leads to or from pArea but NOT both, print it */


void checkexits (ROOM_INDEX_DATA *room, AREA_DATA *pArea, char* buffer)


{


	char buf[MAX_STRING_LENGTH];


	int i;


	EXIT_DATA *exit;


	ROOM_INDEX_DATA *to_room;


	


	strcpy (buffer, "");


	for (i = 0; i < 6; i++)


	{


		exit = room->exit[i];


		if (!exit)


			continue;


		else


			to_room = exit->to_room;


		


		if (to_room)  /* there is something on the other side */





			if ( (room->area == pArea) && (to_room->area != pArea) )


			{ /* an exit from our area to another area */


			  /* check first if it is a two-way exit */


			


				if ( to_room->exit[opposite_dir[i]] &&


					to_room->exit[opposite_dir[i]]->to_room == room )


					room_pair (room,to_room,exit_both,buf); /* <> */


				else


					room_pair (room,to_room,exit_to,buf); /* > */


				


				strcat (buffer, buf);				


			}			


			else			


			if ( (room->area != pArea) && (exit->to_room->area == pArea) )


			{ /* an exit from another area to our area */





				if  (!


			    	 (to_room->exit[opposite_dir[i]] &&


				      to_room->exit[opposite_dir[i]]->to_room == room )


					)


				/* two-way exits are handled in the other if */


				{						


					room_pair (to_room,room,exit_from,buf);


					strcat (buffer, buf);


				}


				


			} /* if room->area */


			


	} /* for */


	


}





/* for now, no arguments, just list the current area */


void do_exlist (CHAR_DATA *ch, char * argument)


{


	AREA_DATA* pArea;


	ROOM_INDEX_DATA* room;


	int i;


	char buffer[MAX_STRING_LENGTH];


	


	pArea = ch->in_room->area; /* this is the area we want info on */


	for (i = 0; i < MAX_KEY_HASH; i++) /* room index hash table */


	for (room = room_index_hash[i]; room != NULL; room = room->next)


	/* run through all the rooms on the MUD */


	


	{


		checkexits (room, pArea, buffer);


		send_to_char (buffer, ch);


	}


} 





/* show a list of all used VNUMS */





#define COLUMNS 		5   /* number of columns */


#define MAX_ROW 		((MAX_SHOW_VNUM / COLUMNS)+1) /* rows */





void do_vlist (CHAR_DATA *ch, char *argument)


{


	int i,j,vnum;


	ROOM_INDEX_DATA *room;


	char buffer[MAX_ROW*100]; /* should be plenty */


	char buf2 [100];


	


	for (i = 0; i < MAX_ROW; i++)


	{


		strcpy (buffer, ""); /* clear the buffer for this row */


		


		for (j = 0; j < COLUMNS; j++) /* for each column */


		{


			vnum = ((j*MAX_ROW) + i); /* find a vnum whih should be there */


			if (vnum < MAX_SHOW_VNUM)


			{


				room = get_room_index (vnum * 100 + 1); /* each zone has to have a XXX01 room */


				sprintf (buf2, "%3d %-8.8s  ", vnum, 


						 room ? area_name(room->area) : "-" ); 


						 /* something there or unused ? */


				strcat (buffer,buf2);				


			} 


		} /* for columns */


		


		send_to_char (buffer,ch);


		send_to_char ("\n\r",ch);


	} /* for rows */


}





/* Super-AT command:





FOR ALL <action>


FOR MORTALS <action>


FOR GODS <action>


FOR MOBS <action>


FOR EVERYWHERE <action>








Executes action several times, either on ALL players (not including yourself),


MORTALS (including trusted characters), GODS (characters with level higher than


L_HERO), MOBS (Not recommended) or every room (not recommended either!)





If you insert a # in the action, it will be replaced by the name of the target.





If # is a part of the action, the action will be executed for every target


in game. If there is no #, the action will be executed for every room containg


at least one target, but only once per room. # cannot be used with FOR EVERY-


WHERE. # can be anywhere in the action.





Example: 





FOR ALL SMILE -> you will only smile once in a room with 2 players.


FOR ALL TWIDDLE # -> In a room with A and B, you will twiddle A then B.





Destroying the characters this command acts upon MAY cause it to fail. Try to


avoid something like FOR MOBS PURGE (although it actually works at my MUD).





FOR MOBS TRANS 3054 (transfer ALL the mobs to Midgaard temple) does NOT work


though :)





The command works by transporting the character to each of the rooms with 


target in them. Private rooms are not violated.





*/





/* Expand the name of a character into a string that identifies THAT


   character within a room. E.g. the second 'guard' -> 2. guard


*/   


const char * name_expand (CHAR_DATA *ch)


{


	int count = 1;


	CHAR_DATA *rch;


	char name[MAX_INPUT_LENGTH]; /*  HOPEFULLY no mob has a name longer than THAT */





	static char outbuf[MAX_INPUT_LENGTH];	


	


	if (!IS_NPC(ch))


		return ch->name;


		


	one_argument (ch->name, name); /* copy the first word into name */


	


	if (!name[0]) /* weird mob .. no keywords */


	{


		strcpy (outbuf, ""); /* Do not return NULL, just an empty buffer */


		return outbuf;


	}


		


	for (rch = ch->in_room->people; rch && (rch != ch);rch = rch->next_in_room)


		if (is_name (name, rch->name))


			count++;


			





	sprintf (outbuf, "%d.%s", count, name);


	return outbuf;


}








void do_for (CHAR_DATA *ch, char *argument)


{


	char range[MAX_INPUT_LENGTH];


	char buf[MAX_STRING_LENGTH];


	bool fGods = FALSE, fMortals = FALSE, fMobs = FALSE, fEverywhere = FALSE, found;


	ROOM_INDEX_DATA *room, *old_room;


	CHAR_DATA *p, *p_next;


	int i;


	


	argument = one_argument (argument, range);


	


	if (!range[0] || !argument[0]) /* invalid usage? */


	{


		send_to_char("Die\n\r",ch);


		return;


	}


	


	if (!str_prefix("quit", argument))


	{


		send_to_char ("Are you trying to crash the MUD or something?\n\r",ch);


		return;


	}


	


	


	if (!str_cmp (range, "all"))


	{


		fMortals = TRUE;


		fGods = TRUE;


	}


	else if (!str_cmp (range, "gods"))


		fGods = TRUE;


	else if (!str_cmp (range, "mortals"))


		fMortals = TRUE;


	else if (!str_cmp (range, "mobs"))


		fMobs = TRUE;


	else if (!str_cmp (range, "everywhere"))


		fEverywhere = TRUE;


	else


		do_help (ch, "for"); /* show syntax */





	/* do not allow # to make it easier */		


	if (fEverywhere && strchr (argument, '#'))


	{


		send_to_char ("Cannot use FOR EVERYWHERE with the # thingie.\n\r",ch);


		return;


	}


		


	if (strchr (argument, '#')) /* replace # ? */


	{ 


		for (p = char_list; p ; p = p_next)


		{


			p_next = p->next; /* In case someone DOES try to AT MOBS SLAY # */


			found = FALSE;


			


			if (!(p->in_room) || room_is_private(p->in_room) || (p == ch))


				continue;


			


			if (IS_NPC(p) && fMobs)


				found = TRUE;


			else if (!IS_NPC(p) && p->level >= LEVEL_IMMORTAL && fGods)


				found = TRUE;


			else if (!IS_NPC(p) && p->level < LEVEL_IMMORTAL && fMortals)


				found = TRUE;





			/* It looks ugly to me.. but it works :) */				


			if (found) /* p is 'appropriate' */


			{


				char *pSource = argument; /* head of buffer to be parsed */


				char *pDest = buf; /* parse into this */


				


				while (*pSource)


				{


					if (*pSource == '#') /* Replace # with name of target */


					{


						const char *namebuf = name_expand (p);


						


						if (namebuf) /* in case there is no mob name ?? */


							while (*namebuf) /* copy name over */


								*(pDest++) = *(namebuf++);





						pSource++;


					}


					else


						*(pDest++) = *(pSource++);


				} /* while */


				*pDest = '\0'; /* Terminate */


				


				/* Execute */


				old_room = ch->in_room;


				char_from_room (ch);


				char_to_room (ch,p->in_room);


				interpret (ch, buf);


				char_from_room (ch);


				char_to_room (ch,old_room);


				


			} /* if found */


		} /* for every char */


	}


	else /* just for every room with the appropriate people in it */


	{


		for (i = 0; i < MAX_KEY_HASH; i++) /* run through all the buckets */


			for (room = room_index_hash[i] ; room ; room = room->next)


			{


				found = FALSE;


				


				/* Anyone in here at all? */


				if (fEverywhere) /* Everywhere executes always */


					found = TRUE;


				else if (!room->people) /* Skip it if room is empty */


					continue;


					


					


				/* Check if there is anyone here of the requried type */


				/* Stop as soon as a match is found or there are no more ppl in room */


				for (p = room->people; p && !found; p = p->next_in_room)


				{





					if (p == ch) /* do not execute on oneself */


						continue;


						


					if (IS_NPC(p) && fMobs)


						found = TRUE;


					else if (!IS_NPC(p) && (p->level >= LEVEL_IMMORTAL) && fGods)


						found = TRUE;


					else if (!IS_NPC(p) && (p->level <= LEVEL_IMMORTAL) && fMortals)


						found = TRUE;


				} /* for everyone inside the room */


						


				if (found && !room_is_private(room)) /* Any of the required type here AND room not private? */


				{


					/* This may be ineffective. Consider moving character out of old_room


					   once at beginning of command then moving back at the end.


					   This however, is more safe?


					*/


				


					old_room = ch->in_room;


					char_from_room (ch);


					char_to_room (ch, room);


					interpret (ch, argument);


					char_from_room (ch);


					char_to_room (ch, old_room);


				} /* if found */


			} /* for every room in a bucket */


	} /* if strchr */


} /* do_for */





#include <types.h>
#else
#include <sys/types.h>
#include <sys/time.h>
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
#include "merc.h"

DECLARE_DO_FUN(do_look     );
int     wrestle;

/*=======================================================================*
 * function: do_wrestle                                                  *
 * purpose: Challenges person to wrestling match                         *
 * written by:  Zaphonite                                                *
 *=======================================================================*/
void do_wrestle(CHAR_DATA *ch, char *argument)
{
  CHAR_DATA *victim; 
  char buf[MAX_STRING_LENGTH]; 
  DESCRIPTOR_DATA *d;

 if(IS_NPC(ch))
  return; 

 if( wrestle == WRESTLE_START )
  {
  send_to_char("The wrestling ring is already being used.\n\r",ch);
  return;
  }

 if( wrestle == WRESTLE_BUSY )
  {
  send_to_char("There is a match in progress at the moment, try in a few minutes.\n\r",ch);
  return; 
  }

 if( wrestle == WRESTLE_LOCK )
  {
  send_to_char("The wrestling ring is currently closed.\n\r",ch);
  return;
  }

 if(IS_SET(ch->act,PLR_CHALLENGED))
  {
  send_to_char("You have already been challenged, either AGREE or DECLINE first.\n\r",ch);
  return; 
  }

 if(ch->hit < ch->max_hit)
  {
  send_to_char("You must be fully healed to wrestle in the ring.\n\r",ch);
  return;
  }


 if(argument[0] == '\0')
  {
  send_to_char("You must specify whom you wish to challenge.\n\r",ch);
  return;
  }

 if((victim = get_char_world(ch,argument)) == NULL)
  {
  send_to_char("They are not playing.\n\r",ch);
  return;
  }



 if(IS_NPC(victim) || IS_IMMORTAL(victim) || victim == ch )
  {
  send_to_char("You cannot challenge NPC's or yourself.\n\r",ch);
  return;
  }


 if(IS_SET(victim->act,PLR_CHALLENGER))
  {
  send_to_char("They are currently challenging someone else in the arena or in wrestling.\n\r",ch);
  return;
  }

 if(victim->fighting != NULL )
  {
  send_to_char("That person is engaged in battle right now.\n\r",ch); 
  return; 
  }

 if(victim->hit < victim->max_hit)
  {
  send_to_char("That player is not healthy enough to wrestle right now.\n\r",ch);
  return;
  }


 if ( victim->desc == NULL )
  {
  send_to_char("That player is linkdead at the moment, try them later.\n\r",ch);
  return;
  }

 ch->challenged = victim;
 SET_BIT(ch->act,PLR_CHALLENGER);
 victim->challenger = ch;
 SET_BIT(victim->act,PLR_CHALLENGED);
 wrestle == WRESTLE_START;
 send_to_char("Your wrestling challenge has been sent\n\r",ch);
 act("$n has challenged you to a wrestling match.",ch,NULL,victim,TO_VICT);
 sprintf(buf,"[Wrestling] %s has challenged %s to a wrestling match.\n\r",
         ch->name, victim->name);
 for ( d = descriptor_list; d; d = d->next )
  {
    if( d->connected == CON_PLAYING)
     {
        ADD_COLOUR(ch,buf,L_RED);
        send_to_char( buf, d->character );
     }
  }
 sprintf(buf,"type: WAGREE %s to meet them in the ring.\n\r",ch->name);
 send_to_char(buf,victim);
 sprintf(buf,"type: WDECLINE %s to run away.\n\r",ch->name); 
 send_to_char(buf,victim);
 return;
}

/*=======================================================================*
 * function: do_wagree                                                   *
 * purpose: to accept the wrestling challenge                            *
 * written by: Zaphonite                                                 *
 *=======================================================================*/
void do_wagree(CHAR_DATA *ch, char *argument)
{
 DESCRIPTOR_DATA *d;
 CHAR_DATA *victim; 
 char buf1[MAX_STRING_LENGTH]; 
 char buf2[MAX_STRING_LENGTH];
 char buf3[MAX_STRING_LENGTH];
 int char_room; 
 int vict_room; 

 char_room = 40001;
 vict_room = 40001;

 if(IS_NPC(ch))
 return;

 if( !IS_SET(ch->act,PLR_CHALLENGED) )
  {
  send_to_char("You have not been challenged.\n\r",ch);
  return;
  }

 if( wrestle == WRESTLE_BUSY )
  {
  send_to_char("Sorry, there is a fight in progress, please wait a few moments.\n\r",ch);
  return;
  }

 if( wrestle == WRESTLE_LOCK )
  {
  send_to_char("Sorry, the wrestling ring is currently closed.\n\r",ch);
  return;
  }

 if(argument[0]=='\0')
  {
  send_to_char("You must specify whose challenge you wish to accept.\n\r",ch);
  return;
  }

 if((victim = get_char_world(ch,argument)) == NULL)
  {
  send_to_char("They aren't logged in!\n\r",ch);
  return;
  }

 if(victim == ch)
  {
  send_to_char("You haven't challenged yourself!\n\r",ch);
  return;
  }

 if(!IS_SET(victim->act,PLR_CHALLENGER) || victim != ch->challenger )
  {
  send_to_char("That player hasn't challenged you!\n\r",ch); 
  return; 
  }

send_to_char("You have accepted the wrestling challenge!\n\r",ch);
act("$n accepts your wrestling challenge!",ch,NULL,victim,TO_VICT);
sprintf(buf1, "[Wrestling] %s (%d wins) (%d losses)\n\r", victim->name,victim->pcdata->wwins,victim->pcdata->wlosses );
sprintf(buf2, "[Wrestling] %s (%d wins) (%d losses)\n\r", ch->name,ch->pcdata->wwins,ch->pcdata->wlosses ); 
for ( d = descriptor_list; d; d = d->next )
  {
     if( d->connected == CON_PLAYING)
     {
        ADD_COLOUR(ch,buf1,L_RED);
        ADD_COLOUR(ch,buf2,L_RED);
        ADD_COLOUR(ch,buf3,L_RED);
        send_to_char( buf1, d->character );
        send_to_char( buf2, d->character );
        send_to_char( buf3, d->character );
        d->character->gladiator = NULL;
     }
  }
send_to_char("You enter the wrestling ring.\n\r",ch);
char_from_room(ch); 
char_to_room(ch,get_room_index(char_room));
do_look(ch, "auto");
send_to_char("You enter the wrestling ring.\n\r",victim); 
char_from_room(victim); 
char_to_room(victim,get_room_index(vict_room)); 
do_look(victim, "auto");
clear_stats(ch);
clear_stats(victim);
wrestle == WRESTLE_BUSY; 
return; 
}

/*=======================================================================*
 * function: do_wdecline                                                 *
 * purpose: to decline a wrestling challenge                             *
 * written by: Zaphonite                                                 *
 *=======================================================================*/
void do_wdecline(CHAR_DATA *ch, char *argument )
{
  CHAR_DATA *victim; 
  char buf[MAX_STRING_LENGTH];
  DESCRIPTOR_DATA *d;

  if(IS_NPC(ch))
   return;

 if( !IS_SET(ch->act,PLR_CHALLENGED) )
  {
  send_to_char("You have not been challenged.\n\r",ch);
  return;
  }

 if(argument[0]=='\0')
  {
  send_to_char("You must specify whose challenge you wish to decline.\n\r",ch);
  return;
  }
  
 if((victim = get_char_world(ch,argument)) == NULL)
  {
  send_to_char("They aren't logged in!\n\r",ch);
  return;
  }

 if(!IS_SET(victim->act,PLR_CHALLENGER) || victim != ch->challenger )
  {
  send_to_char("That player hasn't challenged you.\n\r",ch);
  return;
  }

 if(victim == ch)
 return; 

victim->challenged = NULL;
REMOVE_BIT(victim->act,PLR_CHALLENGER); 
ch->challenger = NULL;
REMOVE_BIT(ch->act,PLR_CHALLENGED);
wrestle == WRESTLE_OPEN;
send_to_char("Challenge declined!\n\r",ch);
act("$n has declined your wrestling match.",ch,NULL,victim,TO_VICT);
sprintf(buf,"[Wrestling] %s has declined %s's wrestling challenge.\n\r",
        ch->name, victim->name);
 for ( d = descriptor_list; d; d = d->next )
  {
     if( d->connected == CON_PLAYING)
     {
        ADD_COLOUR(ch,buf,L_RED);
        send_to_char( buf, d->character );
     }
  }

return;
}



r  
#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"

void do_sclaws( CHAR_DATA *ch, char *argument )
{

   if (IS_NPC(ch))
	return;

   if (!IS_CLASS(ch, CLASS_WEREWOLF))
   {
        send_to_char("What?\n\r",ch);
        return;
   }

   if (ch->power[DISC_WERE_LUNA] < 5)
   {
	send_to_char("You need level 5 in Luna to use Silver Claws.\n\r",ch);
	return;
   }

   if (!IS_SET(ch->newbits, NEW_SCLAWS))
   {
	send_to_char("Your claws turn into pure silver!\n\r",ch);
        act("$n's claws turn to pure silver!",ch,NULL,NULL,TO_ROOM);
        SET_BIT(ch->newbits, NEW_SCLAWS);
	return;
   }

   if (IS_SET(ch->newbits, NEW_SCLAWS))
   {
	send_to_char("Your claws return to their normal state.\n\r",ch);
	act("$n's claws are no longer composed of pure silver.\n\r",ch,NULL,NULL,TO_ROOM);
	REMOVE_BIT(ch->newbits, NEW_SCLAWS);
	return;
   }

}

void do_moonbeam( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char arg1 [MAX_INPUT_LENGTH];

 
    argument = one_argument( argument, arg1 );
  
 
    if ( IS_NPC(ch) )
    	return;
 
 
    if (!IS_CLASS(ch, CLASS_WEREWOLF))
    {
	send_to_char("Huh?\n\r",ch);
      return;
    }
 
    if (ch->power[DISC_WERE_LUNA] < 8 )
    {
	send_to_char("You need to obtain level 8 in Luna to use Moonbeam.\n\r",ch);
    	return;
    }
 

    if (ch->mana < 500)
    {
	send_to_char("You do not have enough energy to summon a Moonbeam.\n\r",ch);
	return;
    }
 
    if ( arg1[0] == '\0' )
    {
	send_to_char( "Who do you wish to strike?\n\r", ch );
      return;
    }

    if ( ( victim = get_char_room( ch, arg1 ) ) == NULL )
    {
   	 send_to_char( "They aren't here.\n\r", ch );
	 return;
    }

    if (is_safe(ch,victim) == TRUE) return;
  
    	act("$N is struck by a huge moonbeam.", ch, NULL, victim,TO_CHAR);
	act("$N is struck by a deadly beam of moonlight from $n.", ch, NULL, victim,TO_NOTVICT);
	act("You are struck by a deadly beam of moonlight!", ch, NULL, victim,TO_VICT);
    if (IS_GOOD(victim))
	victim->hit -= 300;
    if (IS_EVIL(victim))
	victim->hit -= 400;
    if (IS_NEUTRAL(victim))
	victim->hit -= 350;
	ch->mana -= 500;
    if (ch->fighting == NULL)
 	set_fighting(ch,victim);
	update_pos(victim);
	WAIT_STATE(ch,36);
	return;
    
}


void do_moongate(CHAR_DATA *ch, char *argument)
{
    CHAR_DATA *victim;
    OBJ_DATA  *obj;
    char       arg [MAX_INPUT_LENGTH];
 
    one_argument( argument, arg );
 
    if (IS_NPC(ch)) return;
    if (!IS_CLASS(ch, CLASS_WEREWOLF))
    {
      send_to_char("Huh?\n\r",ch);
      return;
    }

    if (ch->power[DISC_WERE_LUNA] < 6)
    {
      send_to_char("You need to obtain level 6 Luna to use moongate.\n\r",ch);
      return;
    }

    if ( arg[0] == '\0')
    {
        send_to_char( "Who do you wish to gate to?\n\r", ch );
	return;
    }
 
    if ( (victim = get_char_world( ch, arg ) ) == NULL )
    {
    send_to_char("They arent here.\n\r",ch);
    return;
    }
 
 
    if ( (victim == ch) 
    ||   victim->in_room == NULL
    ||   IS_NPC(victim)
    ||   (!IS_NPC(victim) && !IS_IMMUNE(victim, IMM_SUMMON) )
    ||   IS_SET(ch->in_room->room_flags, ROOM_PRIVATE)
    ||   IS_SET(ch->in_room->room_flags, ROOM_SOLITARY)
    ||   IS_SET(ch->in_room->room_flags, ROOM_NO_RECALL)
    ||   IS_SET(victim->in_room->room_flags, ROOM_PRIVATE)
    ||   IS_SET(victim->in_room->room_flags, ROOM_SOLITARY)
    ||   IS_SET(victim->in_room->room_flags, ROOM_NO_RECALL)
    ||   victim->in_room->vnum == ch->in_room->vnum)
    {
	send_to_char( "You failed.\n\r", ch );
	return;
    }
 
 
    obj = create_object( get_obj_index( OBJ_VNUM_GATE2 ), 0 );
    obj->value[0] = victim->in_room->vnum;
    obj->value[3] = ch->in_room->vnum;
    obj->timer = 5;
    if (IS_AFFECTED(ch,AFF_SHADOWPLANE))
	obj->extra_flags = ITEM_SHADOWPLANE;
    obj_to_room( obj, ch->in_room );
 
    obj = create_object( get_obj_index( OBJ_VNUM_GATE2 ), 0 );
    obj->value[0] = ch->in_room->vnum;
    obj->value[3] = victim->in_room->vnum;
    obj->timer = 5;
    if (IS_AFFECTED(victim,AFF_SHADOWPLANE))
	obj->extra_flags = ITEM_SHADOWPLANE;
    obj_to_room( obj, victim->in_room );
    act( "A look of concentration passes over $n's face.", ch, NULL,NULL, TO_ROOM );
    send_to_char("A look of concentration passes over your face.\n\r",ch);
    act( "$p appears in front of $n in a beam of moonlight.", ch, obj, NULL, TO_ROOM );
    act( "$p appears in front of you in a beam of moonlight.", ch, obj, NULL, TO_CHAR );
    act( "$p appears in front of $n in a beam of moonlight.", victim, obj, NULL, TO_ROOM );
    act( "$p appears in front of you in a beam of moonlight.", ch, obj, victim, TO_VICT );
    return;
}

void do_gmotherstouch( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char arg1 [MAX_INPUT_LENGTH];
 
    argument = one_argument( argument, arg1 );
  
 
    if ( IS_NPC(ch) )
    	return;
 
 
    if (!IS_CLASS(ch, CLASS_WEREWOLF))
    {
	send_to_char("Huh?\n\r",ch);
      	return;
    }
 
    if (ch->power[DISC_WERE_LUNA] < 4 )
    {
	send_to_char(
	"You need to obtain level 4 in Luna to use Grandmother's Touch.\n\r",ch);
    	return;
    }
 

    if (ch->mana < 400)
    {
	send_to_char("You do not have enough energy to summon the Grandmother's Touch.\n\r",ch);
	return;
    }
 
    if ( arg1[0] == '\0' )
    {
	send_to_char( "Who is in need of your touch?\n\r", ch );
      return;
    }

    if ( ( victim = get_char_room( ch, arg1 ) ) == NULL )
    {
   	send_to_char( "They aren't here.\n\r", ch );
	return;
    }
  
        
    if (ch->fighting != NULL)
    {
    	act("$N is filled with a feeling of warmth.", ch, NULL, victim,TO_CHAR);
	act("$N is surrounded by a beam of moonlight from $n's touch.", ch, NULL, victim,TO_NOTVICT);
	act("You are surrounded by a beam of moonlight, and feel restored.", ch, NULL, victim,TO_VICT);
	victim->hit += 200;
	ch->mana -= 400;
	WAIT_STATE(ch,16);
	return;
    }

    if (ch->fighting == NULL)
    {
        act("$N is filled with a feeling of warmth.", ch, NULL, victim,TO_CHAR);
	act("$N is surrounded by a beam of moonlight from $n's touch.", ch, NULL, victim,TO_NOTVICT);
	act("You are surrounded by a beam of moonlight, and feel restored.", ch, NULL, victim,TO_VICT);
	victim->hit += 600;
	ch->mana -= 400;
	WAIT_STATE(ch,6);
	return;
    }
}


void do_motherstouch( CHAR_DATA *ch, char *argument )
{
    if (IS_NPC(ch))
	return;

    if (ch->power[DISC_WERE_LUNA] < 3 )
    {
	send_to_char("You need to obtain level 3 in Luna to use Mother's Touch.\n\r",ch);
	return;
    }

    if (ch->mana < 400)
    {
	send_to_char("You don't have enough energy to use Mother's Touch.\n\r",ch);
	return;
    }

    if (ch->fighting != NULL)
    {
	send_to_char("You are touched by a beam of light and feel healed.\n\r",ch);
	act("$n is touched by a beam of moonlight, and looks refreshed.\n\r",ch,NULL,NULL,TO_ROOM);
        ch->hit += 100;
        ch->mana -= 400;
	WAIT_STATE(ch,16);
	return;
    }

    if (ch->fighting == NULL)
    {
	send_to_char("You are surrounded by a beam of light, and feel healed.\n\r",ch);
	act("$n is surrounded by a beam of moonlight, and looks much more refreshed.\n\r",ch,NULL,NULL,TO_ROOM);
	ch->hit += 500;
	ch->mana -= 400;
	WAIT_STATE(ch,8);
	return;
    }

}

void do_flameclaws( CHAR_DATA *ch, char *argument )
{

    if (IS_NPC(ch))
	return;
    
   if (!IS_CLASS(ch, CLASS_WEREWOLF))
   {
        send_to_char("What?\n\r",ch);
        return;
   }
    if (ch->power[DISC_WERE_LUNA] < 1)
    {
	send_to_char("You need to obtain level 1 in luna to use flame claws.\n\r",ch);
	return;
    }

    if (IS_SET(ch->newbits, NEW_MONKFLAME))
    {
	send_to_char("The flames surrounding your claws fade.\n\r",ch);
	act("The flames surrounding $n's claws fade.\n\r",ch,NULL,NULL,TO_ROOM);
	REMOVE_BIT(ch->newbits, NEW_MONKFLAME);
	return;
    }

    if (!IS_SET(ch->newbits, NEW_MONKFLAME))
    {
	send_to_char("Your claws are surrounded by blazing flames.\n\r",ch);
        act("$n's claws are surrounded by blazing flames.\n\r",ch,NULL,NULL,TO_ROOM);
	SET_BIT(ch->newbits, NEW_MONKFLAME);
	return;
    }

}

void do_moonarmour( CHAR_DATA *ch, char *argument )
{
    OBJ_INDEX_DATA *pObjIndex;
    OBJ_DATA *obj;
    char arg[MAX_INPUT_LENGTH];
    int vnum = 0;

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch, CLASS_WEREWOLF))
    {
	    send_to_char("Huh?\n\r",ch);
	    return;
    }
    
    if (ch->power[DISC_WERE_LUNA] < 2)
    {
	send_to_char("You must attain level 2 in Luna before you can create moon armour.\n\r",ch);
	return;
    }

    if (arg[0] == '\0')
    {
    send_to_char("What piece of moon armour do you wish to create?.\n\r", ch);
    send_to_char("A Ring, Plate, or Belt? \n\r",ch);
    return;
    }


    if      (!str_cmp(arg,"ring"     )) vnum = 29711;
    else if (!str_cmp(arg,"belt"   )) vnum = 29710;
    else if (!str_cmp(arg,"plate"    )) vnum = 29709;
    else
    {
	send_to_char("What piece of moon armour do you wish to create?.\n\r", ch);
    send_to_char("A Ring, Plate, or Belt? \n\r",ch);
    return;
    }
    if (ch->practice < 65)
    {
	send_to_char("It costs 65 primal to create a piece of moon armour\n\r",ch);
	return;
    }
   
    if ( vnum == 0 || (pObjIndex = get_obj_index( vnum )) == NULL)
    {
	send_to_char("Missing object, please inform Infidel.\n\r",ch);
	return;
    }
    ch->practice -= 65;
    obj = create_object(pObjIndex, 50);
    obj_to_char(obj, ch);
    act("$p appears in a beam of moonlight.",ch,obj,NULL,TO_CHAR);
    act("$p appears in a beam of moonlight.",ch,obj,NULL,TO_ROOM);
    return;
}



void do_rend(CHAR_DATA *ch,char *argument)
{
  if (IS_NPC(ch)) return;
  if (!IS_CLASS(ch,CLASS_WEREWOLF))
  {
  send_to_char("Huh?\n\r",ch);
  return;
  }
  if (ch->power[DISC_WERE_BOAR] < 7)
  {
  send_to_char("You need Boar 7 to Rend equipment.\n\r",ch);
  return;
  }
  if (!IS_SET(ch->newbits, NEW_REND))
  {
  send_to_char("You will now ruthlessly rend your opponents eq.\n\r",ch);
  SET_BIT(ch->newbits, NEW_REND);
  return;
  }
  else if (IS_SET(ch->newbits, NEW_REND))
  { 
  send_to_char("Your no longer mean to your enemies eq.\n\r",ch);
  REMOVE_BIT(ch->newbits,NEW_REND);
  return;
  }
return;
}

void do_skin(CHAR_DATA *ch,char *argument)
{
  if (IS_NPC(ch)) return;
  if (!IS_CLASS(ch,CLASS_WEREWOLF))
  {
  send_to_char("Huh?\n\r",ch);
  return;
  }
  if (ch->power[DISC_WERE_BEAR] < 7)
  {
  send_to_char("You need Bear 7 to toughen your skin.\n\r",ch);
  return;
  }
  if (!IS_SET(ch->newbits, NEW_SKIN))
  {
  send_to_char("Your skin hardens.\n\r",ch);
  ch->armor -= 100 ;
  SET_BIT(ch->newbits, NEW_SKIN);
  return;
  }
  else if (IS_SET(ch->newbits, NEW_SKIN))
  { 
  send_to_char("Your skin softens.\n\r",ch);
  ch->armor += 100;
  REMOVE_BIT(ch->newbits,NEW_SKIN);
  return;
  }
return;
}

void do_jawlock(CHAR_DATA *ch,char *argument)
{
  if (IS_NPC(ch)) return;
  if (!IS_CLASS(ch,CLASS_WEREWOLF))
  {
  send_to_char("Huh?\n\r",ch);
  return;
  }
  if (ch->power[DISC_WERE_RAPT] < 8)
  {
  send_to_char("You need Raptor 8 to use locked jaw.\n\r",ch);
  return;
  }
  if (!IS_SET(ch->newbits, NEW_JAWLOCK))
  {
  send_to_char("Your jaw grows stronger and more ready to clamp on your enemy.\n\r",ch);
  SET_BIT(ch->newbits, NEW_JAWLOCK);
  return;
  }
  else if (IS_SET(ch->newbits, NEW_JAWLOCK))
  { 
  send_to_char("Your jaw weakens.\n\r",ch);
  REMOVE_BIT(ch->newbits,NEW_JAWLOCK);
  return;
  }
return;
}

void do_perception(CHAR_DATA *ch,char *argument)
{
  if (IS_NPC(ch)) return;
  if (!IS_CLASS(ch,CLASS_WEREWOLF))
  {
  send_to_char("Huh?\n\r",ch);
  return;
  }
  if (ch->power[DISC_WERE_RAPT] < 3)
  {
  send_to_char("You need Raptor 3 to heighten your Perception.\n\r",ch);
  return;
  }
  if (!IS_SET(ch->newbits, NEW_PERCEPTION))
  {
  send_to_char("You become more aware of stealthy enemies.\n\r",ch);
  SET_BIT(ch->newbits, NEW_PERCEPTION);
  return;
  }
  else if (IS_SET(ch->newbits, NEW_PERCEPTION))
  { 
  send_to_char("Your perception dulls.\n\r",ch);
  REMOVE_BIT(ch->newbits,NEW_PERCEPTION);
  return;
  }
return;
}

void do_roar(CHAR_DATA *ch,char *argument)
{
CHAR_DATA *victim;
char buf[MAX_STRING_LENGTH];
if (IS_NPC(ch)) return;
if (!IS_CLASS(ch,CLASS_WEREWOLF))
{send_to_char("You let out an insane BeeF-powered ROAR!!!!!!!!\n\r",ch);return;}
if (ch->power[DISC_WERE_BEAR] < 6)
{
send_to_char("You need bear 6 to roar.\n\r",ch);
return;
}
if ((victim=ch->fighting) == NULL)
{
send_to_char("You arent fighting anyone.\n\r",ch);
return;
}

if (number_range(1,6)==2)
{
sprintf(buf,"%s roars and screams, intimidating the hell out of %s.",
ch->name,victim->name);
act(buf,ch,NULL,NULL,TO_ROOM);
sprintf(buf,"You roar and scream, intimidating the hell out of %s.\n\r",
victim->name);
send_to_char(buf,ch);
do_flee(victim,"");
WAIT_STATE(ch,20);
return;
}
else
{
   stc("You roar loudly.\n\r",ch);
   stc("Nothing happens.\n\r",ch);
   act("$n roars loudly.",ch,NULL,NULL,TO_ROOM);
   WAIT_STATE(ch, 10);
   return;
}
}
 
/*
void do_quills(CHAR_DATA *ch,char *argument)
{
  if (IS_NPC(ch)) return;
  if (!IS_CLASS(ch,CLASS_WEREWOLF))
  {
  send_to_char("Huh?\n\r",ch);
  return;
  }
  if (ch->power[DISC_WERE_BEAR] < 5)
  {
  send_to_char("You need Bear 5 to extend your quills.\n\r",ch);
  return;
  }
  if (!IS_SET(ch->newbits, NEW_QUILLS))
  {
  send_to_char("Sharp quills extend from your back.\n\r",ch);
  SET_BIT(ch->newbits, NEW_QUILLS);
  return;
  }
  else if (IS_SET(ch->newbits, NEW_QUILLS))
  { 
  send_to_char("Your quills sink into your back.\n\r",ch);
  REMOVE_BIT(ch->newbits,NEW_QUILLS);
  return;
  }
return;
}
*/

void do_slam(CHAR_DATA *ch,char *argument)
{
  if (IS_NPC(ch)) return;
  if (!IS_CLASS(ch,CLASS_WEREWOLF))
  {
  send_to_char("Huh?\n\r",ch);
  return;
  }
  if (ch->power[DISC_WERE_BEAR] < 8)
  {
  send_to_char("You need Bear 8 to attempt to shoulder slam.\n\r",ch);
  return;
  }
  if (!IS_SET(ch->newbits, NEW_SLAM))
  {
  send_to_char("You will now shoulder slam when you get a chance.\n\r",ch);
  SET_BIT(ch->newbits, NEW_SLAM);
  return;
  }
  else if (IS_SET(ch->newbits, NEW_SLAM))
  { 
  send_to_char("Your now dont shoulderslam when given a chance.\n\r",ch);
  REMOVE_BIT(ch->newbits,NEW_SLAM);
  return;
  }
return;
}
 
void do_congregation(CHAR_DATA *ch, char *argument )
{
 
    char buf [MAX_INPUT_LENGTH];
    char arg[MAX_STRING_LENGTH];
    CHAR_DATA *victim;
    int blah;
    AFFECT_DATA af;
    argument=one_argument(argument,arg);
    if (IS_NPC(ch)) return;
    if (!IS_CLASS(ch, CLASS_WEREWOLF))
     {
     send_to_char("Huh?\n\r",ch);
     return;
     }
if (arg[0]=='\0')
{
send_to_char("Summon what?\n\r",ch);
return;
}
 
blah=ch->power[DISC_WERE_CONG];
 
    if (ch->pcdata->followers > 0)
    {
	send_to_char("Nothing happens.\n\r",ch);
	return;
    }
    ch->pcdata->followers++;
    victim=create_mobile( get_mob_index( MOB_VNUM_DOG ) );
 if (!str_cmp(arg,"scorpion")&& blah>0)
{
    free_string(victim->short_descr);
    free_string(victim->name);
    free_string(victim->long_descr);
    victim->name=str_dup("scorpion");
    victim->short_descr=str_dup("a Huge Scorpion");
    victim->long_descr=str_dup("a Huge Scorpion stands here.");
    victim->level = 40;
    victim->hit = 300;
    victim->max_hit = 300;
    victim->hitroll = 40;
    victim->damroll = 40;
}
else if (!str_cmp(arg,"cobra")&& blah>1)
{
    free_string(victim->short_descr);
    free_string(victim->name);
    free_string(victim->long_descr);
    victim->name=str_dup("huge cobra");
    victim->short_descr=str_dup("a Huge Cobra");
    victim->long_descr=str_dup("a Huge Cobra stands here.");
    victim->level = 50;
    victim->hit = 400;
    victim->max_hit = 400;
    victim->hitroll = 50;
    victim->damroll = 50;
}
else if (!str_cmp(arg,"lynx")&&blah>2)
{
    free_string(victim->short_descr);
    free_string(victim->name);
    free_string(victim->long_descr);
    victim->name=str_dup("sneaky lynx");
    victim->short_descr=str_dup("a Sneaky Lynx");
    victim->long_descr=str_dup("a stealthy lynx stands here.");
    victim->level = 60;
    victim->hit = 500;
    victim->max_hit = 500;
    victim->hitroll = 60;
    victim->damroll = 60;
}
else if ((!str_cmp(arg,"timber")||!str_cmp(arg,"wolf"))&& blah>3)
{
    free_string(victim->short_descr);
    free_string(victim->name);
    free_string(victim->long_descr);
    victim->name=str_dup("timber wolf");
    victim->short_descr=str_dup("a Huge Timber Wolf");
    victim->long_descr=str_dup("a Huge Timber Wolf stands here.");
    victim->level = 70;
    victim->hit = 2000;
    victim->max_hit = 2000;
    victim->hitroll = 70;
    victim->damroll = 70;
}
else if (!str_cmp(arg,"boar")&&blah>4)
{
    free_string(victim->short_descr);
    free_string(victim->name);
    free_string(victim->long_descr);
    victim->name=str_dup("boar");
    victim->short_descr=str_dup("a Huge Boar");
    victim->long_descr=str_dup("a Huge Boar stands here.");
    victim->level = 100;
    victim->hit = 3000;
    victim->max_hit = 3000;
    victim->hitroll = 100;
    victim->damroll = 100;
}
else if ((!str_cmp(arg,"rhino")||!str_cmp(arg,"white"))&&blah>5)
{
    free_string(victim->short_descr);
    free_string(victim->name);
    free_string(victim->long_descr);
    victim->name=str_dup("white rhino");
    victim->short_descr=str_dup("a Huge White Rhino");
    victim->long_descr=str_dup("a Huge Rhino stands here.");
    victim->level = 150;
    victim->hit = 4000;
    victim->max_hit = 4000;
    victim->hitroll = 150;
    victim->damroll = 150;
}
else if (!str_cmp(arg,"black")&& blah>6)
{
    free_string(victim->short_descr);
    free_string(victim->name);
    free_string(victim->long_descr);
    victim->name=str_dup("black rhino");
    victim->short_descr=str_dup("a Huge Black Rhino");
    victim->long_descr=str_dup("a Huge Rhino stands here.");
    victim->level = 200;
    victim->hit = 5000;
    victim->max_hit = 5000;
    victim->hitroll = 200;
    victim->damroll = 200;
}
else if (!str_cmp(arg,"whitewolf")&& blah>7)
{
    free_string(victim->short_descr);
    free_string(victim->name);
    free_string(victim->long_descr);
    victim->name=str_dup("white wolf");
    victim->short_descr=str_dup("a Huge White Wolf");
    victim->long_descr=str_dup("a Huge Wolf stands here.");
    victim->level = 250;
    victim->hit = 6000;
    victim->max_hit = 6000;
    victim->hitroll = 250;
    victim->damroll = 250;
}
else if (!str_cmp(arg,"clone")&&blah>8)
{
    free_string(victim->short_descr);
    free_string(victim->name);
    free_string(victim->long_descr);
    victim->name=str_dup(ch->name);
    victim->short_descr=str_dup(ch->name);
    victim->long_descr=str_dup(ch->name);
    victim->level = 500;
    victim->hit = 10000;
    victim->max_hit = 10000;
    victim->hitroll =500;
    victim->damroll =500;
} 
else if (!str_cmp(arg,"fenris")&&blah>9)
{
    free_string(victim->short_descr);
    free_string(victim->name);
    free_string(victim->long_descr);
    victim->name=str_dup("fenris");
    victim->short_descr=str_dup("Fenris Wolf");
    victim->long_descr=str_dup("Fenris Wolf stands here.");
    victim->level =950;
    victim->hit = 30000;
    victim->max_hit = 30000;
    victim->hitroll = 999;
    victim->damroll = 999;
}
else
{
send_to_char("Your incorrect call attracts a weak partner\n\r",ch);
}
 
    sprintf(buf,"%s runs out of nowhere.\n\r",victim->short_descr);
    send_to_char(buf,ch);
    
    act(buf,ch,NULL,NULL,TO_ROOM);
   sprintf(buf,"%s\n\r",victim->long_descr);
     free_string(victim->long_descr);
     victim->long_descr=str_dup(buf);
    char_to_room( victim, ch->in_room );
    add_follower( victim, ch );
    af.duration  = 666;
    af.location  = APPLY_NONE;
    af.modifier  = 0;
    af.bitvector = AFF_CHARM;
    affect_to_char( victim, &af );
    SET_BIT(victim->act,ACT_NOEXP);
    SET_BIT(victim->act,PLR_HOLYLIGHT);
    do_group(ch,victim->name);
    return;
}

void do_shred( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    int dam;
    argument = one_argument( argument, arg );
 
 
    if(!IS_CLASS(ch,CLASS_WEREWOLF))
    {
    send_to_char("Huh?\n\r",ch);
    return;
    }
    if (ch->power[DISC_WERE_RAPT] < 7)
    {
    send_to_char("You need Raptor 7 to Shred.\n\r",ch);
    return;
    }
 
    if ( arg[0] == '\0' )
    {
        send_to_char( "Shred whom?\n\r", ch );
	return;
    }
 
 
    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }
 
    if ( victim == ch )
    {
        send_to_char( "How can you shred yourself?\n\r", ch );
	return;
    }
 
    if ( victim->fighting != NULL )
    {
        send_to_char( "You can't shred a fighting person.\n\r", ch );
	return;
    }
 
    if ( victim->hit < victim->max_hit )
    {
	act( "$N is hurt and suspicious ... you can't sneak up.",
	    ch, NULL, victim, TO_CHAR );
	return;
    }
    if (!IS_AFFECTED(ch, AFF_SHADOWPLANE))
    {
    send_to_char("You must be ShadowPlaned to Shred!\n\r",ch);
    return;
    }
do_shadowplane(ch,"");
if (is_safe(ch,victim)==TRUE) return;

    if (!IS_NPC(victim)) dam = 400;
    if (IS_NPC(victim)) dam = 1200;
dam += number_range(1,20);
WAIT_STATE(ch,15);
if (ch->power[DISC_WERE_RAPT] >6)
damage(ch,victim,dam,gsn_shred);
damage(ch,victim,dam,gsn_shred);
damage(ch,victim,dam,gsn_shred);
if (ch->power[DISC_WERE_RAPT] > 7)
damage(ch,victim,dam,gsn_shred);
if (ch->power[DISC_WERE_RAPT] == 10)
damage(ch,victim,dam,gsn_shred);
    return;
}

void do_run(CHAR_DATA *ch, char *argument)
{
EXIT_DATA *pexit;
char direct[MAX_STRING_LENGTH];
char arg [MAX_INPUT_LENGTH];
char buf[MAX_STRING_LENGTH];
ROOM_INDEX_DATA *in_room;
ROOM_INDEX_DATA *to_room;
int dir = 0;
argument=one_argument(argument,arg);
in_room=ch->in_room;


if (IS_NPC(ch)) return;
if (!IS_CLASS(ch,CLASS_WEREWOLF))
{
send_to_char("Huh?\n\r",ch);
return;
}
if (ch->power[DISC_WERE_RAPT] < 2)
{
send_to_char("You need Raptor 2 to use Run.\n\r",ch);
return;
}
if ( arg[0] == '\0')
{
send_to_char("Run which direction?\n\r",ch);
return;
}
if (str_cmp(arg, "w") && str_cmp(arg,"e") && str_cmp(arg,"n") &&
   str_cmp(arg, "s"))
{
send_to_char("You can only run n, s, e or w.\n\r",ch);
return;
}
if (!str_cmp(arg,"w")) sprintf(direct,"west");
if (!str_cmp(arg,"e")) sprintf(direct,"east");
if (!str_cmp(arg,"s")) sprintf(direct,"south");
if (!str_cmp(arg,"n")) sprintf(direct,"north");
if (!str_cmp(arg,"w")) 
{
dir=3;
}
if (!str_cmp(arg,"e")) 
{
dir=1;
}
 
if (!str_cmp(arg,"n")) 
{
dir=0;
}
if (!str_cmp(arg,"s")) 
{
dir=2;
}
if ( (pexit =  in_room->exit[dir]) == NULL ||
     (to_room= pexit->to_room) == NULL)
{
send_to_char("You stop running.\n\r",ch);
sprintf(buf,"%s comes to a screeching halt.\n\r",ch->name);
act(buf,ch,NULL,NULL,TO_ROOM);
WAIT_STATE(ch,10);
return;
}
sprintf(buf,"You run %s.\n\r",direct);
send_to_char(buf,ch);
sprintf(buf,"%s RUNS %s.\n\r",ch->name,direct);
act(buf,ch,NULL,NULL,TO_ROOM);
move_char(ch,dir);
do_run(ch,arg);
return;
}
 
 

void do_talons( CHAR_DATA *ch, char *argument )
{
CHAR_DATA *victim;
 
char buf[MAX_STRING_LENGTH];
 
int dam;
if (IS_NPC(ch)) return;
 
if (!IS_CLASS(ch,CLASS_WEREWOLF))
{
send_to_char("Huh?\n\r",ch);
return;
}
if (ch->power[DISC_WERE_RAPT] < 10)
{
send_to_char("You need level 10 Raptor to use talons.\n\r",ch);
    return;
}
 
 
if ( ( victim = ch->fighting ) == NULL )
{
send_to_char( "You aren't fighting anyone.\n\r", ch );
      return;
 
}
WAIT_STATE( ch, 12 );
if (!IS_NPC(victim))
{
dam = 350;
}
else if (IS_NPC(victim))
{
dam = 1000;
}
if ( !IS_NPC(victim) && IS_CLASS(victim, CLASS_WEREWOLF) )
{
    if (victim->power[DISC_WERE_BOAR] > 2 ) dam *= 0.5;
}
 
dam += number_range(1,30);
if ( dam <= 0 )
   dam = 1;
sprintf(buf,"Your talons strike $N incredibly hard! [%d]\n\r",dam);
act(buf,ch,NULL,victim,TO_CHAR);
sprintf(buf,"$n's talons strike you incredibly hard! [%d]\n\r",dam);
act(buf,ch,NULL,victim,TO_VICT);
sprintf(buf,"$n's talons strike $N incredibly hard! [%d]\n\r",dam);
act(buf,ch,NULL,victim,TO_NOTVICT);
 
 
send_to_char("\n\r",ch);
victim->hit -= dam;
return;
}
 
 
 
void do_devour( CHAR_DATA *ch, char *argument )
{
char arg[MAX_INPUT_LENGTH];
OBJ_DATA *obj;
char buf[MAX_INPUT_LENGTH];
int hpgain;
 
one_argument( argument, arg );
if (!IS_CLASS(ch,CLASS_WEREWOLF))
{
send_to_char("Huh?\n\r",ch);
return;
}
if (ch->power[DISC_WERE_RAPT] < 5)
{
send_to_char("You require Raptor 5 to devour.\n\r",ch);
return;
}
 
 
if ( arg[0] == '\0' )
{
    send_to_char("Devour what?\n\r",ch);
    return;
    }
obj = get_obj_list( ch, arg, ch->in_room->contents );
if ( obj == NULL )
    {
        send_to_char( "You can't find it.\n\r", ch );
    return;
}
if (obj->item_type != ITEM_CORPSE_NPC)
{
    act( "You are unable to devour $p.", ch, obj, 0, TO_CHAR);
return;
}
else if (obj->chobj != NULL && !IS_NPC(obj->chobj) &&
obj->chobj->pcdata->obj_vnum != 0)
{
    act( "You are unable to devour $p.", ch, obj, 0, TO_CHAR);
    return;
}
hpgain = number_range(100,250);
ch->hit += hpgain;        
if (ch->hit > ch->max_hit)
{
ch->hit = ch->max_hit;
} 
sprintf( buf,"You devour %d hp of life from $p.", hpgain );
act( buf, ch, obj, NULL, TO_CHAR );
act( "You devour $p.", ch, obj, NULL, TO_CHAR );
act( "$p is devoured by $n.", ch, obj, NULL, TO_ROOM );
extract_obj( obj );
return;
}
 
 





#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"
#include "player.h"

void do_makezerg( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char      arg [MAX_INPUT_LENGTH];

    argument = one_argument( argument, arg );

    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch, CLASS_ZERG) )
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }

    if ( arg[0] == '\0' )
    {
	send_to_char( "Class whom?\n\r", ch );
	return;
    }
    
    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( IS_NPC(victim) )
    {
	send_to_char( "Not on NPC's.\n\r", ch );
	return;
    }

    if ( IS_IMMORTAL(victim) )
    {
	send_to_char( "Not on Immortals's.\n\r", ch );
	return;
    }

    if ( ch == victim )
    {
	send_to_char( "You cannot class yourself.\n\r", ch );
	return;
    }

    if (IS_CLASS(victim, CLASS_MONK))
    {
	send_to_char( "They are Monk.\n\r", ch );
	return;
    }

    if ( victim->level != LEVEL_AVATAR && !IS_IMMORTAL(victim) )
    {
	send_to_char( "You can only guide avatars.\n\r", ch );
	return;
    }

    if (IS_CLASS(victim, CLASS_VAMPIRE) || IS_SET(victim->pcdata->stats[UNI_AFF], VAM_MORTAL))
    {
	send_to_char( "You are unable to class vampires!\n\r", ch );
	return;
    }

    if (IS_CLASS(victim, CLASS_WEREWOLF))
    {
	send_to_char( "You are unable to class werewolves!\n\r", ch );
	return;
    }

    if (IS_CLASS(victim, CLASS_DEMON) || IS_SET(victim->special, SPC_CHAMPION))
    {
	send_to_char( "You are unable to class demons!\n\r", ch );
	return;
    }

    if (IS_CLASS(victim, CLASS_HIGHLANDER))
    {
	send_to_char( "You are unable to class highlanders.\n\r", ch );
	return;
    }  

    if (IS_CLASS(victim, CLASS_ZERG))
    {
	send_to_char( "You are unable to class Zergs.\n\r", ch );
	return;
    }  

	if (IS_CLASS(victim, CLASS_NINJA))
	{
	send_to_char( "You are unable to class ninjas.\n\r", ch);
	return;
	}

    if (!IS_IMMUNE(victim,IMM_VAMPIRE))
    {
	send_to_char( "You cannot class an unwilling person.\n\r", ch );
	return;
    }

    if (ch->exp < 1000)
    {
	send_to_char("You cannot afford the 1000 exp required to guide them.\n\r",ch);
	return;
    }

    if (victim->exp < 1000)
    {
	send_to_char("They cannot afford the 1000 exp required to be guided from you.\n\r",ch);
	return;
    }

    ch->exp -= 1000;
    victim->exp -= 1000;

    act("You make $N a Zerg.", ch, NULL, victim, TO_CHAR);
    act("$n makes $N a Zerg.", ch, NULL, victim, TO_NOTVICT);
    act("$n makes you a Zerg.", ch, NULL, victim, TO_VICT);
    send_to_char( "You are now a Zerg.\n\r", victim );
    free_string(victim->lord);
    victim->lord = str_dup(ch->name);
    victim->class    = CLASS_ZERG;
    victim->generation = ch->generation+1;
    save_char_obj(ch);
    save_char_obj(victim);
    return;
}

void do_zergpower( CHAR_DATA *ch, char *argument )
{
    char arg1 [MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    int improve;
    improve = PZERG; 
    
    argument = one_argument( argument, arg1 );
    
    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch, CLASS_ZERG))
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }

    if (arg1[0] == '\0')
    {
	    send_to_char("     Zerg Powers.\n\r",ch);
	    send_to_char("- Remember to put single quotes ( ' ) around the power.\n\r", ch);
	    if ( ch->pcdata->powers[PZERG] < 1 ) send_to_char("Eyes of Zerg\n\r", ch);
	    if ( ch->pcdata->powers[PZERG] < 2 ) send_to_char("Speed
Power\n\r", ch);
	    if ( ch->pcdata->powers[PZERG] < 3 ) send_to_char("Super Invis\n\r", ch);
	    if ( ch->pcdata->powers[PZERG] < 4 ) send_to_char("Toughness\n\r", ch);
	    if ( ch->pcdata->powers[PZERG] < 5 ) send_to_char("Super 
Shield\n\r", ch);
	    if ( ch->pcdata->powers[PZERG] < 6 ) send_to_char("Travel\n\r", ch);

		return;
    }


	if (!str_cmp(arg1,"eyes of zerg")) 
    {
    	if ( ch->pcdata->powers[PZERG] > 0 )
    		send_to_char("You already have the Eyes of Zerg Power.\n\r", ch);
    	else if ( ch->practice < 10)
    		send_to_char("You don't have the 10 required primal.\n\r", ch);
    	else
    	{
    		ch->pcdata->powers[improve] += 1;
    		ch->practice -= 10;
    		send_to_char("You master the Eyes of Zerg Power.\n\r", ch);
    	}
    	return;
    }
    else if (!str_cmp(arg1,"speed power"))
    {
    	if ( ch->pcdata->powers[PZERG] > 1 )
    		send_to_char("You already have the Speed Power.\n\r", ch);
    	else if ( ch->pcdata->powers[PZERG] < 1 )
    		send_to_char("You need all the powers before this one to receive this power.\n\r", ch);
    	else if ( ch->practice < 20)
    		send_to_char("You don't have the 20 required primal.\n\r", ch);
    	else
    	{
    		ch->pcdata->powers[improve] += 1;
    		ch->practice -= 20;
    		send_to_char("You master the Speed Power.\n\r", ch);
    	}
    	return;
    }
    else if (!str_cmp(arg1,"super invis"))
    {
    	if ( ch->pcdata->powers[PZERG] > 2 )
    		send_to_char("You already have the Super Invis Power.\n\r", ch);
    	else if ( ch->pcdata->powers[PZERG] < 2 )
    		send_to_char("You need all the powers before this one to receive this power.\n\r", ch);
    	else if ( ch->practice < 30)
    		send_to_char("You don't have the 30 required primal.\n\r", ch);
    	else
    	{
    		ch->pcdata->powers[improve] += 1;
    		ch->practice -= 30;
    		send_to_char("You master the Super Invis Power.\n\r", ch);
    	}
    	return;
    }
    else if (!str_cmp(arg1,"toughness"))
    {
    	if ( ch->pcdata->powers[PZERG] > 3 )
    		send_to_char("You already have the Toughness Power.\n\r", ch);
    	else if ( ch->pcdata->powers[PZERG] < 3 )
    		send_to_char("You need all the power before this one to receive this power.\n\r", ch);
    	else if ( ch->practice < 40)
    		send_to_char("You don't have the 40 required primal.\n\r", ch);
    	else
    	{
    		ch->pcdata->powers[improve] += 1;
    		ch->practice -= 40;
    		send_to_char("You master the Toughness Power.\n\r", ch);
    	}
    	return;
    }
    else if (!str_cmp(arg1,"super shield"))
    {
    	if ( ch->pcdata->powers[PZERG] > 4 )
    		send_to_char("You already have the Super Shield power.\n\r", ch);
    	else if ( ch->pcdata->powers[PZERG] < 4 )
    		send_to_char("You need all the power before this one to receive this power.\n\r", ch);
    	else if ( ch->practice < 50)
    		send_to_char("You don't have the 50 required primal.\n\r", ch);
    	else
    	{
    		ch->pcdata->powers[improve] += 1;
    		ch->practice -= 50;
    		send_to_char("You master the Super Shield Power.\n\r", ch);
    	}
    	return;
    }
    else if (!str_cmp(arg1,"travel"))
    {
    	if ( ch->pcdata->powers[PZERG] > 5 )
    		send_to_char("You already have the travel power.\n\r", ch);
    	else if ( ch->pcdata->powers[PZERG] < 5 )
    		send_to_char("You need all the power before this one to receive this power.\n\r", ch);
    	else if ( ch->practice < 60)
    		send_to_char("You don't have the 60 required primal.\n\r", ch);
    	else
    	{
    		ch->pcdata->powers[improve] += 1;
    		ch->practice -= 60;
    		send_to_char("You master the travel power.\n\r", ch);
    	}
    	return;
    }
	sprintf(buf,"Powers Learned (%d).\n\r", ch->pcdata->powers[PZERG]);
	send_to_char(buf,ch);

	return;
}

void do_eyesofzerg( CHAR_DATA *ch, char *argument )
{
    if ( IS_NPC(ch) )
	return;
  
  	if ( !IS_CLASS(ch, CLASS_ZERG) )
  	{
  	send_to_char("Huh?\n\r", ch);
  	return;
  	}
  	
  	if ( ch->pcdata->powers[PZERG] < 1 )
  	{
  	  send_to_char("You have not learned the Eyes of Zerg Power.\n\r", ch);
  	  return;
  	}
  
    if ( IS_SET(ch->act, PLR_HOLYLIGHT) )
    {
	REMOVE_BIT(ch->act, PLR_HOLYLIGHT);
	send_to_char( "Your lose your Zergly sight.\n\r", ch );
    }
    else
    {
	send_to_char( "Xkilla gives you his eye vision.\n\r", ch );
	SET_BIT(ch->act, PLR_HOLYLIGHT);
    }
    return;
}

void do_supershield( CHAR_DATA *ch, char *argument )
{
    if ( IS_NPC(ch) )
	return;
  
  	if (!IS_CLASS(ch, CLASS_ZERG) )
  	{
  	send_to_char("Huh?\n\r", ch);
  	return;
  	}
  	
  	if ( ch->pcdata->powers[PZERG] < 5 )
  	{
  	  send_to_char("You have not learned the Super Shield Power.\n\r", ch);
  	  return;
  	}

/* Remove super shield in handler.c */
  
    if ( IS_AFFECTED(ch, AFF_STEELSHIELD) )
    {
	REMOVE_BIT( ch->affected_by, AFF_STEELSHIELD );
	send_to_char( "Your super shield disappears.\n\r", ch );
    }
    else
    {
	send_to_char( "You are surrounded by a super shield\n\r", ch );
	SET_BIT(ch->affected_by, AFF_STEELSHIELD);
    }
    return;
}

void do_ztravel( CHAR_DATA *ch, char *argument )
{
	char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    CHAR_DATA *mount;

	one_argument( argument, arg );

	if ( !IS_CLASS(ch, CLASS_ZERG) )
	{
		send_to_char("Huh?\n\r", ch);
		return;
	}

	if (IS_CLASS(ch, CLASS_ZERG) && ch->pcdata->powers[PZERG] < 6 )
	{
	  send_to_char("You have not learned the travel power.\n\r", ch);
	  return;
	}

    if ( arg[0] == '\0' )
    {
	send_to_char( "Travel to where?\n\r", ch );
	return;
    }
    
    if ( ch->position == POS_FIGHTING )
    {
	send_to_char( "No way! You are fighting.\n\r", ch );
	return;
    }

    if ( ( victim = get_char_world( ch, arg ) ) == NULL )
    {
	send_to_char( "Nobody by that name.\n\r", ch );
	return;
    }
    if( IS_IMMUNE(victim, IMM_TRAVEL) && !IS_NPC(victim))
    {
        send_to_char( "They don't wish to be traveled to.\n\r", ch);
        return;
    }
	if ( !IS_IMMUNE(victim, IMM_SUMMON) && !IS_NPC(victim))
	{
		send_to_char("They do not wish to be astraled to!\n\r", ch);
		return;
	}
	
    act( "You travel.", ch, NULL, NULL, TO_CHAR );
	act( "$n travels.", ch, NULL, NULL, TO_ROOM );
	char_from_room( ch );
	char_to_room( ch, get_room_index(victim->in_room->vnum) );
    act( "You appear infront of $N", ch, NULL, victim, TO_CHAR );
	act( "$n appears infront of $N.", ch, NULL, victim, TO_ROOM );	

    do_look( ch, "auto" );
    if ( (mount = victim->mount) == NULL ) return;
    char_from_room( mount );
    char_to_room( mount, get_room_index(victim->in_room->vnum) );
    do_look( mount, "auto" );
    return;
}

void do_superinvis( CHAR_DATA *ch, char *argument )
{
    if (IS_NPC(ch)) return;
	
	if (!IS_CLASS(ch, CLASS_ZERG) )
	{
		send_to_char("Huh?\n\r", ch);
		return;
	}
	
	if (IS_CLASS(ch, CLASS_ZERG) && ch->pcdata->powers[PMONK] < 3 )
	{
	  send_to_char("You have not learned the Super Invis.\n\r", ch);
	  return;
	}

    if ( IS_SET(ch->act, PLR_WIZINVIS) )
    {
	REMOVE_BIT(ch->act, PLR_WIZINVIS);
	send_to_char( "You appear from a shroud of light.\n\r", ch );
	act( "$n appears from a shroud of light.", ch, NULL, NULL, TO_ROOM );
    }
    else
    {
	send_to_char( "You shield yourself in a shroud of light.\n\r", ch );
	act( "$n is shielded in a shroud of light.", ch, NULL, NULL, TO_ROOM );
	SET_BIT(ch->act, PLR_WIZINVIS);
    }
    return;
}

void do_zclan( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    CHAR_DATA *gch;
    char lord[MAX_INPUT_LENGTH];

    if (IS_NPC(ch)) return;

    if (!IS_CLASS(ch, CLASS_ZERG) )
    {
	send_to_char("Huh?\n\r",ch);
	return;
    }

    if( ch->generation < 3 )
      strcpy(lord,ch->name);
    else strcpy(lord,ch->lord);

    sprintf( buf, "%s's Zergs:\n\r", ch->lord );
    send_to_char( buf, ch );
    send_to_char("[      Name      ] [ Hits  % ] [ Mana  % ] [ Move  % ]\n\r", ch );
    for ( gch = char_list; gch != NULL; gch = gch->next )
    {
	if ( IS_NPC(gch) ) continue;
	if ( !IS_CLASS(gch, CLASS_ZERG) ) continue;
	if ( !str_cmp(gch->lord,lord)|| !str_cmp(gch->name,lord) )
	{
	    sprintf( buf,
	    "[%-16s] [%-6d%3d] [%-6d%3d] [%-6d%3d]\n\r",
		capitalize( gch->name ),
		gch->hit,  (gch->hit  * 100 / gch->max_hit ),
		gch->mana, (gch->mana * 100 / gch->max_mana),
		gch->move, (gch->move * 100 / gch->max_move) );
		send_to_char( buf, ch );
	}
    }
    return;
}