dbna/clans/
dbna/councils/
dbna/deity/
dbna/gods/
dbna/houses/
dbna/space/
/****************************************************************************
 * [S]imulated [M]edieval [A]dventure multi[U]ser [G]ame      |   \\._.//   *
 * -----------------------------------------------------------|   (0...0)   *
 * SMAUG 1.4 (C) 1994, 1995, 1996, 1998  by Derek Snider      |    ).:.(    *
 * -----------------------------------------------------------|    {o o}    *
 * SMAUG code team: Thoric, Altrag, Blodkai, Narn, Haus,      |   / ' ' \   *
 * Scryn, Rennard, Swordbearer, Gorog, Grishnakh, Nivek,      |~'~.VxvxV.~'~*
 * Tricops and Fireblade                                      |             *
 * ------------------------------------------------------------------------ *
 * Merc 2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael        *
 * Chastain, Michael Quan, and Mitchell Tse.                                *
 * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,          *
 * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.     *
 * ------------------------------------------------------------------------ *
 *			 Online Reset Editing Module			    *
 ****************************************************************************/

/*
 * This file relies heavily on the fact that your linked lists are correct,
 * and that pArea->reset_first is the first reset in pArea.  Likewise,
 * pArea->reset_last *MUST* be the last reset in pArea.  Weird and
 * wonderful things will happen if any of your lists are messed up, none
 * of them good.  The most important are your pRoom->contents,
 * pRoom->people, rch->carrying, obj->contains, and pArea->reset_first ..
 * pArea->reset_last.  -- Altrag
 */

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

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "mud.h"


/* Externals */
extern int top_reset;
char *sprint_reset args( ( CHAR_DATA * ch, RESET_DATA * pReset, sh_int num, bool rlist ) );
RESET_DATA *parse_reset args( ( AREA_DATA * tarea, char *argument, CHAR_DATA * ch ) );
int get_wearloc args( ( char *type ) );
int get_trapflag args( ( char *flag ) );
int get_exflag args( ( char *flag ) );
int get_rflag args( ( char *flag ) );

extern char *const wear_locs[];
extern char *const ex_flags[];
#define MAX_OBJ 50
int put_index, obj_index;
int obj_array[MAX_OBJ][2];
int put_array[MAX_OBJ][3];
#define IS_OBJ_TYPE(obj) ( obj->item_type == ITEM_KEYRING \
                         ||obj->item_type == ITEM_QUIVER \
                         ||obj->item_type == ITEM_CONTAINER )

void add_obj_reset args( ( AREA_DATA * pArea, char cm, OBJ_DATA * obj, int v2, int v3 ) );
void instaroom args( ( AREA_DATA * pArea, ROOM_INDEX_DATA * pRoom, bool dodoors ) );
#define RID ROOM_INDEX_DATA
RID *find_room args( ( CHAR_DATA * ch, char *argument, ROOM_INDEX_DATA * pRoom ) );
#undef RID
void edit_reset args( ( CHAR_DATA * ch, char *argument, AREA_DATA * pArea, ROOM_INDEX_DATA * aRoom ) );
#define RD RESET_DATA
RD *find_reset args( ( AREA_DATA * pArea, ROOM_INDEX_DATA * pRoom, int num ) );
#undef RD
void list_resets args( ( CHAR_DATA * ch, AREA_DATA * pArea, ROOM_INDEX_DATA * pRoom, int start, int end ) );



RESET_DATA *find_reset( AREA_DATA * pArea, ROOM_INDEX_DATA * pRoom, int numb )
{
  RESET_DATA *pReset;
  int num = 0;

  for( pReset = pArea->first_reset; pReset; pReset = pReset->next )
    if( is_room_reset( pReset, pRoom, pArea ) && ++num >= numb )
      return pReset;
  return NULL;
}

/* This is one loopy function.  Ugh. -- Altrag */
bool is_room_reset( RESET_DATA * pReset, ROOM_INDEX_DATA * aRoom, AREA_DATA * pArea )
{
  ROOM_INDEX_DATA *pRoom;
  RESET_DATA *reset;
  int pr;

  if( !aRoom )
    return TRUE;
  switch ( pReset->command )
  {
    case 'M':
    case 'O':
      pRoom = get_room_index( pReset->arg3 );
      if( !pRoom || pRoom != aRoom )
        return FALSE;
      return TRUE;
    case 'P':
    case 'T':
    case 'H':
      if( pReset->command == 'H' )
        pr = pReset->arg1;
      else
        pr = pReset->arg3;
      for( reset = pReset->prev; reset; reset = reset->prev )
        if( ( reset->command == 'O' || reset->command == 'P' ||
              reset->command == 'G' || reset->command == 'E' ) &&
            ( !pr || pr == reset->arg1 ) && get_obj_index( reset->arg1 ) )
          break;
      if( reset && is_room_reset( reset, aRoom, pArea ) )
        return TRUE;
      return FALSE;
    case 'B':
      switch ( pReset->arg2 & BIT_RESET_TYPE_MASK )
      {
        case BIT_RESET_DOOR:
        case BIT_RESET_ROOM:
          return ( aRoom->vnum == pReset->arg1 );
        case BIT_RESET_MOBILE:
          for( reset = pReset->prev; reset; reset = reset->prev )
            if( reset->command == 'M' && get_mob_index( reset->arg1 ) )
              break;
          if( reset && is_room_reset( reset, aRoom, pArea ) )
            return TRUE;
          return FALSE;
        case BIT_RESET_OBJECT:
          for( reset = pReset->prev; reset; reset = reset->prev )
            if( ( reset->command == 'O' || reset->command == 'P' ||
                  reset->command == 'G' || reset->command == 'E' ) &&
                ( !pReset->arg1 || pReset->arg1 == reset->arg1 ) && get_obj_index( reset->arg1 ) )
              break;
          if( reset && is_room_reset( reset, aRoom, pArea ) )
            return TRUE;
          return FALSE;
      }
      return FALSE;
    case 'G':
    case 'E':
      for( reset = pReset->prev; reset; reset = reset->prev )
        if( reset->command == 'M' && get_mob_index( reset->arg1 ) )
          break;
      if( reset && is_room_reset( reset, aRoom, pArea ) )
        return TRUE;
      return FALSE;
    case 'D':
    case 'R':
      pRoom = get_room_index( pReset->arg1 );
      if( !pRoom || pRoom->area != pArea || ( aRoom && pRoom != aRoom ) )
        return FALSE;
      return TRUE;
    default:
      return FALSE;
  }
  return FALSE;
}

ROOM_INDEX_DATA *find_room( CHAR_DATA * ch, char *argument, ROOM_INDEX_DATA * pRoom )
{
  char arg[MAX_INPUT_LENGTH];

  if( pRoom )
    return pRoom;
  one_argument( argument, arg );
  if( !is_number( arg ) && arg[0] != '\0' )
  {
    send_to_char( "Reset to which room?\n\r", ch );
    return NULL;
  }
  if( arg[0] == '\0' )
    pRoom = ch->in_room;
  else
    pRoom = get_room_index( atoi( arg ) );
  if( !pRoom )
  {
    send_to_char( "Room does not exist.\n\r", ch );
    return NULL;
  }
  return pRoom;
}

/* Separate function for recursive purposes */
#define DEL_RESET(area, reset, rprev) \
do { \
  rprev = reset->prev; \
  delete_reset(area, reset); \
  reset = rprev; \
  continue; \
} while(0)
void delete_reset( AREA_DATA * pArea, RESET_DATA * pReset )
{
  RESET_DATA *reset;
  RESET_DATA *reset_prev;

  if( pReset->command == 'M' )
  {
    for( reset = pReset->next; reset; reset = reset->next )
    {
      /*
       * Break when a new mob found 
       */
      if( reset->command == 'M' )
        break;
      /*
       * Delete anything mob is holding 
       */
      if( reset->command == 'G' || reset->command == 'E' )
        DEL_RESET( pArea, reset, reset_prev );
      if( reset->command == 'B' &&
          ( reset->arg2 & BIT_RESET_TYPE_MASK ) == BIT_RESET_MOBILE && ( !reset->arg1 || reset->arg1 == pReset->arg1 ) )
        DEL_RESET( pArea, reset, reset_prev );
    }
  }
  else if( pReset->command == 'O' || pReset->command == 'P' || pReset->command == 'G' || pReset->command == 'E' )
  {
    for( reset = pReset->next; reset; reset = reset->next )
    {
      if( reset->command == 'T' && ( !reset->arg3 || reset->arg3 == pReset->arg1 ) )
        DEL_RESET( pArea, reset, reset_prev );
      if( reset->command == 'H' && ( !reset->arg1 || reset->arg1 == pReset->arg1 ) )
        DEL_RESET( pArea, reset, reset_prev );
      /*
       * Delete nested objects, even if they are the same object. 
       */
      if( reset->command == 'P' && ( reset->arg3 > 0 ||
                                     pReset->command != 'P' || reset->extra - 1 == pReset->extra ) &&
          ( !reset->arg3 || reset->arg3 == pReset->arg1 ) )
        DEL_RESET( pArea, reset, reset_prev );
      if( reset->command == 'B' &&
          ( reset->arg2 & BIT_RESET_TYPE_MASK ) == BIT_RESET_OBJECT && ( !reset->arg1 || reset->arg1 == pReset->arg1 ) )
        DEL_RESET( pArea, reset, reset_prev );

      /*
       * Break when a new object of same type is found 
       */
      if( ( reset->command == 'O' || reset->command == 'P' ||
            reset->command == 'G' || reset->command == 'E' ) && reset->arg1 == pReset->arg1 )
        break;
    }
  }
  if( pReset == pArea->last_mob_reset )
    pArea->last_mob_reset = NULL;
  if( pReset == pArea->last_obj_reset )
    pArea->last_obj_reset = NULL;
  UNLINK( pReset, pArea->first_reset, pArea->last_reset, next, prev );
  DISPOSE( pReset );
  return;
}

#undef DEL_RESET

RESET_DATA *find_oreset( CHAR_DATA * ch, AREA_DATA * pArea, ROOM_INDEX_DATA * pRoom, char *name )
{
  RESET_DATA *reset;

  if( !*name )
  {
    for( reset = pArea->last_reset; reset; reset = reset->prev )
    {
      if( !is_room_reset( reset, pRoom, pArea ) )
        continue;
      switch ( reset->command )
      {
        default:
          continue;
        case 'O':
        case 'E':
        case 'G':
        case 'P':
          break;
      }
      break;
    }
    if( !reset )
      send_to_char( "No object resets in list.\n\r", ch );
    return reset;
  }
  else
  {
    char arg[MAX_INPUT_LENGTH];
    int cnt = 0, num = number_argument( name, arg );
    OBJ_INDEX_DATA *pObjTo = NULL;

    for( reset = pArea->first_reset; reset; reset = reset->next )
    {
      if( !is_room_reset( reset, pRoom, pArea ) )
        continue;
      switch ( reset->command )
      {
        default:
          continue;
        case 'O':
        case 'E':
        case 'G':
        case 'P':
          break;
      }
      if( ( pObjTo = get_obj_index( reset->arg1 ) ) && is_name( arg, pObjTo->name ) && ++cnt == num )
        break;
    }
    if( !pObjTo || !reset )
    {
      send_to_char( "To object not in reset list.\n\r", ch );
      return NULL;
    }
  }
  return reset;
}

RESET_DATA *find_mreset( CHAR_DATA * ch, AREA_DATA * pArea, ROOM_INDEX_DATA * pRoom, char *name )
{
  RESET_DATA *reset;

  if( !*name )
  {
    for( reset = pArea->last_reset; reset; reset = reset->prev )
    {
      if( !is_room_reset( reset, pRoom, pArea ) )
        continue;
      switch ( reset->command )
      {
        default:
          continue;
        case 'M':
          break;
      }
      break;
    }
    if( !reset )
      send_to_char( "No mobile resets in list.\n\r", ch );
    return reset;
  }
  else
  {
    char arg[MAX_INPUT_LENGTH];
    int cnt = 0, num = number_argument( name, arg );
    MOB_INDEX_DATA *pMob = NULL;

    for( reset = pArea->first_reset; reset; reset = reset->next )
    {
      if( !is_room_reset( reset, pRoom, pArea ) )
        continue;
      switch ( reset->command )
      {
        default:
          continue;
        case 'M':
          break;
      }
      if( ( pMob = get_mob_index( reset->arg1 ) ) && is_name( arg, pMob->player_name ) && ++cnt == num )
        break;
    }
    if( !pMob || !reset )
    {
      send_to_char( "Mobile not in reset list.\n\r", ch );
      return NULL;
    }
  }
  return reset;
}

void edit_reset( CHAR_DATA * ch, char *argument, AREA_DATA * pArea, ROOM_INDEX_DATA * aRoom )
{
  char arg[MAX_INPUT_LENGTH];
  RESET_DATA *pReset = NULL;
  RESET_DATA *reset = NULL;
  MOB_INDEX_DATA *pMob = NULL;
  ROOM_INDEX_DATA *pRoom;
  OBJ_INDEX_DATA *pObj;
  int num = 0;
  int vnum;
  char *origarg = argument;

  argument = one_argument( argument, arg );
  if( !*arg || !str_cmp( arg, "?" ) )
  {
    char *nm = ( ch->substate == SUB_REPEATCMD ? "" : ( aRoom ? "rreset " : "reset " ) );
    char *rn = ( aRoom ? "" : " [room#]" );
    ch_printf( ch, "Syntax: %s<list|edit|delete|add|insert|place%s>\n\r", nm, ( aRoom ? "" : "|area" ) );
    ch_printf( ch, "Syntax: %sremove <#>\n\r", nm );
    ch_printf( ch, "Syntax: %smobile <mob#> [limit]%s\n\r", nm, rn );
    ch_printf( ch, "Syntax: %sobject <obj#> [limit [room%s]]\n\r", nm, rn );
    ch_printf( ch, "Syntax: %sobject <obj#> give <mob name> [limit]\n\r", nm );
    ch_printf( ch, "Syntax: %sobject <obj#> equip <mob name> <location> " "[limit]\n\r", nm );
    ch_printf( ch, "Syntax: %sobject <obj#> put <to_obj name> [limit]\n\r", nm );
    ch_printf( ch, "Syntax: %shide <obj name>\n\r", nm );
    ch_printf( ch, "Syntax: %strap <obj name> <type> <charges> <flags>\n\r", nm );
    ch_printf( ch, "Syntax: %strap room <type> <charges> <flags>\n\r", nm );
    ch_printf( ch, "Syntax: %sbit <set|toggle|remove> door%s <dir> " "<exit flags>\n\r", nm, rn );
    ch_printf( ch, "Syntax: %sbit <set|toggle|remove> object <obj name> " "<extra flags>\n\r", nm );
    ch_printf( ch, "Syntax: %sbit <set|toggle|remove> mobile <mob name> " "<affect flags>\n\r", nm );
    ch_printf( ch, "Syntax: %sbit <set|toggle|remove> room%s <room flags>" "\n\r", nm, rn );
    ch_printf( ch, "Syntax: %srandom <last dir>%s\n\r", nm, rn );
    if( !aRoom )
    {
      send_to_char( "\n\r[room#] will default to the room you are in, " "if unspecified.\n\r", ch );
    }
    return;
  }
  if( !str_cmp( arg, "on" ) )
  {
    ch->substate = SUB_REPEATCMD;
    ch->dest_buf = ( aRoom ? ( void * )aRoom : ( void * )pArea );
    send_to_char( "Reset mode on.\n\r", ch );
    return;
  }
  if( !aRoom && !str_cmp( arg, "area" ) )
  {
    if( !pArea->first_reset )
    {
      send_to_char( "You don't have any resets defined.\n\r", ch );
      return;
    }
    num = pArea->nplayer;
    pArea->nplayer = 0;
    reset_area( pArea );
    pArea->nplayer = num;
    send_to_char( "Done.\n\r", ch );
    return;
  }

  if( !str_cmp( arg, "list" ) )
  {
    int start, end;

    argument = one_argument( argument, arg );
    start = is_number( arg ) ? atoi( arg ) : -1;
    argument = one_argument( argument, arg );
    end = is_number( arg ) ? atoi( arg ) : -1;
    list_resets( ch, pArea, aRoom, start, end );
    return;
  }

  if( !str_cmp( arg, "edit" ) )
  {
    argument = one_argument( argument, arg );
    if( !*arg || !is_number( arg ) )
    {
      send_to_char( "Usage: reset edit <number> <command>\n\r", ch );
      return;
    }
    num = atoi( arg );
    if( !( pReset = find_reset( pArea, aRoom, num ) ) )
    {
      send_to_char( "Reset not found.\n\r", ch );
      return;
    }
    if( !( reset = parse_reset( pArea, argument, ch ) ) )
    {
      send_to_char( "Error in reset.  Reset not changed.\n\r", ch );
      return;
    }
    reset->prev = pReset->prev;
    reset->next = pReset->next;
    if( !pReset->prev )
      pArea->first_reset = reset;
    else
      pReset->prev->next = reset;
    if( !pReset->next )
      pArea->last_reset = reset;
    else
      pReset->next->prev = reset;
    DISPOSE( pReset );
    send_to_char( "Done.\n\r", ch );
    return;
  }
  if( !str_cmp( arg, "add" ) )
  {
    if( ( pReset = parse_reset( pArea, argument, ch ) ) == NULL )
    {
      send_to_char( "Error in reset.  Reset not added.\n\r", ch );
      return;
    }
    add_reset( pArea, pReset->command, pReset->extra, pReset->arg1, pReset->arg2, pReset->arg3 );
    DISPOSE( pReset );
    send_to_char( "Done.\n\r", ch );
    return;
  }
  if( !str_cmp( arg, "place" ) )
  {
    if( ( pReset = parse_reset( pArea, argument, ch ) ) == NULL )
    {
      send_to_char( "Error in reset.  Reset not added.\n\r", ch );
      return;
    }
    place_reset( pArea, pReset->command, pReset->extra, pReset->arg1, pReset->arg2, pReset->arg3 );
    DISPOSE( pReset );
    send_to_char( "Done.\n\r", ch );
    return;
  }
  if( !str_cmp( arg, "insert" ) )
  {
    argument = one_argument( argument, arg );
    if( !*arg || !is_number( arg ) )
    {
      send_to_char( "Usage: reset insert <number> <command>\n\r", ch );
      return;
    }
    num = atoi( arg );
    if( ( reset = find_reset( pArea, aRoom, num ) ) == NULL )
    {
      send_to_char( "Reset not found.\n\r", ch );
      return;
    }
    if( ( pReset = parse_reset( pArea, argument, ch ) ) == NULL )
    {
      send_to_char( "Error in reset.  Reset not inserted.\n\r", ch );
      return;
    }
    INSERT( pReset, reset, pArea->first_reset, next, prev );
    send_to_char( "Done.\n\r", ch );
    return;
  }
  if( !str_cmp( arg, "delete" ) )
  {
    int start, end;
    bool found;

    if( !*argument )
    {
      send_to_char( "Usage: reset delete <start> [end]\n\r", ch );
      return;
    }
    argument = one_argument( argument, arg );
    start = is_number( arg ) ? atoi( arg ) : -1;
    end = is_number( arg ) ? atoi( arg ) : -1;
    num = 0;
    found = FALSE;
    for( pReset = pArea->first_reset; pReset; pReset = reset )
    {
      reset = pReset->next;
      if( !is_room_reset( pReset, aRoom, pArea ) )
        continue;
      if( start > ++num )
        continue;
      if( ( end != -1 && num > end ) || ( end == -1 && found ) )
        return;
      UNLINK( pReset, pArea->first_reset, pArea->last_reset, next, prev );
      if( pReset == pArea->last_mob_reset )
        pArea->last_mob_reset = NULL;
      DISPOSE( pReset );
      top_reset--;
      found = TRUE;
    }
    if( !found )
      send_to_char( "Reset not found.\n\r", ch );
    else
      send_to_char( "Done.\n\r", ch );
    return;
  }

  if( !str_cmp( arg, "remove" ) )
  {
    int iarg;

    argument = one_argument( argument, arg );
    if( arg[0] == '\0' || !is_number( arg ) )
    {
      send_to_char( "Delete which reset?\n\r", ch );
      return;
    }
    iarg = atoi( arg );
    for( pReset = pArea->first_reset; pReset; pReset = pReset->next )
    {
      if( is_room_reset( pReset, aRoom, pArea ) && ++num == iarg )
        break;
    }
    if( !pReset )
    {
      send_to_char( "Reset does not exist.\n\r", ch );
      return;
    }
    delete_reset( pArea, pReset );
    send_to_char( "Reset deleted.\n\r", ch );
    return;
  }
  if( !str_prefix( arg, "mobile" ) )
  {
    argument = one_argument( argument, arg );
    if( arg[0] == '\0' || !is_number( arg ) )
    {
      send_to_char( "Reset which mobile vnum?\n\r", ch );
      return;
    }
    if( !( pMob = get_mob_index( atoi( arg ) ) ) )
    {
      send_to_char( "Mobile does not exist.\n\r", ch );
      return;
    }
    argument = one_argument( argument, arg );
    if( arg[0] == '\0' )
      num = 1;
    else if( !is_number( arg ) )
    {
      send_to_char( "Reset how many mobiles?\n\r", ch );
      return;
    }
    else
      num = atoi( arg );
    if( !( pRoom = find_room( ch, argument, aRoom ) ) )
      return;
    pReset = make_reset( 'M', 0, pMob->vnum, num, pRoom->vnum );
    LINK( pReset, pArea->first_reset, pArea->last_reset, next, prev );
    send_to_char( "Mobile reset added.\n\r", ch );
    return;
  }
  if( !str_prefix( arg, "object" ) )
  {
    argument = one_argument( argument, arg );
    if( arg[0] == '\0' || !is_number( arg ) )
    {
      send_to_char( "Reset which object vnum?\n\r", ch );
      return;
    }
    if( !( pObj = get_obj_index( atoi( arg ) ) ) )
    {
      send_to_char( "Object does not exist.\n\r", ch );
      return;
    }
    argument = one_argument( argument, arg );
    if( arg[0] == '\0' )
      strcpy( arg, "room" );
    if( !str_prefix( arg, "put" ) )
    {
      argument = one_argument( argument, arg );
      if( !( reset = find_oreset( ch, pArea, aRoom, arg ) ) )
        return;
      pReset = reset;
      /*
       * Put in_objects after hide and trap resets 
       */
      while( reset->next && ( reset->next->command == 'H' ||
                              reset->next->command == 'T' ||
                              ( reset->next->command == 'B' &&
                                ( reset->next->arg2 & BIT_RESET_TYPE_MASK ) == BIT_RESET_OBJECT &&
                                ( !reset->next->arg1 || reset->next->arg1 == pReset->arg1 ) ) ) )
        reset = reset->next;
/*      pReset = make_reset('P', 1, pObj->vnum, num, reset->arg1);*/
      argument = one_argument( argument, arg );
      if( ( vnum = atoi( arg ) ) < 1 )
        vnum = 1;
      pReset = make_reset( 'P', reset->extra + 1, pObj->vnum, vnum, 0 );
      /*
       * Grumble.. insert puts pReset before reset, and we need it after,
       * so we make a hackup and reverse all the list params.. :P.. 
       */
      INSERT( pReset, reset, pArea->last_reset, prev, next );
      send_to_char( "Object reset in object created.\n\r", ch );
      return;
    }
    if( !str_prefix( arg, "give" ) )
    {
      argument = one_argument( argument, arg );
      if( !( reset = find_mreset( ch, pArea, aRoom, arg ) ) )
        return;
      pReset = reset;
      while( reset->next && reset->next->command == 'B' &&
             ( reset->next->arg2 & BIT_RESET_TYPE_MASK ) == BIT_RESET_OBJECT &&
             ( !reset->next->arg1 || reset->next->arg1 == pReset->arg1 ) )
        reset = reset->next;
      argument = one_argument( argument, arg );
      if( ( vnum = atoi( arg ) ) < 1 )
        vnum = 1;
      pReset = make_reset( 'G', 1, pObj->vnum, vnum, 0 );
      INSERT( pReset, reset, pArea->last_reset, prev, next );
      send_to_char( "Object reset to mobile created.\n\r", ch );
      return;
    }
    if( !str_prefix( arg, "equip" ) )
    {
      argument = one_argument( argument, arg );
      if( !( reset = find_mreset( ch, pArea, aRoom, arg ) ) )
        return;
      pReset = reset;
      while( reset->next && reset->next->command == 'B' &&
             ( reset->next->arg2 & BIT_RESET_TYPE_MASK ) == BIT_RESET_OBJECT &&
             ( !reset->next->arg1 || reset->next->arg1 == pReset->arg1 ) )
        reset = reset->next;
      num = get_wearloc( argument );
      if( num < 0 )
      {
        send_to_char( "Reset object to which location?\n\r", ch );
        return;
      }
      for( pReset = reset->next; pReset; pReset = pReset->next )
      {
        if( pReset->command == 'M' )
          break;
        if( pReset->command == 'E' && pReset->arg3 == num )
        {
          send_to_char( "Mobile already has an item equipped there.\n\r", ch );
          return;
        }
      }
      argument = one_argument( argument, arg );
      if( ( vnum = atoi( arg ) ) < 1 )
        vnum = 1;
      pReset = make_reset( 'E', 1, pObj->vnum, vnum, num );
      INSERT( pReset, reset, pArea->last_reset, prev, next );
      send_to_char( "Object reset equipped by mobile created.\n\r", ch );
      return;
    }
    if( arg[0] == '\0' || !( num = ( int )str_cmp( arg, "room" ) ) || is_number( arg ) )
    {
      if( !( bool ) num )
        argument = one_argument( argument, arg );
      if( !( pRoom = find_room( ch, argument, aRoom ) ) )
        return;
      if( pRoom->area != pArea )
      {
        send_to_char( "Cannot reset objects to other areas.\n\r", ch );
        return;
      }
      if( ( vnum = atoi( arg ) ) < 1 )
        vnum = 1;
      pReset = make_reset( 'O', 0, pObj->vnum, vnum, pRoom->vnum );
      LINK( pReset, pArea->first_reset, pArea->last_reset, next, prev );
      send_to_char( "Object reset added.\n\r", ch );
      return;
    }
    send_to_char( "Reset object to where?\n\r", ch );
    return;
  }
  if( !str_cmp( arg, "random" ) )
  {
    argument = one_argument( argument, arg );
    vnum = get_dir( arg );
    if( vnum < 0 || vnum > 9 )
    {
      send_to_char( "Reset which random doors?\n\r", ch );
      return;
    }
    if( vnum == 0 )
    {
      send_to_char( "There is no point in randomizing one door.\n\r", ch );
      return;
    }
    pRoom = find_room( ch, argument, aRoom );
    if( pRoom->area != pArea )
    {
      send_to_char( "Cannot randomize doors in other areas.\n\r", ch );
      return;
    }
    pReset = make_reset( 'R', 0, pRoom->vnum, vnum, 0 );
    LINK( pReset, pArea->first_reset, pArea->last_reset, next, prev );
    send_to_char( "Reset random doors created.\n\r", ch );
    return;
  }
  if( !str_cmp( arg, "trap" ) )
  {
    char oname[MAX_INPUT_LENGTH];
    int chrg, value, extra = 0;
    bool isobj;

    argument = one_argument( argument, oname );
    argument = one_argument( argument, arg );
    num = is_number( arg ) ? atoi( arg ) : -1;
    argument = one_argument( argument, arg );
    chrg = is_number( arg ) ? atoi( arg ) : -1;
    isobj = is_name( argument, "obj" );
    if( isobj == is_name( argument, "room" ) )
    {
      send_to_char( "Reset: TRAP: Must specify ROOM or OBJECT\n\r", ch );
      return;
    }
    if( !str_cmp( oname, "room" ) && !isobj )
    {
      vnum = ( aRoom ? aRoom->vnum : ch->in_room->vnum );
      extra = TRAP_ROOM;
    }
    else
    {
      if( is_number( oname ) && !isobj )
      {
        vnum = atoi( oname );
        if( !get_room_index( vnum ) )
        {
          send_to_char( "Reset: TRAP: no such room\n\r", ch );
          return;
        }
        reset = NULL;
        extra = TRAP_ROOM;
      }
      else
      {
        if( !( reset = find_oreset( ch, pArea, aRoom, oname ) ) )
          return;
/*        vnum = reset->arg1;*/
        vnum = 0;
        extra = TRAP_OBJ;
      }
    }
    if( num < 1 || num > MAX_TRAPTYPE )
    {
      send_to_char( "Reset: TRAP: invalid trap type\n\r", ch );
      return;
    }
    if( chrg < 0 || chrg > 10000 )
    {
      send_to_char( "Reset: TRAP: invalid trap charges\n\r", ch );
      return;
    }
    while( *argument )
    {
      argument = one_argument( argument, arg );
      value = get_trapflag( arg );
      if( value < 0 || value > 31 )
      {
        send_to_char( "Reset: TRAP: bad flag\n\r", ch );
        return;
      }
      SET_BIT( extra, 1 << value );
    }
    pReset = make_reset( 'T', extra, num, chrg, vnum );
    if( reset )
      INSERT( pReset, reset, pArea->last_reset, prev, next );
    else
      LINK( pReset, pArea->first_reset, pArea->last_reset, next, prev );
    send_to_char( "Trap created.\n\r", ch );
    return;
  }
  if( !str_cmp( arg, "bit" ) )
  {
    int ( *flfunc ) ( char *type );
    int flags = 0;
    char option[MAX_INPUT_LENGTH];
    char *parg;
    bool ext_bv = FALSE;

    argument = one_argument( argument, option );
    if( !*option )
    {
      send_to_char( "You must specify SET, REMOVE, or TOGGLE.\n\r", ch );
      return;
    }
    num = 0;
    if( !str_prefix( option, "set" ) )
      SET_BIT( num, BIT_RESET_SET );
    else if( !str_prefix( option, "toggle" ) )
      SET_BIT( num, BIT_RESET_TOGGLE );
    else if( str_prefix( option, "remove" ) )
    {
      send_to_char( "You must specify SET, REMOVE, or TOGGLE.\n\r", ch );
      return;
    }
    argument = one_argument( argument, option );
    parg = argument;
    argument = one_argument( argument, arg );
    if( !*option )
    {
      send_to_char( "Must specify OBJECT, MOBILE, ROOM, or DOOR.\n\r", ch );
      return;
    }
    if( !str_prefix( option, "door" ) )
    {
      SET_BIT( num, BIT_RESET_DOOR );
      if( aRoom )
      {
        pRoom = aRoom;
        argument = parg;
      }
      else if( !is_number( arg ) )
      {
        pRoom = ch->in_room;
        argument = parg;
      }
      else if( !( pRoom = find_room( ch, arg, aRoom ) ) )
        return;
      argument = one_argument( argument, arg );
      if( !*arg )
      {
        send_to_char( "Must specify direction.\n\r", ch );
        return;
      }
      vnum = get_dir( arg );
      SET_BIT( num, vnum << BIT_RESET_DOOR_THRESHOLD );
      vnum = pRoom->vnum;
      flfunc = &get_exflag;
      reset = NULL;
    }
    else if( !str_prefix( option, "object" ) )
    {
      SET_BIT( num, BIT_RESET_OBJECT );
      vnum = 0;
      flfunc = &get_oflag;
      if( !( reset = find_oreset( ch, pArea, aRoom, arg ) ) )
        return;
      ext_bv = TRUE;
    }
    else if( !str_prefix( option, "mobile" ) )
    {
      SET_BIT( num, BIT_RESET_MOBILE );
      vnum = 0;
      flfunc = &get_aflag;
      if( !( reset = find_mreset( ch, pArea, aRoom, arg ) ) )
        return;
      ext_bv = TRUE;
    }
    else if( !str_prefix( option, "room" ) )
    {
      SET_BIT( num, BIT_RESET_ROOM );
      if( aRoom )
      {
        pRoom = aRoom;
        argument = parg;
      }
      else if( !is_number( arg ) )
      {
        pRoom = ch->in_room;
        argument = parg;
      }
      else if( !( pRoom = find_room( ch, arg, aRoom ) ) )
        return;
      vnum = pRoom->vnum;
      flfunc = &get_rflag;
      reset = NULL;
    }
    else
    {
      send_to_char( "Must specify OBJECT, MOBILE, ROOM, or DOOR.\n\r", ch );
      return;
    }
    while( *argument )
    {
      int value;
      argument = one_argument( argument, arg );
      value = ( *flfunc ) ( arg );
      if( value < 0 || ( !ext_bv && value > 31 ) )
      {
        send_to_char( "Reset: BIT: bad flag\n\r", ch );
        return;
      }
      if( ext_bv )  /* one per flag for extendeds */
      {
        pReset = make_reset( 'B', 1, vnum, num, flags );
        if( reset )
        {
          INSERT( pReset, reset, pArea->last_reset, prev, next );
          reset = pReset;
        }
        else
          LINK( pReset, pArea->first_reset, pArea->last_reset, next, prev );
      }
      else
        SET_BIT( flags, 1 << value );
    }
    if( !flags )
    {
      send_to_char( "Set which flags?\n\r", ch );
      return;
    }
    if( !ext_bv )
    {
      pReset = make_reset( 'B', 1, vnum, num, flags );
      if( reset )
        INSERT( pReset, reset, pArea->last_reset, prev, next );
      else
        LINK( pReset, pArea->first_reset, pArea->last_reset, next, prev );
    }
    send_to_char( "Bitvector reset created.\n\r", ch );
    return;
  }
  if( !str_cmp( arg, "hide" ) )
  {
    argument = one_argument( argument, arg );
    if( !( reset = find_oreset( ch, pArea, aRoom, arg ) ) )
      return;
/*    pReset = make_reset('H', 1, reset->arg1, 0, 0);*/
    pReset = make_reset( 'H', 1, 0, 0, 0 );
    INSERT( pReset, reset, pArea->last_reset, prev, next );
    send_to_char( "Object hide reset created.\n\r", ch );
    return;
  }
  if( ch->substate == SUB_REPEATCMD )
  {
    ch->substate = SUB_NONE;
    interpret( ch, origarg );
    ch->substate = SUB_REPEATCMD;
    ch->last_cmd = ( aRoom ? do_rreset : do_reset );
  }
  else
    edit_reset( ch, "", pArea, aRoom );
  return;
}

void do_reset( CHAR_DATA * ch, char *argument )
{
  AREA_DATA *pArea = NULL;
  char arg[MAX_INPUT_LENGTH];
  char *parg;

  /*
   * Can't have NPC's doing this.  Bug report sent in by Cronel
   * -- Shaddai
   */
  if( IS_NPC( ch ) )
    return;

  parg = one_argument( argument, arg );
  if( ch->substate == SUB_REPEATCMD )
  {
    pArea = ch->dest_buf;
    if( pArea && pArea != ch->pcdata->area && pArea != ch->in_room->area )
    {
      AREA_DATA *tmp;

      for( tmp = first_build; tmp; tmp = tmp->next )
        if( tmp == pArea )
          break;
      if( !tmp )
        for( tmp = first_area; tmp; tmp = tmp->next )
          if( tmp == pArea )
            break;
      if( !tmp )
      {
        send_to_char( "Your area pointer got lost.  Reset mode off.\n\r", ch );
        bug( "do_reset: %s's dest_buf points to invalid area", ch->name );  /* why was this cast to an int? */
        ch->substate = SUB_NONE;
        ch->dest_buf = NULL;
        return;
      }
    }
    if( !*arg )
    {
      ch_printf( ch, "Editing resets for area: %s\n\r", pArea->name );
      return;
    }
    if( !str_cmp( arg, "done" ) || !str_cmp( arg, "off" ) )
    {
      send_to_char( "Reset mode off.\n\r", ch );
      ch->substate = SUB_NONE;
      ch->dest_buf = NULL;
      return;
    }
  }
  if( !pArea && get_trust( ch ) > LEVEL_GOD )
  {
    char fname[80];

    sprintf( fname, "%s.are", capitalize( arg ) );
    for( pArea = first_build; pArea; pArea = pArea->next )
      if( !str_cmp( fname, pArea->filename ) )
      {
        argument = parg;
        break;
      }
    if( !pArea )
      pArea = ch->pcdata->area;
    if( !pArea )
      pArea = ch->in_room->area;
  }
  else
    pArea = ch->pcdata->area;
  if( !pArea )
  {
    send_to_char( "You do not have an assigned area.\n\r", ch );
    return;
  }
  edit_reset( ch, argument, pArea, NULL );
  return;
}

void do_rreset( CHAR_DATA * ch, char *argument )
{
  ROOM_INDEX_DATA *pRoom;

  if( ch->substate == SUB_REPEATCMD )
  {
    pRoom = ch->dest_buf;
    if( !pRoom )
    {
      send_to_char( "Your room pointer got lost.  Reset mode off.\n\r", ch );
      bug( "do_rreset: %s's dest_buf points to invalid room", ( int )ch->name );
    }
    ch->substate = SUB_NONE;
    ch->dest_buf = NULL;
    return;
  }
  else
    pRoom = ch->in_room;
  if( !can_rmodify( ch, pRoom ) )
    return;
  edit_reset( ch, argument, pRoom->area, pRoom );
  return;
}

void add_obj_reset( AREA_DATA * pArea, char cm, OBJ_DATA * obj, int v2, int v3 )
{
  OBJ_DATA *inobj;
  static int iNest;
  int obj_loop, value_loop;
  int reset_count = 0;
  bool found;

  if( ( cm == 'O' || cm == 'P' ) && obj->pIndexData->vnum == OBJ_VNUM_TRAP )
  {
    if( cm == 'O' )
      add_reset( pArea, 'T', obj->value[3], obj->value[1], obj->value[0], v3 );
    return;
  }
  add_reset( pArea, cm, ( cm == 'P' ? iNest : 1 ), obj->pIndexData->vnum, v2, v3 );
  /*
   * Only add hide for in-room objects that are hidden and cant be moved, as
   * hide is an update reset, not a load-only reset. 
   */
  if( cm == 'O' && IS_OBJ_STAT( obj, ITEM_HIDDEN ) && !IS_SET( obj->wear_flags, ITEM_TAKE ) )
    add_reset( pArea, 'H', 1, 0, 0, 0 );
  for( inobj = obj->first_content; inobj; inobj = inobj->next_content )
    if( inobj->pIndexData->vnum == OBJ_VNUM_TRAP )
      add_obj_reset( pArea, 'O', inobj, 0, 0 );
  if( cm == 'P' )
    iNest++;

  if( put_index == 0 )
    for( obj_loop = 0; obj_loop < MAX_OBJ; obj_loop++ )
      for( value_loop = 0; value_loop < 3; value_loop++ )
        put_array[obj_loop][value_loop] = 0;

  for( inobj = obj->first_content; inobj; inobj = inobj->next_content )
  {
    if( IS_OBJ_TYPE( inobj ) )
    {
      found = FALSE;
      for( obj_loop = 0; obj_loop <= obj_index; obj_loop++ )
      {
        if( ( put_array[obj_loop][0] == inobj->pIndexData->vnum ) && ( put_array[obj_loop][2] == iNest ) )
        {
          reset_count = inobj->count + put_array[obj_loop][1];
          put_array[obj_loop][1] = reset_count;
          found = TRUE;
        }
      }
      if( !found )
      {
        reset_count = inobj->count;
        put_array[put_index][0] = inobj->pIndexData->vnum;
        put_array[put_index][1] = inobj->count;
        put_array[put_index][2] = iNest;
        put_index++;
      }
    }
    else
      reset_count = count_obj_list( get_obj_index( inobj->pIndexData->vnum ), obj->first_content );

    add_obj_reset( pArea, 'P', inobj, reset_count, 0 );
  }
  if( cm == 'P' )
    iNest--;
  return;
}

void instaroom( AREA_DATA * pArea, ROOM_INDEX_DATA * pRoom, bool dodoors )
{
  CHAR_DATA *rch;
  OBJ_DATA *obj;
  int obj_loop, value_loop, reset_count;
  bool found;

  for( rch = pRoom->first_person; rch; rch = rch->next_in_room )
  {
    if( !IS_NPC( rch ) )
      continue;
    add_reset( pArea, 'M', 1, rch->pIndexData->vnum, 1, pRoom->vnum );

    obj_index = 0;
    reset_count = 0;
    for( obj_loop = 0; obj_loop < MAX_OBJ; obj_loop++ )
      for( value_loop = 0; value_loop < 2; value_loop++ )
        obj_array[obj_loop][value_loop] = 0;

    for( obj = rch->first_carrying; obj; obj = obj->next_content )
    {
      if( obj->wear_loc == WEAR_NONE )
      {
        if( IS_OBJ_TYPE( obj ) )
        {
          found = FALSE;
          for( obj_loop = 0; obj_loop <= obj_index; obj_loop++ )
          {
            if( obj_array[obj_loop][0] == obj->pIndexData->vnum )
            {
              reset_count = obj->count + obj_array[obj_loop][1];
              obj_array[obj_loop][1] = reset_count;
              found = TRUE;
            }
          }
          if( !found )
          {
            reset_count = obj->count;
            obj_array[obj_index][0] = obj->pIndexData->vnum;
            obj_array[obj_index][1] = obj->count;
            obj_index++;
          }
        }
        else
          reset_count = count_obj_list( get_obj_index( obj->pIndexData->vnum ), rch->first_carrying );
        put_index = 0;
        add_obj_reset( pArea, 'G', obj, reset_count, 0 );
      }
      else
        add_obj_reset( pArea, 'E', obj, 1, obj->wear_loc );
    }
  }

  obj_index = 0;
  reset_count = 0;
  for( obj_loop = 0; obj_loop < MAX_OBJ; obj_loop++ )
    for( value_loop = 0; value_loop < 2; value_loop++ )
      obj_array[obj_loop][value_loop] = 0;

  for( obj = pRoom->first_content; obj; obj = obj->next_content )
  {
    if( IS_OBJ_TYPE( obj ) )
    {
      found = FALSE;
      for( obj_loop = 0; obj_loop <= obj_index; obj_loop++ )
      {
        if( obj_array[obj_loop][0] == obj->pIndexData->vnum )
        {
          reset_count = obj->count + obj_array[obj_loop][1];
          obj_array[obj_loop][1] = reset_count;
          found = TRUE;
        }
      }
      if( !found )
      {
        reset_count = obj->count;
        obj_array[obj_index][0] = obj->pIndexData->vnum;
        obj_array[obj_index][1] = obj->count;
        obj_index++;
      }
    }
    else
      reset_count = count_obj_list( get_obj_index( obj->pIndexData->vnum ), pRoom->first_content );

    put_index = 0;
    add_obj_reset( pArea, 'O', obj, reset_count, pRoom->vnum );
  }
  if( dodoors )
  {
    EXIT_DATA *pexit;

    for( pexit = pRoom->first_exit; pexit; pexit = pexit->next )
    {
      int state = 0;

      if( !IS_SET( pexit->exit_info, EX_ISDOOR ) )
        continue;
      if( IS_SET( pexit->exit_info, EX_CLOSED ) )
      {
        if( IS_SET( pexit->exit_info, EX_LOCKED ) )
          state = 2;
        else
          state = 1;
      }
      add_reset( pArea, 'D', 0, pRoom->vnum, pexit->vdir, state );
    }
  }
  return;
}

void wipe_resets( AREA_DATA * pArea, ROOM_INDEX_DATA * pRoom )
{
  RESET_DATA *pReset;

  for( pReset = pArea->first_reset; pReset; )
  {
    if( pReset->command != 'R' && is_room_reset( pReset, pRoom, pArea ) )
    {
      /*
       * Resets always go forward, so we can safely use the previous reset,
       * providing it exists, or first_reset if it doesnt.  -- Altrag 
       */
      RESET_DATA *prev = pReset->prev;

      delete_reset( pArea, pReset );
      pReset = ( prev ? prev->next : pArea->first_reset );
    }
    else
      pReset = pReset->next;
  }
  return;
}

void do_instaroom( CHAR_DATA * ch, char *argument )
{
  AREA_DATA *pArea;
  ROOM_INDEX_DATA *pRoom;
  bool dodoors;
  char arg[MAX_INPUT_LENGTH];

  if( IS_NPC( ch ) || get_trust( ch ) < LEVEL_SAVIOR || !ch->pcdata || !ch->pcdata->area )
  {
    send_to_char( "You don't have an assigned area to create resets for.\n\r", ch );
    return;
  }
  argument = one_argument( argument, arg );
  if( !str_cmp( argument, "nodoors" ) )
    dodoors = FALSE;
  else
    dodoors = TRUE;
  pArea = ch->pcdata->area;
  if( !( pRoom = find_room( ch, arg, NULL ) ) )
  {
    send_to_char( "Room doesn't exist.\n\r", ch );
    return;
  }
  if( !can_rmodify( ch, pRoom ) )
    return;
  if( pRoom->area != pArea && get_trust( ch ) < LEVEL_GREATER )
  {
    send_to_char( "You cannot reset that room.\n\r", ch );
    return;
  }
  if( pArea->first_reset )
    wipe_resets( pArea, pRoom );
  instaroom( pArea, pRoom, dodoors );
  send_to_char( "Room resets installed.\n\r", ch );
}

void do_instazone( CHAR_DATA * ch, char *argument )
{
  AREA_DATA *pArea;
  int vnum;
  ROOM_INDEX_DATA *pRoom;
  bool dodoors;

  if( IS_NPC( ch ) || get_trust( ch ) < LEVEL_SAVIOR || !ch->pcdata || !ch->pcdata->area )
  {
    send_to_char( "You don't have an assigned area to create resets for.\n\r", ch );
    return;
  }
  if( !str_cmp( argument, "nodoors" ) )
    dodoors = FALSE;
  else
    dodoors = TRUE;
  pArea = ch->pcdata->area;
  if( pArea->first_reset )
    wipe_resets( pArea, NULL );
  for( vnum = pArea->low_r_vnum; vnum <= pArea->hi_r_vnum; vnum++ )
  {
    if( !( pRoom = get_room_index( vnum ) ) || pRoom->area != pArea )
      continue;
    instaroom( pArea, pRoom, dodoors );
  }
  send_to_char( "Area resets installed.\n\r", ch );
  return;
}

int generate_itemlevel( AREA_DATA * pArea, OBJ_INDEX_DATA * pObjIndex )
{
  int olevel;
/*
    int min = UMAX(pArea->low_soft_range, 1);
    int max = UMIN(pArea->hi_soft_range, min + 15);

    if ( pObjIndex->level > 0 )
	olevel = UMIN(pObjIndex->level, MAX_LEVEL);
    else
	switch ( pObjIndex->item_type )
	{
	    default:		olevel = 0;				break;
	    case ITEM_PILL:	olevel = number_range(  min, max );	break;
	    case ITEM_POTION:	olevel = number_range(  min, max );	break;
	    case ITEM_SCROLL:	olevel = pObjIndex->value[0];		break;
	    case ITEM_WAND:	olevel = number_range( min+4, max+1 );	break;
	    case ITEM_STAFF:	olevel = number_range( min+9, max+5 );	break;
	    case ITEM_ARMOR:	olevel = number_range( min+4, max+1 );	break;
	    case ITEM_WEAPON:	olevel = number_range( min+4, max+1 );	break;
	}
*/
  olevel = pObjIndex->level;
  return olevel;
}

void reset_area( AREA_DATA * pArea )
{
  RESET_DATA *pReset;
  RESET_DATA *pResetNext;
  CHAR_DATA *mob;
  OBJ_DATA *obj;
  OBJ_DATA *lastobj;
  ROOM_INDEX_DATA *pRoomIndex = NULL;
  MOB_INDEX_DATA *pMobIndex;
  OBJ_INDEX_DATA *pObjIndex;
  OBJ_INDEX_DATA *pObjToIndex;
  EXIT_DATA *pexit;
  OBJ_DATA *to_obj;
  char buf[MAX_STRING_LENGTH];
  int level = 0;
  void *plc = NULL;
  bool ext_bv = FALSE;
  CHAR_DATA *target;
  bool exit = FALSE;
  char buf2[MAX_STRING_LENGTH];
  AREA_DATA *temp;
  bool proto = FALSE;

  if( !pArea )
  {
    bug( "reset_area: NULL pArea", 0 );
    return;
  }

  for( temp = first_build; temp; temp = temp->next )
  {
    if( !str_cmp( temp->filename, pArea->filename ) )
    {
      proto = TRUE;
      break;
    }
  }

  mob = NULL;
  obj = NULL;
  lastobj = NULL;
  if( !pArea->first_reset )
  {
    bug( "%s: reset_area: no resets", ( int )pArea->filename );
    return;
  }
  level = 0;
  for( pReset = pArea->first_reset; pReset; pReset = pReset->next )
  {
    switch ( pReset->command )
    {
      default:
        sprintf( buf, "%s Reset_area: bad command %c.", pArea->filename, pReset->command );
        bug( buf, 0 );
        break;
      case 'M':
        if( !( pMobIndex = get_mob_index( pReset->arg1 ) ) )
        {
          sprintf( buf, "%s Reset_area: 'M': bad mob vnum %d.", pArea->filename, pReset->arg1 );
          bug( buf, 0 );
          continue;
        }
        if( !( pRoomIndex = get_room_index( pReset->arg3 ) ) )
        {
          sprintf( buf, "%s Reset_area: 'M': bad room vnum %d.", pArea->filename, pReset->arg3 );
          bug( buf, 0 );
          continue;
        }

        if( proto == TRUE && !xIS_SET( pMobIndex->act, ACT_PROTOTYPE ) )
        {
          bug( "Reset tried to invoke non-prototype mobile.  Skipping.", 0 );
          continue;
        }

        for( target = first_char; target; target = target->next )
        {
          if( !IS_NPC( target ) )
            continue;
          if( target->mob_serial == pReset->reset_serial )
          {
            mob = target;
            exit = TRUE;
            break;
          }
        }

        if( exit )
        {
          exit = FALSE;
          break;
        }

        mob = create_mobile( pMobIndex );
        mob->mob_serial = pReset->reset_serial;
        {
          ROOM_INDEX_DATA *pRoomPrev = get_room_index( pReset->arg3 - 1 );
          if( pRoomPrev && xIS_SET( pRoomPrev->room_flags, ROOM_PET_SHOP ) )
            xSET_BIT( mob->act, ACT_PET );
        }
        if( room_is_dark( pRoomIndex ) )
          xSET_BIT( mob->affected_by, AFF_INFRARED );
        char_to_room( mob, pRoomIndex );
        economize_mobgold( mob );
        level = URANGE( 0, mob->level - 2, LEVEL_AVATAR );
        break;
      case 'G':
      case 'E':
        if( !( pObjIndex = get_obj_index( pReset->arg1 ) ) )
        {
          sprintf( buf, "%s Reset_area: 'E' or 'G': bad obj vnum %d.", pArea->filename, pReset->arg1 );
          bug( buf, 0 );
          continue;
        }
        if( proto == TRUE && !IS_OBJ_STAT( pObjIndex, ITEM_PROTOTYPE ) )
        {
          bug( "Reset tried to invoke non-prototype object.  Skipping.", 0 );
          continue;
        }
        if( !mob )
        {
          lastobj = NULL;
          break;
        }
        if( count_obj_list( pObjIndex, mob->first_carrying ) >= pReset->arg2 )
        {
          obj = NULL;
          lastobj = NULL;
          break;
        }
        if( mob->pIndexData->pShop )
        {
          int olevel = generate_itemlevel( pArea, pObjIndex );
          sprintf( buf2, "mob%d@room%d(SHOP)", mob->pIndexData->vnum, mob->in_room->vnum );
          obj = create_object_new( pObjIndex, olevel, ORIGIN_RESET, buf2 );
          xSET_BIT( obj->extra_flags, ITEM_INVENTORY );
/* Inventory problem */
          obj->count = 1;
        }
        else
        {
/* Inventory problem */
          sprintf( buf2, "mob%d@room%d", mob->pIndexData->vnum, mob->in_room->vnum );
          obj = create_object_new( pObjIndex, number_fuzzy( level ), ORIGIN_RESET, buf2 );
          obj->count = ( pReset->arg2 - count_obj_list( pObjIndex, mob->first_carrying ) );
        }
        obj = obj_to_char( obj, mob );
        if( pReset->command == 'E' )
        {
/* Equip reset fault */
          obj->count = 1;
          equip_char( mob, obj, pReset->arg3 );
        }
        lastobj = obj;
        break;
      case 'O':
        if( !( pObjIndex = get_obj_index( pReset->arg1 ) ) )
        {
/*
	sprintf (buf, "%s Reset_area: 'O': bad obj vnum %d.",
		pArea->filename, pReset->arg1 );
	bug ( buf, 0 );
*/
          continue;
        }
        if( !( pRoomIndex = get_room_index( pReset->arg3 ) ) )
        {
/*
	sprintf ( buf, "%s Reset_area: 'O': bad room vnum %d.", pArea->filename,
	   pReset->arg3 );
	bug ( buf, 0 );
*/
          continue;
        }
        if( proto == TRUE && !IS_OBJ_STAT( pObjIndex, ITEM_PROTOTYPE ) )
        {
          bug( "Reset tried to invoke non-prototype object.  Skipping.", 0 );
          continue;
        }
        if( pArea->nplayer > 0 || ( count_obj_list( pObjIndex, pRoomIndex->first_content ) >= pReset->arg2 ) )
        {
          obj = NULL;
/* New section */
          pResetNext = pReset->next;
          if( pResetNext && pResetNext->command == 'P' )
          {
            lastobj = get_obj_type( pObjIndex );  /* find last object reset */
            lastobj->value[1] = lastobj->pIndexData->value[1];  /* reset last object flags */
          } /* eg locked,closed etc */
          else
            lastobj = NULL;
/* New section */
          break;
        }
        sprintf( buf2, "room%d", pRoomIndex->vnum );
        obj = create_object_new( pObjIndex, number_fuzzy( generate_itemlevel( pArea, pObjIndex ) ), ORIGIN_RESET, buf2 );
        obj->count = ( pReset->arg2 - count_obj_list( pObjIndex, pRoomIndex->first_content ) );
        obj_to_room( obj, pRoomIndex );
        lastobj = obj;
        break;

      case 'P':
        if( !( pObjIndex = get_obj_index( pReset->arg1 ) ) )
        {
/*
	sprintf ( buf, "%s Reset_area: 'P': bad obj vnum %d.", pArea->filename,
	   pReset->arg1 );
	bug ( buf, 0 );
*/
          continue;
        }
        if( proto == TRUE && !IS_OBJ_STAT( pObjIndex, ITEM_PROTOTYPE ) )
        {
          bug( "Reset tried to invoke non-prototype object.  Skipping.", 0 );
          continue;
        }
        if( pReset->arg3 > 0 )
        {
          if( !( pObjToIndex = get_obj_index( pReset->arg3 ) ) )
          {
/*
	  sprintf(buf,"%s Reset_area: 'P': bad objto vnum %d.",pArea->filename,
		pReset->arg3 );
	  bug( buf, 0 );
*/
            continue;
          }
          if( pArea->nplayer > 0
              || !( to_obj = get_obj_type( pObjToIndex ) )
              || !to_obj->in_room || ( count_obj_list( pObjIndex, to_obj->first_content ) >= pReset->arg2 ) )
          {
            obj = NULL;
            break;
          }
          lastobj = to_obj;
        }
        else
        {
          int iNest;
          if( !lastobj )
            break;
          to_obj = lastobj;
          for( iNest = 0; iNest < pReset->extra; iNest++ )
            if( !( to_obj = to_obj->last_content ) )
            {
/*
	    sprintf(buf,"%s Reset_area: 'P': Invalid nesting obj %d."
		,pArea->filename, pReset->arg1 );
	    bug( buf, 0 );
*/
              iNest = -1;
              break;
            }
          if( iNest < 0 )
            continue;
/* New Section */
          if( pArea->nplayer > 0 || ( count_obj_list( pObjIndex, to_obj->first_content ) >= pReset->arg2 ) )
          {
            obj = NULL;
            break;
          }
/* New section */
        }
        sprintf( buf2, "inside%d@room%d", to_obj->pIndexData->vnum, pRoomIndex->vnum );
        obj = create_object( pObjIndex, number_fuzzy( UMAX( generate_itemlevel( pArea, pObjIndex ), to_obj->level ) ) );
        obj->count = ( pReset->arg2 - count_obj_list( pObjIndex, to_obj->first_content ) );
/* New section */
        if( IS_OBJ_TYPE( obj ) )
          obj->value[1] = obj->pIndexData->value[1];  /* reset object flags eg closed/locked */
/* New section */
        obj_to_obj( obj, to_obj );
        break;

      case 'T':
        if( IS_SET( pReset->extra, TRAP_OBJ ) )
        {
          /*
           * We need to preserve obj for future 'T' and 'H' checks 
           */
          OBJ_DATA *pobj;

          if( pReset->arg3 > 0 )
          {
            if( !( pObjToIndex = get_obj_index( pReset->arg3 ) ) )
            {
/*
	    sprintf (buf,"%s Reset_area: 'T': bad objto vnum %d."
		,pArea->filename, pReset->arg3 );
	    bug ( buf, 0 );
*/
              continue;
            }
            if( proto == TRUE && !IS_OBJ_STAT( pObjToIndex, ITEM_PROTOTYPE ) )
            {
              bug( "Reset tried to invoke non-prototype object.  Skipping.", 0 );
              continue;
            }
            if( pArea->nplayer > 0 ||
                !( to_obj = get_obj_type( pObjToIndex ) ) ||
                ( to_obj->carried_by && !IS_NPC( to_obj->carried_by ) ) || is_trapped( to_obj ) )
              break;
          }
          else
          {
            if( !lastobj || !obj )
              break;
            to_obj = obj;
          }
          pobj = make_trap( pReset->arg2, pReset->arg1, number_fuzzy( to_obj->level ), pReset->extra );
          obj_to_obj( pobj, to_obj );
        }
        else
        {
          if( !( pRoomIndex = get_room_index( pReset->arg3 ) ) )
          {
/*
	  sprintf(buf,"%s Reset_area: 'T': bad room %d.", pArea->filename,
		pReset->arg3 );
	  bug( buf, 0 );
*/
            continue;
          }
          if( pArea->nplayer > 0 || count_obj_list( get_obj_index( OBJ_VNUM_TRAP ), pRoomIndex->first_content ) > 0 )
            break;
          to_obj = make_trap( pReset->arg1, pReset->arg1, 10, pReset->extra );
          obj_to_room( to_obj, pRoomIndex );
        }
        break;

      case 'H':
        if( pReset->arg1 > 0 )
        {
          if( !( pObjToIndex = get_obj_index( pReset->arg1 ) ) )
          {
/*
	  sprintf(buf,"%s Reset_area: 'H': bad objto vnum %d.",pArea->filename,
		pReset->arg1 );
	  bug( buf, 0 );
*/
            continue;
          }
          if( proto == TRUE && !IS_OBJ_STAT( pObjToIndex, ITEM_PROTOTYPE ) )
          {
            bug( "Reset tried to invoke non-prototype object.  Skipping.", 0 );
            continue;
          }
          if( pArea->nplayer > 0 ||
              !( to_obj = get_obj_type( pObjToIndex ) ) ||
              !to_obj->in_room || to_obj->in_room->area != pArea || IS_OBJ_STAT( to_obj, ITEM_HIDDEN ) )
            break;
        }
        else
        {
          if( !lastobj || !obj )
            break;
          to_obj = obj;
        }
        xSET_BIT( to_obj->extra_flags, ITEM_HIDDEN );
        break;

      case 'B':
        switch ( pReset->arg2 & BIT_RESET_TYPE_MASK )
        {
          case BIT_RESET_DOOR:
          {
            int doornum;

            if( !( pRoomIndex = get_room_index( pReset->arg1 ) ) )
            {
/*
	  sprintf(buf,"%s Reset_area: 'B': door: bad room vnum %d.",
		pArea->filename, pReset->arg1 );
	  bug( buf, 0 );
*/
              continue;
            }
            doornum = ( pReset->arg2 & BIT_RESET_DOOR_MASK ) >> BIT_RESET_DOOR_THRESHOLD;
            if( !( pexit = get_exit( pRoomIndex, doornum ) ) )
              break;
            plc = &pexit->exit_info;
          }
            break;
          case BIT_RESET_ROOM:
            if( !( pRoomIndex = get_room_index( pReset->arg1 ) ) )
            {
/*
	  sprintf(buf,"%s Reset_area: 'B': room: bad room vnum %d.",
		pArea->filename, pReset->arg1 );
	  bug(buf, 0);
*/
              continue;
            }
            plc = &pRoomIndex->room_flags;
            break;
          case BIT_RESET_OBJECT:
            if( pReset->arg1 > 0 )
            {
              if( !( pObjToIndex = get_obj_index( pReset->arg1 ) ) )
              {
/*
	    sprintf(buf,"%s Reset_area: 'B': object: bad objto vnum %d.",
		pArea->filename, pReset->arg1 );
	    bug( buf, 0 );
*/
                continue;
              }
              if( proto == TRUE && !IS_OBJ_STAT( pObjToIndex, ITEM_PROTOTYPE ) )
              {
                bug( "Reset tried to invoke non-prototype object.  Skipping.", 0 );
                continue;
              }
              if( !( to_obj = get_obj_type( pObjToIndex ) ) || !to_obj->in_room || to_obj->in_room->area != pArea )
                continue;
            }
            else
            {
              if( !lastobj || !obj )
                continue;
              to_obj = obj;
            }
            plc = &to_obj->extra_flags;
            ext_bv = TRUE;
            break;
          case BIT_RESET_MOBILE:
            if( !mob )
              continue;
            plc = &mob->affected_by;
            ext_bv = TRUE;
            break;
          default:
/*
	sprintf(buf, "%s Reset_area: 'B': bad options %d.",
		pArea->filename, pReset->arg2 );
	bug( buf, 0 );
*/
            continue;
        }
        if( IS_SET( pReset->arg2, BIT_RESET_SET ) )
        {
          if( ext_bv )
            xSET_BIT( *( EXT_BV * ) plc, pReset->arg3 );
          else
            SET_BIT( *( int * )plc, pReset->arg3 );
        }
        else if( IS_SET( pReset->arg2, BIT_RESET_TOGGLE ) )
        {
          if( ext_bv )
            xTOGGLE_BIT( *( EXT_BV * ) plc, pReset->arg3 );
          else
            TOGGLE_BIT( *( int * )plc, pReset->arg3 );
        }
        else
        {
          if( ext_bv )
            xREMOVE_BIT( *( EXT_BV * ) plc, pReset->arg3 );
          else
            REMOVE_BIT( *( int * )plc, pReset->arg3 );
        }
        break;

      case 'D':
        if( !( pRoomIndex = get_room_index( pReset->arg1 ) ) )
        {
/*
	sprintf(buf, "%s Reset_area: 'D': bad room vnum %d.",
		pArea->filename, pReset->arg1 );
	bug(buf, 0);
*/
          continue;
        }
        if( !( pexit = get_exit( pRoomIndex, pReset->arg2 ) ) )
          break;
        switch ( pReset->arg3 )
        {
          case 0:
            REMOVE_BIT( pexit->exit_info, EX_CLOSED );
            REMOVE_BIT( pexit->exit_info, EX_LOCKED );
            break;
          case 1:
            SET_BIT( pexit->exit_info, EX_CLOSED );
            REMOVE_BIT( pexit->exit_info, EX_LOCKED );
            if( IS_SET( pexit->exit_info, EX_xSEARCHABLE ) )
              SET_BIT( pexit->exit_info, EX_SECRET );
            break;
          case 2:
            SET_BIT( pexit->exit_info, EX_CLOSED );
            SET_BIT( pexit->exit_info, EX_LOCKED );
            if( IS_SET( pexit->exit_info, EX_xSEARCHABLE ) )
              SET_BIT( pexit->exit_info, EX_SECRET );
            break;
        }
        break;

      case 'R':
        if( !( pRoomIndex = get_room_index( pReset->arg1 ) ) )
        {
/*
	sprintf(buf,"%s Reset_area: 'R': bad room vnum %d.",
		pArea->filename, pReset->arg1 );
	bug(buf, 0);
*/
          continue;
        }
        randomize_exits( pRoomIndex, pReset->arg2 - 1 );
        break;
    }
  }
  return;
}

void list_resets( CHAR_DATA * ch, AREA_DATA * pArea, ROOM_INDEX_DATA * pRoom, int start, int end )
{
  RESET_DATA *pReset;
  ROOM_INDEX_DATA *room;
  MOB_INDEX_DATA *mob;
  OBJ_INDEX_DATA *obj, *obj2;
  OBJ_INDEX_DATA *lastobj;
  RESET_DATA *lo_reset;
  bool found;
  int num = 0;
  const char *rname = "???", *mname = "???", *oname = "???";
  char buf[256];
  char *pbuf;

  if( !ch || !pArea )
    return;
  room = NULL;
  mob = NULL;
  obj = NULL;
  lastobj = NULL;
  lo_reset = NULL;
  found = FALSE;

  for( pReset = pArea->first_reset; pReset; pReset = pReset->next )
  {
    if( !is_room_reset( pReset, pRoom, pArea ) )
      continue;
    ++num;
    sprintf( buf, "%2d) ", num );
    pbuf = buf + strlen( buf );
    switch ( pReset->command )
    {
      default:
        sprintf( pbuf, "*** BAD RESET: %c %d %d %d %d ***\n\r",
                 pReset->command, pReset->extra, pReset->arg1, pReset->arg2, pReset->arg3 );
        break;
      case 'M':
        if( !( mob = get_mob_index( pReset->arg1 ) ) )
          mname = "Mobile: *BAD VNUM*";
        else
          mname = mob->player_name;
        if( !( room = get_room_index( pReset->arg3 ) ) )
          rname = "Room: *BAD VNUM*";
        else
          rname = room->name;
        sprintf( pbuf, "%s (%d) -> %s (%d) [%d]", mname, pReset->arg1, rname, pReset->arg3, pReset->arg2 );
        if( !room )
          mob = NULL;
        if( ( room = get_room_index( pReset->arg3 - 1 ) ) && xIS_SET( room->room_flags, ROOM_PET_SHOP ) )
          strcat( buf, " (pet)\n\r" );
        else
          strcat( buf, "\n\r" );
        break;
      case 'G':
      case 'E':
        if( !mob )
          mname = "* ERROR: NO MOBILE! *";
        if( !( obj = get_obj_index( pReset->arg1 ) ) )
          oname = "Object: *BAD VNUM*";
        else
          oname = obj->name;
        sprintf( pbuf, "%s (%d) -> %s (%s) [%d]", oname, pReset->arg1, mname,
                 ( pReset->command == 'G' ? "carry" : wear_locs[pReset->arg3] ), pReset->arg2 );
        if( mob && mob->pShop )
          strcat( buf, " (shop)\n\r" );
        else
          strcat( buf, "\n\r" );
        lastobj = obj;
        lo_reset = pReset;
        break;
      case 'O':
        if( !( obj = get_obj_index( pReset->arg1 ) ) )
          oname = "Object: *BAD VNUM*";
        else
          oname = obj->name;
        if( !( room = get_room_index( pReset->arg3 ) ) )
          rname = "Room: *BAD VNUM*";
        else
          rname = room->name;
        sprintf( pbuf, "(object) %s (%d) -> %s (%d) [%d]\n\r", oname, pReset->arg1, rname, pReset->arg3, pReset->arg2 );
        if( !room )
          obj = NULL;
        lastobj = obj;
        lo_reset = pReset;
        break;
      case 'P':
        if( !( obj = get_obj_index( pReset->arg1 ) ) )
          oname = "Object1: *BAD VNUM*";
        else
          oname = obj->name;
        obj2 = NULL;
        if( pReset->arg3 > 0 )
        {
          obj2 = get_obj_index( pReset->arg3 );
          rname = ( obj2 ? obj2->name : "Object2: *BAD VNUM*" );
          lastobj = obj2;
        }
        else if( !lastobj )
          rname = "Object2: *NULL obj*";
        else if( pReset->extra == 0 )
        {
          rname = lastobj->name;
          obj2 = lastobj;
        }
        else
        {
          int iNest;
          RESET_DATA *reset;

          reset = lo_reset->next;
          for( iNest = 0; iNest < pReset->extra; iNest++ )
          {
            for( ; reset; reset = reset->next )
              if( reset->command == 'O' || reset->command == 'G' ||
                  reset->command == 'E' || ( reset->command == 'P' &&
                                             !reset->arg3 && reset->extra == iNest &&
                                             ( get_obj_index( reset->arg1 )->item_type == ITEM_CONTAINER ) ) )
                break;
            if( !reset || reset->command != 'P' )
              break;
          }
          if( !reset )
            rname = "Object2: *BAD NESTING*";
          else if( !( obj2 = get_obj_index( reset->arg1 ) ) )
            rname = "Object2: *NESTED BAD VNUM*";
          else
            rname = obj2->name;
        }
        sprintf( pbuf, "(Put) %s (%d) -> %s (%d) [%d] {nest %d}\n\r", oname,
                 pReset->arg1, rname, ( obj2 ? obj2->vnum : pReset->arg3 ), pReset->arg2, pReset->extra );
        break;
      case 'T':
        sprintf( pbuf, "TRAP: %d %d %d %d (%s)\n\r", pReset->extra, pReset->arg1,
                 pReset->arg2, pReset->arg3, flag_string( pReset->extra, trap_flags ) );
        break;
      case 'H':
        if( pReset->arg1 > 0 )
          if( !( obj2 = get_obj_index( pReset->arg1 ) ) )
            rname = "Object: *BAD VNUM*";
          else
            rname = obj2->name;
        else if( !obj )
          rname = "Object: *NULL obj*";
        else
          rname = oname;
        sprintf( pbuf, "Hide %s (%d)\n\r", rname, ( pReset->arg1 > 0 ? pReset->arg1 : obj ? obj->vnum : 0 ) );
        break;
      case 'B':
      {
        char *const *flagarray;
        bool ext_bv = FALSE;

        strcpy( pbuf, "BIT: " );
        pbuf += 5;
        if( IS_SET( pReset->arg2, BIT_RESET_SET ) )
        {
          strcpy( pbuf, "Set: " );
          pbuf += 5;
        }
        else if( IS_SET( pReset->arg2, BIT_RESET_TOGGLE ) )
        {
          strcpy( pbuf, "Toggle: " );
          pbuf += 8;
        }
        else
        {
          strcpy( pbuf, "Remove: " );
          pbuf += 8;
        }
        switch ( pReset->arg2 & BIT_RESET_TYPE_MASK )
        {
          case BIT_RESET_DOOR:
          {
            int door;

            if( !( room = get_room_index( pReset->arg1 ) ) )
              rname = "Room: *BAD VNUM*";
            else
              rname = room->name;
            door = ( pReset->arg2 & BIT_RESET_DOOR_MASK ) >> BIT_RESET_DOOR_THRESHOLD;
            door = URANGE( 0, door, MAX_DIR + 1 );
            sprintf( pbuf, "Exit %s%s (%d), Room %s (%d)", dir_name[door],
                     ( room && get_exit( room, door ) ? "" : " (NO EXIT!)" ), door, rname, pReset->arg1 );
          }
            flagarray = ex_flags;
            break;
          case BIT_RESET_ROOM:
            if( !( room = get_room_index( pReset->arg1 ) ) )
              rname = "Room: *BAD VNUM*";
            else
              rname = room->name;
            sprintf( pbuf, "Room %s (%d)", rname, pReset->arg1 );
            flagarray = r_flags;
            break;
          case BIT_RESET_OBJECT:
            if( pReset->arg1 > 0 )
              if( !( obj2 = get_obj_index( pReset->arg1 ) ) )
                rname = "Object: *BAD VNUM*";
              else
                rname = obj2->name;
            else if( !obj )
              rname = "Object: *NULL obj*";
            else
              rname = oname;
            sprintf( pbuf, "Object %s (%d)", rname, ( pReset->arg1 > 0 ? pReset->arg1 : obj ? obj->vnum : 0 ) );
            flagarray = o_flags;
            ext_bv = TRUE;
            break;
          case BIT_RESET_MOBILE:
            if( pReset->arg1 > 0 )
            {
              MOB_INDEX_DATA *mob2;

              if( !( mob2 = get_mob_index( pReset->arg1 ) ) )
                rname = "Mobile: *BAD VNUM*";
              else
                rname = mob2->player_name;
            }
            else if( !mob )
              rname = "Mobile: *NULL mob*";
            else
              rname = mname;
            sprintf( pbuf, "Mobile %s (%d)", rname, ( pReset->arg1 > 0 ? pReset->arg1 : mob ? mob->vnum : 0 ) );
            flagarray = a_flags;
            ext_bv = TRUE;
            break;
          default:
            sprintf( pbuf, "bad type %d", pReset->arg2 & BIT_RESET_TYPE_MASK );
            flagarray = NULL;
            break;
        }
        pbuf += strlen( pbuf );
        if( flagarray )
        {
          if( ext_bv )
          {
            EXT_BV tmp;

            tmp = meb( pReset->arg3 );
            sprintf( pbuf, "; flags: %s [%d]\n\r", ext_flag_string( &tmp, flagarray ), pReset->arg3 );
          }
          else
            sprintf( pbuf, "; flags: %s [%d]\n\r", flag_string( pReset->arg3, flagarray ), pReset->arg3 );
        }
        else
          sprintf( pbuf, "; flags %d\n\r", pReset->arg3 );
      }
        break;
      case 'D':
      {
        char *ef_name;

        pReset->arg2 = URANGE( 0, pReset->arg2, MAX_DIR + 1 );
        if( !( room = get_room_index( pReset->arg1 ) ) )
          rname = "Room: *BAD VNUM*";
        else
          rname = room->name;
        switch ( pReset->arg3 )
        {
          default:
            ef_name = "(* ERROR *)";
            break;
          case 0:
            ef_name = "Open";
            break;
          case 1:
            ef_name = "Close";
            break;
          case 2:
            ef_name = "Close and lock";
            break;
        }
        sprintf( pbuf, "%s [%d] the %s%s [%d] door %s (%d)\n\r", ef_name,
                 pReset->arg3, dir_name[pReset->arg2],
                 ( room && get_exit( room, pReset->arg2 ) ? "" : " (NO EXIT!)" ), pReset->arg2, rname, pReset->arg1 );
      }
        break;
      case 'R':
        if( !( room = get_room_index( pReset->arg1 ) ) )
          rname = "Room: *BAD VNUM*";
        else
          rname = room->name;
        sprintf( pbuf, "Randomize exits 0 to %d -> %s (%d)\n\r", pReset->arg2, rname, pReset->arg1 );
        break;
    }
    if( start == -1 || num >= start )
      send_to_char( buf, ch );
    if( end != -1 && num >= end )
      break;
  }
  if( num == 0 )
    send_to_char( "You don't have any resets defined.\n\r", ch );
  return;
}

/* Setup put nesting levels, regardless of whether or not the resets will
   actually reset, or if they're bugged. */
void renumber_put_resets( AREA_DATA * pArea )
{
  RESET_DATA *pReset, *lastobj = NULL;
  OBJ_INDEX_DATA *putobj;

  for( pReset = pArea->first_reset; pReset; pReset = pReset->next )
  {
    switch ( pReset->command )
    {
      default:
        break;
      case 'G':
      case 'E':
      case 'O':
        lastobj = pReset;
        break;
      case 'P':
        if( pReset->arg3 == 0 )
        {
          if( !lastobj )
            pReset->extra = 1000000;
          else if( lastobj->command != 'P' || lastobj->arg3 > 0 )
            pReset->extra = 0;
          else
          {
            if( ( putobj = get_obj_index( lastobj->arg1 ) ) != NULL )
            {
              if( ( putobj->item_type == ITEM_CONTAINER )
                  || ( putobj->item_type == ITEM_FURNITURE ) || ( putobj->item_type == ITEM_QUIVER ) )
                pReset->extra = lastobj->extra + 1;
              else
                pReset->extra = UMAX( ( lastobj->extra - 1 ), 0 );
            }
          }
          lastobj = pReset;
        }
    }
  }
  return;
}

/*
 * Create a new reset (for online building)			-Thoric
 */
RESET_DATA *make_reset( char letter, int extra, int arg1, int arg2, int arg3 )
{
  RESET_DATA *pReset;

  CREATE( pReset, RESET_DATA, 1 );
  pReset->command = letter;
  pReset->extra = extra;
  pReset->arg1 = arg1;
  pReset->arg2 = arg2;
  pReset->arg3 = arg3;
  if( letter == 'M' )
  {
    top_mob_serial++;
    pReset->reset_serial = top_mob_serial;
  }
  else
    pReset->reset_serial = -1;
  top_reset++;
  return pReset;
}

/*
 * Add a reset to an area				-Thoric
 */
RESET_DATA *add_reset( AREA_DATA * tarea, char letter, int extra, int arg1, int arg2, int arg3 )
{
  RESET_DATA *pReset;

  if( !tarea )
  {
    bug( "add_reset: NULL area!", 0 );
    return NULL;
  }

  letter = UPPER( letter );
  pReset = make_reset( letter, extra, arg1, arg2, arg3 );
  switch ( letter )
  {
    case 'M':
      tarea->last_mob_reset = pReset;
      break;
    case 'H':
      if( arg1 > 0 )
        break;
    case 'E':
    case 'G':
    case 'P':
    case 'O':
      tarea->last_obj_reset = pReset;
      break;
    case 'T':
      if( IS_SET( extra, TRAP_OBJ ) && arg1 == 0 )
        tarea->last_obj_reset = pReset;
      break;
  }

  LINK( pReset, tarea->first_reset, tarea->last_reset, next, prev );
  return pReset;
}

/*
 * Place a reset into an area, insert sorting it		-Thoric
 */
RESET_DATA *place_reset( AREA_DATA * tarea, char letter, int extra, int arg1, int arg2, int arg3 )
{
  RESET_DATA *pReset, *tmp, *tmp2;

  if( !tarea )
  {
    bug( "place_reset: NULL area!", 0 );
    return NULL;
  }

  letter = UPPER( letter );
  pReset = make_reset( letter, extra, arg1, arg2, arg3 );
  if( letter == 'M' )
    tarea->last_mob_reset = pReset;

  if( tarea->first_reset )
  {
    switch ( letter )
    {
      default:
        bug( "place_reset: Bad reset type %c", letter );
        return NULL;
      case 'D':
      case 'R':
        for( tmp = tarea->last_reset; tmp; tmp = tmp->prev )
          if( tmp->command == letter )
            break;
        if( tmp ) /* organize by location */
          for( ; tmp && tmp->command == letter && tmp->arg1 > arg1; tmp = tmp->prev );
        if( tmp ) /* organize by direction */
          for( ; tmp && tmp->command == letter && tmp->arg1 == tmp->arg1 && tmp->arg2 > arg2; tmp = tmp->prev );
        if( tmp )
          INSERT( pReset, tmp, tarea->first_reset, next, prev );
        else
          LINK( pReset, tarea->first_reset, tarea->last_reset, next, prev );
        return pReset;
      case 'M':
      case 'O':
        /*
         * find last reset of same type 
         */
        for( tmp = tarea->last_reset; tmp; tmp = tmp->prev )
          if( tmp->command == letter )
            break;
        tmp2 = tmp ? tmp->next : NULL;
        /*
         * organize by location 
         */
        for( ; tmp; tmp = tmp->prev )
          if( tmp->command == letter && tmp->arg3 <= arg3 )
          {
            tmp2 = tmp->next;
            /*
             * organize by vnum 
             */
            if( tmp->arg3 == arg3 )
              for( ; tmp; tmp = tmp->prev )
                if( tmp->command == letter && tmp->arg3 == tmp->arg3 && tmp->arg1 <= arg1 )
                {
                  tmp2 = tmp->next;
                  break;
                }
            break;
          }
        /*
         * skip over E or G for that mob 
         */
        if( tmp2 && letter == 'M' )
        {
          for( ; tmp2; tmp2 = tmp2->next )
            if( tmp2->command != 'E' && tmp2->command != 'G' )
              break;
        }
        else
          /*
           * skip over P, T or H for that obj 
           */
        if( tmp2 && letter == 'O' )
        {
          for( ; tmp2; tmp2 = tmp2->next )
            if( tmp2->command != 'P' && tmp2->command != 'T' && tmp2->command != 'H' )
              break;
        }
        if( tmp2 )
          INSERT( pReset, tmp2, tarea->first_reset, next, prev );
        else
          LINK( pReset, tarea->first_reset, tarea->last_reset, next, prev );
        return pReset;
      case 'G':
      case 'E':
        /*
         * find the last mob 
         */
        if( ( tmp = tarea->last_mob_reset ) != NULL )
        {
          /*
           * See if there are any resets for this mob yet,
           * put E before G and organize by vnum
           */
          if( tmp->next )
          {
            tmp = tmp->next;
            if( tmp && tmp->command == 'E' )
            {
              if( letter == 'E' )
                for( ; tmp && tmp->command == 'E' && tmp->arg1 < arg1; tmp = tmp->next );
              else
                for( ; tmp && tmp->command == 'E'; tmp = tmp->next );
            }
            else if( tmp && tmp->command == 'G' && letter == 'G' )
              for( ; tmp && tmp->command == 'G' && tmp->arg1 < arg1; tmp = tmp->next );
            if( tmp )
              INSERT( pReset, tmp, tarea->first_reset, next, prev );
            else
              LINK( pReset, tarea->first_reset, tarea->last_reset, next, prev );
          }
          else
            LINK( pReset, tarea->first_reset, tarea->last_reset, next, prev );
          return pReset;
        }
        break;
      case 'P':
      case 'T':
      case 'H':
        /*
         * find the object in question 
         */
        if( ( ( letter == 'P' && arg3 == 0 )
              || ( letter == 'T' && IS_SET( extra, TRAP_OBJ ) && arg1 == 0 )
              || ( letter == 'H' && arg1 == 0 ) ) && ( tmp = tarea->last_obj_reset ) != NULL )
        {
          if( ( tmp = tmp->next ) != NULL )
            INSERT( pReset, tmp, tarea->first_reset, next, prev );
          else
            LINK( pReset, tarea->first_reset, tarea->last_reset, next, prev );
          return pReset;
        }

        for( tmp = tarea->last_reset; tmp; tmp = tmp->prev )
          if( ( tmp->command == 'O' || tmp->command == 'G'
                || tmp->command == 'E' || tmp->command == 'P' ) && tmp->arg1 == arg3 )
          {
            /*
             * See if there are any resets for this object yet,
             * put P before H before T and organize by vnum
             */
            if( tmp->next )
            {
              tmp = tmp->next;
              if( tmp && tmp->command == 'P' )
              {
                if( letter == 'P' && tmp->arg3 == arg3 )
                  for( ; tmp && tmp->command == 'P' && tmp->arg3 == arg3 && tmp->arg1 < arg1; tmp = tmp->next );
                else if( letter != 'T' )
                  for( ; tmp && tmp->command == 'P' && tmp->arg3 == arg3; tmp = tmp->next );
              }
              else if( tmp && tmp->command == 'H' )
              {
                if( letter == 'H' && tmp->arg3 == arg3 )
                  for( ; tmp && tmp->command == 'H' && tmp->arg3 == arg3 && tmp->arg1 < arg1; tmp = tmp->next );
                else if( letter != 'H' )
                  for( ; tmp && tmp->command == 'H' && tmp->arg3 == arg3; tmp = tmp->next );
              }
              else if( tmp && tmp->command == 'T' && letter == 'T' )
                for( ; tmp && tmp->command == 'T' && tmp->arg3 == arg3 && tmp->arg1 < arg1; tmp = tmp->next );
              if( tmp )
                INSERT( pReset, tmp, tarea->first_reset, next, prev );
              else
                LINK( pReset, tarea->first_reset, tarea->last_reset, next, prev );
            }
            else
              LINK( pReset, tarea->first_reset, tarea->last_reset, next, prev );
            return pReset;
          }
        break;
    }
    /*
     * likely a bad reset if we get here... add it anyways 
     */
  }
  LINK( pReset, tarea->first_reset, tarea->last_reset, next, prev );
  return pReset;
}