sunder2.1/clan/
sunder2.1/class/
sunder2.1/class/bak/
sunder2.1/doc/ideas/
sunder2.1/gods/
sunder2.1/log/
sunder2.1/msgbase/
sunder2.1/src/o/
sunder2.1/time/
/***************************************************************************
 *  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.                *
 *                                                                         *
 ***************************************************************************/

/**********************************************************
 *************** S U N D E R M U D *** 2 . 0 **************
 **********************************************************
 * The unique portions of the SunderMud code as well as   *
 * the integration efforts for code from other sources is *
 * based primarily on the efforts of:                     *
 *                                                        *
 * Lotherius <aelfwyne@operamail.com> (Alvin W. Brinson)  *
 *    and many others, see "help sundermud" in the mud.   *
 **********************************************************/

#include "everything.h"
#include "olc.h"

/*
 * Local functions.
 */
AREA_DATA          *get_area_data args ( ( int vnum ) );

/* Executed from comm.c.  Minimizes compiling when changes are made. */
bool run_olc_editor ( DESCRIPTOR_DATA * d )
{
     switch ( d->editor )
     {
     case ED_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: /* MProgs */
          mpedit( d->character, d->incomm );
          break;
     case ED_OPCODE:
          opedit( d->character, d->incomm );
          break;
     case ED_RPCODE:
          rpedit( 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:
          SNP ( buf, "AEdit" );
          break;
     case ED_ROOM:
          SNP ( buf, "REdit" );
          break;
     case ED_OBJECT:
          SNP ( buf, "OEdit" );
          break;
     case ED_MOBILE:
          SNP ( buf, "MEdit" );
          break;
     case ED_MPCODE:
          SNP ( buf, "MPEdit" );
          break;
     case ED_OPCODE:
          SNP( buf, "OPEdit" );
          break;
     case ED_RPCODE:
          SNP( buf, "RPEdit" );
          break;
     case ED_HELP:
          SNP ( buf, "HEdit" );
          break;
     default:
          SNP ( buf, " " );
          break;
     }
     return buf;
}

char     *olc_ed_vnum ( CHAR_DATA * ch )
{
     AREA_DATA          *pArea;
     ROOM_INDEX_DATA    *pRoom;
     OBJ_INDEX_DATA     *pObj;
     MOB_INDEX_DATA     *pMob;
     PROG_CODE *pMprog; /* MProgs */
     PROG_CODE *pOprog;
     PROG_CODE *pRprog;
     HELP_DATA *pHelp;

     static char         buf[10];

     buf[0] = '\0';
     switch ( ch->desc->editor )
     {
     case ED_AREA:
          pArea = ( AREA_DATA * ) ch->desc->pEdit;
          SNP ( buf, "%d", pArea ? pArea->vnum : 0 );
          break;
     case ED_ROOM:
          pRoom = ch->in_room;
          SNP ( buf, "%d", pRoom ? pRoom->vnum : 0 );
          break;
     case ED_OBJECT:
          pObj = ( OBJ_INDEX_DATA * ) ch->desc->pEdit;
          SNP ( buf, "%d", pObj ? pObj->vnum : 0 );
          break;
     case ED_MOBILE:
          pMob = ( MOB_INDEX_DATA * ) ch->desc->pEdit;
          SNP ( buf, "%d", pMob ? pMob->vnum : 0 );
          break;
     case ED_MPCODE: /* MProgs */
          pMprog = (PROG_CODE *)ch->desc->pEdit;
          SNP( buf, "%d", pMprog ? pMprog->vnum : 0 );
          break;
     case ED_OPCODE:
          pOprog = (PROG_CODE *)ch->desc->pEdit;
          SNP( buf, "%d", pOprog ? pOprog->vnum : 0 );
          break;
     case ED_RPCODE:
          pRprog = (PROG_CODE *)ch->desc->pEdit;
          SNP( buf, "%d", pRprog ? pRprog->vnum : 0 );
          break;
     case ED_HELP:
          pHelp = (HELP_DATA *)ch->desc->pEdit;
          SNP( buf, "%s", pHelp ? pHelp->keyword : "" );
          break;
     default:
          SNP ( 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[0] != '\0'; cmd++ )
     {
          SNP ( buf, "%-15.15s", olc_table[cmd].name );
          SLCAT ( buf1, buf );
          if ( ++col % 5 == 0 )
               SLCAT ( buf1, "\n\r" );
     }

     if ( col % 5 != 0 )
          SLCAT ( 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: /* MProgs */
          show_olc_cmds( ch, mpedit_table );
          break;
     case ED_OPCODE:
          show_olc_cmds( ch, opedit_table );
          break;
     case ED_RPCODE:
          show_olc_cmds( ch, rpedit_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},
     {"commands", show_commands},
     {"create", aedit_create},
     {"filename", aedit_file},
     {"flags", aedit_flags},	/* put stupid commands in table - Lotherius */
     {"name", aedit_name},
     {"credits", aedit_credits},
     {"reset", aedit_reset},
     {"security", aedit_security},
     {"show", aedit_show},
     {"vnum", aedit_vnum},
     {"levels", aedit_levels},
     {"zone", aedit_zone},
     {"lvnum", aedit_lvnum},
     {"uvnum", aedit_uvnum},
     {"music", aedit_music},

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

     {"", 0,}
};

const struct olc_cmd_type redit_table[] =
{

/*  {   command		function	}, */

     {"commands", show_commands},
     {"comments", redit_comment },
     {"create", redit_create},
     {"desc", redit_desc},
     {"ed", redit_ed},
     {"flags", redit_flags},	/* Lotherius added */
     {"format", redit_format},
     {"name", redit_name},
     {"sector", redit_sector},
     {"show", redit_show},
     {"used", redit_used},
     {"unused", redit_unused},

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

    /* New reset commands. */
     {"mreset", redit_mreset},
     {"oreset", redit_oreset},
     {"mlist", redit_mlist},
     {"olist", redit_olist},
     {"mshow", redit_mshow},
     {"oshow", redit_oshow},

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

     {"", 0,}
};

const struct olc_cmd_type oedit_table[] =
{

/*  {   command		function	}, */

     {"addaffect", oedit_addaffect},
     {"adddetect", oedit_adddetect},
     {"addprotect", oedit_addprotect},
     {"addapply", oedit_addapply},
     {"commands", show_commands},
     {"comments", oedit_comment },
     {"cost", oedit_cost},
     {"create", oedit_create},
     {"used", oedit_used},
     {"unused", oedit_unused},
     {"default", oedit_default},
     {"delaffect", oedit_delaffect},
     {"delapply", oedit_delaffect},	/* Zeran - yes, looks weird, but works */
     {"ed", oedit_ed},
     {"long", oedit_long},
     {"name", oedit_name},
     {"repop", oedit_repop},
     {"short", oedit_short},
     {"show", oedit_show},
     {"v0", oedit_value0},
     {"v1", oedit_value1},
     {"v2", oedit_value2},
     {"v3", oedit_value3},
     {"v4", oedit_value4},	/* ROM */
     {"weight", oedit_weight},

     {"extra", oedit_extra},	/* ROM */
     {"wear", oedit_wear},	/* ROM */
     {"vflags", oedit_vflags },
     {"type", oedit_type},	/* ROM */
     {"material", oedit_material},	/* ROM */
     {"level", oedit_level},	/* ROM */
     {"condition", oedit_condition},	/* ROM */
     {   "addoprog",     oedit_addoprog  },
     {   "deloprog",     oedit_deloprog  },

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

     {"", 0,}
};

const struct olc_cmd_type medit_table[] =
{

/*  {   command		function	}, */

     {"alignment", medit_align},
     {"commands", show_commands},
     {"comments", medit_comment},
     {"create", medit_create},
     {"used", medit_used},
     {"unused", medit_unused},
     {"default", medit_default},
     {"desc", medit_desc},
     {"level", medit_level},
     {"long", medit_long},
     {"name", medit_name},
     {"shop", medit_shop},
     {"short", medit_short},
     {"show", medit_show},
     {"spec", medit_spec},
     {"sex", medit_sex},		/* ROM */
     {"act", medit_act},		/* ROM */
     {"affect", medit_affect},	/* ROM */
     {"detect", medit_detect},
     {"protect", medit_protect},
     {"form", medit_form},	/* ROM */
     {"part", medit_part},	/* ROM */
     {"imm", medit_imm},		/* ROM */
     {"res", medit_res},		/* ROM */
     {"vuln", medit_vuln},	/* ROM */
     {"material", medit_material},	/* ROM */
     {"off", medit_off},		/* ROM */
     {"size", medit_size},	/* ROM */
     {"hitdice", medit_hitdice},	/* ROM */
     {"manadice", medit_manadice},	/* ROM */
     {"damdice", medit_damdice},	/* ROM */
     {"race", medit_race},	/* ROM */
     {"position", medit_position},	/* ROM */
     {"gold", medit_gold},	/* ROM */
     {"hitroll", medit_hitroll},	/* ROM */
     {"damtype", medit_attack},	/* Zeran - ROM */
     {"teach", medit_teach},	/* Lotherius - Sunder */

     { "addmprog",	medit_addmprog  },  	/* ROM */ /* MProgs */
     { "delmprog",	medit_delmprog	},  	/* ROM */ /* MProgs */

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

     {"", 0,}
};

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

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

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

     return 0;
}

/*****************************************************************************
 Name:		edit_done
 Purpose:	Resets builder information on completion.
 Called by:	aedit, redit, oedit, medit(olc.c)
 ****************************************************************************/
bool edit_done ( CHAR_DATA * ch )
{
     ch->desc->pEdit = NULL;
     ch->desc->editor = 0;
     return FALSE;
}

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

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

     if ( IS_NPC(ch) )
          return;

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

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

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

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

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

    /* Search Table and Dispatch Command. */
     for ( cmd = 0; aedit_table[cmd].name[0] != '\0'; 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;

     if ( IS_NPC(ch) )
          return;

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

     SLCPY ( arg, argument );
     argument = one_argument ( argument, command );

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

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

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

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

    /* Search Table and Dispatch Command. */
     for ( cmd = 0; redit_table[cmd].name[0] != '\0'; 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;

     if ( IS_NPC(ch) )
          return;

     SLCPY ( arg, argument );
     argument = one_argument ( argument, command );

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

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

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

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

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

    /* Search Table and Dispatch Command. */
     for ( cmd = 0; oedit_table[cmd].name[0] != '\0'; 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;

     if ( IS_NPC(ch) )
          return;

     SLCPY ( arg, argument );
     argument = one_argument ( argument, command );

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

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

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

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

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

    /* Search Table and Dispatch Command. */
     for ( cmd = 0; medit_table[cmd].name[0] != '\0'; 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 },
     {   "opcode",       do_opedit       },
     {   "rpcode",       do_rpedit       },
     {"help", do_hedit},
     {"", 0,}
};

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

     if ( IS_NPC(ch) )
          return;

     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[0] != '\0'; 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;

     if ( IS_NPC(ch) )
          return;

     if ( ch->level < MAX_LEVEL )
     {
          send_to_char ( "You must have an implementor create this areafile.\n\r.", ch );
          return;
     }

     pArea = ch->in_room->area;

     if ( is_number ( argument ) )
     {
          value = atoi ( argument );
          if ( !( pArea = get_area_data ( value ) ) )
          {
               send_to_char ( "That area vnum does not exist.\n\r", ch );
               return;
          }
     }
     else
     {
          if ( !str_cmp ( argument, "create" ) )
          {
               pArea = new_area (  );
               area_last->next = pArea;
               area_last = pArea;	/* Thanks, Walker. */
               SET_BIT ( pArea->area_flags, AREA_ADDED );
          }
     }

     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;
     char                arg1[MAX_STRING_LENGTH];

     if ( IS_NPC(ch) )
          return;

     argument = one_argument ( argument, arg1 );

     pRoom = ch->in_room;

     if ( !str_cmp ( arg1, "reset" ) )
     {
          reset_room ( pRoom, TRUE );
          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, ch->desc->pEdit );
               SET_BIT ( pRoom->area->area_flags, AREA_CHANGED );
          }
     }

     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;
          }

          ch->desc->pEdit = ( void * ) pObj;
          ch->desc->editor = ED_OBJECT;
          return;
     }
     else
     {
          if ( !str_cmp ( arg1, "next" ) )
          {
               if ( !( pObj = ( OBJ_INDEX_DATA * ) ch->desc->pEdit ) )
               {
                    send_to_char ( "OEdit: You must edit a beginning Obj.\n\r", ch );
                    return;
               }
               value = pObj->vnum + 1;
               if ( !( pObj = get_obj_index ( value ) ) )
               {
                    send_to_char ( "OEdit: There is no next vnum.\n\r", ch );
                    return;
               }
               ch->desc->pEdit = ( void * ) pObj;
               ch->desc->editor = ED_OBJECT;
               send_to_char ( "Next Object.", ch );
               return;
          }

          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 ( 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];

     if ( IS_NPC(ch) )
          return;

     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;
          }

          ch->desc->pEdit = ( void * ) pMob;
          ch->desc->editor = ED_MOBILE;
          return;
     }
     else
     {
          if ( !str_cmp ( arg1, "next" ) )
          {
               if ( !( pMob = ( MOB_INDEX_DATA * ) ch->desc->pEdit ) )
               {
                    send_to_char
                         ( "MEdit: You must edit a beginning mob.\n\r",
                           ch );
                    return;
               }
               value = pMob->vnum + 1;
               if ( !( pMob = get_mob_index ( value ) ) )
               {
                    send_to_char ( "MEdit: There is no next vnum.\n\r",
                                   ch );
                    return;
               }
               ch->desc->pEdit = ( void * ) pMob;
               ch->desc->editor = ED_MOBILE;
               send_to_char ( "Next Mob.", ch );
               return;
          }

          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 ( 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;

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

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

     for ( pReset = pRoom->reset_first; pReset;
           pReset = pReset->next )
     {
          OBJ_INDEX_DATA     *pObj;
          MOB_INDEX_DATA     *pMobIndex;
          OBJ_INDEX_DATA     *pObjIndex;
          OBJ_INDEX_DATA     *pObjToIndex;
          ROOM_INDEX_DATA    *pRoomIndex;

          final[0] = '\0';
          SNP ( final, "{x[%2d] ", ++iReset );

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

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

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

               pMob = pMobIndex;
               SNP ( buf,
                     "M[%5d] %-13.13s in room             R[%5d] [%4d] %-15.15s \n\r",
                     pReset->arg1, pMob->short_descr,
                     pReset->arg3, pReset->arg2,
                     pRoomIndex->name );
               SLCAT ( 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 ) ) )
               {
                    SNP ( buf, "Load Object - Bad Object %d\n\r",
			  pReset->arg1 );
                    SLCAT ( final, buf );
                    continue;
               }

               pObj = pObjIndex;

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

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

               break;

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

               pObj = pObjIndex;

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

               SNP ( buf,
                     "O[%5d] %-13.13s inside              O[%5d] [%4d] %-15.15s \n\r",
                     pReset->arg1,
                     pObj->short_descr,
                     pReset->arg3,
                     pReset->arg2, pObjToIndex->short_descr );
               SLCAT ( final, buf );

               break;

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

               pObj = pObjIndex;

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

               if ( pMob->pShop )
               {
                    SNP ( buf,
			  "O[%5d] %-13.13s in the inventory of S[%5d] [%4d] %-15.15s \n\r",
			  pReset->arg1,
			  pObj->short_descr,
			  pMob->vnum,
			  pReset->arg2, pMob->short_descr );
               }
               else
                    SNP ( buf,
			  "O[%5d] %-13.13s %-19.19s M[%5d] [%4d] %-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,
			  pReset->arg2, pMob->short_descr );
               SLCAT ( 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 );
               SNP ( 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 ) );
               SLCAT ( final, buf );

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

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

               break;
          }
          send_to_char ( final, ch );
     }

     return;
}

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

     if ( !room->reset_first )
     {
          room->reset_first = pReset;
          room->reset_last = pReset;
          pReset->next = NULL;
          return;
     }

     index--;

     if ( index == 0 )		/* First slot (1) selected. */
     {
          pReset->next = room->reset_first;
          room->reset_first = pReset;
          return;
     }

    /*
     * If negative slot( <= 0 selected) then this will find the last.
     */
     for ( reset = room->reset_first; reset->next;
           reset = reset->next )
     {
          if ( ++iReset == index )
               break;
     }

     pReset->next = reset->next;
     reset->next = pReset;
     if ( !pReset->next )
          room->reset_last = pReset;
     return;
}

/* Zeran - do_resets was doing no checks for valid vnums before ramming
	the resets in...altered to do a few braindeath tests... */
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 );
    /* get additional argument for longest reset commmand */
     argument = one_argument ( argument, arg6 );

    /*
     * Display resets in current room.
     * -------------------------------
     */

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

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

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

	/*
	 * Delete a reset.
	 * ---------------
	 */
          if ( !str_cmp ( arg2, "delete" ) )
          {
               int                 insert_loc = atoi ( arg1 );

               if ( !ch->in_room->reset_first )
               {
                    send_to_char ( "No resets in this area.\n\r", ch );
                    return;
               }

               if ( insert_loc - 1 <= 0 )
               {
                    pReset = pRoom->reset_first;
                    pRoom->reset_first = pRoom->reset_first->next;
                    if ( !pRoom->reset_first )
                         pRoom->reset_last = NULL;
               }
               else
               {
                    int                 iReset = 0;
                    RESET_DATA         *prev = NULL;

                    for ( pReset = pRoom->reset_first;
                          pReset; pReset = pReset->next )
                    {
                         if ( ++iReset == insert_loc )
                              break;
                         prev = pReset;
                    }

                    if ( !pReset )
                    {
                         send_to_char ( "Reset not found.\n\r", ch );
                         return;
                    }

                    if ( prev )
                         prev->next = prev->next->next;
                    else
                         pRoom->reset_first = pRoom->reset_first->next;

                    for ( pRoom->reset_last = pRoom->reset_first;
                          pRoom->reset_last->next;
                          pRoom->reset_last =
                          pRoom->reset_last->next );
               }

               free_reset_data ( pReset );
               send_to_char ( "Reset deleted.\n\r", ch );
          }
          else
	    /*
	     * Add a reset.
	     * ------------
	     */
               if ( ( !str_cmp ( arg2, "mob" ) && is_number ( arg3 ) )
                    || ( !str_cmp ( arg2, "obj" ) &&
                         is_number ( arg3 ) ) )
               {

/*        send_to_char ("Use ORESET or MRESET please.\n\r.",ch);
	return; */
	    /*
	     * Check for Mobile reset.
	     * -----------------------
	     */
                    if ( !str_cmp ( arg2, "mob" ) )
                    {
		/* Zeran - check the mob vnum first */
                         if ( !get_mob_index ( atoi ( arg3 ) ) )
                         {
                              send_to_char
                                   ( "Bad mobile vnum, please try again.\n\r",
                                     ch );
                              return;
                         }
                         pReset = new_reset_data (  );
                         pReset->command = 'M';
                         pReset->arg1 = atoi ( arg3 );
                         pReset->arg2 =
                              is_number ( arg4 ) ? atoi ( arg4 ) : 1;
                         pReset->arg3 = ch->in_room->vnum;
                    }
                    else
		/*
		 * * Check for Object reset.
		 * * -----------------------
		 */
                         if ( !str_cmp ( arg2, "obj" ) )
                         {
		/* Zeran - check object vnum first */
                              if ( !get_obj_index ( atoi ( arg3 ) ) )
                              {
                                   send_to_char
                                        ( "Bad object vnum, please try again.\n\r",
                                          ch );
                                   return;
                              }
                              pReset = new_reset_data (  );
                              pReset->arg1 = atoi ( arg3 );
		/*
		 * * Inside another object.
		 * * ----------------------
		 */
                              if ( !str_prefix ( arg4, "inside" ) )
                              {
                                   pReset->command = 'P';
                                   pReset->arg2 =
                                        is_number ( arg6 ) ? atoi ( arg6 ) : 9999;
                                   pReset->arg3 =
                                        is_number ( arg5 ) ? atoi ( arg5 ) : 1;
		    /* Check inside object vnum */
                                   if ( !get_obj_index ( pReset->arg3 ) )
                                   {
                                        send_to_char ( "Bad inside object vnum, please try again.\n\r",ch);
                                        free_reset_data
                                             ( pReset ); return;
                                   }
                              }
                              else
				   /*
				    * * Inside the room.
				    * * ----------------
				    */
				   if ( !str_cmp ( arg4, "room" ) )
				   {

/*		    pReset           = new_reset_data(); */
                                        pReset->command = 'O';
                                        pReset->arg2 =
                                             is_number ( arg5 ) ?
                                             atoi ( arg5 ) : 9999;
                                        pReset->arg3 =
                                             ch->in_room->vnum;
                                   }
                              else
				   /*
				    * * Into a Mobile's inventory.
				    * * --------------------------
				    */
                              {
				   if ( flag_value
					( wear_loc_flags,
					  arg4 ) == NO_FLAG )
				   {
                                        send_to_char
                                             ( "Resets: '? wear-loc'\n\r",
                                               ch ); return;
                                   }
				   /*   pReset = new_reset_data(); */
				   pReset->arg3 =
                                        flag_value ( wear_loc_flags,
                                                     arg4 );
				   pReset->arg2 =
                                        is_number ( arg5 ) ?
                                        atoi ( arg5 ) : 9999;
				   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
                    ( "Syntax: 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)
 Now Sorts by VNUM.
****************************************************************************/
void do_alist ( CHAR_DATA * ch, char *argument )
{
     AREA_DATA *pArea;
     BUFFER *output;
     int i,x,y;

     output = buffer_new(1000);
     x = MAX_VNUM;
     y = 0;

     bprintf( output, "[%3s] [%-27s] (%-5s-%5s) [%-10s] %3s %3s [%-10s] %s\n\r",
              "Num", "Area Name", "lvnum", "uvnum", "Filename", "Sec", "Zon", "Builders", "Music" );

     for ( i = area_first->vnum; i <= area_last->vnum; i++ )
     {
          for ( pArea = area_first; pArea; pArea = pArea->next )

               if ( pArea->lvnum < x && pArea->lvnum > y )
                    x = pArea->lvnum;

          y = x;
          x = MAX_VNUM;  /* If you have vnums higher than this, make this number bigger */

          for ( pArea = area_first; pArea; pArea = pArea->next )

               if ( y == pArea->lvnum )
               {
                    bprintf( output, "{W[{w%3d{W] {w%-29.29s {W({G%-5d{W-{G%5d{W) {w%-12.12s {W[{R%d{W] {Y%3d{W [{C%-10.10s{W] {w%s\n\r",
                             pArea->vnum,
                             pArea->name,
                             pArea->lvnum,
                             pArea->uvnum,
                             pArea->filename,
                             pArea->security,
                             pArea->zone,
                             pArea->builders,
                             !IS_NULLSTR (pArea->soundfile) ? pArea->soundfile : "" );
               }
     }

     page_to_char( output->data, ch );
     buffer_free(output);
     return;
}