area/
build/testing/
log/
player/
player/backup/
/***************************************************************************
 *  File: olc.c                                                            *
 *                                                                         *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 *                                                                         *
 *  This code was freely distributed with the The Isles 1.1 source code,   *
 *  and has been used here for OLC - OLC would not be what it is without   *
 *  all the previous coders who released their source code.                *
 *                                                                         *
 ***************************************************************************/
#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>
#include <time.h>
#include <merc.h>
#include <olc.h>
#include <tables.h>
//#include <actaffect.h>
#include <recycle.h>
#include <interp.h>


/*External calls since I can't figure out why i can't put these in OLC.h */
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 ) );

/*
 * Local functions.
 */

AREA_DATA *get_area_data	args( ( int vnum ) );


/* Executed from comm.c.  Minimizes compiling when changes are made. */
bool run_olc_editor( DESCRIPTOR_DATA *d )
{
    switch ( d->editor )
    {
    case ED_AREA:
	aedit( d->character, d->incomm );
	break;
    case ED_ROOM:
	redit( d->character, d->incomm );
	break;
    case ED_OBJECT:
	oedit( d->character, d->incomm );
	break;
    case ED_MOBILE:
	medit( d->character, d->incomm );
	break;
    case ED_MPCODE:
	mpedit( d->character, d->incomm );
	break;
    case ED_HELP:
	hedit( d->character, d->incomm );
	break;
    default:
	return FALSE;
    }
    return TRUE;
}



char *olc_ed_name( CHAR_DATA *ch )
{
    static char buf[10];
    
    buf[0] = '\0';
    switch (ch->desc->editor)
    {
    case ED_AREA:
	sprintf( buf, "AEdit" );
	break;
    case ED_ROOM:
	sprintf( buf, "REdit" );
	break;
    case ED_OBJECT:
	sprintf( buf, "OEdit" );
	break;
    case ED_MOBILE:
	sprintf( buf, "MEdit" );
	break;
    case ED_MPCODE:
	sprintf( buf, "MPEdit" );
	break;
    case ED_HELP:
	sprintf( buf, "HEdit" );
	break;
    default:
	sprintf( buf, " " );
	break;
    }
    return buf;
}



char *olc_ed_vnum( CHAR_DATA *ch )
{
    AREA_DATA *pArea;
    ROOM_INDEX_DATA *pRoom;
    OBJ_INDEX_DATA *pObj;
    MPROG_CODE *pMprog;
    MOB_INDEX_DATA *pMob;
    static char buf[10];
	
    buf[0] = '\0';
    switch ( ch->desc->editor )
    {
    case ED_AREA:
	pArea = (AREA_DATA *)ch->desc->pEdit;
	sprintf( buf, "%d", pArea ? pArea->vnum : 0 );
	break;
    case ED_ROOM:
	pRoom = ch->in_room;
	sprintf( buf, "%d", pRoom ? pRoom->vnum : 0 );
	break;
    case ED_OBJECT:
	pObj = (OBJ_INDEX_DATA *)ch->desc->pEdit;
	sprintf( buf, "%d", pObj ? pObj->vnum : 0 );
	break;
    case ED_MOBILE:
	pMob = (MOB_INDEX_DATA *)ch->desc->pEdit;
	sprintf( buf, "%d", pMob ? pMob->vnum : 0 );
	break;
    case ED_MPCODE:
	pMprog = (MPROG_CODE *)ch->desc->pEdit;
	sprintf( buf, "%d", pMprog ? pMprog->vnum : 0 );
	break;
    default:
	sprintf( buf, " " );
	break;
    }

    return buf;
}

/*****************************************************************************
 Name:		show_olc_cmds
 Purpose:	Format up the commands from given table.
 Called by:	show_commands(olc_act.c).
 ****************************************************************************/

void show_olc_cmds( CHAR_DATA *ch, const struct olc_cmd_type *olc_table )
{
    char buf  [ MAX_STRING_LENGTH ];
    char buf1 [ MAX_STRING_LENGTH ];
    int  cmd;
    int  col;
 
    buf1[0] = '\0';
    col = 0;
    for (cmd = 0; olc_table[cmd].name != NULL; cmd++)
    {
	sprintf( buf, "%-15.15s", olc_table[cmd].name );
	strcat( buf1, buf );
	if ( ++col % 5 == 0 )
	    strcat( buf1, "\n\r" );
    }
 
    if ( col % 5 != 0 )
	strcat( buf1, "\n\r" );

    send_to_char( buf1, ch );
    return;
}

/*****************************************************************************
 Name:		show_commands
 Purpose:	Display all olc commands.
 Called by:	olc interpreters.
 ****************************************************************************/

bool show_commands( CHAR_DATA *ch, char *argument )
{
    switch (ch->desc->editor)
    {
	case ED_AREA:
	    show_olc_cmds( ch, aedit_table );
	    break;
	case ED_ROOM:
	    show_olc_cmds( ch, redit_table );
	    break;
	case ED_OBJECT:
	    show_olc_cmds( ch, oedit_table );
	    break;
	case ED_MOBILE:
	    show_olc_cmds( ch, medit_table );
	    break;
	case ED_MPCODE:
	    show_olc_cmds( ch, mpedit_table );
	    break;
	case ED_HELP:
	    show_olc_cmds( ch, hedit_table );
	    break;
    }

    return FALSE;
}


/*****************************************************************************
 *                           Interpreter Tables.                             *
 *****************************************************************************/

const struct olc_cmd_type aedit_table[] =
{
/*  {   command		function	}, */

    {   "age",		aedit_age	},
    {   "builder",	aedit_builder	}, /* s removed -- Hugin */
    {   "commands",	show_commands	},
    {   "create",	aedit_create	},
    {   "filename",	aedit_file	},
    {   "name",		aedit_name	},
/*  {   "recall",	aedit_recall	},   ROM OLC */
    {	"reset",	aedit_reset	},
    {   "security",	aedit_security	},
    {	"show",		aedit_show	},
    {   "vnum",		aedit_vnum	},
    {   "lvnum",	aedit_lvnum	},
    {   "uvnum",	aedit_uvnum	},
    {   "credits",	aedit_credits	},

    {   "?",		show_help	},
    {   "version",	show_version	},

    {	NULL,		0,		}
};



const struct olc_cmd_type redit_table[] =
{
/*  {   command		function	}, */

    {   "commands",	show_commands	},
    {   "create",	redit_create	},
    {   "desc",		redit_desc	},
    {   "ed",		redit_ed	},
    {   "format",	redit_format	},
    {   "name",		redit_name	},
    {	"show",		redit_show	},

    {   "north",	redit_north	},
    {   "south",	redit_south	},
    {   "east",		redit_east	},
    {   "west",		redit_west	},
    {   "up",		redit_up	},
    {   "down",		redit_down	},

    /* New reset commands. */
    {	"mreset",	redit_mreset	},
    {	"oreset",	redit_oreset	},
    {	"mlist",	redit_mlist	},
    {	"rlist",	redit_rlist	},
    {   "copy",         redit_copy      },
    {	"olist",	redit_olist	},
    {	"mshow",	redit_mshow	},
    {	"oshow",	redit_oshow	},
    {   "addmprog",	redit_addmprog  },  /* ROM */
    {	"delmprog",	redit_delmprog	},  /* ROM */

    {   "?",		show_help	},
    {   "version",	show_version	},

    {	NULL,		0,		}
};



const struct olc_cmd_type oedit_table[] =
{
/*  {   command		function	}, */
    {   "addapply",	oedit_addapply	},
    {   "addaffect",	oedit_addaffect	},
    {   "delaffect",	oedit_delaffect	},
    {   "commands",	show_commands	},
    {   "cost",		oedit_cost	},
    {   "create",	oedit_create	},
    {   "ed",		oedit_ed	},
    {   "long",		oedit_long	},
    {   "name",		oedit_name	},
    {   "short",	oedit_short	},
    {	"show",		oedit_show	},
    {   "v0",		oedit_value0	},
    {   "v1",		oedit_value1	},
    {   "copy",         oedit_copy      },
    {   "delete",       oedit_delete    },
    {   "v2",		oedit_value2	},
    {   "v3",		oedit_value3	},
    //{   "v4",		oedit_value4	},  /* ROM */
    {   "weight",	oedit_weight	},

    {   "extra",        oedit_extra     },  /* ROM */
    {   "wear",         oedit_wear      },  /* ROM */
    {   "type",         oedit_type      },  /* ROM */
    {   "condition",    oedit_condition },  /* ROM */
    {   "addmprog",	oedit_addmprog  },  /* ROM */
    {	"delmprog",	oedit_delmprog	},  /* ROM */

    {   "?",		show_help	},
    {   "version",	show_version	},

    {	NULL,		0,		}
};



const struct olc_cmd_type medit_table[] =
{
/*  {   command		function	}, */

    {   "alignment",	medit_align	},
    {   "commands",	show_commands	},
    {   "create",	medit_create	},
    {   "desc",		medit_desc	},
    {   "level",	medit_level	},
    {   "long",		medit_long	},
    {   "name",		medit_name	},
    {   "shop",		medit_shop	},
    {   "copy",         medit_copy      },
    {   "delete",       medit_delete    },
    {   "short",	medit_short	},
    {	"show",		medit_show	},
    {   "spec",		medit_spec	},

    {   "sex",          medit_sex       },  /* ROM */
    {   "ac",           medit_ac        },  /* ROM */
    {   "act",          medit_act       },  /* ROM */
    {   "stance",       medit_fstyle    },  /* ROM */
    {   "affect",       medit_affect    },  /* ROM */
    {   "mob_con",      medit_mob_con   },  /* ROM */
    {   "hitroll",      medit_hitroll   },  /* ROM */
    {   "hitdice",      medit_hitdice   },  /* ROM */
    {   "damdice",      medit_damdice   },  /* ROM */
    {   "?",		show_help	},
    {   "addmprog",	medit_addmprog  },  /* ROM */
    {	"delmprog",	medit_delmprog	},  /* ROM */
    {   "version",	show_version	},

    {	NULL,		0,		}
};

const struct olc_cmd_type hedit_table[]=
{
	{  "commands", show_commands },
	{  "create", hedit_create    },
	{  "?", show_help  },
	{  "level", hedit_level },
	{  "text", hedit_text },
	{  "index", hedit_index },
	{  "change", hedit_change },
	{  "keyword", hedit_keyword },
	{  "delete", hedit_delete },
        {  "show", hedit_show },
	{  NULL,  0, }
};
/*****************************************************************************
 *                          End Interpreter Tables.                          *
 *****************************************************************************/


/*****************************************************************************
 Name:		get_area_data
 Purpose:	Returns pointer to area with given vnum.
 Called by:	do_aedit(olc.c).
 ****************************************************************************/

AREA_DATA *get_area_data( int vnum )
{
    AREA_DATA *pArea;

    for (pArea = area_first; pArea; pArea = pArea->next )
    {
        if (pArea->vnum == vnum)
            return pArea;
    }

    return 0;
}


/*****************************************************************************
 Name:		edit_done
 Purpose:	Resets builder information on completion.
 Called by:	aedit, redit, oedit, medit(olc.c)
 ****************************************************************************/

bool edit_done( CHAR_DATA *ch )
{
    ch->desc->pEdit = NULL;
    ch->desc->editor = 0;
    return FALSE;
}


/*****************************************************************************
 *                              Interpreters.                                *
 *****************************************************************************/

/* Area Interpreter, called by do_aedit. */
void aedit( CHAR_DATA *ch, char *argument )
{
    AREA_DATA *pArea;
    char command[MAX_INPUT_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    int  cmd;
    int  value;

    EDIT_AREA(ch, pArea);
    smash_tilde( argument );
    str_cpy( arg, argument );
    argument = one_argument( argument, command );

    if ( !IS_BUILDER( ch, pArea ) )
      {
	send_to_char( "AEdit:  Insufficient security to modify area.\n\r", ch );
	edit_done( ch );
	return;
      }

    if ( !str_cmp(command, "done") )
    {
	edit_done( ch );
	return;
    }

    if ( !IS_BUILDER( ch, pArea ) )
    {
	interpret( ch, arg );
	return;
    }

    if ( command[0] == '\0' )
    {
	aedit_show( ch, argument );
	return;
    }

    if ( ( value = flag_value( area_flags, command ) ) != NO_FLAG )
    {
	TOGGLE_BIT(pArea->area_flags, value);

	send_to_char( "Flag toggled.\n\r", ch );
	return;
    }

    /* Search Table and Dispatch Command. */
    for ( cmd = 0; aedit_table[cmd].name != NULL; cmd++ )
    {
	if ( !str_prefix( command, aedit_table[cmd].name ) )
	{
	    if ( (*aedit_table[cmd].olc_fun) ( ch, argument ) )
	    {
		SET_BIT( pArea->area_flags, AREA_CHANGED );
		return;
	    }
	    else
		return;
	}
    }

    /* Default to Standard Interpreter. */
    interpret( ch, arg );
    return;
}



/* Room Interpreter, called by do_redit. */
void redit( CHAR_DATA *ch, char *argument )
{
    ROOM_INDEX_DATA *pRoom;
    AREA_DATA *pArea;
    char arg[MAX_STRING_LENGTH];
    char command[MAX_INPUT_LENGTH];
    int  cmd;
    int  value;

    EDIT_ROOM(ch, pRoom);
    pArea = pRoom->area;

    smash_tilde( argument );
    str_cpy( arg, argument );
    argument = one_argument( argument, command );

    if ( !IS_BUILDER( ch, pArea ) )
    {
        send_to_char( "REdit:  Insufficient security to modify room.\n\r", ch );
	edit_done( ch );
	return;
    }

    if ( !str_cmp(command, "done") )
    {
	edit_done( ch );
	return;
    }

    if ( !IS_BUILDER( ch, pArea ) )
    {
        interpret( ch, arg );
        return;
    }

    if ( command[0] == '\0' )
    {
	redit_show( ch, argument );
	return;
    }

    if ( ( value = flag_value( room_flags, command ) ) != NO_FLAG )
    {
        TOGGLE_BIT(pRoom->room_flags, value);

        SET_BIT( pArea->area_flags, AREA_CHANGED );
        send_to_char( "Room flag toggled.\n\r", ch );
        return;
    }

    if ( ( value = flag_value( sector_flags, command ) ) != NO_FLAG )
    {
        pRoom->sector_type  = value;

        SET_BIT( pArea->area_flags, AREA_CHANGED );
        send_to_char( "Sector type set.\n\r", ch );
        return;
    }

    /* Search Table and Dispatch Command. */
    for ( cmd = 0; redit_table[cmd].name != NULL; cmd++ )
    {
	if ( !str_prefix( command, redit_table[cmd].name ) )
	{
	    if ( (*redit_table[cmd].olc_fun) ( ch, argument ) )
	    {
		SET_BIT( pArea->area_flags, AREA_CHANGED );
		return;
	    }
	    else
		return;
	}
    }

    /* Default to Standard Interpreter. */
    interpret( ch, arg );
    return;
}



/* Object Interpreter, called by do_oedit. */
void oedit( CHAR_DATA *ch, char *argument )
{
    AREA_DATA *pArea;
    OBJ_INDEX_DATA *pObj;
    char arg[MAX_STRING_LENGTH];
    char command[MAX_INPUT_LENGTH];
    int  cmd;
/*  int  value;   ROM */

    smash_tilde( argument );
    str_cpy( arg, argument );
    argument = one_argument( argument, command );

    EDIT_OBJ(ch, pObj);
    pArea = pObj->area;

    if ( !IS_BUILDER( ch, pArea ) )
      {
	send_to_char( "OEdit: Insufficient security to modify area.\n\r", ch );
	edit_done( ch );
	return;
      }

    if ( !str_cmp(command, "done") )
    {
	edit_done( ch );
	return;
    }

    if ( !IS_BUILDER( ch, pArea ) )
    {
	interpret( ch, arg );
	return;
    }

    if ( command[0] == '\0' )
    {
	oedit_show( ch, argument );
	return;
    }

    /* Search Table and Dispatch Command. */
    for ( cmd = 0; oedit_table[cmd].name != NULL; cmd++ )
    {
	if ( !str_prefix( command, oedit_table[cmd].name ) )
	{
	    if ( (*oedit_table[cmd].olc_fun) ( ch, argument ) )
	    {
		SET_BIT( pArea->area_flags, AREA_CHANGED );
		return;
	    }
	    else
		return;
	}
    }

    /* Default to Standard Interpreter. */
    interpret( ch, arg );
    return;
}



/* Mobile Interpreter, called by do_medit. */
void medit( CHAR_DATA *ch, char *argument )
{
    AREA_DATA *pArea;
    MOB_INDEX_DATA *pMob;
    char command[MAX_INPUT_LENGTH];
    char arg[MAX_STRING_LENGTH];
    int  cmd;
/*  int  value;    ROM */

    smash_tilde( argument );
    str_cpy( arg, argument );
    argument = one_argument( argument, command );

    EDIT_MOB(ch, pMob);
    pArea = pMob->area;

    if ( !IS_BUILDER( ch, pArea ) )
      {
	send_to_char( "MEdit: Insufficient security to modify area.\n\r", ch );
	edit_done( ch );
	return;
      }

    if ( !str_cmp(command, "done") )
    {
	edit_done( ch );
	return;
    }

    if ( !IS_BUILDER( ch, pArea ) )
    {
	interpret( ch, arg );
	return;
    }

    if ( command[0] == '\0' )
    {
        medit_show( ch, argument );
        return;
    }

    /* Search Table and Dispatch Command. */
    for ( cmd = 0; medit_table[cmd].name != NULL; cmd++ )
    {
	if ( !str_prefix( command, medit_table[cmd].name ) )
	{
	    if ( (*medit_table[cmd].olc_fun) ( ch, argument ) )
	    {
		SET_BIT( pArea->area_flags, AREA_CHANGED );
		return;
	    }
	    else
		return;
	}
    }

    /* Default to Standard Interpreter. */
    interpret( ch, arg );
    return;
}



const struct editor_cmd_type editor_table[] =
{
/*  {   command		function	}, */

    {   "area",		do_aedit	},
    {   "room",		do_redit	},
    {   "object",	do_oedit	},
    {   "mobile",	do_medit	},
    {   "mpcode",	do_mpedit	},
    {   "help",		do_hedit	},

    {	NULL,		0,		}
};


/* Entry point for all editors. */
void do_olc( CHAR_DATA *ch, char *argument )
{
    char command[MAX_INPUT_LENGTH];
    int  cmd;

    argument = one_argument( argument, command );

    if ( command[0] == '\0' )
    {
        do_help( ch, "olc" );
        return;
    }
 
    /* Search Table and Dispatch Command. */
    for ( cmd = 0; editor_table[cmd].name != NULL; cmd++ )
    {
	if ( !str_prefix( command, editor_table[cmd].name ) )
	{
	    (*editor_table[cmd].do_fun) ( ch, argument );
	    return;
	}
    }

    /* Invalid command, send help. */
    do_help( ch, "olc" );
    return;
}



/* Entry point for editing area_data. */
void do_aedit( CHAR_DATA *ch, char *argument )
{
    AREA_DATA *pArea;
    int value;
    char value2[MAX_STRING_LENGTH];
    char arg[MAX_STRING_LENGTH];

    pArea = ch->in_room->area;

    argument = one_argument(argument,arg);
    if ( is_number( arg ) )
    {
	value = atoi( arg );
	if ( !( pArea = get_area_data( value ) ) )
	{
	    send_to_char( "That area vnum does not exist.\n\r", ch );
	    return;
	}
    }
    else
    {
	if ( !str_cmp( arg, "create" ) )
	{
	    if (!IS_NPC(ch) && (ch->pcdata->security < 5) )
		{
		   send_to_char("Too low security to add areas.\n\r",ch);
		   return;
		}
	    argument    	=   one_argument(argument,value2);
	    value = atoi (value2);
	    if (get_area_data(value) != NULL)
	       {
	        	send_to_char("Already an area there.",ch);
	        	return;
	       }
	    pArea               =   new_area();
	    area_last->next     =   pArea;
	    area_last		=   pArea;	/* Thanks, Walker. */
	    SET_BIT( pArea->area_flags, AREA_ADDED );
	    send_to_char("Area created.\n\r",ch);
	}
    }

    if (!IS_BUILDER(ch,pArea))
    {
    	send_to_char("Your security is too low for this..\n\r",ch);
    	return;
    }

    ch->desc->pEdit = (void *)pArea;
    ch->desc->editor = ED_AREA;
    return;
}



/* Entry point for editing room_index_data. */
void do_redit( CHAR_DATA *ch, char *argument )
{
    ROOM_INDEX_DATA *pRoom, *pRoom2;
    char arg1[MAX_STRING_LENGTH];

    argument = one_argument( argument, arg1 );

    pRoom = ch->in_room;

    if ( !str_cmp( arg1, "reset" ) )
    {
	if ( !IS_BUILDER( ch, pRoom->area ) )
	{
		send_to_char( "You don't have the security for this..\n\r" , ch );
        	return;
	}

	reset_room( pRoom );
	send_to_char( "Room reset.\n\r", ch );
	return;
    }
    else
    if ( !str_cmp( arg1, "create" ) )
    {
	if ( argument[0] == '\0' || atoi( argument ) == 0 )
	{
	    send_to_char( "Syntax:  edit room create [vnum]\n\r", ch );
	    return;
	}

	if ( redit_create( ch, argument ) )
	{
	    char_from_room( ch );
	    char_to_room( ch, (ROOM_INDEX_DATA*)ch->desc->pEdit );
	    SET_BIT( pRoom->area->area_flags, AREA_CHANGED );
	    pRoom = ch->in_room;
	}
    }
    else
    {
	    pRoom2 = get_room_index(atoi(arg1));
    
	    if ( (pRoom2 != NULL) && IS_BUILDER(ch,pRoom2->area) )
	    {
	       char_from_room( ch );
	       char_to_room( ch, pRoom2 );
	       pRoom = ch->in_room;
	    }
	    else
	    if (atoi(arg1) != 0)
	    {
	       send_to_char("Oh what a mess.  That room doesn't exist, or you can't touch it.\n\r",ch);
	       return;
	    }   
    }

    if ( !IS_BUILDER( ch, pRoom->area ) )
    {
	send_to_char( "No way! Not at your security rating..\n\r" , ch );
       	return;
    }

    ch->desc->editor = ED_ROOM;
    return;
}



/* Entry point for editing obj_index_data. */
void do_oedit( CHAR_DATA *ch, char *argument )
{
    OBJ_INDEX_DATA *pObj;
    AREA_DATA *pArea;
    char arg1[MAX_STRING_LENGTH];
    int value;

    if ( IS_NPC(ch) )
	return;

    argument = one_argument( argument, arg1 );

    if ( is_number( arg1 ) )
    {
	value = atoi( arg1 );
	if ( !( pObj = get_obj_index( value ) ) )
	{
	    send_to_char( "OEdit:  That vnum does not exist.\n\r", ch );
	    return;
	}
         
	if ( !IS_BUILDER( ch, pObj->area ) )
	    {
		send_to_char( "Keep your grubby hands off these objects.\n\r" , ch );
	        return;
	    }

	ch->desc->pEdit = (void *)pObj;
	ch->desc->editor = ED_OBJECT;
	return;
    }
    else
    {
	if ( !str_cmp( arg1, "create" ) )
	{
	    value = atoi( argument );
	    if ( argument[0] == '\0' || value == 0 )
	    {
		send_to_char( "Syntax:  edit object create [vnum]\n\r", ch );
		return;
	    }

	    pArea = get_vnum_area( value );

	    if ( !pArea )
	    {
		send_to_char( "OEdit:  That vnum is not assigned an area.\n\r", ch );
		return;
	    }

	    if ( !IS_BUILDER( ch, pArea ) )
	    {
		send_to_char( "What makes you think you're allowed to do this?\n\r" , ch );
	        return;
	    }

	    if ( oedit_create( ch, argument ) )
	    {
		SET_BIT( pArea->area_flags, AREA_CHANGED );
		ch->desc->editor = ED_OBJECT;
	    }
	    return;
	}
    }

    send_to_char( "OEdit:  There is no default object to edit.\n\r", ch );
    return;
}



/* Entry point for editing mob_index_data. */
void do_medit( CHAR_DATA *ch, char *argument )
{
    MOB_INDEX_DATA *pMob;
    AREA_DATA *pArea;
    int value;
    char arg1[MAX_STRING_LENGTH];

    argument = one_argument( argument, arg1 );

    if ( is_number( arg1 ) )
    {
	value = atoi( arg1 );
	if ( !( pMob = get_mob_index( value ) ))
	{
	    send_to_char( "MEdit:  That vnum does not exist.\n\r", ch );
	    return;
	}

	if ( !IS_BUILDER( ch, pMob->area ) )
	{
		send_to_char( "Pick on a mob your own security!\n\r" , ch );
	        return;
	}

	ch->desc->pEdit = (void *)pMob;
	ch->desc->editor = ED_MOBILE;
	return;
    }
    else
    {
	if ( !str_cmp( arg1, "create" ) )
	{
	    value = atoi( argument );
	    if ( arg1[0] == '\0' || value == 0 )
	    {
		send_to_char( "Syntax:  edit mobile create [vnum]\n\r", ch );
		return;
	    }

	    pArea = get_vnum_area( value );

	    if ( !pArea )
	    {
		send_to_char( "OEdit:  That vnum is not assigned an area.\n\r", ch );
		return;
	    }

	    if ( !IS_BUILDER( ch, pArea ) )
	    {
		send_to_char( "Herr Hassan tells us your papers are NOT in order.\n\r" , ch );
	        return;
	    }

	    if ( medit_create( ch, argument ) )
	    {
		SET_BIT( pArea->area_flags, AREA_CHANGED );
		ch->desc->editor = ED_MOBILE;
	    }
	    return;
	}
    }

    send_to_char( "MEdit:  There is no default mobile to edit.\n\r", ch );
    return;
}

void display_resets( CHAR_DATA *ch )
{
	ROOM_INDEX_DATA	*pRoom;
	RESET_DATA		*pReset;
	MOB_INDEX_DATA	*pMob = NULL;
	char 		buf   [ MAX_STRING_LENGTH ];
	char 		final [ MAX_STRING_LENGTH ];
	int 		iReset = 0;
	GSList *ResetList;

	EDIT_ROOM(ch, pRoom);
	final[0]  = '\0';

	send_to_char ( 
			" No.  Loads    Description       Location         Vnum   Mx Mn Description"
			"\n\r"
			"==== ======== ============= =================== ======== ===== ==========="
			"\n\r", ch );

	for ( ResetList = pRoom->reset_list; ResetList; ResetList = g_slist_next(ResetList))
	{
		OBJ_INDEX_DATA  *pObj;
		MOB_INDEX_DATA  *pMobIndex;
		OBJ_INDEX_DATA  *pObjIndex;
		OBJ_INDEX_DATA  *pObjToIndex;
		ROOM_INDEX_DATA *pRoomIndex;
		pReset = (RESET_DATA*)ResetList->data;
		final[0] = '\0';
		sprintf( final, "[%2d] ", ++iReset );

		switch ( pReset->command )
		{
			default:
				sprintf( buf, "Bad reset command: %c.", pReset->command );
				strcat( final, buf );
				break;

			case 'M':
				if ( !( pMobIndex = get_mob_index( pReset->arg1 ) ) )
				{
					sprintf( buf, "Load Mobile - Bad Mob %d\n\r", pReset->arg1 );
					strcat( final, buf );
					continue;
				}

				if ( !( pRoomIndex = get_room_index( pReset->arg3 ) ) )
				{
					sprintf( buf, "Load Mobile - Bad Room %d\n\r", pReset->arg3 );
					strcat( final, buf );
					continue;
				}

				pMob = pMobIndex;
				sprintf( buf, "M[%5d] %-13.13s in room             R[%5d] %2d-%2d %-15.15s\n\r",
						pReset->arg1, pMob->short_descr, pReset->arg3,
						pReset->arg2, pReset->arg4, pRoomIndex->name );
				strcat( final, buf );

				/*
				 * Check for pet shop.
				 * -------------------
				 */
				{
					ROOM_INDEX_DATA *pRoomIndexPrev;

					pRoomIndexPrev = get_room_index( pRoomIndex->vnum - 1 );
					if ( pRoomIndexPrev
							&& IS_SET( pRoomIndexPrev->room_flags, ROOM_PET_SHOP ) )
						final[5] = 'P';
				}

				break;

			case 'O':
				if ( !( pObjIndex = get_obj_index( pReset->arg1 ) ) )
				{
					sprintf( buf, "Load Object - Bad Object %d\n\r",
							pReset->arg1 );
					strcat( final, buf );
					continue;
				}

				pObj       = pObjIndex;

				if ( !( pRoomIndex = get_room_index( pReset->arg3 ) ) )
				{
					sprintf( buf, "Load Object - Bad Room %d\n\r", pReset->arg3 );
					strcat( final, buf );
					continue;
				}

				sprintf( buf, "O[%5d] %-13.13s in room             "
						"R[%5d]       %-15.15s\n\r",
						pReset->arg1, pObj->short_descr,
						pReset->arg3, pRoomIndex->name );
				strcat( final, buf );

				break;

			case 'P':
				if ( !( pObjIndex = get_obj_index( pReset->arg1 ) ) )
				{
					sprintf( buf, "Put Object - Bad Object %d\n\r",
							pReset->arg1 );
					strcat( final, buf );
					continue;
				}

				pObj       = pObjIndex;

				if ( !( pObjToIndex = get_obj_index( pReset->arg3 ) ) )
				{
					sprintf( buf, "Put Object - Bad To Object %d\n\r",
							pReset->arg3 );
					strcat( final, buf );
					continue;
				}

				sprintf( buf,
						"O[%5d] %-13.13s inside              O[%5d] %2d    %-15.15s\n\r",
						pReset->arg1,
						pObj->short_descr,
						pReset->arg3,
						pReset->arg4,
						pObjToIndex->short_descr );
				strcat( final, buf );

				break;

			case 'G':
			case 'E':
				if ( !( pObjIndex = get_obj_index( pReset->arg1 ) ) )
				{
					sprintf( buf, "Give/Equip Object - Bad Object %d\n\r",
							pReset->arg1 );
					strcat( final, buf );
					continue;
				}

				pObj       = pObjIndex;

				if ( !pMob )
				{
					sprintf( buf, "Give/Equip Object - No Previous Mobile\n\r" );
					strcat( final, buf );
					break;
				}

				if ( pMob->pShop )
				{
					sprintf( buf,
							"O[%5d] %-13.13s in the inventory of S[%5d]       %-15.15s\n\r",
							pReset->arg1,
							pObj->short_descr,                           
							pMob->vnum,
							pMob->short_descr  );
				}
				else
					sprintf( buf,
							"O[%5d] %-13.13s %-19.19s M[%5d]       %-15.15s\n\r",
							pReset->arg1,
							pObj->short_descr,
							(pReset->command == 'G') ?
							flag_string( wear_loc_strings, WEAR_NONE )
							: flag_string( wear_loc_strings, pReset->arg3 ),
							pMob->vnum,
							pMob->short_descr );
				strcat( final, buf );

				break;

				/*
				 * Doors are set in rs_flags don't need to be displayed.
				 * If you want to display them then uncomment the new_reset
				 * line in the case 'D' in load_resets in db.c and here.
				 */
			case 'D':
				pRoomIndex = get_room_index( pReset->arg1 );
				sprintf( buf, "R[%5d] %s door of %-19.19s reset to %s\n\r",
						pReset->arg1,
						capitalize( dir_name[ pReset->arg2 ] ),
						pRoomIndex->name,
						flag_string( door_resets, pReset->arg3 ) );
				strcat( final, buf );

				break;
				/*
				 * End Doors Comment.
				 */
			case 'R':
				if ( !( pRoomIndex = get_room_index( pReset->arg1 ) ) )
				{
					sprintf( buf, "Randomize Exits - Bad Room %d\n\r",
							pReset->arg1 );
					strcat( final, buf );
					continue;
				}

				sprintf( buf, "R[%5d] Exits are randomized in %s\n\r",
						pReset->arg1, pRoomIndex->name );
				strcat( final, buf );

				break;
		}
		send_to_char( final, ch );
	}
	g_slist_free(ResetList);
	return;
}



/*****************************************************************************
 Name:		add_reset
 Purpose:	Inserts a new reset in the given index slot.
 Called by:	do_resets(olc.c).
 ****************************************************************************/
void add_reset( ROOM_INDEX_DATA *room, RESET_DATA *pReset, int index )
{
	room->reset_list = g_slist_append(room->reset_list, pReset);
    return;
}



void do_resets( CHAR_DATA *ch, char *argument )
{
	char arg1[MAX_INPUT_LENGTH];
	char arg2[MAX_INPUT_LENGTH];
	char arg3[MAX_INPUT_LENGTH];
	char arg4[MAX_INPUT_LENGTH];
	char arg5[MAX_INPUT_LENGTH];
	char arg6[MAX_INPUT_LENGTH];
	RESET_DATA *pReset = NULL;

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

	if ( !IS_BUILDER( ch, ch->in_room->area ) )
	{
		send_to_char( "Resets: Invalid security for editing this area.\n\r",
				ch );
		return;
	}

	/*
	 * Display resets in current room.
	 * -------------------------------
	 */
	if ( arg1[0] == '\0' )
	{
		if ( ch->in_room->reset_list )
		{
			send_to_char(
					"Resets: M = mobile, R = room, O = object, "
					"P = pet, S = shopkeeper\n\r", ch );
			display_resets( ch );
		}
		else
			send_to_char( "No resets in this room.\n\r", ch );
	}


	/*
	 * Take index number and search for commands.
	 * ------------------------------------------
	 */
	if ( is_number( arg1 ) )
	{
		ROOM_INDEX_DATA *pRoom = ch->in_room;

		/*
		 * Delete a reset.
		 * ---------------
		 */
		if ( !str_cmp( arg2, "delete" ) )
		{
			if ( g_slist_length(ch->in_room->reset_list) <= 0 )
			{
				send_to_char( "No resets in this area.\n\r", ch );
				return;
			}

			pRoom->reset_list = g_slist_remove(pRoom->reset_list,pReset);
			
			free_reset_data( pReset );
			send_to_char( "Reset deleted.\n\r", ch );
		}
		else
			/*
			 * Add a reset.
			 * ------------
			 */
			if ( (!str_cmp( arg2, "mob" ) && is_number( arg3 ))
					|| (!str_cmp( arg2, "obj" ) && is_number( arg3 )) )
			{
				/*
				 * Check for Mobile reset.
				 * -----------------------
				 */
				if ( !str_cmp( arg2, "mob" ) )
				{
					pReset = new_reset_data();
					pReset->command = 'M';
					if (get_mob_index( is_number(arg3) ? atoi( arg3 ) : 1 ) == NULL)
					{
						send_to_char("That mob exists only in your mind.\n\r",ch);
						return;
					}
					pReset->arg1    = atoi( arg3 );
					pReset->arg2    = is_number( arg4 ) ? atoi( arg4 ) : 1; /* Max # */
					pReset->arg3    = ch->in_room->vnum;
					pReset->arg4	= is_number( arg5 ) ? atoi( arg5 ) : 1; /* Min # */
				}
				else
					/*
					 * Check for Object reset.
					 * -----------------------
					 */
					if ( !str_cmp( arg2, "obj" ) )
					{
						pReset = new_reset_data();
						pReset->arg1    = atoi( arg3 );
						/*
						 * Inside another object.
						 * ----------------------
						 */
						if ( !str_prefix( arg4, "inside" ) )
						{
							pReset->command = 'P';
							pReset->arg2    = 0;
							if ((get_obj_index(is_number(arg5)? atoi(arg5) : 1 ))->item_type != ITEM_CONTAINER)
							{
								send_to_char( "Object 2 is no container!\n\r", ch);
								return;
							}
							pReset->arg3    = is_number( arg5 ) ? atoi( arg5 ) : 1;
							pReset->arg4    = is_number( arg6 ) ? atoi( arg6 ) : 1;
						}
						else
							/*
							 * Inside the room.
							 * ----------------
							 */
							if ( !str_cmp( arg4, "room" ) )
							{
								pReset           = new_reset_data();
								pReset->command  = 'O';
								if (get_obj_index(atoi(arg3)) == NULL)
								{
									send_to_char( "Vnum does not exist.\n\r",ch);
									return;
								}
								pReset->arg1     = atoi ( arg3 );
								pReset->arg2     = 0;
								pReset->arg3     = ch->in_room->vnum;
								pReset->arg4     = 0;
							}
							else
								/*
								 * Into a Mobile's inventory.
								 * --------------------------
								 */
							{
								if ( flag_value( wear_loc_flags, arg4 ) == NO_FLAG )
								{
									send_to_char( "Resets: '? wear-loc'\n\r", ch );
									return;
								}
								pReset = new_reset_data();
								if (get_obj_index(atoi(arg3)) == NULL)
								{
									send_to_char( "Vnum does not exist.\n\r",ch);
									return;
								}
								pReset->arg1 = atoi(arg3);
								pReset->arg3 = flag_value( wear_loc_flags, arg4 );
								if ( pReset->arg3 == WEAR_NONE )
									pReset->command = 'G';
								else
									pReset->command = 'E';
							}
					}

				add_reset( ch->in_room, pReset, atoi( arg1 ) );
				send_to_char( "Reset added.\n\r", ch );
			}
			else
			{
				send_to_char( "Syntax: RESET <number> OBJ <vnum> <wear_loc>\n\r", ch );
				send_to_char( "        RESET <number> OBJ <vnum> in <vnum>\n\r", ch );
				send_to_char( "        RESET <number> OBJ <vnum> room\n\r", ch );
				send_to_char( "        RESET <number> MOB <vnum> [< max # >]\n\r", ch );
				send_to_char( "        RESET <number> DELETE\n\r", ch );
			}
	}

	return;
}



/*****************************************************************************
 Name:		do_alist
 Purpose:	Normal command to list areas and display area information.
 Called by:	interpreter(interp.c)
 ****************************************************************************/
void do_alist( CHAR_DATA *ch, char *argument )
{
    char buf    [ MAX_STRING_LENGTH ];
  /*  char result [ MAX_STRING_LENGTH*2 ]; */	/* May need tweaking. */
    GString *output;
    AREA_DATA *pArea;

    output = g_string_new("");
    sprintf( buf, "[%3s] [%-27s] (%-5s-%5s) [%-10s] %3s [%-10s]\n\r",
       "Num", "Area Name", "lvnum", "uvnum", "Filename", "Sec", "Builders" );

    for ( pArea = area_first; pArea; pArea = pArea->next )
    {
	sprintf( buf, "[%3d] %-29.29s (%-5d-%5d) %-12.12s [%d] [%-10.10s]\n\r",
	     pArea->vnum,
	     pArea->name,
	     pArea->min_vnum,
	     pArea->max_vnum,
	     pArea->file_name,
	     pArea->security,
	     pArea->builders );
	     output = g_string_append( output, buf );
    }

    page_to_char(output->str,ch);
    g_string_free(output,TRUE);
    return;
}

void hedit( CHAR_DATA *ch, char *argument )
{
    HELP_DATA *pHelp;
    char command[MAX_INPUT_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    int  cmd;

	if(str_cmp(argument, "change"))
		EDIT_HELP(ch, pHelp);
	smash_tilde( argument );
    str_cpy( arg, argument );
    argument = one_argument( argument, command );

    if ( !str_cmp(command, "done") )
    {
	edit_done( ch );
	return;
    }
     if ( command[0] == '\0' )
    {
	hedit_show( ch, argument );
	return;
    }

       /* Search Table and Dispatch Command. */
    for ( cmd = 0; hedit_table[cmd].name != NULL; cmd++ )
    {
	if ( !str_prefix( command, hedit_table[cmd].name ) )
	{
	    (*hedit_table[cmd].olc_fun) ( ch, argument );
	    return;
	}
    }

    /* Default to Standard Interpreter. */
    interpret( ch, arg );
    return;
}


void do_hedit(CHAR_DATA *ch, char *argument )
{
/* 	HELP_DATA *pHelp; */
char arg1[MAX_INPUT_LENGTH + 20];

    argument = one_argument( argument, arg1 );
if (ch->level < (MAX_LEVEL - 10)){
	send_to_char("huh?\n\r", ch);
return;	}
if (!str_cmp( arg1, "create"))
{
	hedit_create(ch, argument);
	ch->desc->editor = ED_HELP;
	return;
}
else if (!str_cmp( arg1, "change"))
{
	hedit_change(ch, argument);
	ch->desc->editor = ED_HELP;
	return;
}
else if(!str_cmp(arg1, "index"))
{
	hedit_index(ch, argument);
	ch->desc->editor = ED_HELP;
	return;
}
else if(!str_cmp(arg1, "delete"))
{
	hedit_delete(ch, argument);
	ch->desc->editor = ED_HELP;
	return;
}
else if ( !is_number( arg1 ) ) /* thnx to Draknor for this default */
    {    HELP_DATA *pHelp;
        for ( pHelp = help_first; pHelp != NULL; pHelp = pHelp->next )
        {
            if ( is_name( arg1, pHelp->keyword ) )
            {
                ch->desc->pEdit = (void *)pHelp;
                ch->desc->editor = ED_HELP;
                return;
            }
        }
    }
    else
 
{
	send_to_char("Hedit mode entered, no default command or help to edit.\n\r", ch);
	ch->desc->editor = ED_HELP;
	return;
}
}