/
Ghost/
Ghost/gods/
Ghost/log/
Ghost/player/
/*******************************************************************************
 *         _               | File Name:   act_newc.c
 *        / \      _-'     | Description: New Action code
 *      _/|  \-''- _ /     |
 * __-' |          \       |
 *     /              \    |
 *     /       "o.  |o |   |
 *     |            \ ;    |
 *                   ',    |
 *        \_         __\   | (c) 2000-2001 TAKA
 *          ''-_    \.//   | (c) 2000-2001 The GhostMud Project Team
 *            / '-____'    |
 *           /             | You may use this code under GNU license restriction
 *         _'  The Wolf    | 1) This header block remains in the code.
 *       _-'   strikes!    | 2) You email me at a_ghost_dancer@excite.com
 *_________________________|    letting me know you are using this code
 *                              please incluse your name, your mud name
 * All rights reserved          your mud address, your email and this file
 * GhostMud is copyrighted      name.
 * by TAKA                   3) In your help files mention me where appropriate
 *                              IE: help snippets.
 *********************************************************************************/
#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#include <sys/time.h>
#endif
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include "merc.h"
#include "recycle.h"
#include "tables.h"
#include "magic.h"

DECLARE_DO_FUN(	do_knock		);
DECLARE_DO_FUN( do_ushare       );
DECLARE_DO_FUN( do_rename       );
DECLARE_DO_FUN( do_butcher      );
DECLARE_DO_FUN( do_wpeace       );
DECLARE_DO_FUN( do_area_list    );
DECLARE_DO_FUN( do_fremove      );
DECLARE_DO_FUN( do_frecall      );
DECLARE_DO_FUN( do_transfer     );
DECLARE_DO_FUN( do_whowas       );
DECLARE_DO_FUN( do_look			);


extern void do_quit( CHAR_DATA *ch, char *argument );
extern int	find_door	args( ( CHAR_DATA *ch, char *arg ) );
extern void update_handler2( bool forced );
extern bool	check_parse_name	args( ( char *name ) );
bool write_version(char *argument);
void read_version(char *version);
void do_butcher(CHAR_DATA *ch, char *argument);
extern bool remove_obj args ((CHAR_DATA * ch, int iWear, bool fReplace));
void do_frecall( CHAR_DATA *ch, char *argument );
void whowas(CHAR_DATA *ch, FILE *fp);
void do_whowas(CHAR_DATA *ch, char *argument);
void do_rsetpword( CHAR_DATA *ch, char *argument );
void do_history( CHAR_DATA *ch, char *argument );


/*
	Mortal spells and skills stat for immortals commands
	by TAKA     March 2000 (c)
 */

void do_mortskill(CHAR_DATA *ch, char *argument)
{
	BUFFER *buffer;
	char arg[MAX_INPUT_LENGTH];
	char buf[MAX_STRING_LENGTH];
	char skill_list[LEVEL_HERO + 1][MAX_STRING_LENGTH];
	char skill_columns[LEVEL_HERO + 1];
	int sn, level, min_lev = 1, max_lev = LEVEL_HERO;
	bool found = FALSE;
	CHAR_DATA *victim;

	if (IS_NPC(ch))
		return;

	one_argument(argument,arg);

	if ( arg[0] == '\0' )
	{
		send_to_char( "{RList skills for whom?{x\n\r", ch );
		return;
	}

	if ( ( victim = get_char_world( ch, argument ) ) == NULL )
	{
		send_to_char( "{RThey aren't here.{x\n\r", ch );
		return;
	}

	if (IS_NPC(victim))
	{
		send_to_char( "{RUse this for skills on players.{x\n\r", ch );
		return;
	}

	/* initialize data */
	for (level = 0; level < LEVEL_HERO + 1; level++)
	{
		skill_columns[level] = 0;
		skill_list[level][0] = '\0';
	}

	for (sn = 0; sn < MAX_SKILL; sn++)
	{
		if (skill_table[sn].name == NULL )
			break;

		if ((level = skill_table[sn].skill_level[victim->class]) < LEVEL_HERO + 1
			&&  level >= min_lev && level <= max_lev
			&&  skill_table[sn].spell_fun == spell_null
			&&  victim->pcdata->learned[sn] > 0)
		{
			found = TRUE;
			level = skill_table[sn].skill_level[victim->class];

			if (victim->level < level)
				sprintf(buf,"{C%-18s {Yn{W/{Ya      {x", skill_table[sn].name);
			else
				sprintf(buf,"{C%-18s {Y%3d%%      {x",skill_table[sn].name,
					victim->pcdata->learned[sn]);

			if (skill_list[level][0] == '\0')
				sprintf(skill_list[level],"\n\rLevel {W%3d:{x %s",level,buf);
			else /* append */
			{
				if ( ++skill_columns[level] % 2 == 0)
					strcat(skill_list[level],"\n\r           ");
				strcat(skill_list[level],buf);
			}
		}
	}

	/* return results */
	if (!found)
	{
		send_to_char("{RNo skills found.{x\n\r",ch);
		return;
	}

	buffer = new_buf();

	for (level = 0; level < LEVEL_HERO + 1; level++)
		if (skill_list[level][0] != '\0')
			add_buf(buffer,skill_list[level]);

	add_buf(buffer,"\n\r");
	page_to_char(buf_string(buffer),ch);
	free_buf(buffer);
}

void do_mortspell(CHAR_DATA *ch, char *argument)
{
	BUFFER *buffer;
	char buff[100];
	char arg[MAX_INPUT_LENGTH];
	char spell_list[LEVEL_HERO + 1][MAX_STRING_LENGTH];
	char spell_columns[LEVEL_HERO + 1];
	int sn, gn, col, level, min_lev = 1, max_lev = LEVEL_HERO, mana;
	bool found = FALSE;
	char buf[MAX_STRING_LENGTH];
	CHAR_DATA *victim;

	if (IS_NPC(ch))
		return;

	one_argument(argument,arg);

	if ( arg[0] == '\0' )
	{
		send_to_char( "{RList spells for whom?{x\n\r", ch );
		return;
	}

	if ( ( victim = get_char_world( ch, argument ) ) == NULL )
	{
		send_to_char( "{RThey aren't here.{x\n\r", ch );
		return;
	}

	if (IS_NPC(victim))
	{
		send_to_char( "{RUse this for skills on players.{x\n\r", ch );
		return;
	}

	/* groups */
	col = 0;
	for (gn = 0; gn < MAX_GROUP; gn++)
	{
		if (group_table[gn].name == NULL)
			break;
		if (victim->pcdata->group_known[gn])
		{
			sprintf(buff,"{G%-20s{x ",group_table[gn].name);
			send_to_char(buff,ch);

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

	if ( col % 3 != 0 )
	{
		send_to_char( "\n\r", ch );
		sprintf(buff,"{GCreation points: {W%d{x\n\r",victim->pcdata->points);
		send_to_char(buff,ch);
	}

	/* initialize data */
	for (level = 0; level < LEVEL_HERO + 1; level++)
	{
		spell_columns[level] = 0;
		spell_list[level][0] = '\0';
	}

	for (sn = 0; sn < MAX_SKILL; sn++)
	{
		if (skill_table[sn].name == NULL )
		break;

		if ((level = skill_table[sn].skill_level[victim->class]) < LEVEL_HERO + 1
			&&  level >= min_lev && level <= max_lev
			&&  skill_table[sn].spell_fun != spell_null
			&&  victim->pcdata->learned[sn] > 0)
		{
			found = TRUE;
			level = skill_table[sn].skill_level[victim->class];
			if (victim->level < level)
				sprintf(buf,"{C%-18s {Yn{W/{Ya{x      ", skill_table[sn].name);
			else
			{
				mana = UMAX(skill_table[sn].min_mana, 100/(2 + victim->level - level));
				sprintf(buf,"{C%-18s  {Y%3d {Gmana{x  ",skill_table[sn].name,mana);
			}

			if (spell_list[level][0] == '\0')
				sprintf(spell_list[level],"\n\rLevel {W%3d:{x %s",level,buf);
			else /* append */
			{
				if ( ++spell_columns[level] % 2 == 0)
					strcat(spell_list[level],"\n\r           ");
				strcat(spell_list[level],buf);
			}
		}
	}

	/* return results */
	if (!found)
	{
		send_to_char("{RNo spells found.{x\n\r",ch);
		return;
	}

	buffer = new_buf();
	for (level = 0; level < LEVEL_HERO + 1; level++)
		if (spell_list[level][0] != '\0')
			add_buf(buffer,spell_list[level]);
	add_buf(buffer,"\n\r");
	page_to_char(buf_string(buffer),ch);
	free_buf(buffer);
}

/* End TAKA     spell adds */

/*
 * UNREMORT by TAKA of Ghost Dancer mud project.....
 * (c) 2000 TAKA
 */

bool do_unremort args( ( CHAR_DATA *ch, char *argument ) )
{

    char strsave[MAX_INPUT_LENGTH];
    char strbackup[MAX_INPUT_LENGTH+4];
    char buf[MAX_INPUT_LENGTH+4];
	FILE *fp;
	int result;

	sprintf( strsave, "%s%s", PLAYER_DIR, capitalize( ch->name ) );
	strcpy( strbackup, strsave );
	strcat( strbackup, ".rmt" );

	if ( ( fp = fopen( strbackup, "r" ) ) == NULL )
	{
		send_to_char("Invalid unremort state or you have already unremorted!\n\r", ch);
		bug("close file", 0);
		return FALSE;
	}
	fclose(fp);

	/*
	 * unlink player
	 */
	send_to_char("wait about 30 seconds then resign in.....\n\r", ch);
	do_quit(ch,"");


	/*
	 * reset old pfile
	 */
	unlink( strsave );
	result = rename ( strbackup, strsave );
	if (result != 0)
	{
		sprintf( buf, "%s was not renamed to %s", strbackup, strsave);
		bug(buf, 0);
	}
	else
	{
		sprintf( buf, "%s was renamed to %s", strbackup, strsave);
		bug(buf, 0);
	}

	return TRUE;
}


/*
	I saw comm stat on dark scapes I liked it and it and swiped it
	the idea for me started there the code however is all original
	-- TAKA
 */

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

 	DESCRIPTOR_DATA *d;
	char buf[MAX_INPUT_LENGTH + 80];

 	send_to_char("{W  Player   gos auc mus  ?  quo gra rac sho qui AFK dea{x\n\r", ch);

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

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

		sprintf(buf, "{W%-10s{G %s %s %s %s %s %s %s %s %s %s %s\n\r",
			victim->name, IS_SET(victim->comm,COMM_NOGOSSIP)?"OFF":"ON ",
			IS_SET(victim->comm,COMM_NOAUCTION)?"OFF":"ON ",
			IS_SET(victim->comm,COMM_NOMUSIC)?"OFF":"ON ",
			IS_SET(victim->comm,COMM_NOQUESTION)?"OFF":"ON ",
			IS_SET(victim->comm,COMM_NOQUOTE)?"OFF":"ON ",
			IS_SET(victim->comm,COMM_NOGRATS)?"OFF":"ON ",
			/*IS_SET(victim->comm,COMM_NORACE)?"OFF":"ON ",*/
			"OFF",
			IS_SET(victim->comm,COMM_NOSHOUT)?"OFF":"ON ",
			IS_SET(victim->comm,COMM_QUIET)?"{RON {x":"{ROFF{x",
			IS_SET(victim->comm,COMM_AFK)?"{YYes{x":"{YNo {x",
			IS_SET(victim->comm,COMM_DEAF)?"{DON {x":"{DOFF{x");
		send_to_char(buf, ch);

		if (IS_IMMORTAL(ch))
    	{
			sprintf(buf, "{MGod channel: %s  %s\n\r",
				IS_SET(victim->comm,COMM_NOWIZ)?"OFF ":" ON ",
				IS_SET(victim->comm,COMM_SNOOP_PROOF)?"{CImmune to snooping.{x\n\r":
				"{CNot Immune to snooping.{x\n\r");
			send_to_char(buf, ch);
		}
 	}
	return;
}

/**************************************************************************/

/*
 *  This function allows a character to knock on a door.
 *  -- TAKA (you're welcome)
 */

void do_knock(CHAR_DATA *ch, char *argument)
{
	/* Some code taken from do_open().  */
  	long door;
  	char arg[MAX_INPUT_LENGTH];

  	one_argument(argument,arg);

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

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

      	pexit = ch->in_room->exit[door];

      	act( "{W$n {Rknocks on the $d.{x", ch, NULL, pexit->keyword, TO_ROOM );
      	act( "{RYou knock on the $d.{x", ch, NULL, pexit->keyword, TO_CHAR );

      	/* Notify the other side.  */
      	if (   ( to_room   = pexit->u1.to_room            ) != NULL
      	    && ( pexit_rev = to_room->exit[rev_dir[door]] ) != NULL
      	    && pexit_rev->u1.to_room == ch->in_room )
      	{
          		CHAR_DATA *rch;
          		for ( rch = to_room->people; rch != NULL; rch = rch->next_in_room )
            		act( "{RYou hear someone knocking.{x", rch, NULL, pexit_rev->keyword, TO_CHAR );
        	}
    	}
  	return;
}


void do_ushare( CHAR_DATA *ch, char *argument )         /* by Maniac */
{
	char    arg1[MAX_INPUT_LENGTH];
	char    arg2[MAX_INPUT_LENGTH];


	if ( argument[0] == '\0' )      /* No options ??? */
	{
		send_to_char( "Ushare\n\r", ch );
		send_to_char( "Ushare bankI   (share_value1).\n\r", ch );
		send_to_char( "Ushare bankII  (share_value2).\n\r", ch );
		send_to_char( "Ushare bankIII (share_value3).\n\r", ch );
		send_to_char( "Ushare bankIV  (share_value4).\n\r", ch );

		return;
	}

	argument = one_argument(argument, arg1);
	if (!str_prefix(arg1, "bankI" ) )
	{

		argument = one_argument(argument, arg2);
	    /*
		 * Snarf the value (which need not be numeric).
		 */
		share_value1 = is_number( arg2 ) ? atoi( arg2 ) : -1;

		if (share_value1 < 0)
			share_value1 = 1;

		bank_update2( );
		send_to_char ("Ok...bank share value I updated.\n\r", ch);

		return;
	}

	if (!str_prefix(arg1, "bankII" ) )
	{

		argument = one_argument(argument, arg2);
	    /*
		 * Snarf the value (which need not be numeric).
		 */
		share_value2 = is_number( arg2 ) ? atoi( arg2 ) : -1;

		if (share_value2 < 0)
			share_value2 = 1;

		bank_update2( );
		send_to_char ("Ok...bank share value II updated.\n\r", ch);

		return;
	}

	if (!str_prefix(arg1, "bankIII" ) )
	{

		argument = one_argument(argument, arg2);
	    /*
		 * Snarf the value (which need not be numeric).
		 */
		share_value3 = is_number( arg2 ) ? atoi( arg2 ) : -1;

		if (share_value3 < 0)
			share_value3 = 1;

		bank_update2( );
		send_to_char ("Ok...bank share value III updated.\n\r", ch);

		return;
	}

	if (!str_prefix(arg1, "bankIV" ) )
	{

		argument = one_argument(argument, arg2);
	    /*
		 * Snarf the value (which need not be numeric).
		 */
		share_value4 = is_number( arg2 ) ? atoi( arg2 ) : -1;

		if (share_value4 < 0)
			share_value4 = 1;

		bank_update2( );
		send_to_char ("Ok...bank share value IV updated.\n\r", ch);

		return;
	}

	return;
}

/* allow force tick */

void do_force_tick (CHAR_DATA *ch, char *argument )
{
    update_handler2( TRUE );
    send_to_char( "You Have Forced Time To Fly By....TICK\n\r", ch );
    return;
}

/* end force tick TAKA     */

/*
 * Coded by: Thale (Andrew Maslin)
 * Syntax: Rename <victim> <new_name>
 * Limitations: This header must be kept with this function.  In addition,
 * this file is subject to the ROM license.  The code in this file is
 * copywritten by Andrew Maslin, 1998.  If you have a "credits" help in your
 * mud, please add the name Thale to that as credit for this function.
 */

void do_rename(CHAR_DATA *ch, char *argument)
{
	CHAR_DATA *victim;
	FILE *fp;
	char strsave[MAX_INPUT_LENGTH];
	char *name;
	char arg1[MAX_INPUT_LENGTH];
	char arg2[MAX_INPUT_LENGTH];
	char buf[MAX_INPUT_LENGTH];
	char playerfile[MAX_INPUT_LENGTH];

	if (!IS_IMMORTAL(ch))
	{
		send_to_char("{RYou don't have the power to do that.{x\n\r",ch);
		return;
	}

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

	if (arg1[0] == '\0')
	{
		send_to_char("{RRename who?{x\n\r",ch);
		return;
	}

	if (arg2[0] == '\0')
	{
		send_to_char("{RWhat should their new name be?{x\n\r",ch);
		return;
	}

	arg2[0] = UPPER(arg2[0]);

	if ((victim = get_char_world(ch,arg1)) == NULL)
	{
		send_to_char("{RThey aren't connected.{x\n\r",ch);
		return;
	}

	if (IS_NPC(victim))
	{
		send_to_char("{RUse string for NPC's.{x\n\r",ch);
		return;
	}

	if (!check_parse_name(arg2))
	{
		sprintf(buf,"{RThe name {c%s{x is {Rnot allowed{x.\n\r",arg2);
		send_to_char(buf,ch);
		return;
	}

	sprintf(playerfile, "%s%s", PLAYER_DIR, capitalize(arg2));

	if ((fp = fopen(playerfile, "r")) != NULL)
	{
		sprintf(buf,"{RThere is already someone named {W%s{R.{x\n\r",capitalize(arg2));
		send_to_char(buf,ch);
		fclose(fp);
		return;
	}

	if ((victim->level >= ch->level) && (victim->level >= ch->trust)
		&&((ch->level != IMPLEMENTOR) || (ch->trust != IMPLEMENTOR))
		&&(ch != victim))
	{
		send_to_char("{RI don't think that's a good idea.{x\n\r",ch);
		return;
	}

	if (victim->position == POS_FIGHTING)
	{
		send_to_char("{RThey are fighting right now.{x\n\r",ch);
		return;
	}

	name = str_dup(victim->name);
	sprintf( strsave, "%s%s", PLAYER_DIR, capitalize(victim->name));
	arg2[0] = UPPER(arg2[0]);
	free_string(victim->name);
	victim->name = str_dup(arg2);
	save_char_obj(victim);
	unlink(strsave);

#if defined(unix)
	if (IS_IMMORTAL(victim))
	{
		sprintf(strsave,"%s%s", GOD_DIR, capitalize(name));
		unlink(strsave);
	}
#endif

	if (victim != ch)
	{
		sprintf(buf,"{YNOTICE: {xYou have been renamed to {c%s{x.\n\r",arg2);
		send_to_char(buf,victim);
	}

	send_to_char("{RDone.{x\n\r",ch);
	return;
}

/*
 * Version command read/write ect...
 * by TAKA
 */

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

	version[0]='\0';

	if (IS_NPC(ch))
		return;

	if (ch->level < MAX_LEVEL)	/* Stuff trusted characters! */
	{
		read_version( version );
		sprintf(buf, "Current version is :- %s\n\r", version );
		send_to_char(buf, ch);
		return;
	}
	else
	{
		if (argument[0] == '\0')
		{
			read_version( version );
			sprintf(buf, "Current version is :- %s\n\r", version );
			send_to_char(buf, ch);
			return;
		}
		else
	    {
			if( write_version(argument) )
		    {
				sprintf(buf, "Current version changed to %s\n\r", argument);
				send_to_char(buf, ch);
				sprintf(buf, "%s has changed the current version number to %s", ch->name, argument);
				log_string( buf );
			}
			else
				send_to_char("Write version failed - please report", ch);

			/* report it on wiznet as well if you like... */
			return;
		}
	}

}


bool write_version(char *argument) /*Returns true if sucsessful, else false*/
{
	FILE *versionfp;
	bool situation;
	char buf[MAX_STRING_LENGTH];

	fclose(fpReserve);

	if ((versionfp = fopen(VERSION_FILE, "w"))==NULL)
	{
		bug("write_version : can't open version file",0);
		situation = FALSE;
	}
	else
	{
		sprintf( buf, "%s\n", argument);

		fprintf( versionfp, "#\n" );
		fprintf( versionfp, buf);

		fclose( versionfp );
		situation = TRUE;
	}

	fpReserve = fopen(NULL_FILE, "r");

	return situation;
}

void read_version(char *version) /*dumps the version No. in version */
{
	FILE *versionfp;

	fclose( fpReserve );

	if ((versionfp = fopen(VERSION_FILE, "r"))==NULL)
	{
		bug("read_version : can't open version file",0);
		sprintf( version, "V0.0 -- Please report!\n\r" );
	}
	else
	{
		if (fread_letter(versionfp) != '#')
		{
			bug("read_version : # not found",0);
			sprintf( version, "V0.0 -- Please report!\n\r" );
			fclose( versionfp );
		}
		else
		{
			sprintf(version, fread_string_eol( versionfp ));
			fclose( versionfp );
		}
	}

	fpReserve = fopen(NULL_FILE, "r");

	return;
}

/* end of versions code by TAKA */

/*
 * new commands added here are all by TAKA
 * of ghost dancer.
 * butcher	- allows player to butcher corpses for food.
 */

/* Butcher Skill By TAKA     */
void do_butcher(CHAR_DATA *ch, char *argument)
{

    /* If you have an interest in this skill, feel free */
    /* to use it in your mud if you so desire. */

    char buf[MAX_STRING_LENGTH];
    char arg[MAX_STRING_LENGTH];
    int numst = 0;
    OBJ_DATA *steak;
    OBJ_DATA *obj;

    one_argument(argument, arg);

    if(get_skill(ch,gsn_butcher)==0)
    {
       send_to_char("Butchering is beyond your skills.\n\r",ch);
       return;
    }

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

    obj = get_obj_list( ch, arg, ch->in_room->contents );

    if ( obj == NULL )
    {
        send_to_char( "It's not here.\n\r", ch );
        return;
    }

    if( (obj->item_type != ITEM_CORPSE_NPC)
        && (obj->item_type!=ITEM_CORPSE_PC) )
    {
        send_to_char( "You can only butcher corpses.\n\r", ch );
        return;
    }

    /* create and rename the steak */
    buf[0]='\0';
    strcat(buf,"A steak of ");
    strcat(buf,str_dup(obj->short_descr));
    strcat(buf," is here.");

    steak = create_object( get_obj_index(OBJ_VNUM_STEAK), 0 );

    steak->description=str_dup(buf);
    steak->value[0] = ch->level / 2;
    steak->value[1] = ch->level;

    buf[0]='\0';
    strcat(buf,"A steak of ");
    strcat(buf,str_dup(obj->short_descr));

    steak->short_descr=str_dup(buf);

    /* Check the skill roll, and put a random ammount of steaks here. */
    if(number_percent( ) < get_skill(ch,gsn_butcher))
    {
       numst = dice(1,4);
       switch(numst)
       {
       case 1:
         steak = create_object( get_obj_index( OBJ_VNUM_STEAK ), 0 );
         obj_to_room( steak, ch->in_room );
         act( "$n butchers a corpse and creates a steak.", ch, steak, NULL, TO_ROOM );
         act( "You butcher a corpse and create a steak.", ch, steak, NULL, TO_CHAR );
         break;
       case 2:
         steak = create_object( get_obj_index( OBJ_VNUM_STEAK ), 0 );
         obj_to_room( steak, ch->in_room );
         steak = create_object( get_obj_index( OBJ_VNUM_STEAK ), 0 );
         obj_to_room( steak, ch->in_room );
         act( "$n butchers a corpse and creates two steaks.", ch, steak, NULL, TO_ROOM );
         act( "You butcher a corpse and create two steaks.", ch, steak, NULL, TO_CHAR );
         break;
       case 3:
         steak = create_object( get_obj_index( OBJ_VNUM_STEAK ), 0 );
         obj_to_room( steak, ch->in_room );
         steak = create_object( get_obj_index( OBJ_VNUM_STEAK ), 0 );
         obj_to_room( steak, ch->in_room );
         steak = create_object( get_obj_index( OBJ_VNUM_STEAK ), 0 );
         obj_to_room( steak, ch->in_room );
         act( "$n butchers a corpse and creates three steaks.", ch, steak, NULL, TO_ROOM );
         act( "You butcher a corpse and create three steaks.", ch, steak, NULL, TO_CHAR );
         break;
       case 4:
         steak = create_object( get_obj_index( OBJ_VNUM_STEAK ), 0 );
         obj_to_room( steak, ch->in_room );
         steak = create_object( get_obj_index( OBJ_VNUM_STEAK ), 0 );
         obj_to_room( steak, ch->in_room );
         steak = create_object( get_obj_index( OBJ_VNUM_STEAK ), 0 );
         obj_to_room( steak, ch->in_room );
         steak = create_object( get_obj_index( OBJ_VNUM_STEAK ), 0 );
         obj_to_room( steak, ch->in_room );
         act( "$n butchers a corpse and creates four steaks.", ch, steak, NULL, TO_ROOM );
         act( "You butcher a corpse and create four steaks.", ch, steak, NULL, TO_CHAR );
         break;
      }
      check_improve(ch,gsn_butcher,TRUE,1);

    }
    else
    {
       act( "$n fails to butcher a corpse, and destroys it.", ch, steak, NULL, TO_ROOM );
       act( "You fail to butcher a corpse, and destroy it.", ch, steak, NULL, TO_CHAR );
       check_improve(ch,gsn_butcher,FALSE,1);
    }
    /* dump items caried */
    /* Taken from the original ROM code and added into here. */

    if ( obj->item_type == ITEM_CORPSE_PC )
    {   /* save the contents */
       {
            OBJ_DATA *t_obj, *next_obj;
            for (t_obj = obj->contains; t_obj != NULL; t_obj = next_obj)
            {
                next_obj = t_obj->next_content;
                obj_from_obj(t_obj);
                if (obj->in_obj) /* in another object */
                    obj_to_obj(t_obj,obj->in_obj);
                else if (obj->carried_by) /* carried */
                    if (obj->wear_loc == WEAR_FLOAT)
                        if (obj->carried_by->in_room == NULL)
                            extract_obj(t_obj);
                        else
                            obj_to_room(t_obj,obj->carried_by->in_room);
                    else
                        obj_to_char(t_obj,obj->carried_by);
               else if (obj->in_room == NULL) /* destroy it */
                    extract_obj(t_obj);
                else /* to a room */
                    obj_to_room(t_obj,obj->in_room);
           }
      }
  }
  if ( obj->item_type == ITEM_CORPSE_NPC )
    {
       {
            OBJ_DATA *t_obj, *next_obj;
            for (t_obj = obj->contains; t_obj != NULL; t_obj = next_obj)
            {
                next_obj = t_obj->next_content;
                obj_from_obj(t_obj);
                if (obj->in_obj) /* in another object */
                    obj_to_obj(t_obj,obj->in_obj);
                else if (obj->carried_by) /* carried */
                    if (obj->wear_loc == WEAR_FLOAT)
                        if (obj->carried_by->in_room == NULL)
                            extract_obj(t_obj);
                        else
                            obj_to_room(t_obj,obj->carried_by->in_room);
                    else
                        obj_to_char(t_obj,obj->carried_by);
                else if (obj->in_room == NULL) /* destroy it */
                    extract_obj(t_obj);
                else /* to a room */
                    obj_to_room(t_obj,obj->in_room);
         }
     }
  }

    /* Now remove the corpse */
    extract_obj(obj);
    return;
}

/*
 * (c) TAKA 2000 Ghost Dancer MUD Project
 * forced remove and sieze
 */

void do_fremove( CHAR_DATA *ch, char *argument )
{
	char arg1[MAX_INPUT_LENGTH];
	CHAR_DATA *victim;
	OBJ_DATA *obj_next;
	OBJ_DATA *obj;

	argument = one_argument( argument, arg1 );

	if ( arg1[0] == '\0' )
	{
		send_to_char( "Syntax: fremove <char>\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 ( victim->level > get_trust( ch) )
	{
		send_to_char( "Limited to your trust level.\n\r", ch );
		return;
	}

	for (obj = victim->carrying; obj; obj = obj_next)
	{
		obj_next = obj->next_content;
		if (obj->wear_loc != WEAR_NONE)
		{
			remove_obj (victim, obj->wear_loc, TRUE);
			obj_from_char (obj);
			obj_to_char (obj, ch);
		}
	}

	save_char_obj(victim);
	return;
}

/*
 * (c) 2000 TAKA
 * makes the world at peace took some of the code from do_peace
 */

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

	rch = get_char_world( ch, buf );

	for ( rch = char_list; rch; rch = rch->next )
	{
		if ( ch->desc == NULL || ch->desc->connected != CON_PLAYING )
			continue;
		if ( rch->fighting )
		{
			sprintf( buf, "%s has declared World Peace.\n\r", ch->name );
			send_to_char( buf, rch );
			stop_fighting( rch, TRUE );
		}
	}
	send_to_char( "You have declared World Peace.\n\r", ch );
	return;
}


/*
 * (c) 2000 TAKA Ghost Dancer MUD Project
 * list all areas
 */
void do_area_list( CHAR_DATA *ch, char *argument )
{
    BUFFER *output;
	char buf[MAX_STRING_LENGTH];
    char result [ MAX_STRING_LENGTH*2 ];	/* May need tweaking. */
    AREA_DATA *pArea;

	output = new_buf();

    sprintf( result, "{C[{M%3s{C] [{W%-27s{C] ({G%-5s{W-{G%5s{C) [{B%-10s{C]{x\n\r",
       "Num", "Area Name", "lvnum", "uvnum", "Filename" );
	send_to_char( result, ch );

    for ( pArea = area_first; pArea; pArea = pArea->next )
    {
	sprintf( buf, "{C[{M%3ld{C] {W%-29.29s {C({G%-5ld{W-{G%5ld{C) {B%-12.12s{x\n\r",
	     pArea->vnum,
	     pArea->name,
	     pArea->min_vnum,
	     pArea->max_vnum,
	     pArea->file_name);
	     add_buf(output,buf);
    }

    page_to_char(buf_string(output),ch);
	free_buf(output);
}

/*
 * (c) 2000 TAKA Ghost Dancer MUD Project
 * Loads a player file.
 */
void do_lpfile( CHAR_DATA *ch, char *argument )
{
  DESCRIPTOR_DATA d;
  bool isChar = FALSE;
  char name[MAX_INPUT_LENGTH];

  if (argument[0] == '\0')
  {
    send_to_char("{RLoad who?{x\n\r", ch);
    return;
  }

  argument[0] = UPPER(argument[0]);
  argument = one_argument(argument, name);

  /*
   * if player is already on do not load it
   */
  if ( get_char_world( ch, name ) != NULL )
  {
    send_to_char( "{RThat person is allready playing!{x\n\r", ch );
    return;
  }

  isChar = load_char_obj(&d, name); /* char pfile exists? */

  if (!isChar)
  {
    send_to_char("{RThey do not exist!{x\n\r", ch);
    return;
  }

  d.character->desc     = NULL;
  d.character->next     = char_list;
  char_list             = d.character;
  d.connected           = CON_PLAYING;
  reset_char(d.character);

  /*
   * player to imm room
   */
  if ( d.character->in_room != NULL )
  {
    char_to_room( d.character, ch->in_room);
  }

  act( "{W$n {Ghas loaded {W$N!{x",
        ch, NULL, d.character, TO_ROOM );

  if (d.character->pet != NULL)
   {
     char_to_room(d.character->pet,d.character->in_room);
     act("{W$n {Ghas entered the game.{x",d.character->pet,NULL,NULL,TO_ROOM);
   }

}

/*
 * (c) 2000 TAKA Ghost Dancer MUD Project
 * Loads a player file.
 */
void do_ulpfile( CHAR_DATA *ch, char *argument )
{
  CHAR_DATA *victim;
  char who[MAX_INPUT_LENGTH];

  argument = one_argument(argument, who);

  /*
   * unload only if found in the world
   */
  if ( ( victim = get_char_world( ch, who ) ) == NULL )
  {
    send_to_char( "{RThey aren't here.{x\n\r", ch );
    return;
  }

  /*
   * player description == NULL then the player was a loaded pfile!
   */
  if (victim->desc != NULL)
  {
    send_to_char("{RI dont think that would be a good idea...{x\n\r", ch);
    return;
  }

  /*
   * return player and pet to thier original room
   */
  if (victim->was_in_room != NULL)
  {
    char_to_room(victim, victim->was_in_room);
    if (victim->pet != NULL)
      char_to_room(victim->pet, victim->was_in_room);
  }

  save_char_obj(victim);
  do_quit(victim,"");

  act("{W$n {Ghas released {W$N!",
       ch, NULL, victim, TO_ROOM);
}

/*
 * (c) TAKA 2000 Ghost Dancer MUD Project
 * IMM Set password command
 */

void do_rsetpword( CHAR_DATA *ch, char *argument )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    CHAR_DATA *victim;
    char *pwdnew;

    if ( IS_NPC(ch) )
    return;

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

    victim = get_char_world(ch, arg1);

    if (  ( ch->pcdata->pwd != '\0' )
    && ( arg1[0] == '\0' || arg2[0] == '\0')  )
    {
        send_to_char( "Syntax: rsetpword <char> <new>.\n\r", ch );
        return;
    }
    if( victim == '\0' )
    {
		send_to_char( "That person isn't here, they have to be here to reset pwd's.\n\r", ch);
	 	return;
    }
    if ( IS_NPC( victim ) )
    {
		send_to_char( "You cannot change the password of NPCs!\n\r",ch);
		return;
    }

    if (( victim->level > LEVEL_IMMORTAL ) || ( get_trust(victim) > LEVEL_IMMORTAL ))
	{
		send_to_char( "You can't change the password of that player.\n\r",ch);
		return;
    }

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

    pwdnew = (char *) crypt( arg2, victim->name );
    free_string( victim->pcdata->pwd );
    victim->pcdata->pwd = str_dup( pwdnew );
    save_char_obj( victim );
    send_to_char( "Ok.\n\r", ch );
    sprintf( buf, "Your password has been changed to %s.", arg2 );
    send_to_char( buf, victim);
    return;
}

/*
 * (c) 2000 TAKA Ghost Dancer MUD Project
 * gets the player pword for the imp!
 */
void do_getpw( CHAR_DATA *ch, char *argument )
{
   CHAR_DATA *victim;
   char buf[MAX_STRING_LENGTH];

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

    if ((victim = get_char_world(ch,argument)) == NULL)
    {
	send_to_char("You can't find them.\n\r",ch);
	return;
    }


 	sprintf(buf,"PW = %s", victim->pcdata->pwd);/*(char *) crypt(ch->pcdata->pwd, ch->name));*/
	send_to_char(buf,ch);
	return;

}

/*
 * Lore written by TAKA (c) 2000 Ghost Dancer MUD Project
 */
void do_lore( CHAR_DATA *ch, char *argument )
{
    OBJ_DATA *obj;
    char arg[MAX_STRING_LENGTH];
    char buf[MAX_STRING_LENGTH];

    one_argument( argument, arg );

    obj = get_obj_world( ch, arg );

    if ( obj == NULL )
    {
    sprintf( buf, "You've never heard of a %s.\n\r", arg );
    send_to_char( buf, ch );
    return;
    }

    if ( get_skill( ch, gsn_lore ) == 0 )
    {
    send_to_char( "You don't know anything about it.\n\r", ch );
    return;
    }

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

    if ( number_percent( ) < get_skill( ch, gsn_lore ) )
    {
    sprintf( buf, "'%s' is type %s, extra flags %s.\n\rLevel %d.\n\r",
        obj->name, item_name(obj->item_type), extra_bit_name( obj->extra_flags),
        obj->level );
    send_to_char( buf, ch );

    check_improve( ch, gsn_lore, TRUE, 1 );
    }
    else
    {
    send_to_char( "You can't remember a thing about it.\n\r", ch );
        check_improve( ch, gsn_lore, FALSE, 1 );
    }

    return;
}

/*
 * forced recall for when a player was accidentally trapped in a
 * no recall, no teleport, type area.
 * It should only be used if the imm was at fualt for the mess
 * It give a message on wiznet.
 *
 * (c) 2000 TAKA Ghost Dancer MUD Project
 * a PYROX - ribbed for her pleasure - original idea!
 *
 * It will only transfer them to the temple vnum nowhere else
 * so i believe it safe for a low level imm.
 */

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

	one_argument( argument, arg );

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

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

	if ( IS_NPC(victim) )
	{
		send_to_char( "{RNot on NPC's.{x\n\r", ch );
		return;
	}

	if ( get_trust( victim ) >= get_trust( ch ) )
	{
		send_to_char( "{RYou failed.{x\n\r", ch );
		return;
	}

	sprintf(buf,"$N force recalled %s",victim->name);
	wiznet(buf,ch,NULL,WIZ_PENALTIES,WIZ_SECURE,0);
	send_to_char( "Force Recall Done.\n\r", ch );

	stop_fighting(victim,TRUE);
	sprintf( buf, "%s %d", victim->name, ROOM_VNUM_TEMPLE );

	do_transfer( ch, buf);

	return;
}


/*
 * This is whowas for players logged off
 * parts of this stolen from load_characer
 */

void do_whowas(CHAR_DATA *ch, char *argument)

{

    FILE *fp;
    char arg[MAX_INPUT_LENGTH];
    char strsave[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    char *name;
    DESCRIPTOR_DATA *d;
    bool found = FALSE;
    char letter;
    char *word;

    one_argument(argument,arg);

    if (arg[0] == '\0')
    {
        send_to_char("You must provide a name.\n\r",ch);
        return;
    }

    name = arg;

    for (d = descriptor_list; d; d = d->next)
    {
        CHAR_DATA *wch;

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

        wch = ( d->original != NULL ) ? d->original : d->character;

		if ( !can_see(ch,wch) )
	    	continue;

        if (!str_prefix(arg,wch->name))
        {
            found = TRUE;
            if ((wch->level > ch->level) && !can_see(wch, ch))
            {
				sprintf(buf, "{GName:{W %s %s{x\n\r", wch->name, wch->pcdata->title );
				send_to_char(buf, ch);

				if (wch->level >= LEVEL_IMMORTAL)
				{
				   	sprintf(buf, "{RIs an IMMORTAL.{x\n\r");
				   	send_to_char(buf, ch);
					sprintf(buf, "{GLevel:{W %d {GRace:{W %s{G Class:{W %s{x\n\r",
				   		wch->level,
				   		race_table[wch->race].name,
				   		class_table[wch->class].name);

				}
				else
					sprintf(buf, "{GLevel:{W %d {GRace:{W %s{G Class:{W %s{x\n\r",
				   		wch->level,
				   		race_table[wch->race].name,
				   		class_table[wch->class].name);

				send_to_char(buf, ch);

				send_to_char("{CHistory{x\n\r", ch);
	            sprintf(buf, ch->pcdata->history );
                send_to_char(buf, ch);


			}
		}
    }

    if (found)
    {
        send_to_char("That char is playing right now use whois.\n\r",ch);
        return;
    }
    else
    {
       /* open file */
#if defined(unix)
       /* decompress if .gz file exists */
       sprintf( strsave, "%s%s%s", PLAYER_DIR, capitalize(name),".gz");
       if ( ( fp = fopen( strsave, "r" ) ) != NULL )
       {
          fclose(fp);
          sprintf(buf,"gzip -dfq %s",strsave);
          system(buf);
       }
#endif

       sprintf( strsave, "%s%s", PLAYER_DIR, capitalize( name ) );
       if ( ( fp = fopen( strsave, "r" ) ) != NULL ) /* open file */
       {
          letter = fread_letter( fp );

          if ( letter == '*' )
             fread_to_eol( fp );

          if ( letter != '#' )
          {
             bug( "Do_whowas: # not found.", 0 );
             return;
          }

          word = fread_word( fp );

          if ( str_cmp( word, "PLAYER" ) )
          {
	         bug("Bug in whowas: File opened is not Player file.",0);
             fclose( fp );
             return;
	      }

           whowas(ch,fp);
           fclose(fp);
       }
       else
       {
      	   send_to_char("There is no player by that name.\n\r",ch);
      	   return;
       }

    }

}


/*
 * get file information
 */
void whowas(CHAR_DATA *ch, FILE *fp)
{
    char buf[MAX_STRING_LENGTH];
    char *word;
    bool fMatch;
    char *name, *race, *date, *title, *history;
    int classnum, level, sex;
    long LLogT;

/* Initialize variables to Error checking states. */

    name = NULL;
    race = NULL;
    history = NULL;
    date = NULL;
    title = NULL;
    classnum = -1;
    level    = -1;
    sex      = -1;

    for ( ; ; )
    {
    	word   = feof( fp ) ? "End" : fread_word( fp );
    	fMatch = FALSE;

    	switch ( UPPER(word[0]) )
    	{
    	case '*':
    	    fMatch = TRUE;
    	    fread_to_eol( fp );
    	    break;

    	case 'C':
            if ( !str_cmp( word, "Cla" ) )
            {
		       classnum = fread_number(fp);
               fMatch = TRUE;
               break;
            }
            break;

	    case 'E':
	        if ( !str_cmp( word, "End" ) )
	        {
                if ( (name    == NULL)
                   ||(race    == NULL)
/*                   ||(date    == NULL) */
                   ||(sex     == -1 )
                   ||(classnum== -1 )
                   ||(level   == -1 ) )
                {
                   send_to_char("Information not available.\n\r",ch);
                   return;
                }

	            sprintf(buf, "{GName:{W %s %s{x\n\r", name, title );
                send_to_char(buf, ch);

                if (level >= LEVEL_IMMORTAL)
                {
           	       	sprintf(buf, "{RIs an IMMORTAL.{x\n\r");
	            	send_to_char(buf, ch);
               		sprintf(buf, "{GLevel:{W %d {GRace:{W %s{G Class:{W %s{x\n\r",
	               		level, race, class_table[classnum].name);

           		}
            	else
               		sprintf(buf, "{GLevel:{W %d {GRace:{W %s{G Class:{W %s{x\n\r",
	               		level, race, class_table[classnum].name);

            	send_to_char(buf, ch);

		        if (((ch->level >= LEVEL_IMMORTAL) && (ch->level >= level))
		        	|| (level < LEVEL_IMMORTAL))
				{
	              	sprintf(buf,"{YLast seen on:{m %s{x\n\r", (char *) ctime(&LLogT));
	              	send_to_char(buf, ch);
				}

				send_to_char("{CHistory{x\n\r", ch);
	            sprintf(buf, history );
                send_to_char(buf, ch);


                free_string(name);
                free_string(race);
                free_string(date);
                free_string(title);
       			return;
        	}
        	break;

    	case 'L':
            if ( !str_cmp(word,"Levl")
               ||!str_cmp(word,"Lev")
               ||!str_cmp(word,"Level") )

           	{
		       level = fread_number( fp );
		       fMatch = TRUE;
               break;

            }

            if ( !str_cmp(word, "LogO") )
            {
       			/* date = str_dup(fread_string( fp )); */
				LLogT = fread_number(fp);
       			fMatch = TRUE;
       			break;
           	}
        	break;

    	case 'H':
            if (!str_cmp(word,"Hist") )
	       	{
       			history = str_dup(fread_string( fp ));
       			fMatch = TRUE;
       			break;
            }
        	break;

    	case 'N':
            if (!str_cmp(word,"Name") )
	       	{
       			name = str_dup(fread_string( fp ));
       			fMatch = TRUE;
       			break;
            }
        	break;

    	case 'R':
	      	if ( !str_cmp( word, "Race") )
            {
       			race = str_dup(fread_string( fp ));
       			fMatch = TRUE;
       			break;
       		}
			break;

    	case 'S':
			if ( !str_cmp( word, "Sex") )
       		{
       			sex = fread_number( fp );
       			fMatch = TRUE;
       			break;
        	}
        	break;

    	case 'T':
			if ( !str_cmp( word, "Titl") )
       		{
       			title = str_dup(fread_string( fp ));
       			fMatch = TRUE;
       			break;
        	}
        	break;

        }

    	if ( !fMatch )

    	{
	        fread_to_eol( fp );
	    }

    }

}

/*
 * home recall selectable by character
 * (c) 2000 TAKA Ghost Dancer MUD Project
 */
void do_hrecall( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
	int location;

    argument = one_argument( argument, arg );

	/*
	 * Check flexable options here
	 */
	if (USE_HOME_RECALL != 1)
	{
		send_to_char("This option disabled!\n\r", ch);
		return;
	}

	if (ch->level < MIN_HOME_LEVEL)
	{
		sprintf(buf, "You must be level %d or greater to use this command.\n\r", MIN_HOME_LEVEL);
		send_to_char(buf, ch);
		return;
	}

	/*
	 * set home location with hrecall set
	 */
    if ( !str_cmp( arg, "set"))
    {
		ch->pcdata->hrecall = ch->in_room->vnum;
		send_to_char ("This is now your home recall.\n\r", ch);
		return;
	}

	location = ch->pcdata->hrecall;

	/*
	 * checks
	 * 1) not an NPC
	 * 2) already standing in the home recall point
	 * 3) not in a no recall room
	 * 4) not fighting
	 */
    if (IS_NPC(ch) && !IS_SET(ch->act,ACT_PET))
    {
		send_to_char("You are always home. NPC lives where they are.\n\r",ch);
		return;
    }

  	/* Be sure they are not currently home */
    if (( ch->in_room->vnum == ch->pcdata->hrecall ))
    {
		send_to_char("{RYou are at your home recall.\n\r", ch);
		return;
	}

    if ( IS_SET(ch->in_room->room_flags, ROOM_NO_RECALL))
    {
		send_to_char( "That is impossible in a no-recall area.\n\r", ch );
		return;
    }

    if ( ( victim = ch->fighting ) != NULL )
    {
	    sprintf( buf, "That is not possible while fighting!.\n\r");
	    send_to_char( buf, ch );
	    return;
	}

	/*
	 * recall penalties half move
	 */
    ch->move /= 2;
    act( "$n prays for transportation and disappears.", ch, NULL, NULL, TO_ROOM );
    char_from_room( ch );
    char_to_room( ch, get_room_index(location) );
    act( "$n appears in the room.", ch, NULL, NULL, TO_ROOM );
	send_to_char ("You return to your home recall spot.\n\r", ch);
    do_look( ch, "" );

}

/*
 * Allows PC to make and store a history.
 * by TAKA
 * (c) 2000 TAKA of the Ghost Dancer MUD Project
 */
void do_history( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];

    if ( argument[0] != '\0' )
    {
	buf[0] = '\0';
	smash_tilde( argument );

    	if (argument[0] == '-')
    	{
            int len;
            bool found = FALSE;

            if (ch->pcdata->history == NULL || ch->pcdata->history[0] == '\0')
            {
                send_to_char("No lines left to remove.\n\r",ch);
                return;
            }

  			strcpy(buf,ch->pcdata->history);

            for (len = strlen(buf); len > 0; len--)
            {
                if (buf[len] == '\r')
                {
                    if (!found)  /* back it up */
                    {
                        if (len > 0)
                            len--;
                        found = TRUE;
                    }
                    else /* found the second one */
                    {
                        buf[len + 1] = '\0';
						free_string(ch->pcdata->history);
						ch->pcdata->history = str_dup(buf);
						send_to_char( "Your history is:\n\r", ch );
						page_to_char( ch->pcdata->history ? ch->pcdata->history :
						    "(None).\n\r", ch );
                        return;
                    }
                }
            }
            buf[0] = '\0';
			free_string(ch->pcdata->history);
			ch->pcdata->history = str_dup(buf);
			send_to_char("{RHistory cleared.{x\n\r",ch);
			return;
        }

		if ( argument[0] == '+' )
		{
		    if ( ch->pcdata->history != NULL )
				strcat( buf, ch->pcdata->history );

			argument++;

			while ( isspace(*argument) )
				argument++;
		}

		if ( strlen(buf) >= 4096)
		{
			send_to_char( "History too long.\n\r", ch );
			return;
		}

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

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

/*
	TAKA     add skill pill
	1) get chance of success     number_test
	2) imbue the spell			 embue_spell
	3) do skill make pill		 do_mpill
	TAKA     add skill brew
	4) do skill brew potion		 do_brew
 */

/* 1 */
bool number_test(int num)
{
	if (number_range(1,100) <= num)
		return TRUE;
	else
		return FALSE;
}

/* 2 embue the spell into potion of pill */
void embue_spell( int sn, int level, CHAR_DATA * ch, void *vo )
{
	char      buf [ MAX_STRING_LENGTH ];
	OBJ_DATA *obj = ( OBJ_DATA * ) vo;
	int       free_slots, i, mana, class;
	int       snlev = 0, srate = 0;

	for ( free_slots = i = 1; i <= 4; i++ )
		if ( obj->value[i] != 0 )
			free_slots++;

	if ( free_slots > 4 )
	{
		act( "{R$p cannot contain any more spells.{x", ch, obj, NULL, TO_CHAR);
		return;
	}
	mana = 40;
	mana += skill_table[sn].min_mana;

	if ( !IS_NPC( ch ) && ch->mana < mana )
	{
		send_to_char( "{RYou don't have enough mana.{x\n\r", ch );
		return;
	}

	if ( IS_IMMORTAL(ch) )
		srate = 85 + ( MAX_LEVEL - (ch->level -1));
	else
		srate = (100 - (free_slots * 20));

	if ( number_percent() > ch->pcdata->learned[sn] )
	{
		send_to_char( "{RYou lost your concentration.{x\n\r", ch );
		ch->mana -= mana / 2;
		return;
	}
	ch->mana -= mana;
	obj->value[free_slots] = sn;

 	if ( number_percent() > srate )
	{
		sprintf( buf, "{RThe magic enchantment has failed: the {W%s {Rvanishes.{x\n\r",
		                item_name( obj->item_type ) );
		send_to_char( buf, ch );
		obj->value[0] = -1;
		return;
	}

	free_string( obj->short_descr );
	sprintf( buf, "{Ra {W%s {Rof {G", item_name( obj->item_type ) );
	for ( i = 1; i <= free_slots; i++ )
		if ( obj->value[ i ] != -1 )
		{
			strcat( buf, skill_table[ obj->value[ i ] ].name );
			( i != free_slots ) ? strcat( buf, ", " ) : strcat( buf, "{x" );
		}

	obj->short_descr = str_dup( buf );
	sprintf( buf, "%s %s", obj->name, item_name( obj->item_type ) );
	free_string( obj->name );
	obj->name = str_dup( buf );

	for (class = 0;class < MAX_CLASS;class++)
	{
		if(skill_table[sn].skill_level[class] < snlev)
		{
			snlev = skill_table[sn].skill_level[class];
		}
	 }

	if(obj->level < snlev) {obj->level = snlev; }
	sprintf( buf, "{RYou have imbued a new spell to the %s.{x\n\r", item_name( obj->item_type ) );
	send_to_char( buf, ch );
	return;
}

/* 3 make a pill */
void do_mpill( CHAR_DATA * ch,char *argument )
{
	OBJ_DATA  *pill;
	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];
	int        sn;

	if(IS_NPC(ch))
	{
		send_to_char("{RYou don't have any need for pills.{x\n\r",ch);
		return;
	}

	if(get_skill(ch,gsn_mpill) < 1)
	{
		send_to_char("Huh?\n\r",ch);
		return;
	}

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

	if ( arg1[0] == '\0' )
	{
		send_to_char( "{RMake a pill out of what spells?{x\n\r", ch );
		send_to_char( "{G  mpill {M<spell1> <spell2> <spell3> <spell4>{x\n\r", ch );
		return;
	}

	if ( ( sn = skill_lookup( arg1 ) ) < 0 )
	{
		sprintf( buf, "{RYou don't know any spells by that name {W%s.{x\n\r", arg1);
		send_to_char( buf, ch );
		return;
	}
	/* check spell selections 2,3,4 */
	if (( arg2[0] != '\0' ) && (( sn = skill_lookup( arg2 )) < 0 ))
	{
		sprintf( buf, "{RYou don't know any spells by that name {W%s.{x\n\r", arg2);
		send_to_char( buf, ch );
		return;
	}

	if (( arg3[0] != '\0' ) && (( sn = skill_lookup( arg3 )) < 0 ))
	{
		sprintf( buf, "{RYou don't know any spells by that name {W%s.{x\n\r", arg3);
		send_to_char( buf, ch );
		return;
	}


	if (( arg4[0] != '\0' ) && (( sn = skill_lookup( arg4 )) < 0 ))
	{
		sprintf( buf, "{RYou don't know any spells by that name {W%s.{x\n\r", arg4);
		send_to_char( buf, ch );
		return;
	}


	sn = skill_lookup( arg1 );
	if(!number_test(get_skill(ch,sn)))
	{
		send_to_char("{RYou don't know that spell well enough to make a pill of it!{x\n\r",ch);
		return;
	}

	if ( skill_table[sn].target != TAR_CHAR_DEFENSIVE
		&& skill_table[sn].target != TAR_CHAR_SELF
		&& skill_table[sn].target != TAR_OBJ_CHAR_DEF )
	{
		send_to_char( "{RYou cannot make a pill of that spell.{x\n\r", ch );
		return;
	}

	pill = create_object( get_obj_index( OBJ_VNUM_PILL ), 0 );
	pill->value[1]    = 0;
	pill->value[2]    = 0;
	pill->value[3]    = 0;
	pill->value[4]    = 0;

	if(!pill)
	{
		send_to_char("{RCould not find the pill object, please notify an 	IMP!{x\n\r",ch);
		return;
	}

	obj_to_char(pill,ch);
	send_to_char("{RYou begin focus your energy and mutter the words.{x\n\r",ch);
	act( "{W$n {Rbegins focusing and chanting.{x", ch, NULL, NULL, TO_ROOM);
	WAIT_STATE( ch, skill_table[ gsn_mpill ].beats );
	act( "{R$p appears suddenly.{x",ch, pill, NULL, TO_CHAR);
	act( "{R$p appears suddenly.{x",ch, pill, NULL, TO_ROOM);

	if ( !IS_NPC( ch ) && ( number_percent( ) > ch->pcdata->learned[gsn_mpill]
		|| number_percent( ) > ( ( get_curr_stat(ch,STAT_INT) - 13 ) * 5 +
 		( get_curr_stat(ch,STAT_WIS) - 13 ) * 3 ) ) )
	{
		act( "$p {Yexplodes {Rviolently{x!", ch, pill, NULL, TO_CHAR );
		act( "$p {Yexplodes {Rviolently{x!", ch, pill, NULL, TO_ROOM );
		extract_obj( pill );
		sn = skill_lookup( "energy drain" );
		damage( ch, ch, ch->max_hit / 10, sn, DAM_ENERGY, FALSE );
    	check_improve(ch,gsn_mpill,FALSE,1);
		return;
	}

	pill->level       = 1;
	pill->value[0]    = ch->level;
	if ( arg1[0] != '\0' )
	{
			sn = skill_lookup( arg1 );
			embue_spell( sn, ch->level, ch, pill );
			if (pill->value[0] == -1)
			{
				extract_obj( pill );
				return;
			}

	}
	if ( arg2[0] != '\0' )
	{
			sn = skill_lookup( arg2 );
			embue_spell( sn, ch->level, ch, pill );
			if (pill->value[0] == -1)
			{
				extract_obj( pill );
				return;
			}

	}
	if ( arg3[0] != '\0' )
	{
			sn = skill_lookup( arg3 );
			embue_spell( sn, ch->level, ch, pill );
			if (pill->value[0] == -1)
			{
				extract_obj( pill );
				return;
			}

	}
	if ( arg4[0] != '\0' )
	{
			sn = skill_lookup( arg4 );
			embue_spell( sn, ch->level, ch, pill );
			if (pill->value[0] == -1)
			{
				extract_obj( pill );
				return;
			}

	}

	check_improve(ch,gsn_mpill,TRUE,1);
	return;
}

/* 4 brew potion */
void do_brew( CHAR_DATA * ch,char *argument )
{
	OBJ_DATA  *potion;
	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];
	int        sn;

	if(IS_NPC(ch))
	{
		send_to_char("{RYou don't have any need for potions.{x\n\r",ch);
		return;
	}

	if(get_skill(ch,gsn_brew) < 1)
	{
		send_to_char("Huh?\n\r",ch);
		return;
	}

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

	if ( arg1[0] == '\0' )
	{
		send_to_char( "{RMake a potion out of what spells?{x\n\r", ch );
		send_to_char( "{G  brew {M<spell1> <spell2> <spell3> <spell4>{x\n\r", ch );
		return;
	}

	if ( ( sn = skill_lookup( arg1 ) ) < 0 )
	{
		sprintf( buf, "{RYou don't know any spells by that name {W%s.{x\n\r", arg1);
		send_to_char( buf, ch );
		return;
	}
	/* check spell selections 2,3,4 */
	if (( arg2[0] != '\0' ) && (( sn = skill_lookup( arg2 )) < 0 ))
	{
		sprintf( buf, "{RYou don't know any spells by that name {W%s.{x\n\r", arg2);
		send_to_char( buf, ch );
		return;
	}

	if (( arg3[0] != '\0' ) && (( sn = skill_lookup( arg3 )) < 0 ))
	{
		sprintf( buf, "{RYou don't know any spells by that name {W%s.{x\n\r", arg3);
		send_to_char( buf, ch );
		return;
	}


	if (( arg4[0] != '\0' ) && (( sn = skill_lookup( arg4 )) < 0 ))
	{
		sprintf( buf, "{RYou don't know any spells by that name {W%s.{x\n\r", arg4);
		send_to_char( buf, ch );
		return;
	}


	sn = skill_lookup( arg1 );
	if(!number_test(get_skill(ch,sn)))
	{
		send_to_char("{RYou don't know that spell well enough to make a potion of it!{x\n\r",ch);
		return;
	}

	if ( skill_table[sn].target != TAR_CHAR_DEFENSIVE
		&& skill_table[sn].target != TAR_CHAR_SELF
		&& skill_table[sn].target != TAR_OBJ_CHAR_DEF )
	{
		send_to_char( "{RYou cannot make a potion of that spell.{x\n\r", ch );
		return;
	}

	potion = create_object( get_obj_index( OBJ_VNUM_POTION ), 0 );
	potion->value[1]    = 0;
	potion->value[2]    = 0;
	potion->value[3]    = 0;
	potion->value[4]    = 0;

	if(!potion)
	{
		send_to_char("{RCould not find the potion object, please notify an 	IMP!{x\n\r",ch);
		return;
	}

	obj_to_char(potion,ch);
	send_to_char("{RYou begin focus your energy and mutter the words.{x\n\r",ch);
	act( "{W$n {Rbegins focusing and chanting.{x", ch, NULL, NULL, TO_ROOM);
	WAIT_STATE( ch, skill_table[ gsn_brew ].beats );
	act( "{R$p appears suddenly.{x",ch, potion, NULL, TO_CHAR);
	act( "{R$p appears suddenly.{x",ch, potion, NULL, TO_ROOM);

	if ( !IS_NPC( ch ) && ( number_percent( ) > ch->pcdata->learned[gsn_mpill]
		|| number_percent( ) > ( ( get_curr_stat(ch,STAT_INT) - 13 ) * 5 +
 		( get_curr_stat(ch,STAT_WIS) - 13 ) * 3 ) ) )
	{
		act( "$p {Yexplodes {Rviolently{x!", ch, potion, NULL, TO_CHAR );
		act( "$p {Yexplodes {Rviolently{x!", ch, potion, NULL, TO_ROOM );
		extract_obj( potion );
		sn = skill_lookup( "energy drain" );
		damage( ch, ch, ch->max_hit / 10, sn, DAM_ENERGY, FALSE );
    	check_improve(ch,gsn_brew,FALSE,1);
		return;
	}

	potion->level       = 1;
	potion->value[0]    = ch->level;
	if ( arg1[0] != '\0' )
	{
			sn = skill_lookup( arg1 );
			embue_spell( sn, ch->level, ch, potion );
			if (potion->value[0] == -1)
			{
				extract_obj( potion );
				return;
			}

	}
	if ( arg2[0] != '\0' )
	{
			sn = skill_lookup( arg2 );
			embue_spell( sn, ch->level, ch, potion );
			if (potion->value[0] == -1)
			{
				extract_obj( potion );
				return;
			}

	}
	if ( arg3[0] != '\0' )
	{
			sn = skill_lookup( arg3 );
			embue_spell( sn, ch->level, ch, potion );
			if (potion->value[0] == -1)
			{
				extract_obj( potion );
				return;
			}

	}
	if ( arg4[0] != '\0' )
	{
			sn = skill_lookup( arg4 );
			embue_spell( sn, ch->level, ch, potion );
			if (potion->value[0] == -1)
			{
				extract_obj( potion );
				return;
			}

	}

	check_improve(ch,gsn_brew,TRUE,1);
	return;
}

/* End make pill & brew TAKA     */