Nested reset fix
----------------

This is a large and very involved fix, which affects several key systems.
You are strongly advised to backup all area files and keep them in a safe
place for awhile after you've added this fix. If you are not comfortable
with large sweeping changes, this probably isn't right for you.

You should also back up your source code to be safe.

The problem
-----------

Nested put resets in Smaug have had a notorious history for not working correctly.
In stock form, the code is incapable of generating them properly using the OLC, 
incapable of processing them properly when area files are loaded, and incapable of
loading items properly according to how resets are defined in the file even if the
file is manually edited.

Part of this was corrected with a previous bugfix which allowed the OLC to generate
the proper resets which will then save correctly into the area files. These resets
load to the area in the proper order but the nested puts still did not perform as
expected.

An example of the issue:

Load a chest into a room.
Load a bag into the chest.
Load a pouch into the bag.
Load a trinket into the pouch.

The expected result would of course be to have to dig through all that to get the trinket
out of the chest, but what really happens is that it all just loads as contents of the chest.
This problem has existed at least as far back as Smaug 1.4a and therefore affects practically
all codebases derived from it. I have confirmed that this problem exists on Smaug FUSS, as well
as ResortMUD and the public AFKMud code, so in all likelyhood all Smaug derivatives are affected.

The solution
------------

In order to fix this problem, I decided it would be best to disassociate resets with an overall
area and instead focus them on individual rooms, which are then associated with an area so
that normal whole area resetting can still take place. Of course this required alot of reworking
of how the entire system works. But the end result is that the example above will perform properly
and all objects assigned to put resets will load exactly as intended.

Areas now have a list of rooms.
Rooms now have a list of resets that should take place in them.
Object and Mobile resets now have child resets which belong to them.

There is one caveat to be aware of though. Area files may have invalid data still in them and once
the fix is applied they may produce unexpected results, such as swords loading inside of shoes, etc.
Affected area files will need to be fixed by hand, so you will need a working knowledge of how
they are formatted. Trap and Hide resets will also not be convertable because the code has no
confirmed way to know where they should be place. These will also need to be hand corrected.
There may also be items and mobs loading into unexpected rooms. Some functionality of the
manual reset editing has also been removed for now. Best to scale back and rebuild rather than keep
kludgy code that would only need to be rewritten anyway. If this functionality is desired, it
can be added back in easily enough.

Once all that is corrected though, the reset system will hum along quite nicely. :)

What you need to do
-------------------

1. Open act_wiz.c and locate the close_area function.

Remove the following from the declarations:
   RESET_DATA *ereset, *ereset_next;

Find and remove the following segment of code:
   for( ereset = pArea->first_reset; ereset; ereset = ereset_next )
   {
      ereset_next = ereset->next;
      UNLINK( ereset, pArea->first_reset, pArea->last_reset, next, prev );
      DISPOSE( ereset );
   }

2. Open build.c

Locate the following near the top:

extern int top_affect;
extern int top_reset;
extern int top_ed;
extern bool fBootDb;

Below it, add:

char *sprint_reset( RESET_DATA *pReset, short *num );
void fix_exits( void );

Locate do_redit and find the following:

   if( !str_cmp( arg, "rlist" ) )
   {
      RESET_DATA *pReset;
      char *bptr;
      AREA_DATA *tarea;
      short num;

      tarea = location->area;
      if( !tarea->first_reset )
      {
         send_to_char( "This area has no resets to list.\r\n", ch );
         return;
      }
      num = 0;
      for( pReset = tarea->first_reset; pReset; pReset = pReset->next )
      {
         num++;
         if( ( bptr = sprint_reset( ch, pReset, num, TRUE ) ) == NULL )
            continue;
         send_to_char( bptr, ch );
      }
      return;
   }

Relace it with the following:

   if( !str_cmp( arg, "rlist" ) )
   {
      RESET_DATA *pReset;
      char *rbuf;
      short num;

      if( !location->first_reset )
      {
         send_to_char( "This room has no resets to list.\r\n", ch );
         return;
      }
      num = 0;
      for( pReset = location->first_reset; pReset; pReset = pReset->next )
      {
         ++num;
         if( !( rbuf = sprint_reset( pReset, &num ) ) )
            continue;
         send_to_char( rbuf, ch );
      }
      return;
   }

Locate the sprint_reset function and remove it. It will be replaced in reset.c

Locate the fold_area function.

In the declarations, find:

   RESET_DATA *treset;

Replace with:

   RESET_DATA *pReset, *tReset, *gReset;

Locate the following:

      for( xit = room->first_exit; xit; xit = xit->next )
      {
         if( IS_SET( xit->exit_info, EX_PORTAL ) ) /* don't fold portals */
            continue;
         fprintf( fpout, "D%d\n", xit->vdir );
         fprintf( fpout, "%s~\n", strip_cr( xit->description ) );
         fprintf( fpout, "%s~\n", strip_cr( xit->keyword ) );
         if( xit->distance > 1 || xit->pull )
            fprintf( fpout, "%d %d %d %d %d %d\n",
                     xit->exit_info & ~EX_BASHED, xit->key, xit->vnum, xit->distance, xit->pulltype, xit->pull );
         else
            fprintf( fpout, "%d %d %d\n", xit->exit_info & ~EX_BASHED, xit->key, xit->vnum );
      }

Directly below that, add:

      for( pReset = room->first_reset; pReset; pReset = pReset->next )
      {
	   switch( pReset->command ) /* extra arg1 arg2 arg3 */
	   {
	      default:  case '*': break;
	      case 'm': case 'M':
	      case 'o': case 'O':
		   fprintf( fpout, "R %c %d %d %d %d\n", UPPER( pReset->command ),
		      pReset->extra, pReset->arg1, pReset->arg2, pReset->arg3 );
            
               for( tReset = pReset->first_reset; tReset; tReset = tReset->next_reset )
               {
                     switch( tReset->command )
                     {
                        case 'p':
                        case 'P':
                        case 'e':
                        case 'E':
                           fprintf( fpout, "  R %c %d %d %d %d\n", UPPER( tReset->command ),
                              tReset->extra, tReset->arg1, tReset->arg2, tReset->arg3 );
                           if( tReset->first_reset )
                           {
                              for( gReset = tReset->first_reset; gReset; gReset = gReset->next_reset )
                              {
                                 if( gReset->command != 'p' && gReset->command != 'P' )
                                    continue;
                                 fprintf( fpout, "    R %c %d %d %d %d\n", UPPER( gReset->command ),
                                    gReset->extra, gReset->arg1, gReset->arg2, gReset->arg3 );
                              }
                           }
                           break;

                        case 'g':
                        case 'G':
                           fprintf( fpout, "  R %c %d %d %d\n", UPPER( tReset->command ),
                              tReset->extra, tReset->arg1, tReset->arg2 );
                           if( tReset->first_reset )
                           {
                              for( gReset = tReset->first_reset; gReset; gReset = gReset->next_reset )
                              {
                                 if( gReset->command != 'p' && gReset->command != 'P' )
                                    continue;
                                 fprintf( fpout, "    R %c %d %d %d %d\n", UPPER( gReset->command ),
                                    gReset->extra, gReset->arg1, gReset->arg2, gReset->arg3 );
                              }
                           }
                        break;

                        case 't':
                        case 'T':
                        case 'h':
                        case 'H':
                           fprintf( fpout, "  R %c %d %d %d %d\n", UPPER( tReset->command ),
                              tReset->extra, tReset->arg1, tReset->arg2, tReset->arg3 );
                           break;
                     }
               }
		   break;

	      case 'd': case 'D':
	      case 't': case 'T':
	  	case 'h': case 'H':
		   fprintf( fpout, "R %c %d %d %d %d\n", UPPER( pReset->command ),
		      pReset->extra, pReset->arg1, pReset->arg2, pReset->arg3 );
		   break;

	      case 'r': case 'R':
		   fprintf( fpout, "R %c %d %d %d\n", UPPER( pReset->command ), pReset->extra, pReset->arg1, pReset->arg2 );
		   break;
	   }
      }

Locate the following and remove it:

   /*
    * save resets   
    */
   fprintf( fpout, "#RESETS\n" );
   for( treset = tarea->first_reset; treset; treset = treset->next )
   {
      switch ( treset->command ) /* extra arg1 arg2 arg3 */
      {
         default:
         case '*':
            break;
         case 'm':
         case 'M':
         case 'o':
         case 'O':
         case 'p':
         case 'P':
         case 'e':
         case 'E':
         case 'd':
         case 'D':
         case 't':
         case 'T':
         case 'b':
         case 'B':
         case 'h':
         case 'H':
            fprintf( fpout, "%c %d %d %d %d\n", UPPER( treset->command ),
                     treset->extra, treset->arg1, treset->arg2, treset->arg3 );
            break;
         case 'g':
         case 'G':
         case 'r':
         case 'R':
            fprintf( fpout, "%c %d %d %d\n", UPPER( treset->command ), treset->extra, treset->arg1, treset->arg2 );
            break;
      }
   }
   fprintf( fpout, "S\n\n\n" );

Find and remove the free_area function.
Find and remove the free_reset function.

Locate function assign_area and find:

         tarea->first_reset = NULL;
         tarea->last_reset = NULL;

Replace with:

         tarea->first_room = tarea->last_room = NULL;

Locate function do_loadarea

Find:

   if( tarea->first_reset )

Replace with:

   if( tarea->first_room )

Find and remove the add_reset_nested function.
Find and reomve the parse_reset function.

Locate function do_rdelete.

Find:

   delete_room( location );

Below that, add:

   fix_exits(  ); /* Need to call this to solve a crash */

Locate function do_goto.

Find:

      location = make_room( vnum );

Replace with:

      location = make_room( vnum, ch->pcdata->area );

3. Open db.c

Locate:

void renumber_put_resets args( ( AREA_DATA * pArea ) );

Replace it with:

void renumber_put_resets( ROOM_INDEX_DATA *room );
void wipe_resets( ROOM_INDEX_DATA *room );

Locate the load_area function and find:

   pArea->first_reset = NULL;
   pArea->last_reset = NULL;

Replace that with:

   pArea->first_room = pArea->last_room = NULL;

Find the load_resets function and replace the ENTIRE function with:

/*
 * Load a reset section.
 */
void load_resets( AREA_DATA *tarea, FILE *fp )
{
   ROOM_INDEX_DATA *pRoomIndex = NULL;
   ROOM_INDEX_DATA *roomlist;
   bool not01 = FALSE;
   int count = 0;

   if( !tarea )
   {
      bug( "%s", "Load_resets: no #AREA seen yet." );
      if( fBootDb )
      {
         shutdown_mud( "No #AREA" );
         exit( 1 );
      }
      else
         return;
   }

   if( !tarea->first_room )
   {
      bug( "%s: No #ROOMS section found. Cannot load resets.", __FUNCTION__ );
      if( fBootDb )
      {
         shutdown_mud( "No #ROOMS" );
         exit(1);
      }
      else
         return;
   }

   for( ; ; )
   {
      EXIT_DATA *pexit;
      char letter;
      int extra, arg1, arg2, arg3;

      if( ( letter = fread_letter( fp ) ) == 'S' )
         break;

      if( letter == '*' )
      {
         fread_to_eol( fp );
         continue;
      }

      extra = fread_number( fp );
      if( letter == 'M' || letter == 'O' )
         extra = 0;
      arg1	= fread_number( fp );
      arg2	= fread_number( fp );
      arg3	= (letter == 'G' || letter == 'R') ? 0 : fread_number( fp );
      fread_to_eol( fp );
      ++count;

      /*
       * Validate parameters.
       * We're calling the index functions for the side effect.
       */
      switch( letter )
      {
         default:
            bug( "%s: bad command '%c'.", __FUNCTION__, letter );
            if( fBootDb )
               boot_log( "%s: %s (%d) bad command '%c'.", __FUNCTION__, tarea->filename, count, letter );
            return;

         case 'M':
            if( get_mob_index( arg1 ) == NULL && fBootDb )
               boot_log( "%s: %s (%d) 'M': mobile %d doesn't exist.", __FUNCTION__, tarea->filename, count, arg1 );

            if( ( pRoomIndex = get_room_index( arg3 ) ) == NULL && fBootDb )
               boot_log( "%s: %s (%d) 'M': room %d doesn't exist.", __FUNCTION__, tarea->filename, count, arg3 );
            else
               add_reset( pRoomIndex, letter, extra, arg1, arg2, arg3 );
            break;

         case 'O':
            if( get_obj_index( arg1 ) == NULL && fBootDb )
               boot_log( "%s: %s (%d) '%c': object %d doesn't exist.", __FUNCTION__, tarea->filename, count, letter, arg1 );

            if( ( pRoomIndex = get_room_index( arg3 ) ) == NULL && fBootDb )
               boot_log( "%s: %s (%d) '%c': room %d doesn't exist.", __FUNCTION__, tarea->filename, count, letter, arg3 );
            else
            {
               if( !pRoomIndex )
                  bug( "%s: Unable to add room reset - room not found.", __FUNCTION__ );
               else
                  add_reset( pRoomIndex, letter, extra, arg1, arg2, arg3 );
            }
            break;

         case 'P':
            if( get_obj_index( arg1 ) == NULL && fBootDb )
               boot_log( "%s: %s (%d) '%c': object %d doesn't exist.", __FUNCTION__, tarea->filename, count, letter, arg1 );
            if( arg3 > 0 )
            {
               if( get_obj_index( arg3 ) == NULL && fBootDb )
                  boot_log( "%s: %s (%d) 'P': destination object %d doesn't exist.", __FUNCTION__, tarea->filename, count, arg3 );
               if( extra > 1 )
                  not01 = TRUE;
            }
            if( !pRoomIndex )
               bug( "%s: Unable to add room reset - room not found.", __FUNCTION__ );
            else
            {
               if( arg3 == 0 )
                  arg3 = OBJ_VNUM_MONEY_ONE; // This may look stupid, but for some reason it works.
               add_reset( pRoomIndex, letter, extra, arg1, arg2, arg3 );
            }
            break;

         case 'G':
         case 'E':
            if( get_obj_index( arg1 ) == NULL && fBootDb )
               boot_log( "%s: %s (%d) '%c': object %d doesn't exist.", __FUNCTION__, tarea->filename, count, letter, arg1 );
            if( !pRoomIndex )
               bug( "%s: Unable to add room reset - room not found.", __FUNCTION__ );
            else
               add_reset( pRoomIndex, letter, extra, arg1, arg2, arg3 );
            break;

         case 'T':
            if( IS_SET( extra, TRAP_OBJ ) )
               bug( "%s: Unable to add legacy object trap reset. Must be converted manually.", __FUNCTION__ );
            else
            {
               if( !( pRoomIndex = get_room_index( arg3 ) ) )
                  bug( "%s: Unable to add trap reset - room not found.", __FUNCTION__ );
               else
                  add_reset( pRoomIndex, letter, extra, arg1, arg2, arg3 );
            }
            break;

         case 'H':
            bug( "%s: Unable to convert legacy hide reset. Must be converted manually.", __FUNCTION__ );
            break;

         case 'D':
            if( !( pRoomIndex = get_room_index( arg1 ) ) )
            {
               bug( "%s: 'D': room %d doesn't exist.", __FUNCTION__, arg1 );
               bug( "Reset: %c %d %d %d %d", letter, extra, arg1, arg2, arg3 );
               if( fBootDb )
                  boot_log( "%s: %s (%d) 'D': room %d doesn't exist.", __FUNCTION__, tarea->filename, count, arg1 );
               break;
            }

            if( arg2 < 0 || arg2 > MAX_DIR + 1
                || !( pexit = get_exit( pRoomIndex, arg2 ) ) || !IS_SET( pexit->exit_info, EX_ISDOOR ) )
            {
               bug( "%s: 'D': exit %d not door.", __FUNCTION__, arg2 );
               bug( "Reset: %c %d %d %d %d", letter, extra, arg1, arg2, arg3 );
               if( fBootDb )
                  boot_log( "%s: %s (%d) 'D': exit %d not door.", __FUNCTION__, tarea->filename, count, arg2 );
            }

            if( arg3 < 0 || arg3 > 2 )
            {
               bug( "%s: 'D': bad 'locks': %d.", __FUNCTION__, arg3 );
               if( fBootDb )
                  boot_log( "%s: %s (%d) 'D': bad 'locks': %d.", __FUNCTION__, tarea->filename, count, arg3 );
            }
            add_reset( pRoomIndex, letter, extra, arg1, arg2, arg3 );
            break;

         case 'R':
            if( !( pRoomIndex = get_room_index( arg1 ) ) && fBootDb )
               boot_log( "%s: %s (%d) 'R': room %d doesn't exist.", __FUNCTION__, tarea->filename, count, arg1 );
            else
               add_reset( pRoomIndex, letter, extra, arg1, arg2, arg3 );
            if( arg2 < 0 || arg2 > 10 )
            {
               bug( "%s: 'R': bad exit %d.", __FUNCTION__, arg2 );
               if( fBootDb )
                  boot_log( "%s: %s (%d) 'R': bad exit %d.", __FUNCTION__, tarea->filename, count, arg2 );
               break;
            }
            break;
	}
    }
   if( !not01 )
   {
      for( roomlist = tarea->first_room; roomlist; roomlist = roomlist->next_aroom )
         renumber_put_resets( roomlist );
   }
   return;
}

Find the load_rooms function, and DIRECTLY ABOVE IT, add:

void load_room_reset( ROOM_INDEX_DATA *room, FILE *fp )
{
   EXIT_DATA *pexit;
   char letter;
   int extra, arg1, arg2, arg3;
   bool not01 = FALSE;
   int count = 0;

   letter = fread_letter( fp );
   extra = fread_number( fp );
   if( letter == 'M' || letter == 'O' )
      extra = 0;
   arg1 = fread_number( fp );
   arg2 = fread_number( fp );
   arg3 = ( letter == 'G' || letter == 'R' ) ? 0 : fread_number( fp );
   fread_to_eol( fp );
   ++count;

   /*
    * Validate parameters.
    * We're calling the index functions for the side effect.
    */
   switch( letter )
   {
      default:
         bug( "%s: bad command '%c'.", __FUNCTION__, letter );
         if( fBootDb )
            boot_log( "%s: %s (%d) bad command '%c'.", __FUNCTION__, room->area->filename, count, letter );
         return;

      case 'M':
         if( get_mob_index( arg1 ) == NULL && fBootDb )
            boot_log( "%s: %s (%d) 'M': mobile %d doesn't exist.", __FUNCTION__, room->area->filename, count, arg1 );
         break;

      case 'O':
         if( get_obj_index( arg1 ) == NULL && fBootDb )
            boot_log( "%s: %s (%d) '%c': object %d doesn't exist.", __FUNCTION__, room->area->filename, count, letter, arg1 );
         break;

      case 'P':
         if( get_obj_index( arg1 ) == NULL && fBootDb )
            boot_log( "%s: %s (%d) '%c': object %d doesn't exist.", __FUNCTION__, room->area->filename, count, letter, arg1 );

         if( arg3 <= 0 )
            arg3 = OBJ_VNUM_MONEY_ONE; // This may look stupid, but for some reason it works.
         if( get_obj_index( arg3 ) == NULL && fBootDb )
            boot_log( "%s: %s (%d) 'P': destination object %d doesn't exist.", __FUNCTION__, room->area->filename, count, arg3 );
         if( extra > 1 )
            not01 = TRUE;
         break;

      case 'G':
      case 'E':
         if( get_obj_index( arg1 ) == NULL && fBootDb )
            boot_log( "%s: %s (%d) '%c': object %d doesn't exist.", __FUNCTION__, room->area->filename, count, letter, arg1 );
         break;

      case 'T':
      case 'H':
         break;

      case 'D':
         if( arg2 < 0 || arg2 > MAX_DIR + 1
             || !( pexit = get_exit( room, arg2 ) ) || !IS_SET( pexit->exit_info, EX_ISDOOR ) )
         {
            bug( "%s: 'D': exit %d not door.", __FUNCTION__, arg2 );
            bug( "Reset: %c %d %d %d %d", letter, extra, arg1, arg2, arg3 );
            if( fBootDb )
               boot_log( "%s: %s (%d) 'D': exit %d not door.", __FUNCTION__, room->area->filename, count, arg2 );
         }

         if( arg3 < 0 || arg3 > 2 )
         {
            bug( "%s: 'D': bad 'locks': %d.", __FUNCTION__, arg3 );
            if( fBootDb )
               boot_log( "%s: %s (%d) 'D': bad 'locks': %d.", __FUNCTION__, room->area->filename, count, arg3 );
         }
         break;

      case 'R':
         if( arg2 < 0 || arg2 > 10 )
         {
            bug( "%s: 'R': bad exit %d.", __FUNCTION__, arg2 );
            if( fBootDb )
               boot_log( "%s: %s (%d) 'R': bad exit %d.", __FUNCTION__, room->area->filename, count, arg2 );
            break;
         }
         break;
   }
   add_reset( room, letter, extra, arg1, arg2, arg3 );

   if( !not01 )
      renumber_put_resets( room );
   return;
}

Now inside load_rooms, locate:

   if( !tarea )
   {
      bug( "Load_rooms: no #AREA seen yet." );
      shutdown_mud( "No #AREA" );
      exit( 1 );
   }

Directly below that, add:

   tarea->first_room = tarea->last_room = NULL;

Then locate:

         else if( letter == 'E' )
         {
            EXTRA_DESCR_DATA *ed;

            CREATE( ed, EXTRA_DESCR_DATA, 1 );
            ed->keyword = fread_string( fp );
            ed->description = fread_string( fp );
            LINK( ed, pRoomIndex->first_extradesc, pRoomIndex->last_extradesc, next, prev );
            top_ed++;
         }

Directly below that, add:

         else if( letter == 'R' )
            load_room_reset( pRoomIndex, fp );

Then locate:

         pRoomIndex->next = room_index_hash[iHash];
         room_index_hash[iHash] = pRoomIndex;

Directly below that, add:

         LINK( pRoomIndex, tarea->first_room, tarea->last_room, next_aroom, prev_aroom );

Locate function delete_room.

Find:

   MPROG_ACT_LIST *mpact;
   MPROG_DATA *mp;

Below that, add:

   UNLINK( room, room->area->first_room, room->area->last_room, next_aroom, prev_aroom );

Find:

   while( ( o = room->first_content ) != NULL )
      extract_obj( o );

Below that, add:

   wipe_resets( room );

Locate function make_room.

Find:

ROOM_INDEX_DATA *make_room( int vnum )

Replace with:

ROOM_INDEX_DATA *make_room( int vnum, AREA_DATA *area )

Find:

   pRoomIndex->first_content = NULL;
   pRoomIndex->last_content = NULL;

Directly below that, add:

      pRoomIndex->first_reset = pRoomIndex->last_reset = NULL;

Find:

   pRoomIndex->area = NULL;

Replace with:

   pRoomIndex->area = area;

Locate function load_buildlist.

Find:

            pArea->first_reset = NULL;
            pArea->last_reset = NULL;

Replace with:

            pArea->first_room = pArea->last_room = NULL;

4. Open handler.c

Locate:

OBJ_DATA *group_object( OBJ_DATA * obj1, OBJ_DATA * obj2 );

Below that, add:

void delete_reset( RESET_DATA *pReset );

Then locate the clean_resets function and replace it with:

/*
 * Remove all resets from a room -Thoric
 */
void clean_resets( ROOM_INDEX_DATA *room )
{
    RESET_DATA *pReset, *pReset_next;

    for( pReset = room->first_reset; pReset; pReset = pReset_next )
    {
	pReset_next = pReset->next;
	delete_reset( pReset );
	--top_reset;
    }
    room->first_reset	= NULL;
    room->last_reset	= NULL;
}

Find and remove the count_obj_list function.
Find and remove the get_obj_type function.

5. Open mud.h

Locate struct reset_data and find:

   RESET_DATA *next;
   RESET_DATA *prev;

Below that, add:

   RESET_DATA *first_reset;
   RESET_DATA *last_reset;
   RESET_DATA *next_reset;
   RESET_DATA *prev_reset;

Locate struct area_data and find:

   RESET_DATA *first_reset;
   RESET_DATA *last_reset;

Remove it.

Then find:

   RESET_DATA *last_mob_reset;
   RESET_DATA *last_obj_reset;

Remove it as well.

Then add:

   ROOM_INDEX_DATA *first_room;
   ROOM_INDEX_DATA *last_room;

Locate struct room_index_data.

Add the following:

   RESET_DATA *first_reset;
   RESET_DATA *last_reset;
   RESET_DATA *last_mob_reset;
   RESET_DATA *last_obj_reset;
   ROOM_INDEX_DATA *next_aroom; /* Rooms within an area */
   ROOM_INDEX_DATA *prev_aroom;

Then locate the following:
void wipe_resets( AREA_DATA * pArea, ROOM_INDEX_DATA * pRoom );
RD *add_reset args( ( AREA_DATA * tarea, char letter, int extra, int arg1, int arg2, int arg3 ) );
RD *place_reset args( ( AREA_DATA * tarea, char letter, int extra, int arg1, int arg2, int arg3 ) );

Remove them all and replace with:

RD *add_reset( ROOM_INDEX_DATA *room, char letter, int extra, int arg1, int arg2, int arg3 );

Locate:

void clean_resets args( ( AREA_DATA * tarea ) );

Replace with:

void clean_resets( ROOM_INDEX_DATA *room );

Locate:

RID *make_room args( ( int vnum ) );

Replace with:

RID *make_room( int vnum, AREA_DATA *area );

Find and remove the DECLARE_DO_FUN for do_rreset.

6. Open space.c

Locate function destroy_ship, find and remove the following:

wipe_resets( sroom->area, sroom );

6. Open tables.c, and remove the entries for do_rreset

7. Backup and store reset.c for safe-keeping.
Then upload the new reset.c file included with this fix.
The entire file has been rewritten so there would be little point in wading through a pile of replacement steps.
Any modifications you made to your old one will need to be reapplied to this new one.

8. Make clean, compile, and pray to God... :)

If there are any problems with this installation, feel free to post your
question to the forums at http://forums.alsherok.net

This code has been installed and tested on Smaug 1.6 FUSS, which is a bugfixed
and cleaned up version of the base Smaug 1.4a code. The Smaug FUSS Project is
maintained on servers which run the Redhat and Fedora family of Linux. Limited
testing has also been done on the Cygwin package under WindowsXP SP1 and SP2.
Users of BSD, MSVC, MSVC++, or Macintosh platforms are on their own as The
Smaug FUSS Project does not have access to these development environments for testing.
The Smaug FUSS Project can be found at: http://www.fussproject.org

No guarantees are made that this code will be compatible with your codebase and any
modifications you may have made to it. No warranty of any kind is expressed or implied
by the use of this code, and we are not responsible for any damages which may result
from the application of this snippet to your codebase.

Adventure beckons in the lands of mystique....
Samson, Implementor of Alsherok
http://www.alsherok.net
telnet://alsherok.net:5500

IMC2 contact: Samson@Alsherok