area/
build/testing/
log/
player/
player/backup/
/***************************************************************************
 *  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.                *
 *                                                                         *
 ***************************************************************************/

#include <glib.h>

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

#if defined(unix)
#include <unistd.h>
#endif

#include <errno.h>
#if defined(unix)
#include <sys/wait.h>
#endif
#include <time.h>
#include <merc.h>
#include <tables.h>
#include <olc.h>
#include <recycle.h>
#include <lookup.h>
#include <interp.h>
#include <recycle.h>

/* external procedures to get that damn copy over working -Spiral */
extern void init_copyover_descriptor args((DESCRIPTOR_DATA *dnew, int desc));
extern int flag_value			args ( ( const struct flag_type *flag_table, char *argument) );
extern char *flag_string		args ( ( const struct flag_type *flag_table, int bits ) );
extern void destroy_memory_chunck args(());

char * mprog_type_to_name ( int type );

/* Return TRUE if area changed, FALSE if not. */
#define REDIT( fun )		bool fun( CHAR_DATA *ch, char *argument )
#define OEDIT( fun )		bool fun( CHAR_DATA *ch, char *argument )
#define MEDIT( fun )		bool fun( CHAR_DATA *ch, char *argument )
#define AEDIT( fun )		bool fun( CHAR_DATA *ch, char *argument )
#define HEDIT( fun )		bool fun( CHAR_DATA *ch, char *argument )

/*IS SPELL SHIT*/

#define Stringify(x) Str(x)
#define Str(x) #x
static FILE *ispell_out;
static int ispell_pid = -1;
static int to[2],
from[2];
#define ISPELL_BUF_SIZE 1024

struct olc_help_type
{
	char *command;
	const void *structure;
	char *desc;
};



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."	 },
	{	"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." 	 },
	{	"container",	container_flags, "Container status."		 },
	{	"stance",	mob_fight_flags, "List of stances."		 },
	{	"furniture",	furniture_flags, "List of furniture flags."	 },
	{	"mob_con",	mob_con_flags,	 "List of Mob Control bits."     },
	{	NULL,		NULL,		 NULL				 }
};



/*****************************************************************************
 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 != NULL; 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].function != NULL; spec++)
    {
	sprintf( buf, "%-19.18s", &spec_table[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 != NULL; 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 != NULL; 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 == liq_table )
	    {
	        show_liqlist( ch );
	        return FALSE;
	    }
	    else
	    if ( help_table[cnt].structure == attack_table )
	    {
	        show_damlist( 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, (const flag_type*)help_table[cnt].structure );
				return FALSE;
			}
		}
	}
	
	show_help( ch, "" );
	return FALSE;
}

REDIT( redit_rlist )
{
	ROOM_INDEX_DATA	*pRoomIndex;
	AREA_DATA		*pArea;
	char		buf  [ MAX_STRING_LENGTH   ];
	GString		*buf1;
	char		arg  [ MAX_INPUT_LENGTH    ];
	bool found;
	int vnum;
	int  col = 0;
	
	one_argument( argument, arg );
	
	pArea = ch->in_room->area;
	buf1=g_string_new("");
/*    buf1[0] = '\0'; */
	found   = FALSE;
	
	for ( vnum = pArea->min_vnum; vnum <= pArea->max_vnum; vnum++ )
	{
		if ( ( pRoomIndex = get_room_index( vnum ) ) )
		{
			found = TRUE;
			sprintf( buf, "[%5d] %-17.16s",
				vnum, capitalize( pRoomIndex->name ) );
			buf1 = g_string_append( buf1, buf );
			if ( ++col % 3 == 0 )
				buf1 = g_string_append( buf1, "\n\r" );
		}
	}
	
	if ( !found )
	{
		send_to_char( "Room(s) not found in this area.\n\r", ch);
		return FALSE;
	}
	
	if ( col % 3 != 0 )
		buf1 = g_string_append( buf1, "\n\r" );
	
	page_to_char(buf1->str, ch );
	g_string_free(buf1,TRUE);
	return FALSE;
}

REDIT( redit_mlist )
{
	MOB_INDEX_DATA	*pMobIndex;
	AREA_DATA		*pArea;
	char		buf  [ MAX_STRING_LENGTH   ];
	GString		*buf1;
	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;
	}
	
	buf1=g_string_new("");
	pArea = ch->in_room->area;
/*    buf1[0] = '\0'; */
	fAll    = !str_cmp( arg, "all" );
	found   = FALSE;
	
	for ( vnum = pArea->min_vnum; vnum <= pArea->max_vnum; vnum++ )
	{
		if ( ( pMobIndex = get_mob_index( vnum ) ) != NULL )
		{
			if ( fAll || is_name( arg, pMobIndex->player_name ) )
			{
				found = TRUE;
				sprintf( buf, "[%5d] %-17.16s",
					pMobIndex->vnum, capitalize( pMobIndex->short_descr ) );
				buf1 = g_string_append( buf1, buf );
				if ( ++col % 3 == 0 )
					buf1 = g_string_append( buf1, "\n\r" );
			}
		}
	}
	
	if ( !found )
	{
		send_to_char( "Mobile(s) not found in this area.\n\r", ch);
		return FALSE;
	}
	
	if ( col % 3 != 0 )
		buf1 = g_string_append( buf1, "\n\r" );
	
	page_to_char( buf1->str, ch );
	g_string_free(buf1,TRUE);
	return FALSE;
}



REDIT( redit_olist )
{
	OBJ_INDEX_DATA	*pObjIndex;
	AREA_DATA		*pArea;
	char		buf  [ MAX_STRING_LENGTH   ];
	GString		*buf1;
	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=g_string_new("");
/*    buf1[0] = '\0'; */
	fAll    = !str_cmp( arg, "all" );
	found   = FALSE;
	
	for ( vnum = pArea->min_vnum; vnum <= pArea->max_vnum; 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 ) );
				buf1 = g_string_append( buf1, buf );
				if ( ++col % 3 == 0 )
					buf1 = g_string_append( buf1, "\n\r" );
			}
		}
	}
	
	if ( !found )
	{
		send_to_char( "Object(s) not found in this area.\n\r", ch);
		return FALSE;
	}
	
	if ( col % 3 != 0 )
		buf1 = g_string_append( buf1, "\n\r" );
	
	page_to_char( buf1->str, ch );
	g_string_free(buf1,TRUE);
	return FALSE;
}



REDIT( redit_mshow )
{
	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 ) )
	{
		send_to_char( "REdit: Ingresa un numero.\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; 
}



REDIT( redit_oshow )
{
	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 ) )
	{
		send_to_char( "REdit: Ingresa un numero.\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->min_vnum && pArea->min_vnum <= upper )
			||   ( lower <= pArea->max_vnum && pArea->max_vnum <= upper ) )
			++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->min_vnum
			&& vnum <= pArea->max_vnum )
			return pArea;
	}
	
	return 0;
}



/*
 * Area Editor Functions.
 */
AEDIT( aedit_show )
{
	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 );
	
#if 0  /* ROM OLC */
	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 );
#endif /* ROM */
	
	sprintf( buf, "File:     %s\n\r", pArea->file_name );
	send_to_char( buf, ch );
	
	sprintf( buf, "Vnums:    [%d-%d]\n\r", pArea->min_vnum, pArea->max_vnum );
	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, "Credits : [%s]\n\r", pArea->credits );
	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;
}



AEDIT( aedit_reset )
{
	AREA_DATA *pArea;
	
	EDIT_AREA(ch, pArea);
	
	reset_area( pArea );
	send_to_char( "Area reset.\n\r", ch );
	
	return FALSE;
}



AEDIT( aedit_create )
{
	AREA_DATA *pArea;
	
	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 FALSE;
}



AEDIT( aedit_name )
{
	AREA_DATA *pArea;
	
	EDIT_AREA(ch, pArea);
	
	if ( argument[0] == '\0' )
	{
		send_to_char( "Syntax:   name [$name]\n\r", ch );
		return FALSE;
	}
	
	pArea->name = g_strdup( argument );
	
	send_to_char( "Name set.\n\r", ch );
	return TRUE;
}

AEDIT( aedit_credits )
{
	AREA_DATA *pArea;
	
	EDIT_AREA(ch, pArea);
	
	if ( argument[0] == '\0' )
	{
		send_to_char( "Syntax:   credits [$credits]\n\r", ch );
		return FALSE;
	}
	
	pArea->credits = g_strdup( argument );
	
	send_to_char( "Credits set.\n\r", ch );
	return TRUE;
}


AEDIT( aedit_file )
{
	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;
		}
	}    
	
	strcat( file, ".are" );
	pArea->file_name = g_strdup( file );
	
	send_to_char( "Filename set.\n\r", ch );
	return TRUE;
}



AEDIT( aedit_age )
{
	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 [#xage]\n\r", ch );
		return FALSE;
	}
	
	pArea->age = atoi( age );
	
	send_to_char( "Age set.\n\r", ch );
	return TRUE;
}


#if 0 /* ROM OLC */
AEDIT( aedit_recall )
{
	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 [#xrvnum]\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;
}
#endif /* ROM OLC */


AEDIT( aedit_security )
{
	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 [#xlevel]\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;
}



AEDIT( aedit_builder )
{
	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' )
		{
			pArea->builders = g_strdup("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 );
		pArea->builders = g_strdup(string_proper( buf ));
		
		send_to_char( "Builder added.\n\r", ch );
		send_to_char( pArea->builders,ch);
		return TRUE;
	}
	
	return FALSE;
}



AEDIT( aedit_vnum )
{
	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 [#xlower] [#xupper]\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;
	}
	
	if ( !check_range( atoi( lower ), atoi( upper ) ) )
	{
		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->min_vnum = 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->max_vnum = iupper;
	send_to_char( "Upper vnum set.\n\r", ch );
	
	return TRUE;
}



AEDIT( aedit_lvnum )
{
	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:  min_vnum [#xlower]\n\r", ch );
		return FALSE;
	}
	
	if ( ( ilower = atoi( lower ) ) > ( iupper = pArea->max_vnum ) )
	{
		send_to_char( "AEdit:  Value must be less than the max_vnum.\n\r", 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->min_vnum = ilower;
	send_to_char( "Lower vnum set.\n\r", ch );
	return TRUE;
}



AEDIT( aedit_uvnum )
{
	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:  max_vnum [#xupper]\n\r", ch );
		return FALSE;
	}
	
	if ( ( ilower = pArea->min_vnum ) > ( iupper = atoi( upper ) ) )
	{
		send_to_char( "AEdit:  Upper must be larger then lower.\n\r", 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->max_vnum = iupper;
	send_to_char( "Upper vnum set.\n\r", ch );
	
	return TRUE;
}



/*
 * Room Editor Functions.
 */
REDIT( redit_show )
{
	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;
	MPROG_LIST *list;
	
	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->heal_rate != 100 || pRoom->mana_rate != 100 )
    {
	sprintf( buf, "Health rec: [%d]\n\rMana rec  : [%d]\n\r",
		pRoom->heal_rate , pRoom->mana_rate );
	strcat( buf1, buf );
    }

    if ( pRoom->clan > 0 )
    {
	sprintf( buf, "Clan      : [%d] %s\n\r",
		pRoom->clan,
		clan_table[pRoom->clan].name );
	strcat( buf1, buf );
    }

    if ( !IS_NULLSTR(pRoom->owner) )
    {
	sprintf( buf, "Owner     : [%s]\n\r", pRoom->owner );
	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->str, 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->str, 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,      /* ROM OLC */
				pexit->key );
			strcat( buf1, buf );
			
	    /*
	     * Format up the exit info.
	     * Capitalize all flags that are not part of the reset info.
	     */
			str_cpy( 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] = UPPER(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 );
			}
		}
	}
	
	if ( pRoom->mprogs )
	{
	int cnt;

	sprintf(buf, "\n\rMUDPrograms for [%5d]:\n\r", pRoom->vnum);
	send_to_char( buf, ch );

	for (cnt=0, list=pRoom->mprogs; list; list=list->next)
	{
		if (cnt ==0)
		{
			send_to_char ( " Number Vnum Trigger Phrase\n\r", ch );
			send_to_char ( " ------ ---- ------- ------\n\r", ch );
		}

		sprintf(buf, "[%5d] %4d %7s %s\n\r", cnt,
			list->vnum,mprog_type_to_name(list->trig_type),
			list->trig_phrase->str);
		send_to_char( buf, ch );
		cnt++;
	}
	}
	
	send_to_char( buf1, ch );
	return FALSE;
}

/*
 * redit_copy function thanks to Zanthras of Mystical Realities MUD.
 */
REDIT( redit_copy )
{
	ROOM_INDEX_DATA	*pRoom;
	ROOM_INDEX_DATA	*pRoom2; /* Room to copy */
	int vnum;
	
	if ( argument[0] == '\0' )
	{
		send_to_char("Syntax: copy <vnum> \n\r",ch);
		return FALSE;
	}
	
	if ( !is_number(argument) )
	{
		send_to_char("REdit: You must enter a number (vnum).\n\r",ch);
		return FALSE;
	}
	else /* argument is a number */
	{
		vnum = atoi(argument);
		if( !( pRoom2 = get_room_index(vnum) ) )
		{
			send_to_char("REdit: That room does not exist.\n\r",ch);
			return FALSE;
		}
	}
	
	EDIT_ROOM(ch, pRoom);
	
	pRoom->description = g_strdup( pRoom2->description );
	
	pRoom->name = g_strdup(pRoom2->name );
	
    /* sector flags */
	pRoom->sector_type = pRoom2->sector_type;
	
    /* room flags */
	pRoom->room_flags = pRoom2->room_flags;
	
	pRoom->owner = g_strdup( pRoom2->owner );
	
	pRoom->extra_descr = pRoom2->extra_descr;
	
	send_to_char( "Room info copied.", ch );
	return TRUE;
}



/* 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];
	int  value;
	
	EDIT_ROOM(ch, pRoom);
	
    /*
     * Set the exit flags, needs full argument.
     * ----------------------------------------
     */
	if ( ( value = flag_value( exit_flags, argument ) ) != NO_FLAG )
	{
		ROOM_INDEX_DATA *pToRoom;
		sh_int rev;                                    /* ROM OLC */
		
		if ( !pRoom->exit[door] )
		{
			send_to_char("Exit does not exist.\n\r",ch);
			return FALSE;
		}
	 /*   pRoom->exit[door] = new_exit(); */
		
	/*
	 * This room.
	 */
		TOGGLE_BIT(pRoom->exit[door]->rs_flags,  value);
	/* Don't toggle exit_info because it can be changed by players. */
		pRoom->exit[door]->exit_info = pRoom->exit[door]->rs_flags;
		
	/*
	 * Connected room.
	 */
		pToRoom = pRoom->exit[door]->to_room;     /* ROM OLC */
		rev = rev_dir[door];
		
		if (pToRoom->exit[rev] != NULL)
		{
			TOGGLE_BIT(pToRoom->exit[rev]->rs_flags,  value);
			TOGGLE_BIT(pToRoom->exit[rev]->exit_info, value);
		}
		
		send_to_char( "Exit flag toggled.\n\r", ch );
		return TRUE;
	}
	
    /*
     * Now parse the arguments.
     */
	argument = one_argument( argument, command );
	one_argument( argument, arg );
	
	if ( command[0] == '\0' && argument[0] == '\0' )	/* Move command. */
	{
		move_char( ch, door );                    /* ROM OLC */
		return FALSE;
	}
	
	if ( command[0] == '?' )
	{
		do_help( ch, "EXIT" );
		return FALSE;
	}
	
	if ( !str_cmp( command, "delete" ) )
	{
		ROOM_INDEX_DATA *pToRoom;
		sh_int rev;                                     /* ROM OLC */
		
		if ( !pRoom->exit[door] )
		{
			send_to_char( "REdit:  Cannot delete a null exit.\n\r", ch );
			return FALSE;
		}
		
	/*
	 * Remove ToRoom Exit.
	 */
		rev = rev_dir[door];
		pToRoom = pRoom->exit[door]->to_room;       /* ROM OLC */
		
		if ( pToRoom != NULL )
		{	
			if ( pToRoom->exit[rev] != 0 )
			{
				free_exit( pToRoom->exit[rev] );
				pToRoom->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;
	}
	
	if ( !str_cmp( command, "link" ) )
	{
		EXIT_DATA *pExit;
		
		if ( arg[0] == '\0' || !is_number( arg ) )
		{
			send_to_char( "Syntax:  [direction] link [vnum]\n\r", ch );
			return FALSE;
		}
		
		value = atoi( arg );
		
		if ( !get_room_index( value ) )
		{
			send_to_char( "REdit:  Cannot link to non-existant room.\n\r", ch );
			return FALSE;
		}
		
		if ( !IS_BUILDER( ch, get_room_index( value )->area ) )
		{
			send_to_char( "REdit:  Cannot link to that area.\n\r", ch );
			return FALSE;
		}
		
		if ( get_room_index( value )->exit[rev_dir[door]] )
		{
			send_to_char( "REdit:  Remote side's exit already exists.\n\r", ch );
			return FALSE;
		}
		
		if ( !pRoom->exit[door] )
		{
			pRoom->exit[door] = new_exit();
		}
		
		pRoom->exit[door]->to_room = get_room_index( value );   /* ROM OLC */
		pRoom->exit[door]->orig_door = door;
		
		pRoom->exit[door]->vnum = value;     
		
		pRoom                   = get_room_index( value );
		door                    = rev_dir[door];
		pExit                   = new_exit();
		pExit->to_room       = ch->in_room;
		pExit->vnum             = ch->in_room->vnum;    
		pExit->orig_door	= door;
		pRoom->exit[door]       = pExit;
		
		send_to_char( "Two-way link established.\n\r", ch );
		return TRUE;
	}
	
	if ( !str_cmp( command, "dig" ) )
	{
		char buf[MAX_STRING_LENGTH];
		
		if ( arg[0] == '\0' || !is_number( arg ) )
		{
			send_to_char( "Syntax: [direction] dig <vnum>\n\r", ch );
			return FALSE;
		}
		
		redit_create( ch, arg );
		sprintf( buf, "link %s", arg );
		change_exit( ch, buf, door);
		return TRUE;
	}
	
	if ( !str_cmp( command, "room" ) )
	{
		if ( arg[0] == '\0' || !is_number( arg ) )
		{
			send_to_char( "Syntax:  [direction] room [vnum]\n\r", ch );
			return FALSE;
		}
		
		if ( !pRoom->exit[door] )
		{
			pRoom->exit[door] = new_exit();
		}
		
		value = atoi( arg );
		
		if ( !get_room_index( value ) )
		{
			send_to_char( "REdit:  Cannot link to non-existant room.\n\r", ch );
			return FALSE;
		}
		
		pRoom->exit[door]->to_room = get_room_index( value );    /* ROM OLC */
		pRoom->exit[door]->orig_door = door;
		pRoom->exit[door]->vnum = value;                 
		
		send_to_char( "One-way link established.\n\r", ch );
		return TRUE;
	}
	
	if ( !str_cmp( command, "key" ) )
	{
		if ( arg[0] == '\0' || !is_number( arg ) )
		{
			send_to_char( "Syntax:  [direction] key [vnum]\n\r", ch );
			return FALSE;
		}
		
		if ( !pRoom->exit[door] )
		{
			send_to_char("Exit does not exist.\n\r",ch);
			return FALSE;
		}
		
/*	if ( !pRoom->exit[door] )
	{
	    pRoom->exit[door] = new_exit();
	} */
		
		value = atoi( arg );
		
		if ( !get_obj_index( value ) )
		{
			send_to_char( "REdit:  Item doesn't exist.\n\r", ch );
			return FALSE;
		}
		
		if ( get_obj_index( atoi( argument ) )->item_type != ITEM_KEY )
		{
			send_to_char( "REdit:  Key doesn't exist.\n\r", ch );
			return FALSE;
		}
		
		pRoom->exit[door]->key = value;
		
		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 );
			send_to_char( "         [direction] name none\n\r", ch );
			return FALSE;
		}
		
		if ( !pRoom->exit[door] )
		{
			send_to_char("Exit does not exist.\n\r",ch);
			return FALSE;
		}
		
/*	if ( !pRoom->exit[door] )
	{
	    pRoom->exit[door] = new_exit();
	} */
		
		if (str_cmp(arg,"none"))
			pRoom->exit[door]->keyword = g_strdup( arg );
		else
			pRoom->exit[door]->keyword = g_strdup( "" );
		
		send_to_char( "Exit name set.\n\r", ch );
		return TRUE;
	}
	
	if ( !str_prefix( command, "description" ) )
	{
		if ( arg[0] == '\0' )
		{
			if ( !pRoom->exit[door] )
			{
			        send_to_char("Exit does not exist.\n\r",ch);
				return FALSE;
			}
			
/*	    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;
	}
	
	return FALSE;
}



REDIT( redit_north )
{
	if ( change_exit( ch, argument, DIR_NORTH ) )
		return TRUE;
	
	return FALSE;
}



REDIT( redit_south )
{
	if ( change_exit( ch, argument, DIR_SOUTH ) )
		return TRUE;
	
	return FALSE;
}



REDIT( redit_east )
{
	if ( change_exit( ch, argument, DIR_EAST ) )
		return TRUE;
	
	return FALSE;
}



REDIT( redit_west )
{
	if ( change_exit( ch, argument, DIR_WEST ) )
		return TRUE;
	
	return FALSE;
}



REDIT( redit_up )
{
	if ( change_exit( ch, argument, DIR_UP ) )
		return TRUE;
	
	return FALSE;
}



REDIT( redit_down )
{
	if ( change_exit( ch, argument, DIR_DOWN ) )
		return TRUE;
	
	return FALSE;
}



REDIT( redit_ed )
{
	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		=   g_strdup( keyword );
		ed->description		=   g_strdup( "" );
		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;
		}
		
		ed->description = format_string( ed->description );
		
		send_to_char( "Extra description formatted.\n\r", ch );
		return TRUE;
	}
	
	redit_ed( ch, "" );
	return FALSE;
}



REDIT( redit_create )
{
	AREA_DATA *pArea;
	ROOM_INDEX_DATA *pRoom;
	int value;
	int iHash;
	
	EDIT_ROOM(ch, pRoom);
	
	value = atoi( argument );
	
	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;
}



REDIT( redit_name )
{
	ROOM_INDEX_DATA *pRoom;
	
	EDIT_ROOM(ch, pRoom);
	
	if ( argument[0] == '\0' )
	{
		send_to_char( "Syntax:  name [name]\n\r", ch );
		return FALSE;
	}
	pRoom->name = g_strdup( argument );
	
	send_to_char( "Name set.\n\r", ch );
	return TRUE;
}



REDIT( redit_desc )
{
	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;
}
/*
REDIT( redit_heal )
{
    ROOM_INDEX_DATA *pRoom;
    
    EDIT_ROOM(ch, pRoom);
    
    if (is_number(argument))
       {
          pRoom->heal_rate = atoi ( argument );
          send_to_char ( "Heal rate set.\n\r", ch);
          return TRUE;
       }

    send_to_char ( "Syntax : heal <#xnumber>\n\r", ch);
    return FALSE;
}       

REDIT( redit_mana )
{
    ROOM_INDEX_DATA *pRoom;
    
    EDIT_ROOM(ch, pRoom);
    
    if (is_number(argument))
       {
          pRoom->mana_rate = atoi ( argument );
          send_to_char ( "Mana rate set.\n\r", ch);
          return TRUE;
       }

    send_to_char ( "Syntax : mana <#xnumber>\n\r", ch);
    return FALSE;
}       

REDIT( redit_clan )
{
    ROOM_INDEX_DATA *pRoom;

    EDIT_ROOM(ch, pRoom);
    
    pRoom->clan = clan_lookup(argument);
    
    send_to_char ( "Clan set.\n\r", ch);
    return TRUE;
}
*/      
REDIT( redit_format )
{
	ROOM_INDEX_DATA *pRoom;
	
	EDIT_ROOM(ch, pRoom);
	
	pRoom->description = format_string( pRoom->description );
	
	send_to_char( "String formatted.\n\r", ch );
	return TRUE;
}



REDIT( redit_mreset )
{
	ROOM_INDEX_DATA	*pRoom;
	MOB_INDEX_DATA	*pMobIndex;
	CHAR_DATA		*newmob;
	char		arg [ MAX_INPUT_LENGTH ];
	char		arg2 [ MAX_INPUT_LENGTH ];
	
	RESET_DATA		*pReset;
	char		output [ MAX_STRING_LENGTH ];
	
	EDIT_ROOM(ch, pRoom);
	
	argument = one_argument( argument, arg );
	argument = one_argument( argument, arg2 );
	
	if ( arg[0] == '\0' || !is_number( arg ) )
	{
		send_to_char ( "Syntax:  mreset <vnum> <max #x> <mix #x>\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( arg2 ) ? atoi( arg2 ) : MAX_MOB;
	pReset->arg3	= pRoom->vnum;
	pReset->arg4	= is_number( argument ) ? atoi (argument) : 1;
	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;
}



REDIT( redit_oreset )
{
	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;
		pReset->arg4	= 0;
		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;
			pReset->arg4	= 1;
			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->str ),
				newobj->pIndexData->vnum,
				to_obj->short_descr->str,
				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->str,
					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 || obj->value[2] == 999 ) /* ROM OLC */
				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_PET_FOOD:
			sprintf( buf, "[v0] Hunger:  [%d]\n\r", obj->value[0] );
			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_PORTAL:
			sprintf( buf,
				"[v0] Goes To:         [%d]\n\r"
				"[v1] Charges:         [%d]\n\r"
				"[v2] Is Closed:       [%d]\n\r"
				"[v3] Room in:         [%d]\n\r",
				obj->value[0],
				obj->value[1],
				obj->value[2],
				obj->value[3] );
			send_to_char( buf, ch);
			break;
        case ITEM_SLOT_MACHINE:
             sprintf( buf, "[v0] Gold Cost:       [%d]\n\r"
                   "[v1] Jackpot Value:   [%d]\n\r"
                   "[v2] Number of Bars:  [%d]\n\r"
                   "[v3] Partial Jackpot:  [%d]\n\r", obj->value[0], obj->value[1], obj->value[2], obj->value[3]);
             send_to_char(buf, ch);
            break;

	   case ITEM_TOOL:
			sprintf( buf,
				"[v0] Tool Type:         [%d]\n\r",
		   	obj->value[0] );
			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;
			
/* ARMOR for ROM */
			
		case ITEM_ARMOR:
			sprintf( buf,
				"[v0] Afffect         [%d]\n\r"
				"[v1] Unused          [%d]\n\r"
				"[v2] Unused          [%d]\n\r"
				"[v3] Unused          [%d]\n\r",
				obj->value[0],
				obj->value[1],
				obj->value[2],
				obj->value[3] );
			send_to_char( buf, ch );
			break;
			
/* WEAPON changed in ROM: */
/* I had to split the output here, I have no idea why, but it helped -- Hugin */
/* It somehow fixed a bug in showing scroll/pill/potions too ?! */
		case ITEM_WEAPON:
			sprintf( buf, "\n\r[v0] Not Used: [%d]\n\r"
				"[v1] Not Used: [%d]\n\r"
				"[v2] Not Used: [%d]\n\r"
				"[v3] Damage Type: [%s]\n\r",
				obj->value[0],
				obj->value[1],
				obj->value[2],
				attack_table[obj->value[3]].name );
			send_to_char( buf, ch );
			break;
			
		case ITEM_CONTAINER:
			sprintf( buf,
				"[v0] Weight:     [%d kg]\n\r"
				"[v1] Flags:      [%s]\n\r"
				"[v2] Key:     %s [%d]\n\r"
				"[v3] Capacity    [%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],
				obj->value[3]);
			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],
				liq_table[obj->value[2]].liq_name,
				obj->value[3] != 0 ? "Yes" : "No" );
			send_to_char( buf, ch );
			break;
			
		case ITEM_FOUNTAIN:
			sprintf( buf,
				"[v0] Liquid Total: [%d]\n\r"
				"[v1] Liquid Left:  [%d]\n\r"
				"[v2] Liquid:	    %s\n\r",
				obj->value[0],
				obj->value[1],
				liq_table[obj->value[2]].liq_name );
			send_to_char( buf,ch );
			break;
			
		case ITEM_FOOD:
			sprintf( buf,
				"[v0] Food hours: [%d]\n\r"
				"[v1] Full hours: [%d]\n\r"
				"[v3] Poisoned:   %s\n\r",
				obj->value[0],
				obj->value[1],
				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;
		case ITEM_FURNITURE:          
	    		sprintf( buf,
	       		"[v0] Max people:      [%d]\n\r"
	        	"[v1] Max weight:      [%d]\n\r"
	        	"[v2] Furniture Flags: %s\n\r"
	        	"[v3] Heal bonus:      [%d]\n\r",
	        	obj->value[0],
	        	obj->value[1],
	        	flag_string( furniture_flags, obj->value[2]),
	        	obj->value[3] );
	    	send_to_char( buf, ch );
	    break;
	}
	
	return;
}



bool set_obj_values( CHAR_DATA *ch, OBJ_INDEX_DATA *pObj, int value_num, char *argument)
{
	int val;
	switch( pObj->item_type )
	{
		default:
			break;
        case ITEM_SLOT_MACHINE:
            switch (value_num)
            {
                case 0:
                    send_to_char( "GOLD COST SET.\n\r\n\r", ch);
                    pObj->value[0] = atoi( argument );
                    break;
                case 1:
                    send_to_char( "JACKPOT VALUE.\n\r\n\r", ch);
                    pObj->value[1] = atoi( argument );
                    break;
                case 2:
                    send_to_char( "NUMBER OF BARS SET.\n\r\n\r", ch);
                    pObj->value[2] = atoi( argument );
                    break;
                case 3:
                    send_to_char( "PARTIAL JACKPOT SET.\n\r\n\r", ch);
                    pObj->value[3] = atoi( argument );
                    break;
             }
             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_PET_FOOD:
        	switch ( value_num )
			{
				default:
					do_help( ch, "ITEM_PET_FOOD" );
					return FALSE;
				case 0:
					send_to_char( "Hunger Set.\n\r\n\r", ch );
					pObj->value[0] = 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;
				case 4:
					send_to_char( "SPELL TYPE 4 SET.\n\r\n\r", ch );
					pObj->value[4] = skill_lookup( argument );
					break;
			}
			break;
			
/* ARMOR for ROM: */
			
		case ITEM_ARMOR:
			switch ( value_num )
			{
				default:
					do_help( ch, "ITEM_ARMOR" );
					return FALSE;
				case 0:
					send_to_char( "AC PIERCE SET.\n\r\n\r", ch );
					pObj->value[0] = atoi( argument );
					break;
				case 1:
					send_to_char( "AC BASH SET.\n\r\n\r", ch );
					pObj->value[1] = atoi( argument );
					break;
				case 2:
					send_to_char( "AC SLASH SET.\n\r\n\r", ch );
					pObj->value[2] = atoi( argument );
					break;
				case 3:
					send_to_char( "AC EXOTIC SET.\n\r\n\r", ch );
					pObj->value[3] = atoi( argument );
					break;
			}
			break;
			
/* WEAPONS changed in ROM */
			
		case ITEM_WEAPON:
			switch ( value_num )
			{
				default:
					do_help( ch, "ITEM_WEAPON" );
					return FALSE;
				case 0:
					send_to_char( "Value Set.\n\r\n\r", ch );
					pObj->value[0] = atoi( argument );
					break;
				case 1:
					send_to_char( "Value Set.\n\r\n\r", ch );
					pObj->value[1] = atoi( argument );
					break;
				case 2:
					send_to_char( "Value Set.\n\r\n\r", ch );
					pObj->value[2] = atoi( argument );
					break;
				case 3:
					for (val = 0; attack_table[val].settable != 0;val++)
					{
						if (!str_prefix(argument,attack_table[val].name))
						{
							send_to_char( "Value Set.\n\r\n\r", ch );
							pObj->value[3] = val;
							return TRUE;
						}
					}
					send_to_char("Weapon type not found!\n\r",ch);
					return FALSE;
					break;
			}
			break;
			
		case ITEM_PORTAL:
			switch ( value_num )
			{
				default:
					do_help(ch, "ITEM_PORTAL" );
					return FALSE;
					
				case 0:
					send_to_char( "Room to Set.\n\r\n\r", ch);
					pObj->value[0] = atoi ( argument );
					break;
				case 1:
					send_to_char( "Charges Set.\n\r\n\r", ch);
					pObj->value[1] = atoi( argument );
					break;
				case 2:
					send_to_char( "Closed SET.\n\r\n\r", ch);
					pObj->value[1] = atoi ( argument );
					break;
				case 3:
					send_to_char( "In Room SET.\n\r\n\r", ch);
					pObj->value[3] = atoi ( argument );
					break;
			}
			break;
		case ITEM_FURNITURE:
			switch ( value_num )
			{
				default:
					do_help( ch, "ITEM_FURNITURE" );
					return FALSE;
					
				case 0:
					send_to_char( "NUMBER OF PEOPLE SET.\n\r\n\r", ch);
					pObj->value[0] = atoi ( argument );
					break;
				case 1:
					send_to_char( "MAX WEIGHT SET.\n\r\n\r", ch);
					pObj->value[1] = atoi ( argument );
					break;
				case 2:
					send_to_char( "FURNITURE FLAGS TOGGLED.\n\r\n\r", ch);
					pObj->value[2] ^= (flag_value( furniture_flags, argument ) != NO_FLAG
						? flag_value( furniture_flags, argument ) : 0);
					break;
				case 3:
					send_to_char( "HEAL BONUS SET.\n\r\n\r", ch);
					pObj->value[3] = atoi ( argument );
					break;
				case 4:
					send_to_char( "MANA BONUS SET.\n\r\n\r", ch);
					pObj->value[4] = atoi ( 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;
				case 3:
					send_to_char( "CONTAINER MAX WEIGHT SET.\n\r", ch);
					pObj->value[3] = atoi( argument );
					break;
				case 4:
					send_to_char( "WEIGHT MULTIPLIER SET.\n\r\n\r", ch );
					pObj->value[4] = atoi ( argument );
					break;
			}
			break;
			
		case ITEM_DRINK_CON:
			switch ( value_num )
			{
				default:
					do_help( ch, "ITEM_DRINK" );
/* OLC		    do_help( ch, "liquids" );    */
					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 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_FOUNTAIN:
			switch (value_num)
			{
				default:
					do_help( ch, "ITEM_FOUNTAIN" );
/* OLC		    do_help( ch, "liquids" );    */
					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;
			}
			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 1:
					send_to_char( "HOURS OF FULL SET.\n\r\n\r", ch );
					pObj->value[1] = 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_TOOL: 
		    switch ( value_num )
			{
				default:
					do_help( ch, "ITEM_FOOD" );
					return FALSE;
				case 0:
					send_to_char( "OK.\n\r\n\r", ch );
					pObj->value[0] = atoi( argument );
					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;
				case 1:
					send_to_char( "SILVER AMOUNT SET.\n\r\n\r", ch );
					pObj->value[1] = atoi( argument );
					break;
			}
			break;
	}
	
	show_obj_values( ch, pObj );
	
	return TRUE;
}



OEDIT( oedit_show )
{
	OBJ_INDEX_DATA *pObj;
	AFFECT_DATA *paf;
	char buf[MAX_STRING_LENGTH];
	int cnt;
	MPROG_LIST *list;
	
	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, "Material:    [%s]\n\r",              
	pObj->material );
    send_to_char( buf, ch );
*/
	
	sprintf( buf, "Condition:   [%5d]\n\r",               /* ROM */
		pObj->condition );
	send_to_char( buf, ch );
	
	sprintf( buf, "Weight:      [%5d]\n\rCost:        [%5d]\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 );
	
	if ( pObj->mprogs )
	{
	int cnt;

	sprintf(buf, "\n\rMUDPrograms for [%5d]:\n\r", pObj->vnum);
	send_to_char( buf, ch );

	for (cnt=0, list=pObj->mprogs; list; list=list->next)
	{
		if (cnt ==0)
		{
			send_to_char ( " Number Vnum Trigger Phrase\n\r", ch );
			send_to_char ( " ------ ---- ------- ------\n\r", ch );
		}

		sprintf(buf, "[%5d] %4d %7s %s\n\r", cnt,
			list->vnum,mprog_type_to_name(list->trig_type),
			list->trig_phrase->str);
		send_to_char( buf, ch );
		cnt++;
	}
	}
	
	return FALSE;
}


/*
 * oedit_copy function thanks to Zanthras of Mystical Realities MUD.
 */
OEDIT( oedit_copy )
{
	OBJ_INDEX_DATA *pObj;
	OBJ_INDEX_DATA *pObj2; /* The object to copy */
	int vnum, i;
	
	if ( argument[0] == '\0' )
	{
		send_to_char("Syntax: copy <vnum> \n\r",ch);
		return FALSE;
	}
	
	if ( !is_number(argument) )
	{
		send_to_char("OEdit: You must enter a number (vnum).\n\r",ch);
		return FALSE;
	}
	else /* argument is a number */
	{
		vnum = atoi(argument);
		if( !( pObj2 = get_obj_index(vnum) ) )
		{
			send_to_char("OEdit: That object does not exist.\n\r",ch);
			return FALSE;
		}
	}
	
	EDIT_OBJ(ch, pObj);
	
	pObj->name = g_strdup(pObj2->name  );
	
	pObj->item_type = pObj2->item_type;
	
	pObj->wear_flags  = pObj2->wear_flags;
	pObj->extra_flags = pObj2->extra_flags;
	
	pObj->condition = pObj2->condition;
	
	pObj->weight = pObj2->weight;
	pObj->cost   = pObj2->cost;
	
	/*pObj->extra_descr = pObj2->extra_descr;*/
	
	pObj->short_descr = g_strdup( pObj2->short_descr  );
	
	pObj->description = g_strdup( pObj2->description  );
	
	pObj->affected = pObj2->affected;
	
	for (i = 0; i < 5; i++)
	{
		pObj->value[i] = pObj2->value[i];
	}
	
	send_to_char( "Object info copied.", ch );
	return TRUE;
}


/*
 * Need to issue warning if flag isn't valid. -- does so now -- Hugin.
 */
OEDIT( oedit_addaffect )
{
	int value;
	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] [#xmod]\n\r", ch );
		return FALSE;
	}
	
	if ( ( value = flag_value( apply_flags, loc ) ) == NO_FLAG )
	{
		send_to_char( "Valid affects are:\n\r", ch );
		show_help( ch, "apply" );
		return FALSE;
	}
	
	//pAf             =   alloc_perm( sizeof(*pAf));
	pAf = new_affect();

	pAf->location   =   value;
	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;
}

OEDIT( oedit_addapply )
{
	int value,bv,typ;
	OBJ_INDEX_DATA *pObj;
	AFFECT_DATA *pAf;
	char loc[MAX_STRING_LENGTH];
	char mod[MAX_STRING_LENGTH];
	char type[MAX_STRING_LENGTH];
	char bvector[MAX_STRING_LENGTH];
	
	EDIT_OBJ(ch, pObj);
	
	argument = one_argument( argument, type );
	argument = one_argument( argument, loc );
	argument = one_argument( argument, mod );
	one_argument( argument, bvector );
	
	if ( type[0] == '\0' || ( typ = flag_value( apply_types, type ) ) == NO_FLAG )
	{
		send_to_char( "Invalid apply type. Valid apply types are:\n\r", ch);
		show_help( ch, "apptype" );
		return FALSE;
	}
	
	if ( loc[0] == '\0' || ( value = flag_value( apply_flags, loc ) ) == NO_FLAG )
	{
		send_to_char( "Valid applys are:\n\r", ch );
		show_help( ch, "apply" );
		return FALSE;
	}
	
	if ( bvector[0] == '\0' || ( bv = flag_value( bitvector_type[typ].table, bvector ) ) == NO_FLAG )
	{
		send_to_char( "Invalid bitvector type.\n\r", ch );
		send_to_char( "Valid bitvector types are:\n\r", ch );
		show_help( ch, bitvector_type[typ].help );
		return FALSE;
	}
	
	if ( mod[0] == '\0' || !is_number( mod ) )
	{
		send_to_char( "Syntax:  addapply [type] [location] [#xmod] [bitvector]\n\r", ch );
		return FALSE;
	}
	
	//pAf             =   alloc_perm(sizeof(*pAf));
	pAf = new_affect();
	pAf->location   =   value;
	pAf->type	    =	-1;
	pAf->duration   =   -1;
	pAf->bitvector  =   bv;
	pAf->next       =   pObj->affected;
	pObj->affected  =   pAf;
	
	send_to_char( "Apply added.\n\r", ch);
	return TRUE;
}
/*
 * My thanks to Hans Hvidsten Birkeland and Noam Krendel(Walker)
 * for really teaching me how to manipulate pointers.
*/
OEDIT( oedit_delaffect )
{
	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 [#xaffect]\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 )	
	{
		pAf = pObj->affected;
		pObj->affected = pAf->next;
	}
	else	
	{
		while ( ( pAf_next = pAf->next ) && ( ++cnt < value ) )
			pAf = pAf_next;
		
		if( pAf_next )		
		{
			pAf->next = pAf_next->next;
		}
		else                   
		{
			send_to_char( "No such affect.\n\r", ch );
			return FALSE;
		}
	}
	
	send_to_char( "Affect removed.\n\r", ch);
	return TRUE;
}

OEDIT( oedit_name )
{
	OBJ_INDEX_DATA *pObj;
	
	EDIT_OBJ(ch, pObj);
	
	if ( argument[0] == '\0' )
	{
		send_to_char( "Syntax:  name [string]\n\r", ch );
		return FALSE;
	}
	
	pObj->name = g_strdup( argument );
	
	send_to_char( "Name set.\n\r", ch);
	return TRUE;
}



OEDIT( oedit_short )
{
	OBJ_INDEX_DATA *pObj;
	
	EDIT_OBJ(ch, pObj);
	
	if ( argument[0] == '\0' )
	{
		send_to_char( "Syntax:  short [string]\n\r", ch );
		return FALSE;
	}
	
	pObj->short_descr = g_strdup( argument );
	pObj->short_descr[0] = LOWER( pObj->short_descr[0] );
	
	send_to_char( "Short description set.\n\r", ch);
	return TRUE;
}



OEDIT( oedit_long )
{
	OBJ_INDEX_DATA *pObj;
	
	EDIT_OBJ(ch, pObj);
	
	if ( argument[0] == '\0' )
	{
		send_to_char( "Syntax:  long [string]\n\r", ch );
		return FALSE;
	}
	
	pObj->description = g_strdup( 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' changed to "" -- Hugin */
		return FALSE;
	}
	
	if ( set_obj_values( ch, pObj, value, argument ) )
		return TRUE;
	
	return FALSE;
}

OEDIT( oedit_delete )
{
	OBJ_INDEX_DATA *pObj;
	OBJ_INDEX_DATA *iObj;
	OBJ_INDEX_DATA *sObj;
	RESET_DATA *pReset = NULL;
	ROOM_INDEX_DATA *pRoom = NULL;
	GSList *ResetList;
	char arg[MIL];
	char buf[MAX_STRING_LENGTH];
	int index, count, iHash, i;
	
	if ( argument[0] == '\0' )
	{
		send_to_char( "Syntax:  oedit delete [vnum]\n\r", ch );
		return FALSE;
	}
	
	one_argument( argument, arg );
	
	if( is_number( arg ) )
	{
		index = atoi( arg );
		pObj = get_obj_index( index );
	}
	else
	{
		send_to_char( "That is not a number.\n\r", ch );
		return FALSE;
	}
	
	SET_BIT( pObj->area->area_flags, AREA_CHANGED );
	
     /* Remove it from the object list */
	
	iHash = index % MAX_KEY_HASH;
	
	sObj = obj_index_hash[iHash];
	
	if( sObj->next == NULL ) /* only entry */
		obj_index_hash[iHash] = NULL;
	else if( sObj == pObj ) /* first entry */
		obj_index_hash[iHash] = pObj->next;
	else /* everything else */
	{
		for( iObj = sObj; iObj != NULL; iObj = iObj->next )
		{
			if( iObj ==  pObj )
			{
				sObj->next = pObj->next;
				break;
			}
			sObj = iObj;
		}
	}
	
 	if( top_vnum_obj == index )
		for( i = 1; i < index; i++ )
			if( get_obj_index( i ) )
				top_vnum_obj = i;
			
			
	top_obj_index--;
	
    /* Now crush all resets */
	count = 0;
	for( iHash = 0; iHash < MAX_KEY_HASH; iHash++ )
	{
		for( pRoom = room_index_hash[iHash]; pRoom; pRoom = pRoom->next )
		{
			for( ResetList = pRoom->reset_list; ResetList; ResetList = g_slist_next(ResetList) )
			{
				pReset = (RESET_DATA*)ResetList->data;
				switch( pReset->command )
				{
					case 'O':
					case 'E':
					case 'P':
					case 'G':
						if( ( pReset->arg1 == index ) ||
							( (  pReset->command == 'P' ) && (
								pReset->arg3 == index ) ) )
						{
							
							pRoom->reset_list = g_slist_remove(	pRoom->reset_list, pReset);
							count++;
							SET_BIT( pRoom->area->area_flags,
								AREA_CHANGED );
							
						}
				}
			}
			g_slist_free(ResetList);

		}
	}
	sprintf( buf, "Removed object vnum ^C%d^x and ^C%d^x resets.\n\r", index,
		count );
	send_to_char( buf, ch );
	return TRUE;
}

/*****************************************************************************
 Name:		oedit_values
 Purpose:	Finds the object and sets its value.
 Called by:	The four valueX functions below. (now five -- Hugin )
 ****************************************************************************/
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;
}


OEDIT( oedit_value0 )
{
	if ( oedit_values( ch, argument, 0 ) )
		return TRUE;
	
	return FALSE;
}



OEDIT( oedit_value1 )
{
	if ( oedit_values( ch, argument, 1 ) )
		return TRUE;
	
	return FALSE;
}



OEDIT( oedit_value2 )
{
	if ( oedit_values( ch, argument, 2 ) )
		return TRUE;
	
	return FALSE;
}



OEDIT( oedit_value3 )
{
	if ( oedit_values( ch, argument, 3 ) )
		return TRUE;
	
	return FALSE;
}



OEDIT( oedit_value4 )
{
	if ( oedit_values( ch, argument, 4 ) )
		return TRUE;
	
	return FALSE;
}



OEDIT( oedit_weight )
{
	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;
}

OEDIT( oedit_cost )
{
	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;
}



OEDIT( oedit_create )
{
	OBJ_INDEX_DATA *pObj;
	AREA_DATA *pArea;
	int  value;
	int  iHash;
	
	value = atoi( argument );
	if ( argument[0] == '\0' || value == 0 )
	{
		send_to_char( "Syntax:  oedit create [vnum]\n\r", 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;
	pObj->name			= g_strdup("no name");
	pObj->short_descr		= g_strdup("(null)");
	
	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;
}



OEDIT( oedit_ed )
{
	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         =   g_strdup( 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;
		}
		
		ed->description = format_string( ed->description );
		
		send_to_char( "Extra description formatted.\n\r", ch );
		return TRUE;
	}
	
	oedit_ed( ch, "" );
	return FALSE;
}





/* ROM object functions : */

OEDIT( oedit_extra )      /* Moved out of oedit() due to naming conflicts -- Hugin */
{
	OBJ_INDEX_DATA *pObj;
	int value;
	
	if ( argument[0] != '\0' )
	{
		EDIT_OBJ(ch, pObj);
		
		if ( ( value = flag_value( extra_flags, argument ) ) != NO_FLAG )
		{
			TOGGLE_BIT(pObj->extra_flags, value);
			
			send_to_char( "Extra flag toggled.\n\r", ch);
			return TRUE;
		}
	}
	
	send_to_char( "Syntax:  extra [flag]\n\r"
		"Type '? extra' for a list of flags.\n\r", ch );
	return FALSE;
}


OEDIT( oedit_wear )      /* Moved out of oedit() due to naming conflicts -- Hugin */
{
	OBJ_INDEX_DATA *pObj;
	int value;
	
	if ( argument[0] != '\0' )
	{
		EDIT_OBJ(ch, pObj);
		
		if ( ( value = flag_value( wear_flags, argument ) ) != NO_FLAG )
		{
			TOGGLE_BIT(pObj->wear_flags, value);
			
			send_to_char( "Wear flag toggled.\n\r", ch);
			return TRUE;
		}
	}
	
	send_to_char( "Syntax:  wear [flag]\n\r"
		"Type '? wear' for a list of flags.\n\r", ch );
	return FALSE;
}


OEDIT( oedit_type )      /* Moved out of oedit() due to naming conflicts -- Hugin */
{
	OBJ_INDEX_DATA *pObj;
	int value;
	
	if ( argument[0] != '\0' )
	{
		EDIT_OBJ(ch, pObj);
		
		if ( ( value = flag_value( type_flags, argument ) ) != NO_FLAG )
		{
			pObj->item_type = value;
			
			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 TRUE;
		}
	}
	
	send_to_char( "Syntax:  type [flag]\n\r"
		"Type '? type' for a list of flags.\n\r", ch );
	return FALSE;
}
/*
OEDIT( oedit_material )
{
    OBJ_INDEX_DATA *pObj;

    EDIT_OBJ(ch, pObj);

    if ( argument[0] == '\0' )
    {
	send_to_char( "Syntax:  material [string]\n\r", ch );
	return FALSE;
    }

    free_string( pObj->material );
    pObj->material = g_strdup( argument );

    send_to_char( "Material set.\n\r", ch);
    return TRUE;
}

OEDIT( oedit_level )
{
    OBJ_INDEX_DATA *pObj;

    EDIT_OBJ(ch, pObj);

    if ( argument[0] == '\0' || !is_number( argument ) )
    {
	send_to_char( "Syntax:  level [number]\n\r", ch );
	return FALSE;
    }

    pObj->level = atoi( argument );

    send_to_char( "Level set.\n\r", ch);
    return TRUE;
}

*/

OEDIT( oedit_condition )
{
	OBJ_INDEX_DATA *pObj;
	int value;
	
	if ( argument[0] != '\0'
		&& ( value = atoi (argument ) ) >= 0
		&& ( value <= 100 ) )
	{
		EDIT_OBJ( ch, pObj );
		
		pObj->condition = value;
		send_to_char( "Condition set.\n\r", ch );
		
		return TRUE;
	}
	
	send_to_char( "Syntax:  condition [number]\n\r"
		"Where number can range from 0 (ruined) to 100 (perfect).\n\r",
		ch );
	return FALSE;
}





/*
 * Mobile Editor Functions.
 */
MEDIT( medit_show )
{
	MOB_INDEX_DATA *pMob;
	char buf[MAX_STRING_LENGTH];
	MPROG_LIST *list;
	
	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, "Mob_Con:         [%s]\n\r",
		flag_string( mob_con_flags, pMob->mob_con ) );
	send_to_char( buf, ch );
	
	sprintf( buf, "Stance:         [%s]\n\r",
		flag_string( mob_fight_flags, pMob->mob_fight ) );
	send_to_char( buf, ch );

	sprintf( buf, "Vnum:        [%5d] Sex:   [%s]\n\r",
		pMob->vnum,
		pMob->sex == SEX_MALE    ? "male   " :
		pMob->sex == SEX_FEMALE  ? "female " : 
		pMob->sex == 3           ? "random " : "neutral");
	send_to_char( buf, ch );
	
	sprintf( buf,
		"Level:       [%2d]    Align: [%4d]\n\r",
		pMob->level,	pMob->alignment);
	send_to_char( buf, ch );
/*
    if ( pMob->group )
    {
	sprintf( buf, "Group:       [%5d]\n\r", pMob->group );
	send_to_char( buf, ch );
    }
*/
	sprintf( buf, "Hitroll:   [%d]\n\r",
		pMob->hitroll );
	send_to_char (buf,ch);
	sprintf( buf, "Hit dice:    [%2dd%-3d+%4d] ",
		pMob->hitnodice,
		pMob->hitsizedice,
		pMob->hitplus );
	send_to_char( buf, ch );
	
	sprintf( buf, "Damage dice: [%2dd%-3d+%4d]\n\r",
		pMob->damnodice,
		pMob->damsizedice,
		pMob->damplus );
	send_to_char( buf, ch );
/*
    sprintf( buf, "Mana dice:   [%2dd%-3d+%4d]\n\r",
	     pMob->mana[DICE_NUMBER],
	     pMob->mana[DICE_TYPE],
	     pMob->mana[DICE_BONUS] );
    send_to_char( buf, ch );

 ROM values end  */
	
	sprintf( buf, "Affected by: [%s]\n\r",
		flag_string( affect_flags, pMob->affected_by ) );
	send_to_char( buf, ch );
	
	sprintf( buf, "Armor: [%d]\n\r",
		pMob->ac );
	send_to_char( buf, ch );
	
/* ROM values: 
    sprintf( buf, "Form:        [%s]\n\r",
	flag_string( form_flags, pMob->form ) );
    send_to_char( buf, ch );

    sprintf( buf, "Parts:       [%s]\n\r",
	flag_string( part_flags, pMob->parts ) );
    send_to_char( buf, ch );

    sprintf( buf, "Imm:         [%s]\n\r",
	flag_string( imm_flags, pMob->imm_flags ) );
    send_to_char( buf, ch );

    sprintf( buf, "Res:         [%s]\n\r",
	flag_string( res_flags, pMob->res_flags ) );
    send_to_char( buf, ch );

    sprintf( buf, "Vuln:        [%s]\n\r",
	flag_string( vuln_flags, pMob->vuln_flags ) );
    send_to_char( buf, ch );

    sprintf( buf, "Off:         [%s]\n\r",
	flag_string( off_flags,  pMob->off_flags ) );
    send_to_char( buf, ch );

    sprintf( buf, "Size:        [%s]\n\r",
	flag_string( size_flags, pMob->size ) );
    send_to_char( buf, ch );

    sprintf( buf, "Material:    [%s]\n\r",
        pMob->material );
    send_to_char( buf, ch );

    sprintf( buf, "Start pos.   [%s]\n\r",
	flag_string( position_flags, pMob->start_pos ) );
    send_to_char( buf, ch );

    sprintf( buf, "Default pos  [%s]\n\r",
	flag_string( position_flags, pMob->default_pos ) );
    send_to_char( buf, ch );

    sprintf( buf, "Wealth:      [%5ld]\n\r",
	pMob->wealth );
    send_to_char( buf, ch );

 ROM values end */

    if ( pMob->spec_fun )
    {
	sprintf( buf, "Spec fun:    [%s]\n\r",  spec_name( 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 );
			}
		}
	}
    if ( pMob->mprogs )
    {
	int cnt;

	sprintf(buf, "\n\rMOBPrograms for [%5d]:\n\r", pMob->vnum);
	send_to_char( buf, ch );

	for (cnt=0, list=pMob->mprogs; list; list=list->next)
	{
		if (cnt ==0)
		{
			send_to_char ( " Number Vnum Trigger Phrase\n\r", ch );
			send_to_char ( " ------ ---- ------- ------\n\r", ch );
		}

		sprintf(buf, "[%5d] %4d %7s %s\n\r", cnt,
			list->vnum,mprog_type_to_name(list->trig_type),
			list->trig_phrase->str);
		send_to_char( buf, ch );
		cnt++;
	}
    }
	return FALSE;
}


/*
 * medit_copy function thanks to Zanthras of Mystical Realities MUD.
 * Thanks to Ivan for what there is of the incomplete mobprog part.
 * Hopefully it will be finished in a later release of this snippet.
 */
MEDIT( medit_copy )
{
	MOB_INDEX_DATA *pMob;
	MOB_INDEX_DATA *pMob2; /* The mob to copy */
	int vnum;
	
    /* MPROG_LIST *list; */ /* Used for the mob prog for loop */
	
	if ( argument[0] == '\0' )
	{
		send_to_char("Syntax: copy <vnum> \n\r",ch);
		return FALSE;
	}
	
	if ( !is_number(argument) )
	{
		send_to_char("MEdit: You must enter a number (vnum).\n\r",ch);
		return FALSE;
	}
	else /* argument is a number */
	{
		vnum = atoi(argument);
		if( !( pMob2 = get_mob_index(vnum) ) )
		{
			send_to_char("MEdit: That mob does not exist.\n\r",ch);
			return FALSE;
		}
	}
	
	EDIT_MOB(ch, pMob);
	
	pMob->player_name = g_strdup( pMob2->player_name );
	
	pMob->act = pMob2->act;
	pMob->sex = pMob2->sex;
	
	pMob->level = pMob2->level;
	
	pMob->alignment = pMob2->alignment;
	
	pMob->hitroll = pMob2->hitroll;
	
	pMob->hitnodice = pMob2->hitnodice;
	pMob->hitsizedice   = pMob2->hitsizedice;
	pMob->hitplus  = pMob2->hitplus;
	
	pMob->damnodice = pMob2->damnodice;
	pMob->damsizedice   = pMob2->damsizedice;
	pMob->damplus  = pMob2->damplus;
	
	pMob->affected_by = pMob2->affected_by;
	
	pMob->ac = pMob2->ac;
	
	pMob->spec_fun = pMob2->spec_fun;
	
	pMob->short_descr = g_strdup( pMob2->short_descr );
	
	pMob->long_descr = g_strdup( pMob2->long_descr    );
	
	pMob->description = g_strdup( pMob2->description  );
	
    /* Hopefully get the shop data to copy later
     * This is the fields here if you get it copying send me
     * a copy and I'll add it to the snippet with credit to
     * you of course :) same with the mobprogs for loop :)
     */
	
/*
    if ( pMob->pShop )
    {
	SHOP_DATA *pShop, *pShop2;

	pShop =  pMob->pShop;
	pShop2 = pMob2->pShop;
 
	pShop->profit_buy = pShop2->profit_buy;
	pShop->profit_sell = pShop2->profit_sell;
	
	pShop->open_hour = pShop2->open_hour;
	pShop->close_hour = pShop2->close_hour;
	
	pShop->buy_type[iTrade] = pShop2->buy_type[iTrade];
    }
*/
/*  for loop thanks to Ivan, still needs work though

    for (list = pMob->mprogs; list; list = list->next )
    {
      MPROG_LIST *newp = new_mprog();
      newp->trig_type = list->trig_type;

      newp->trig_phrase = g_strdup( list->trig_phrase );

      newp->vnum = list->vnum;

      newp->code = g_strdup( list->code );

      pMob->mprogs = newp;
    }
*/
	
	send_to_char( "Mob info copied.", ch );
	return FALSE;
}

MEDIT( medit_create )
{
	MOB_INDEX_DATA *pMob;
	AREA_DATA *pArea;
	int  value;
	int  iHash;
	
	value = atoi( argument );
	if ( argument[0] == '\0' || value == 0 )
	{
		send_to_char( "Syntax:  medit create [vnum]\n\r", 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;
}

MEDIT( medit_delete )
{
	MOB_INDEX_DATA *pMob;
	MOB_INDEX_DATA *sMob;
	MOB_INDEX_DATA *iMob;
	RESET_DATA *pReset = NULL;
	RESET_DATA *prev= NULL;
	ROOM_INDEX_DATA *pRoom = NULL;
	char arg[MIL];
	char buf[MAX_STRING_LENGTH];
	int index, count, iHash, i;
	int dobj[100]; /* I highly doubt one mobile will have 100 unique object
resets */
	bool foundmob = FALSE;
	bool exist = FALSE;
	bool foundobj = FALSE;
	GSList *ResetList;
	
	if ( argument[0] == '\0' )
	{
		send_to_char( "Syntax:  medit delete [vnum]\n\r", ch );
		return FALSE;
	}
	
	one_argument( argument, arg );
	
	if( is_number( arg ) )
	{
		index = atoi( arg );
		pMob = get_mob_index( index );
	}
	else
	{
		send_to_char( "That is not a number.\n\r", ch );
		return FALSE;
	}
	
	if( !pMob )
	{
		send_to_char( "No such mobile.\n\r", ch );
		return FALSE;
	}
	
	SET_BIT( pMob->area->area_flags, AREA_CHANGED );
	
     /* Remove it from the object list */
	
	iHash = index % MAX_KEY_HASH;
	
     /* DEBUG CODE - uncomment this if you have doubts */
     /* printf("\nMobile hash for location %d:\n", iHash);
     for ( tMob = mob_index_hash[iHash]; tMob != NULL; tMob = tMob->next )
          printf("short_desc: %s  vnum: %d\n", tMob->short_descr, tMob->vnum );
*/
	
	sMob = mob_index_hash[iHash];
	
	if( sMob->next == NULL ) /* only entry */
		mob_index_hash[iHash] = NULL;
	else if( sMob == pMob ) /* first entry */
		mob_index_hash[iHash] = pMob->next;
	else /* everything else */
	{
		for( iMob = sMob; iMob != NULL; iMob = iMob->next )
		{
			if( iMob ==  pMob )
			{
				sMob->next = pMob->next;
				break;
			}
		}
	}
	
     /* See oedit_delete for why i dont free pMob here */
	
     /* DEBUG CODE - uncomment this if you have doubts */
     /* printf("\nMobile hash for location %d after removal:\n", iHash);
     for ( tMob = mob_index_hash[iHash]; tMob != NULL; tMob = tMob->next )
          printf("short_desc: %s  vnum: %d\n", tMob->short_descr, tMob->vnum );
*/
	
	if( top_vnum_mob == index )
		for( i = 1; i < index; i++ )
			if( get_obj_index( i ) )
				top_vnum_obj = i;
			
	top_mob_index--;
	
     /* Now crush all resets */
	count = 0;
	for( iHash = 0; iHash < MAX_KEY_HASH; iHash++ )
	{
		for( pRoom = room_index_hash[iHash]; pRoom; pRoom = pRoom->next )
		{
			dobj[0] = -1;
			for( ResetList = pRoom->reset_list; ResetList; ResetList = g_slist_next(ResetList) )
			{
				pReset = (RESET_DATA*)ResetList->data;
				switch( pReset->command )
				{
					case 'M':
						if( pReset->arg1 == index )
						{
							foundmob = TRUE;
							
                                   /* DEBUG CODE - uncomment this if you have
doubts */
                                   /* printf("\nReset info for room %d:\n",
pRoom->vnum );
                                   for( tReset = pRoom->reset_first; tReset;
tReset = tReset->next )
                                        printf("command: %c  vnum: %d\n",
tReset->command, tReset->arg1 ); */
							
							pRoom->reset_list = g_slist_remove(pRoom->reset_list, pReset);						
							
							count++;
							SET_BIT( pRoom->area->area_flags,
								AREA_CHANGED );
							
                                   /* DEBUG CODE - uncomment this if you have
doubts */
                                   /* printf("\nReset info for room %d after
removal:\n", pRoom->vnum );
                                   for( tReset = pRoom->reset_first; tReset;
tReset = tReset->next )
                                        printf("command: %c  vnum: %d\n",
tReset->command, tReset->arg1 ); */
							
						}
						else
							foundmob = FALSE;
						
						break;
					case 'E':
					case 'G':
						if( foundmob )
						{
                                  /* printf( "Removing: command: %c  vnum:
%d\n", pReset->command, pReset->arg1 ); */
							
                                   /* DEBUG CODE - uncomment this if you have
doubts */
                                   /* printf("\nReset info for room %d:\n",
pRoom->vnum );
                                   for( tReset = pRoom->reset_first; tReset;
tReset = tReset->next )
                                        printf("command: %c  vnum: %d\n",
tReset->command, tReset->arg1 ); */
							
							exist = FALSE;
							
							for( i = 0; dobj[i] != -1; i++ )
							{
								if( dobj[i] == pReset->arg1 )
								{
									exist = TRUE;
									break;
								}
							}
							
							if( !exist )
							{
								dobj[i] = pReset->arg1;
								dobj[i + 1] = -1;
								
                                        /* DEBUG CODE */
                                        /* for( i = 0; dobj[i] != -1; i++ )
                                             printf( "dobj[%d] : %d\n", i,
dobj[i] ); */
							}
							
							pRoom->reset_list = g_slist_remove(pRoom->reset_list, pReset);						
							
							count++;
							SET_BIT( pRoom->area->area_flags,
								AREA_CHANGED );
							
                                   /* DEBUG CODE - uncomment this if you have
doubts */
                                   /* printf("\nReset info for room %d after
removal:\n", pRoom->vnum );
                                   for( tReset = pRoom->reset_first; tReset;
tReset = tReset->next )
                                        printf("command: %c  vnum: %d\n",
tReset->command, tReset->arg1 ); */
						}
						
						break;
					case 'P':
						foundobj = FALSE;
						
						for( i = 0; dobj[i] != -1; i++ )
							if( dobj[i] == pReset->arg3 )
								foundobj = TRUE;
							
						if( foundobj )
						{
							printf( "Removing: command: %c  vnum: %d\n",
								pReset->command, pReset->arg1 );
							
                                   /* DEBUG CODE - uncomment this if you have
doubts */
                                   /* printf("\nReset info for room %d:\n",
pRoom->vnum );
                                   for( tReset = pRoom->reset_first; tReset;
tReset = tReset->next )
                                        printf("command: %c  vnum: %d\n",
tReset->command, tReset->arg1 ); */
							
							pRoom->reset_list = g_slist_remove(pRoom->reset_list, pReset);						
							
							count++;
							SET_BIT( pRoom->area->area_flags,
								AREA_CHANGED );
							
                                   /* DEBUG CODE - uncomment this if you have
doubts */
                                   /* printf("\nReset info for room %d after
removal:\n", pRoom->vnum );
                                   for( tReset = pRoom->reset_first; tReset;
tReset = tReset->next )
                                        printf("command: %c  vnum: %d\n",
tReset->command, tReset->arg1 ); */
						}
				}
				prev = pReset;
			}
		}
	}
	
     /* This is a dumb way to fix what is probably someone elses problem */
     /* The reason for the kludge is that sometime after the exit of
medit_delete */
     /* ch->mount becomes 0x10000000 and I have no idea how or where */
     /*   Narbo */
	
	sprintf( buf, "Removed mobile vnum ^C%d^x and ^C%d^x resets.\n\r", index,
		count );
	send_to_char( buf, ch );
	return TRUE;
}

MEDIT( medit_spec )
{
	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;
}
/*
MEDIT( medit_damtype )
{
    MOB_INDEX_DATA *pMob;

    EDIT_MOB(ch, pMob);

    if ( argument[0] == '\0' )
    {
	send_to_char( "Syntax:  damtype [damage message]\n\r", ch );
	send_to_char( "Para ver una lista de tipos de mensajes, pon '? weapon'.\n\r", ch );
	return FALSE;
    }

    pMob->dam_type = attack_lookup(argument);
    send_to_char( "Damage type set.\n\r", ch);
    return TRUE;
}

*/
MEDIT( medit_align )
{
	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;
}



MEDIT( medit_level )
{
	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;
}



MEDIT( medit_desc )
{
	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;
}




MEDIT( medit_long )
{
	MOB_INDEX_DATA *pMob;
	
	EDIT_MOB(ch, pMob);
	
	if ( argument[0] == '\0' )
	{
		send_to_char( "Syntax:  long [string]\n\r", ch );
		return FALSE;
	}
	
	strcat( argument, "\n\r" );
	pMob->long_descr = g_strdup( argument );
	pMob->long_descr[0] = UPPER( pMob->long_descr[0]  );
	
	send_to_char( "Long description set.\n\r", ch);
	return TRUE;
}



MEDIT( medit_short )
{
	MOB_INDEX_DATA *pMob;
	
	EDIT_MOB(ch, pMob);
	
	if ( argument[0] == '\0' )
	{
		send_to_char( "Syntax:  short [string]\n\r", ch );
		return FALSE;
	}
	
	pMob->short_descr = g_strdup( argument );
	
	send_to_char( "Short description set.\n\r", ch);
	return TRUE;
}



MEDIT( medit_name )
{
	MOB_INDEX_DATA *pMob;
	
	EDIT_MOB(ch, pMob);
	
	if ( argument[0] == '\0' )
	{
		send_to_char( "Syntax:  name [string]\n\r", ch );
		return FALSE;
	}
	
	pMob->player_name = g_strdup( argument );
	
	send_to_char( "Name set.\n\r", ch);
	return TRUE;
}

MEDIT( medit_shop )
{
	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 [#xopening] [#xclosing]\n\r", ch );
		send_to_char( "         shop profit [#xbuying%] [#xselling%]\n\r", ch );
		send_to_char( "         shop type [#x0-4] [item type]\n\r", ch );
		send_to_char( "         shop assign\n\r", ch );
		send_to_char( "         shop remove\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 [#xopening] [#xclosing]\n\r", ch );
			return FALSE;
		}
		
		if ( !pMob->pShop )
		{
			send_to_char( "MEdit:  Debes crear un shop primero (shop assign).\n\r", ch );
			return FALSE;
		}
		
		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 [#xbuying%] [#xselling%]\n\r", ch );
			return FALSE;
		}
		
		if ( !pMob->pShop )
		{
			send_to_char( "MEdit:  Debes crear un shop primero (shop assign).\n\r", ch );
			return FALSE;
		}
		
		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 [#x0-4] [item type]\n\r", ch );
			return FALSE;
		}
		
		if ( atoi( arg1 ) >= MAX_TRADE )
		{
			sprintf( buf, "MEdit:  May sell %d items max.\n\r", MAX_TRADE );
			send_to_char( buf, ch );
			return FALSE;
		}
		
		if ( !pMob->pShop )
		{
			send_to_char( "MEdit:  Debes crear un shop primero (shop assign).\n\r", ch );
			return FALSE;
		}
		
		if ( ( value = flag_value( type_flags, argument ) ) == NO_FLAG )
		{
			send_to_char( "MEdit:  That type of item is not known.\n\r", ch );
			return FALSE;
		}
		
		pMob->pShop->buy_type[atoi( arg1 )] = value;
		
		send_to_char( "Shop type set.\n\r", ch);
		return TRUE;
	}
	
    /* shop assign && shop delete by Phoenix */
	
	if ( !str_prefix(command, "assign") )
	{
		if ( pMob->pShop )
		{
			send_to_char("Mob already has a shop assigned to it.\n\r", ch);
			return FALSE;
		}
		
		pMob->pShop		= new_shop();
		if ( !shop_first )
			shop_first	= pMob->pShop;
		if ( shop_last )
			shop_last->next	= pMob->pShop;
		shop_last		= pMob->pShop;
		
		pMob->pShop->keeper	= pMob->vnum;
		
		send_to_char("New shop assigned to mobile.\n\r", ch);
		return TRUE;
	}
	
	if ( !str_prefix(command, "remove") )
	{
		SHOP_DATA *pShop;
		
		pShop		= pMob->pShop;
		pMob->pShop	= NULL;
		
		if ( pShop == shop_first )
		{
			if ( !pShop->next )
			{
				shop_first = NULL;
				shop_last = NULL;
			}
			else
				shop_first = pShop->next;
		}
		else
		{
			SHOP_DATA *ipShop;
			
			for ( ipShop = shop_first; ipShop; ipShop = ipShop->next )
			{
				if ( ipShop->next == pShop )
				{
					if ( !pShop->next )
					{
						shop_last = ipShop;
						shop_last->next = NULL;
					}
					else
						ipShop->next = pShop->next;
				}
			}
		}
		
		free_shop(pShop);
		
		send_to_char("Mobile is no longer a shopkeeper.\n\r", ch);
		return TRUE;
	}
	
	medit_shop( ch, "" );
	return FALSE;
}


/* ROM medit functions: */


MEDIT( medit_sex )          /* Moved out of medit() due to naming conflicts -- Hugin */
{
	MOB_INDEX_DATA *pMob;
	int value;
	
	if ( argument[0] != '\0' )
	{
		EDIT_MOB( ch, pMob );
		
		if ( ( value = flag_value( sex_flags, argument ) ) != NO_FLAG )
		{
			pMob->sex = value;
			
			send_to_char( "Sex set.\n\r", ch);
			return TRUE;
		}
	}
	
	send_to_char( "Syntax: sex [sex]\n\r"
		"Type '? sex' for a list of flags.\n\r", ch );
	return FALSE;
}


MEDIT( medit_act )          /* Moved out of medit() due to naming conflicts -- Hugin */
{
	MOB_INDEX_DATA *pMob;
	int value;
	
	if ( argument[0] != '\0' )
	{
		EDIT_MOB( ch, pMob );
		
		if ( ( value = flag_value( act_flags, argument ) ) != NO_FLAG )
		{
			pMob->act ^= value;
			SET_BIT( pMob->act, ACT_IS_NPC );
			
			send_to_char( "Act flag toggled.\n\r", ch);
			return TRUE;
		}
	}
	
	send_to_char( "Syntax: act [flag]\n\r"
		"Type '? act' for a list of flags.\n\r", ch );
	return FALSE;
}

MEDIT( medit_mob_con )          /* Moved out of medit() due to naming conflicts -- Hugin */
{
	MOB_INDEX_DATA *pMob;
	int value;
	
	if ( argument[0] != '\0' )
	{
		EDIT_MOB( ch, pMob );
		
		if ( ( value = flag_value( mob_con_flags, argument ) ) != NO_FLAG )
		{
			pMob->mob_con ^= value;
						
			send_to_char( "Mob_Con flag toggled.\n\r", ch);
			return TRUE;
		}
	}
	
	send_to_char( "Syntax: mob_con [flag]\n\r"
		"Type '? mob_con' for a list of flags.\n\r", ch );
	return FALSE;
}

MEDIT( medit_fstyle )          /* Moved out of medit() due to naming conflicts -- Hugin */
{
	MOB_INDEX_DATA *pMob;
	int value;
	
	if ( argument[0] != '\0' )
	{
		EDIT_MOB( ch, pMob );
		
		if ( ( value = flag_value( mob_fight_flags, argument ) ) != NO_FLAG )
		{
			pMob->mob_fight ^= value;
			//SET_BIT( pMob->act, ACT_IS_NPC );
			
			send_to_char( "stance flag toggled.\n\r", ch);
			return TRUE;
		}
	}
	
	send_to_char( "Syntax: stance [flag]\n\r"
		"Type '? stance' for a list of flags.\n\r", ch );
	return FALSE;
}

MEDIT( medit_affect )      /* Moved out of medit() due to naming conflicts -- Hugin */
{
	MOB_INDEX_DATA *pMob;
	int value;
	
	if ( argument[0] != '\0' )
	{
		EDIT_MOB( ch, pMob );
		
		if ( ( value = flag_value( affect_flags, argument ) ) != NO_FLAG )
		{
			pMob->affected_by ^= value;
			
			send_to_char( "Affect flag toggled.\n\r", ch);
			return TRUE;
		}
	}
	
	send_to_char( "Syntax: affect [flag]\n\r"
		"Type '? affect' for a list of flags.\n\r", ch );
	return FALSE;
}

MEDIT( medit_ac )
{
	MOB_INDEX_DATA *pMob;
	char arg[MAX_INPUT_LENGTH];
	
	do   
	{
		if ( argument[0] == '\0' )  break;
		
		EDIT_MOB(ch, pMob);
		argument = one_argument( argument, arg );
		
		if ( !is_number( arg ) )  break;
		pMob->ac = atoi( arg );
		argument = one_argument( argument, arg );
		
		send_to_char( "Ac set.\n\r", ch );
		return TRUE;
	} while ( FALSE );   
	
	send_to_char( "Syntax:  ac [ac]\n\r"
		"help MOB_AC  gives a list of reasonable ac-values.\n\r", ch );
	return FALSE;
}
/*
MEDIT( medit_form )
{
    MOB_INDEX_DATA *pMob;
    int value;

    if ( argument[0] != '\0' )
    {
	EDIT_MOB( ch, pMob );

	if ( ( value = flag_value( form_flags, argument ) ) != NO_FLAG )
	{
	    pMob->form ^= value;
	    send_to_char( "Form toggled.\n\r", ch );
	    return TRUE;
	}
    }

    send_to_char( "Syntax: form [flags]\n\r"
		  "Type '? form' for a list of flags.\n\r", ch );
    return FALSE;
}

MEDIT( medit_part )
{
    MOB_INDEX_DATA *pMob;
    int value;

    if ( argument[0] != '\0' )
    {
	EDIT_MOB( ch, pMob );

	if ( ( value = flag_value( part_flags, argument ) ) != NO_FLAG )
	{
	    pMob->parts ^= value;
	    send_to_char( "Parts toggled.\n\r", ch );
	    return TRUE;
	}
    }

    send_to_char( "Syntax: part [flags]\n\r"
		  "Type '? part' for a list of flags.\n\r", ch );
    return FALSE;
}

MEDIT( medit_imm )
{
    MOB_INDEX_DATA *pMob;
    int value;

    if ( argument[0] != '\0' )
    {
	EDIT_MOB( ch, pMob );

	if ( ( value = flag_value( imm_flags, argument ) ) != NO_FLAG )
	{
	    pMob->imm_flags ^= value;
	    send_to_char( "Immunity toggled.\n\r", ch );
	    return TRUE;
	}
    }

    send_to_char( "Syntax: imm [flags]\n\r"
		  "Type '? imm' for a list of flags.\n\r", ch );
    return FALSE;
}

MEDIT( medit_res )
{
    MOB_INDEX_DATA *pMob;
    int value;

    if ( argument[0] != '\0' )
    {
	EDIT_MOB( ch, pMob );

	if ( ( value = flag_value( res_flags, argument ) ) != NO_FLAG )
	{
	    pMob->res_flags ^= value;
	    send_to_char( "Resistance toggled.\n\r", ch );
	    return TRUE;
	}
    }

    send_to_char( "Syntax: res [flags]\n\r"
		  "Type '? res' for a list of flags.\n\r", ch );
    return FALSE;
}

MEDIT( medit_vuln )
{
    MOB_INDEX_DATA *pMob;
    int value;

    if ( argument[0] != '\0' )
    {
	EDIT_MOB( ch, pMob );

	if ( ( value = flag_value( vuln_flags, argument ) ) != NO_FLAG )
	{
	    pMob->vuln_flags ^= value;
	    send_to_char( "Vulnerability toggled.\n\r", ch );
	    return TRUE;
	}
    }

    send_to_char( "Syntax: vuln [flags]\n\r"
		  "Type '? vuln' for a list of flags.\n\r", ch );
    return FALSE;
}

MEDIT( medit_material )
{
    MOB_INDEX_DATA *pMob;

    EDIT_MOB(ch, pMob);

    if ( argument[0] == '\0' )
    {
	send_to_char( "Syntax:  material [string]\n\r", ch );
	return FALSE;
    }

    pMob->material = g_strdup( argument );

    send_to_char( "Material set.\n\r", ch);
    return TRUE;
}


MEDIT( medit_off )
{
    MOB_INDEX_DATA *pMob;
    int value;

    if ( argument[0] != '\0' )
    {
	EDIT_MOB( ch, pMob );

	if ( ( value = flag_value( off_flags, argument ) ) != NO_FLAG )
	{
	    pMob->off_flags ^= value;
	    send_to_char( "Offensive behaviour toggled.\n\r", ch );
	    return TRUE;
	}
    }

    send_to_char( "Syntax: off [flags]\n\r"
		  "Type '? off' for a list of flags.\n\r", ch );
    return FALSE;
}

MEDIT( medit_size )
{
    MOB_INDEX_DATA *pMob;
    int value;

    if ( argument[0] != '\0' )
    {
	EDIT_MOB( ch, pMob );

	if ( ( value = flag_value( size_flags, argument ) ) != NO_FLAG )
	{
	    pMob->size = value;
	    send_to_char( "Size set.\n\r", ch );
	    return TRUE;
	}
    }

    send_to_char( "Syntax: size [size]\n\r"
		  "Type '? size' for a list of sizes.\n\r", ch );
    return FALSE;
}
*/
MEDIT( medit_hitdice )
{
	static char syntax[] = "Syntax:  hitdice <number> d <type> + <bonus>\n\r";
	char *num, *type, *bonus, *cp;
	MOB_INDEX_DATA *pMob;
	
	EDIT_MOB( ch, pMob );
	
	if ( argument[0] == '\0' )
	{
		send_to_char( syntax, ch );
		return FALSE;
	}
	
	num = cp = argument;
	
	while ( isdigit( *cp ) ) ++cp;
	while ( *cp != '\0' && !isdigit( *cp ) )  *(cp++) = '\0';
	
	type = cp;
	
	while ( isdigit( *cp ) ) ++cp;
	while ( *cp != '\0' && !isdigit( *cp ) ) *(cp++) = '\0';
	
	bonus = cp;
	
	while ( isdigit( *cp ) ) ++cp;
	if ( *cp != '\0' ) *cp = '\0';
	
	if ( ( !is_number( num   ) || atoi( num   ) < 1 )
		||   ( !is_number( type  ) || atoi( type  ) < 1 ) 
		||   ( !is_number( bonus ) || atoi( bonus ) < 0 ) )
	{
		send_to_char( syntax, ch );
		return FALSE;
	}
	
	pMob->hitnodice = atoi( num   );
	pMob->hitsizedice   = atoi( type  );
	pMob->hitplus  = atoi( bonus );
	
	send_to_char( "Hitdice set.\n\r", ch );
	return TRUE;
}
/*
MEDIT( medit_manadice )
{
    static char syntax[] = "Syntax:  manadice <number> d <type> + <bonus>\n\r";
    char *num, *type, *bonus, *cp;
    MOB_INDEX_DATA *pMob;

    EDIT_MOB( ch, pMob );

    if ( argument[0] == '\0' )
    {
	send_to_char( syntax, ch );
	return FALSE;
    }

    num = cp = argument;

    while ( isdigit( *cp ) ) ++cp;
    while ( *cp != '\0' && !isdigit( *cp ) )  *(cp++) = '\0';

    type = cp;

    while ( isdigit( *cp ) ) ++cp;
    while ( *cp != '\0' && !isdigit( *cp ) ) *(cp++) = '\0';

    bonus = cp;

    while ( isdigit( *cp ) ) ++cp;
    if ( *cp != '\0' ) *cp = '\0';

    if ( !( is_number( num ) && is_number( type ) && is_number( bonus ) ) )
    {
	send_to_char( syntax, ch );
	return FALSE;
    }

    if ( ( !is_number( num   ) || atoi( num   ) < 1 )
    ||   ( !is_number( type  ) || atoi( type  ) < 1 ) 
    ||   ( !is_number( bonus ) || atoi( bonus ) < 0 ) )
    {
	send_to_char( syntax, ch );
	return FALSE;
    }

    pMob->mana[DICE_NUMBER] = atoi( num   );
    pMob->mana[DICE_TYPE]   = atoi( type  );
    pMob->mana[DICE_BONUS]  = atoi( bonus );

    send_to_char( "Manadice set.\n\r", ch );
    return TRUE;
}
*/
MEDIT( medit_damdice )
{
	static char syntax[] = "Syntax:  damdice <number> d <type> + <bonus>\n\r";
	char *num, *type, *bonus, *cp;
	MOB_INDEX_DATA *pMob;
	
	EDIT_MOB( ch, pMob );
	
	if ( argument[0] == '\0' )
	{
		send_to_char( syntax, ch );
		return FALSE;
	}
	
	num = cp = argument;
	
	while ( isdigit( *cp ) ) ++cp;
	while ( *cp != '\0' && !isdigit( *cp ) )  *(cp++) = '\0';
	
	type = cp;
	
	while ( isdigit( *cp ) ) ++cp;
	while ( *cp != '\0' && !isdigit( *cp ) ) *(cp++) = '\0';
	
	bonus = cp;
	
	while ( isdigit( *cp ) ) ++cp;
	if ( *cp != '\0' ) *cp = '\0';
	
	if ( !( is_number( num ) && is_number( type ) && is_number( bonus ) ) )
	{
		send_to_char( syntax, ch );
		return FALSE;
	}
	
	if ( ( !is_number( num   ) || atoi( num   ) < 1 )
		||   ( !is_number( type  ) || atoi( type  ) < 1 ) 
		||   ( !is_number( bonus ) || atoi( bonus ) < 0 ) )
	{
		send_to_char( syntax, ch );
		return FALSE;
	}
	
	pMob->damnodice = atoi( num   );
	pMob->damsizedice   = atoi( type  );
	pMob->damplus  = atoi( bonus );
	
	send_to_char( "Damdice set.\n\r", ch );
	return TRUE;
}
/*
MEDIT( medit_race )
{
    MOB_INDEX_DATA *pMob;
    int race;

    if ( argument[0] != '\0'
    && ( race = race_lookup( argument ) ) != 0 )
    {
	EDIT_MOB( ch, pMob );

	pMob->race = race;
	pMob->act	  |= race_table[race].act;
	pMob->affected_by |= race_table[race].aff;
	pMob->off_flags   |= race_table[race].off;
	pMob->imm_flags   |= race_table[race].imm;
	pMob->res_flags   |= race_table[race].res;
	pMob->vuln_flags  |= race_table[race].vuln;
	pMob->form        |= race_table[race].form;
	pMob->parts       |= race_table[race].parts;

	send_to_char( "Race set.\n\r", ch );
	return TRUE;
    }

    if ( argument[0] == '?' )
    {
	char buf[MAX_STRING_LENGTH];

	send_to_char( "Available races are:", ch );

	for ( race = 0; race_table[race].name != NULL; race++ )
	{
	    if ( ( race % 3 ) == 0 )
		send_to_char( "\n\r", ch );
	    sprintf( buf, " %-15s", race_table[race].name );
	    send_to_char( buf, ch );
	}

	send_to_char( "\n\r", ch );
	return FALSE;
    }

    send_to_char( "Syntax:  race [race]\n\r"
		  "Type 'race ?' for a list of races.\n\r", ch );
    return FALSE;
}

MEDIT( medit_position )
{
    MOB_INDEX_DATA *pMob;
    char arg[MAX_INPUT_LENGTH];
    int value;

    argument = one_argument( argument, arg );

    switch ( arg[0] )
    {
    default:
	break;

    case 'S':
    case 's':
	if ( str_prefix( arg, "start" ) )
	    break;

	if ( ( value = flag_value( position_flags, argument ) ) == NO_FLAG )
	    break;

	EDIT_MOB( ch, pMob );

	pMob->start_pos = value;
	send_to_char( "Start position set.\n\r", ch );
	return TRUE;

    case 'D':
    case 'd':
	if ( str_prefix( arg, "default" ) )
	    break;

	if ( ( value = flag_value( position_flags, argument ) ) == NO_FLAG )
	    break;

	EDIT_MOB( ch, pMob );

	pMob->default_pos = value;
	send_to_char( "Default position set.\n\r", ch );
	return TRUE;
    }

    send_to_char( "Syntax:  position [start/default] [position]\n\r"
		  "Type '? position' for a list of positions.\n\r", ch );
    return FALSE;
}

MEDIT( medit_gold )
{
    MOB_INDEX_DATA *pMob;

    EDIT_MOB(ch, pMob);

    if ( argument[0] == '\0' || !is_number( argument ) )
    {
	send_to_char( "Syntax:  wealth [number]\n\r", ch );
	return FALSE;
    }

    pMob->wealth = atoi( argument );

    send_to_char( "Wealth set.\n\r", ch);
    return TRUE;
}
*/

MEDIT( medit_hitroll )
{
	MOB_INDEX_DATA *pMob;
	
	EDIT_MOB(ch, pMob);
	
	if ( argument[0] == '\0' || !is_number( argument ) )
	{
		send_to_char( "Syntax:  hitroll [number]\n\r", ch );
		return FALSE;
	}
	
	pMob->hitroll = atoi( argument );
	
	send_to_char( "Hitroll set.\n\r", ch);
	return TRUE;
}
/*
void show_liqlist(CHAR_DATA *ch)
{
    int liq;
    BUFFER *buffer;
    char buf[MAX_STRING_LENGTH];
    
    buffer = new_buf();
    
    for ( liq = 0; liq_table[liq].liq_name != NULL; liq++)
    {
	if ( (liq % 21) == 0 )
	    add_buf(buffer,"Name                 Color          Proof Full Thirst Food Ssize\n\r");

	sprintf(buf, "%-20s %-14s %5d %4d %6d %4d %5d\n\r",
		liq_table[liq].liq_name,liq_table[liq].liq_color,
		liq_table[liq].liq_affect[0],liq_table[liq].liq_affect[1],
		liq_table[liq].liq_affect[2],liq_table[liq].liq_affect[3],
		liq_table[liq].liq_affect[4] );
	add_buf(buffer,buf);
    }

    page_to_char(buf_string(buffer),ch);
    free_buf(buffer);

return;
}

void show_damlist(CHAR_DATA *ch)
{
    int att;
    BUFFER *buffer;
    char buf[MAX_STRING_LENGTH];
    
    buffer = new_buf();
    
    for ( att = 0; attack_table[att].name != NULL; att++)
    {
	if ( (att % 21) == 0 )
	    add_buf(buffer,"Name                 Noun\n\r");

	sprintf(buf, "%-20s %-20s\n\r",
		attack_table[att].name,attack_table[att].noun );
	add_buf(buffer,buf);
    }

    page_to_char(buf_string(buffer),ch);
    free_buf(buffer);

return;
}

MEDIT( medit_group )
{
    MOB_INDEX_DATA *pMob;
    MOB_INDEX_DATA *pMTemp;
    char arg[MAX_STRING_LENGTH];
    char buf[MAX_STRING_LENGTH];
    int temp;
    BUFFER *buffer;
    bool found = FALSE;
    
    EDIT_MOB(ch, pMob);
    
    if ( argument[0] == '\0' )
    {
    	send_to_char( "Syntax: group [number]\n\r", ch);
    	send_to_char( "        group show [number]\n\r", ch);
    	return FALSE;
    }
    
    if (is_number(argument))
    {
	pMob->group = atoi(argument);
    	send_to_char( "Group set.\n\r", ch );
	return TRUE;
    }
    
    argument = one_argument( argument, arg );
    
    if ( !strcmp( arg, "show" ) && is_number( argument ) )
    {
	if (atoi(argument) == 0)
	{
		send_to_char( "Are you crazy?\n\r", ch);
		return FALSE;
	}

	buffer = new_buf ();

    	for (temp = 0; temp < 65536; temp++)
    	{
    		pMTemp = get_mob_index(temp);
    		if ( pMTemp && ( pMTemp->group == atoi(argument) ) )
    		{
			found = TRUE;
    			sprintf( buf, "[%5d] %s\n\r", pMTemp->vnum, pMTemp->player_name );
			add_buf( buffer, buf );
    		}
    	}

	if (found)
		page_to_char( buf_string(buffer), ch );
	else
		send_to_char( "No mobs in that group.\n\r", ch );

	free_buf( buffer );
        return FALSE;
    }
    
    return FALSE;
}
*/
REDIT( redit_owner )
{
	ROOM_INDEX_DATA *pRoom;
	
	EDIT_ROOM(ch, pRoom);
	
	if ( argument[0] == '\0' )
	{
		send_to_char( "Syntax:  owner [owner]\n\r", ch );
		send_to_char( "         owner none\n\r", ch );
		return FALSE;
	}
	
	if (!str_cmp(argument, "none"))
		pRoom->owner = g_strdup("");
	else
		pRoom->owner = g_strdup( argument );
	
	send_to_char( "Owner set.\n\r", ch );
	return TRUE;
}

/*
MEDIT ( medit_addmprog )
{
  int value;
  MOB_INDEX_DATA *pMob;
  MPROG_LIST *list;
  MPROG_CODE *code;
  char trigger[MAX_STRING_LENGTH];
  char phrase[MAX_STRING_LENGTH];
  char num[MAX_STRING_LENGTH];

  EDIT_MOB(ch, pMob);
  argument=one_argument(argument, num);
  argument=one_argument(argument, trigger);
  argument=one_argument(argument, phrase);

  if (!is_number(num) || trigger[0] =='\0' || phrase[0] =='\0' )
  {
        send_to_char("Syntax:   addmprog [vnum] [trigger] [phrase]\n\r",ch);
        return FALSE;
  }

  if ( (value = flag_value (mprog_flags, trigger) ) == NO_FLAG)
  {
        send_to_char("Valid flags are:\n\r",ch);
        show_help( ch, "mprog");
        return FALSE;
  }

  if ( ( code =get_mprog_index (atoi(num) ) ) == NULL)
  {
        send_to_char("No such MOBProgram.\n\r",ch);
        return FALSE;
  }

  list                  = new_mprog();
  list->vnum            = atoi(num);
  list->trig_type       = value;
  list->trig_phrase     = g_strdup(phrase);
  list->code            = code->code;
  SET_BIT(pMob->mprog_flags,value);
  list->next            = pMob->mprogs;
  pMob->mprogs          = list;

  send_to_char( "Mprog Added.\n\r",ch);
  return TRUE;
}

MEDIT ( medit_delmprog )
{
    MOB_INDEX_DATA *pMob;
    MPROG_LIST *list;
    MPROG_LIST *list_next;
    char mprog[MAX_STRING_LENGTH];
    int value;
    int cnt = 0;

    EDIT_MOB(ch, pMob);

    one_argument( argument, mprog );
    if (!is_number( mprog ) || mprog[0] == '\0' )
    {
       send_to_char("Syntax:  delmprog [#mprog]\n\r",ch);
       return FALSE;
    }

    value = atoi ( mprog );

    if ( value < 0 )
    {
        send_to_char("Only non-negative mprog-numbers allowed.\n\r",ch);
        return FALSE;
    }

    if ( !(list= pMob->mprogs) )
    {
        send_to_char("MEdit:  Non existant mprog.\n\r",ch);
        return FALSE;
    }

    if ( value == 0 )
    {
	REMOVE_BIT(pMob->mprog_flags, pMob->mprogs->trig_type);
        list = pMob->mprogs;
        pMob->mprogs = list->next;
        free_mprog( list );
    }
    else
    {
        while ( (list_next = list->next) && (++cnt < value ) )
                list = list_next;

        if ( list_next )
        {
		REMOVE_BIT(pMob->mprog_flags, list_next->trig_type);
                list->next = list_next->next;
                free_mprog(list_next);
        }
        else
        {
                send_to_char("No such mprog.\n\r",ch);
                return FALSE;
        }
    }

    send_to_char("Mprog removed.\n\r", ch);
    return TRUE;
}
*/
REDIT( redit_room )
{
	ROOM_INDEX_DATA *room;
	int value;
	
	EDIT_ROOM(ch, room);
	
	if ( (value = flag_value( room_flags, argument )) == NO_FLAG )
	{
		send_to_char( "Sintaxis: room [flags]\n\r", ch );
		return FALSE;
	}
	
	TOGGLE_BIT(room->room_flags, value);
	send_to_char( "Room flags toggled.\n\r", ch );
	return TRUE;
}

REDIT( redit_sector )
{
	ROOM_INDEX_DATA *room;
	int value;
	
	EDIT_ROOM(ch, room);
	
	if ( (value = flag_value( sector_flags, argument )) == NO_FLAG )
	{
		send_to_char( "Sintaxis: sector [tipo]\n\r", ch );
		return FALSE;
	}
	
	room->sector_type = value;
	send_to_char( "Sector type set.\n\r", ch );
	
	return TRUE;
}

extern int port,control; /* db.c */

void echocp()
{
	GSList *desc_list = NULL;
	DESCRIPTOR_DATA *d;

	for ( desc_list = descriptor_list; desc_list != NULL; desc_list = g_slist_next(desc_list) )
	{
		d = (DESCRIPTOR_DATA*)desc_list->data;
		write_to_descriptor (d->descriptor, "\n\rCOPYOVER STARTED PLEASE REMAIN SEATED.\n\r",0);
		
	}
}

void do_copyover (CHAR_DATA *ch, char * argument)
{
	FILE *fp;
	DESCRIPTOR_DATA *d;
	CHAR_DATA *och;
	char buf [100], buf2[100];
	char copyover_info[MAX_STRING_LENGTH];
	GSList *desc_list;
	
	fp = fopen (COPYOVER_FILE, "w");
	
	if (!fp)
	{
		send_to_char ("Copyover file not writeable, aborted.\n\r",ch);
		bug ("Could not write to copyover file",0);
		return;
	}
	
	/**
	 * CHANGE TO WRITE_TO_DESCRIPTOR!!!
	 */
	echocp();
	
	/* For each playing descriptor, save its state */
	for ( desc_list = descriptor_list; desc_list != NULL; desc_list = g_slist_next(desc_list) )
	{
		d = (DESCRIPTOR_DATA*)desc_list->data;
		och = d->character;
		
		if (och != NULL && IS_NPC(och))
		{
			bug("Wierdness found in the descriptor list.. please look.",0);
			continue;
		}
			
		if (!d->character || d->connected < 0) /* drop those logging on */
		{
			write_to_buffer (d, "\n\rSorry, we are rebooting. Come back in a few minutes.\n\r", 0);
			close_socket(d); /* throw'em out */
		}
		else
		{
			fprintf (fp, "%d %s %s\n", d->descriptor, och->name->str, d->host->str);
			sprintf(copyover_info, "Copyover Info WRITE, Name: %s Host: %s", och->name->str, d->host->str);
			bug(copyover_info,0);
			save_char_obj (och);
			//Flush the buffer...
			write_to_buffer (d, "\n\r", 2);
		}
	}
	g_slist_free(desc_list);
	fprintf (fp, "-1\n");
	fclose (fp);
	
	/* Close reserve and other always-open files and release other resources */
	
	fclose (fpReserve);
	
	//Free up lists back to the system.
	destroy_memory_chunck();
	
	/* exec - descriptors are inherited */
	
	sprintf (buf, "%d", port);
	sprintf (buf2, "%d", control);
	execl (EXE_FILE, "lurf", buf, "copyover", buf2, (char *) NULL);
	
	/* Failed - sucessful exec will not return */
	
	do_echo(ch,"Copyover FAILED!\n\r");
	
	/* Here you might want to reopen fpReserve */
}

/* Recover from a copyover - load players */
void copyover_recover ()
{
	DESCRIPTOR_DATA *d;
	FILE *fp;
	char copyover_info[MAX_STRING_LENGTH];
	char name [100];
	char host[MAX_STRING_LENGTH];
	int desc;
	bool fOld;
	
	log_string2("Copyover recovery initiated");
	
	fp = fopen (COPYOVER_FILE, "r");
	
	if (!fp) /* there are some descriptors open which will hang forever then ? */
	{
		log_string2("Copyover file not found. Exitting.\n\r");
		exit (1);
	}
	
	unlink (COPYOVER_FILE); /* In case something crashes - doesn't prevent reading	*/
	
	for (;;)
	{
		fscanf (fp, "%d %s %s\n", &desc, name, host);
		sprintf(copyover_info, "Copyover Info READ, Name: %s Host: %s", name, host);
		bug(copyover_info,0);
		if (desc == -1)
			break;
		
		/* Write something, and check if it goes error-free */		
		if (!write_to_descriptor (desc, "\n\rRestoring from copyover...\n\r",0))
		{
			sprintf(copyover_info, "lost descriptor.");
			bug(copyover_info,0);
			close (desc); /* nope */
			continue;
		}
		
		d = new_descriptor();
		init_copyover_descriptor (d,desc); 
		
		d->descriptor = desc;
		d->host = g_string_assign(d->host,host);
		d->connected = CON_COPYOVER_RECOVER; /* -15, so close_socket frees the char */
		
		descriptor_list = g_slist_append(descriptor_list,d);
		
		/* Now, find the pfile */
		copyover_start = TRUE;
		
		fOld = load_char_obj (d, name);

		copyover_start = FALSE;
		
		if (!fOld) /* Player file not found?! */
		{
			write_to_descriptor (desc, "\n\rSomehow, your character was lost in the copyover. Sorry.\n\r", 0);
			close_socket (d);			
		}
		else /* ok! */
		{
			write_to_descriptor (desc, "\n\rCopyover recovery complete.\n\r",0);
			
			/* Just In Case */
			if (!d->character->in_room)
				d->character->in_room = get_room_index (ROOM_VNUM_TEMPLE);
			
/*
			check_playing( d, d->character->name );
			check_kickoff( d, d->character->name, FALSE ) ;
			check_player_ID( d, d->character->name, FALSE );
*/
			
			/* Insert in the char_list */
			d->character->next = char_list;
			char_list = d->character;
			
			char_to_room (d->character, d->character->in_room);
			do_look (d->character, "");
			act ("$n materializes!", d->character, NULL, NULL, TO_ROOM);
			d->connected = CON_PLAYING;
		}
		
	}
	mudsetting->last_proc_logged = 81;
	return;
}
#if defined(unix)
void ispell_init()
{
	char ignore_buf[1024];
	
	pipe(to);
	pipe(from);
	
	ispell_pid = fork();
	if (ispell_pid < 0)
	{
		char errmsg[MAX_STRING_LENGTH];
		sprintf(errmsg, "ispell_init: fork: %s", strerror(errno));
		bug(errmsg, 0);
	}
	else if (ispell_pid == 0)   /* child */
	{
		int i;
		dup2(to[0], 0);         /* this is where we read commands from - make
                                   it stdin */
		close(to[0]);
		close(to[1]);
		
		dup2(from[1], 1);       /* this is where we write stuff to */
		close(from[0]);
		close(from[1]);
		
        /* Close all the other files */
		for (i = 2; i < 255; i++)
			close(i);
		
		execlp("ispell", "ispell", "-a", (char *)
			NULL);
		abort();
	}
	else
	{                           /* ok ! */
		close(to[0]);
		close(from[1]);
		ispell_out = fdopen(to[1], "w");
		setbuf(ispell_out, NULL);
#if !defined( sun )             /* that ispell on sun gives no (c) msg */
		read(from[0], ignore_buf, 1024);
#endif
	}
}

void ispell_done()
{
	if (ispell_pid != -1)
	{
		fprintf(ispell_out, "#\n");
		fclose(ispell_out);
		close(from[0]);
		waitpid(ispell_pid, NULL, 0);
		ispell_pid = -1;
	}
}

char *get_ispell_line(char *word)
{
	static char buf[ISPELL_BUF_SIZE];
	char buf2[MSL];
	int len;
	
	if (ispell_pid == -1)
		return NULL;
	
	if (word)
	{
		fprintf(ispell_out, "^%s\n", word);
		fflush(ispell_out);
	}
	
	len = read(from[0], buf2, ISPELL_BUF_SIZE);
	buf2[len] = '\0';
	
    /* Read up to max 1024 characters here */
	if (sscanf(buf2, "%" Stringify(ISPELL_BUF_SIZE) "[^\n]\n\n", buf) != 1)
		return NULL;
	
	return buf;
}

void do_ispell(CHAR_DATA * ch, char *argument)
{
	char *pc,
		buf[MSL];
	
	if (ispell_pid <= 0)
	{
		send_to_char("ispell is not running.\n\r", ch);
		return;
	}
	
	if (!argument[0] || strchr(argument, ' '))
	{
		send_to_char("Invalid input.\n\r", ch);
		return;
	}
	
	if (argument[0] == '+')
	{
		for (pc = argument + 1; *pc; pc++)
			if (!isalpha(*pc))
			{
				sprintf(buf, "'%c' is not a letter.\n\r",
					*pc);
				send_to_char(buf, ch);
				return;
			}
		fprintf(ispell_out, "*%s\n", argument + 1);
		fflush(ispell_out);
		return;                 /* we assume everything is OK.. better be so! */
	}
	
	pc = get_ispell_line(argument);
	if (!pc)
	{
		send_to_char("ispell: failed.\n\r", ch);
		return;
	}
	
	switch (pc[0])
	{
		case '*':
		case '+':               /* root */
		case '-':               /* compound */
			send_to_char("Correct.\n\r", ch);
			break;
			
		case '&':               /* miss */
			sprintf(buf, "Not found. Possible words: %s\n\r", strchr(pc, ':') + 1);
			send_to_char(buf, ch);
			break;
			
		case '?':               /* guess */
			sprintf(buf, "Not found. Possible words: %s\n\r",
				strchr(pc, ':') + 1);
			send_to_char(buf, ch);
			break;
			
		case '#':               /* none */
			send_to_char("Unable to find anything that matches.\n\r", ch);
			break;
			
		default:
			sprintf(buf, "Weird output from ispell: %s\n\r",
				pc);
			send_to_char(buf, ch);
	}
}

/*
* Function to add ispell support within an editor
* It takes the string the char is currently editing as it's source,
* and passes it a word at a time to ispell.  A check is kept on
* what words have been checked to prevent repetition of the same
* 'error', mainly useful with proper names etc.
*/
void ispell_string(CHAR_DATA * ch)
{
	char *result;
	char word[MSL];
	char checked_list[MSL];
	char buf[MSL];
	char *str;
	int i = 0;
	bool errors = FALSE;
	GString *buffer;
	
	buffer = g_string_new("");
	str_cpy(checked_list, "");
	
	str = *ch->desc->pString;
	
	while (*str != '\0')
	{
		while (*str != ' ' && *str != '\0' && *str != '\n' && *str != '\r')
		{
			word[i++] = *str;
			
			str++;
		}
		
		word[i++] = '\0';
		
		if (!is_exact_name(word, checked_list))
		{
			sprintf(checked_list + strlen(checked_list), "%s ", word);
			
			result = get_ispell_line(word);
			
			if (!IS_NULLSTR(result))
			{
				if (result[0] == '&')
				{
					sprintf(buf, "%s failed - Possible words : %s\n\r",
						word, strchr(result, ':'));
					errors = TRUE;
					buffer = g_string_append(buffer, buf);
				}
				
				if (result[0] == '#')
				{
					sprintf(buf, "%s failed - no similar words found.\n\r", word);
					errors = TRUE;
					buffer = g_string_append(buffer, buf);
				}
			}
		}
		str++;
		i = 0;
	}
	send_to_char("\n\r", ch);
	if (errors)
		page_to_char(buffer->str, ch);
	else
		send_to_char("No errors found.\n\r", ch);
	
	g_string_free(buffer,TRUE);
	
	return;
}
#endif
HEDIT( hedit_show )
{
	char buf[500];
	
	HELP_DATA *pHelp;
	EDIT_HELP(ch, pHelp);
	
	if (!pHelp) { /* thnx to Rob for this check! */
		send_to_char( "{rYou're not currently editing a help!{x\n\r", ch );
		return FALSE;
	}
	sprintf(buf, " %s\n\r Level: %d\n\r", pHelp->keyword, pHelp->level); 
	send_to_char( buf, ch);
	send_to_char( pHelp->text, ch);
	return TRUE;
}

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;
	}
	
	if (!pHelp) { /* thnx to Rob for this check! */
		send_to_char( "{rYou're not currently editing a help!{x\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 = g_strdup(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')
	{
		if (!pHelp) {  /* thnx to rob for this crash fix! */
			send_to_char( "You're not currently editing a help!\n\r", ch );
			return FALSE;
		}
		
		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("{r Synatx: Hedit change '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 Help found, Entering String editor{x\n\r", ch);
		
			ch->desc->pEdit		= (void *)tHelp;
			send_to_char( tHelp->keyword, ch);
			send_to_char("{x\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)
{
	GString *output;
	HELP_DATA *pHelp;
	char buf[MAX_STRING_LENGTH];
	int bob, level;
	bob = 0;
	output = g_string_new("");
	
	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);
		output = g_string_append(output, buf);
		if (++bob % 3 == 0)  /* column check */
			output = g_string_append(output, "\n\r");
	}
	page_to_char(output->str,ch);
	g_string_free(output,TRUE);
	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 = g_strdup(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 = g_strdup(" ");
	
	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;
}

MEDIT ( medit_addmprog )
{
  int value;
  MOB_INDEX_DATA *pMob;
  MPROG_LIST *list;
  MPROG_CODE *code;
  char trigger[MAX_STRING_LENGTH];
  char phrase[MAX_STRING_LENGTH];
  char num[MAX_STRING_LENGTH];

  EDIT_MOB(ch, pMob);
  argument=one_argument(argument, num);
  argument=one_argument(argument, trigger);
  argument=one_argument(argument, phrase);

  if (!is_number(num) || trigger[0] =='\0' || phrase[0] =='\0' )
  {
        send_to_char("Syntax:   addmprog [vnum] [trigger] [phrase]\n\r",ch);
        return FALSE;
  }

  if ( (value = flag_value (mprog_flags, trigger) ) == NO_FLAG)
  {
        send_to_char("Valid flags are:\n\r",ch);
        show_help( ch, "mprog");
        return FALSE;
  }

  if ( ( code =get_mprog_index (atoi(num) ) ) == NULL)
  {
        send_to_char("No such MOBProgram.\n\r",ch);
        return FALSE;
  }

  list                  = new_mprog();
  list->vnum            = atoi(num);
  list->trig_type       = value;
  list->trig_phrase     = g_string_assign(list->trig_phrase,phrase);
  list->code            = code->code;
  SET_BIT(pMob->mprog_flags,value);
  list->next            = pMob->mprogs;
  pMob->mprogs          = list;

  send_to_char( "Mprog Added.\n\r",ch);
  return TRUE;
}

MEDIT ( medit_delmprog )
{
    MOB_INDEX_DATA *pMob;
    MPROG_LIST *list;
    MPROG_LIST *list_next;
    char mprog[MAX_STRING_LENGTH];
    int value;
    int cnt = 0;

    EDIT_MOB(ch, pMob);

    one_argument( argument, mprog );
    if (!is_number( mprog ) || mprog[0] == '\0' )
    {
       send_to_char("Syntax:  delmprog [#mprog]\n\r",ch);
       return FALSE;
    }

    value = atoi ( mprog );

    if ( value < 0 )
    {
        send_to_char("Only non-negative mprog-numbers allowed.\n\r",ch);
        return FALSE;
    }

    if ( !(list= pMob->mprogs) )
    {
        send_to_char("MEdit:  Non existant mprog.\n\r",ch);
        return FALSE;
    }

    if ( value == 0 )
    {
	REMOVE_BIT(pMob->mprog_flags, pMob->mprogs->trig_type);
        list = pMob->mprogs;
        pMob->mprogs = list->next;
        free_mprog( list );
    }
    else
    {
        while ( (list_next = list->next) && (++cnt < value ) )
                list = list_next;

        if ( list_next )
        {
		REMOVE_BIT(pMob->mprog_flags, list_next->trig_type);
                list->next = list_next->next;
                free_mprog(list_next);
        }
        else
        {
                send_to_char("No such mprog.\n\r",ch);
                return FALSE;
        }
    }

    send_to_char("Mprog removed.\n\r", ch);
    return TRUE;
}


OEDIT ( oedit_addmprog )
{
  int value;
  OBJ_INDEX_DATA *pMob;
  MPROG_LIST *list;
  MPROG_CODE *code;
  char trigger[MAX_STRING_LENGTH];
  char phrase[MAX_STRING_LENGTH];
  char num[MAX_STRING_LENGTH];

  EDIT_OBJ(ch, pMob);
  argument=one_argument(argument, num);
  argument=one_argument(argument, trigger);
  argument=one_argument(argument, phrase);

  if (!is_number(num) || trigger[0] =='\0' || phrase[0] =='\0' )
  {
        send_to_char("Syntax:   addmprog [vnum] [trigger] [phrase]\n\r",ch);
        return FALSE;
  }

  if ( (value = flag_value (mprog_obj_flags, trigger) ) == NO_FLAG)
  {
        send_to_char("Valid flags are:\n\r",ch);
        show_help( ch, "mprog");
        return FALSE;
  }

  if ( ( code =get_mprog_index (atoi(num) ) ) == NULL)
  {
        send_to_char("No such MUDProgram.\n\r",ch);
        return FALSE;
  }

  list                  = new_mprog();
  list->vnum            = atoi(num);
  list->trig_type       = value;
  list->trig_phrase     = g_string_assign(list->trig_phrase,phrase);
  list->code            = code->code;
  SET_BIT(pMob->mprog_flags,value);
  list->next            = pMob->mprogs;
  pMob->mprogs          = list;

  send_to_char( "Mprog Added.\n\r",ch);
  return TRUE;
}

OEDIT ( oedit_delmprog )
{
    OBJ_INDEX_DATA *pMob;
    MPROG_LIST *list;
    MPROG_LIST *list_next;
    char mprog[MAX_STRING_LENGTH];
    int value;
    int cnt = 0;

    EDIT_OBJ(ch, pMob);

    one_argument( argument, mprog );
    if (!is_number( mprog ) || mprog[0] == '\0' )
    {
       send_to_char("Syntax:  delmprog [#mprog]\n\r",ch);
       return FALSE;
    }

    value = atoi ( mprog );

    if ( value < 0 )
    {
        send_to_char("Only non-negative mprog-numbers allowed.\n\r",ch);
        return FALSE;
    }

    if ( !(list= pMob->mprogs) )
    {
        send_to_char("MEdit:  Non existant mprog.\n\r",ch);
        return FALSE;
    }

    if ( value == 0 )
    {
	REMOVE_BIT(pMob->mprog_flags, pMob->mprogs->trig_type);
        list = pMob->mprogs;
        pMob->mprogs = list->next;
        free_mprog( list );
    }
    else
    {
        while ( (list_next = list->next) && (++cnt < value ) )
                list = list_next;

        if ( list_next )
        {
		REMOVE_BIT(pMob->mprog_flags, list_next->trig_type);
                list->next = list_next->next;
                free_mprog(list_next);
        }
        else
        {
                send_to_char("No such mprog.\n\r",ch);
                return FALSE;
        }
    }

    send_to_char("Mprog removed.\n\r", ch);
    return TRUE;
}

REDIT ( redit_addmprog )
{
  int value;
  ROOM_INDEX_DATA *pMob;
  MPROG_LIST *list;
  MPROG_CODE *code;
  char trigger[MAX_STRING_LENGTH];
  char phrase[MAX_STRING_LENGTH];
  char num[MAX_STRING_LENGTH];

  EDIT_ROOM(ch, pMob);
  argument=one_argument(argument, num);
  argument=one_argument(argument, trigger);
  argument=one_argument(argument, phrase);

  if (!is_number(num) || trigger[0] =='\0' || phrase[0] =='\0' )
  {
        send_to_char("Syntax:   addmprog [vnum] [trigger] [phrase]\n\r",ch);
        return FALSE;
  }

  if ( (value = flag_value (mprog_room_flags, trigger) ) == NO_FLAG)
  {
        send_to_char("Valid flags are:\n\r",ch);
        show_help( ch, "mprog");
        return FALSE;
  }

  if ( ( code =get_mprog_index (atoi(num) ) ) == NULL)
  {
        send_to_char("No such MOBProgram.\n\r",ch);
        return FALSE;
  }

  list                  = new_mprog();
  list->vnum            = atoi(num);
  list->trig_type       = value;
  list->trig_phrase     = g_string_assign(list->trig_phrase,phrase);
  list->code            = code->code;
  SET_BIT(pMob->mprog_flags,value);
  list->next            = pMob->mprogs;
  pMob->mprogs          = list;

  send_to_char( "Mprog Added.\n\r",ch);
  return TRUE;
}

REDIT ( redit_delmprog )
{
    ROOM_INDEX_DATA *pMob;
    MPROG_LIST *list;
    MPROG_LIST *list_next;
    char mprog[MAX_STRING_LENGTH];
    int value;
    int cnt = 0;

    EDIT_ROOM(ch, pMob);

    one_argument( argument, mprog );
    if (!is_number( mprog ) || mprog[0] == '\0' )
    {
       send_to_char("Syntax:  delmprog [#mprog]\n\r",ch);
       return FALSE;
    }

    value = atoi ( mprog );

    if ( value < 0 )
    {
        send_to_char("Only non-negative mprog-numbers allowed.\n\r",ch);
        return FALSE;
    }

    if ( !(list= pMob->mprogs) )
    {
        send_to_char("MEdit:  Non existant mprog.\n\r",ch);
        return FALSE;
    }

    if ( value == 0 )
    {
	REMOVE_BIT(pMob->mprog_flags, pMob->mprogs->trig_type);
        list = pMob->mprogs;
        pMob->mprogs = list->next;
        free_mprog( list );
    }
    else
    {
        while ( (list_next = list->next) && (++cnt < value ) )
                list = list_next;

        if ( list_next )
        {
		REMOVE_BIT(pMob->mprog_flags, list_next->trig_type);
                list->next = list_next->next;
                free_mprog(list_next);
        }
        else
        {
                send_to_char("No such mprog.\n\r",ch);
                return FALSE;
        }
    }

    send_to_char("Mprog removed.\n\r", ch);
    return TRUE;
}