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

/*
 * The save functions in this file are influenced and even used from
 * the original ILAB OLC used throughout SunderMud, and thus wouldn't
 * be possible without the contributions from code distributed
 * freely with The Isles 1.1 source code.
 *
 * The loading functions are derived from the Rom 2.3 functions and have
 * been highly modified to remove "vestigal tails" and add additional
 * functionality.
 *
 * The overal purpose of this file is to group all the saving/loading
 * functions so that changes may more easily be made to the mud's areafile
 * formats when needed and most updates will be contained to this one file.
 */

#include "everything.h"
#include "olc.h"
#include "db.h"
#include "convert.h"

/* Local Prototypes */
void 		do_asave 		args ( ( CHAR_DATA *ch, char *argument 	  ) );
void 		db_save_area 		args ( ( AREA_DATA *pArea 		  ) );
void 		db_save_area_header 	args ( ( char *filename, AREA_DATA *pArea ) );
void 		db_save_area_rooms 	args ( ( char *filename, AREA_DATA *pArea ) );
void 		db_save_area_objects    args ( ( char *filename, AREA_DATA *pArea ) );
void 		db_save_area_mobiles    args ( ( char *filename, AREA_DATA *pArea ) );
void 		db_save_area_resets     args ( ( char *filename, AREA_DATA *pArea ) );
void 		db_save_area_shops 	args ( ( char *filename, AREA_DATA *pArea ) );
void 		db_save_area_specials 	args ( ( char *filename, AREA_DATA *pArea ) );
void 		db_save_area_progs	args ( ( char *filename, AREA_DATA *pArea ) );
AREA_DATA      *db_load_area_header 	args ( ( char *filename 		  ) );
void            db_load_area_rooms      args ( ( char *filename, AREA_DATA *pArea ) );
void 		db_load_area_mobiles 	args ( ( char *filename, AREA_DATA *pArea ) );
void            db_load_area_objects    args ( ( char *filename, AREA_DATA *pArea ) );
void            db_load_area_resets     args ( ( char *filename, AREA_DATA *pArea ) );
void            db_load_area_shops      args ( ( char *filename, AREA_DATA *pArea ) );
void            db_load_area_specials   args ( ( char *filename, AREA_DATA *pArea ) );
void            db_load_area_progs	args ( ( char *filename, AREA_DATA *pArea ) );

/* External functions needed */
char *fwrite_flag 		args ( ( long flags, char buf[] ) );

extern int flag_lookup 		args ( (const char *name, const struct flag_type *flag_table) );

/* Local Variables */
sh_int 		versions[9];			/* Temporarily stores version info from header while loading */

/*
 * Defines for version confident files.
 * The first value for each type is the position in the array,
 * and the second is the actual version. Don't change the array
 * position defines unless you what you're messing up!
 */

#define DB_HEADER			0
#define DB_HEADER_VERSION 		20
#define DB_ROOMS			1
#define DB_ROOMS_VERSION  		20
#define DB_OBJS				2
#define DB_OBJS_VERSION			20
#define DB_MOBS				3
#define DB_MOBS_VERSION			20
#define DB_RESETS			4
#define DB_RESETS_VERSION		20
#define DB_PROGS			5
#define DB_PROGS_VERSION		20
#define DB_SHOPS			6
#define DB_SHOPS_VERSION		20
#define DB_SPECIALS			7
#define DB_SPECIALS_VERSION		20
#define DB_LEASE			8
#define DB_LEASE_VERSION		20

/* SUNDERMUD VERSIONS:
 * SunderMud 2.0:  release version number is: 20
 *
 * All compatibility versions require pre-split files. See "area-converting.doc"
 * in the doc directory for information and more specific notes for each format.
 * SunderMud 1.0 is not supported since few muds use this format. Additionally,
 * old-style mobprogs cannot be imported automatically.
 *
 * Obviously, importing foreign areas subjects you to the license of the mud or
 * area archive from which you have taken the area.
 *
 * (*) Denotes version # not used but reserved for future use.
 * (-) Denotes incomplete, partial or broken support
 * (+) Denotes good support but missing a few details
 * (Y) Denotes complete support
 * 
 *
 * COMPATIBILITY VERSIONS:
 *          Name:   Version:  (?) (Room/Obj/Mob/Reset/Shop/Spec/Prog)
 *       DikuMud:   Version 0 (*)
 *      Merc 2.2:   Version 1 (*)
 * 	 Rom 2.3:   Version 2 (-) (RO-----)
 * 	 Rom 2.4:   Version 3 (*)
 * 	 Rot 1.4:   Version 5 (*)
 *	Envy 2.2:   Version 6 (*)
 *  Ember 0.9.44:   Version 7 (*)
 *     Rogue 2.1:   Version 8 (*)
 * Circle 3bpl20:   Version 9 (*)
 *    Smaug 1.4a:   Version 10(*)
 * SunderMud 2.0:   Version 20(Y) (ROMRSSP)
 */

#define SKEY( string, field )                       	\
          if ( !str_cmp( word, string ) )     		\
                    {                                   \
                         free_string( field );          \
                         field = fread_string( fpArea );\
                         fMatch = TRUE;                 \
                         break;                         \
                    }

/*---------------------------------------------------------
 * Name:       do_asave
 * Purpose:    Entry point for saving new Sunder Area data.
 *-------------------------------------------------------*/
void do_asave ( CHAR_DATA *ch, char *argument )
{
     char		 arg1[MIL];
     int		 value;
     AREA_DATA          *pArea;

     /* Put autosave here */
     
     if ( IS_NPC ( ch ) )
          return;

     SLCPY ( arg1, argument );
     
     if ( arg1[0] == '\0' )
     {
          send_to_char ( "Syntax:\n\r", ch );
          send_to_char ( "  asave list     - saves the area.lst file\n\r", ch );
          send_to_char ( "  asave changed  - saves all changed zones\n\r", ch );
          send_to_char ( "  asave <vnum>   - saves a particular area\n\r", ch );
          send_to_char ( "  asave area     - saves the current area\n\r", ch );
          send_to_char ( "  asave world    - saves the world! (db dump)\n\r", ch );
          send_to_char ( "\n\r", ch );
          return;
     }
     
     /* Save area of given numeric vnum. */
     /* -------------------------------- */     
     if ( is_number ( arg1 ) )
     {
          value = atoi ( arg1 );
          
          if ( !( pArea = get_area_data ( value ) ) )
          {
               send_to_char ( "That area does not exist.\n\r", ch );
               return;
          }
          
          if ( is_number ( arg1 ) )
          {
               if ( !IS_BUILDER ( ch, pArea ) )
               {
                    send_to_char ( "You are not a builder for this area.\n\r", ch );
                    return;
               }
               save_area_list (  );
               db_save_area ( pArea );
               return;
          }
     }
     
     /* Save the world, only authorized areas. */
     /* -------------------------------------- */     
     if ( !str_cmp ( "world", arg1 ) )
     {
          save_area_list (  );
          for ( pArea = area_first; pArea; pArea = pArea->next )
          {
               /* Builder must be assigned this area. */
               if ( !IS_BUILDER ( ch, pArea ) )
                    continue;
               db_save_area ( pArea );
               REMOVE_BIT ( pArea->area_flags, AREA_CHANGED );
          }
          send_to_char ( "You saved the world.\n\r", ch );
          return;
     }
     
     /* Save changed areas, only authorized areas. */
     /* ------------------------------------------ */     
     if ( !str_cmp ( "changed", arg1 ) )
     {
          bool amatch = FALSE;
          save_area_list (  );
          
          send_to_char ( "Saved zones:\n\r", ch );
          
          for ( pArea = area_first; pArea; pArea = pArea->next )
          {
               /* Builder must be assigned this area. */
               if ( !IS_BUILDER ( ch, pArea ) )
                    continue;               
               /* Save changed areas. */
               if ( IS_SET ( pArea->area_flags, AREA_CHANGED ) )
               {
                    amatch = TRUE; // Got at least one.
                    db_save_area ( pArea );
                    form_to_char ( ch, "%24s - '%s'\n\r", pArea->name, pArea->filename );
                    REMOVE_BIT ( pArea->area_flags, AREA_CHANGED );
               }
          }
          if ( !amatch )
               send_to_char ( "None.\n\r", ch );
          return;
     }
     
     /* Save the area.lst file. */
     /* ----------------------- */
     if ( !str_cmp ( arg1, "list" ) )
     {
          save_area_list (  );
          return;
     }
     

     /* Save current area. Either the one being edited, or the one the ch is in. */
     if ( !str_cmp ( "area", arg1 ) )
     {
          switch ( ch->desc->editor )
          {
          case ED_AREA:    pArea = ( AREA_DATA * ) ch->desc->pEdit;
               break;
          case ED_ROOM:    pArea = ch->in_room->area;
               break;
          case ED_OBJECT:  pArea = ( ( OBJ_INDEX_DATA * ) ch->desc->pEdit )->area;
               break;
          case ED_MOBILE:  pArea = ( ( MOB_INDEX_DATA * ) ch->desc->pEdit )->area;
               break;
          default:         pArea = ch->in_room->area;
               break;
          }
          if ( !IS_BUILDER ( ch, pArea ) )
          {
               send_to_char ( "You are not a builder for this area.\n\r", ch );
               return;
          }
          save_area_list (  );          
          db_save_area ( pArea );
          //REMOVE_BIT ( pArea->area_flags, AREA_CHANGED );
          send_to_char ( "Area saved.\n\r", ch );
          return;
     }

     /* Show correct syntax. */
     do_asave ( ch, "" );
     return;
}

/*
 * db_save_area - Calls all the area saver functions for given pArea
 */

void db_save_area ( AREA_DATA *pArea )
{
     fclose ( fpReserve );

     db_save_area_header     (pArea->filename, pArea );
     db_save_area_rooms      (pArea->filename, pArea );
     db_save_area_objects    (pArea->filename, pArea );
     db_save_area_mobiles    (pArea->filename, pArea );
     db_save_area_resets     (pArea->filename, pArea );
     db_save_area_shops      (pArea->filename, pArea );
     db_save_area_specials   (pArea->filename, pArea );
     db_save_area_progs      (pArea->filename, pArea ); // Mob, Obj & Room progs.
     // db_save_area_leases     (pArea->filename, pArea ); // Leases
     //
     fpReserve = fopen ( NULL_FILE, "r" );
     return;
}

/* Loads a specific area into memory */
void db_load_area ( char *filename )
{
     AREA_DATA 		*pArea;

     fImportDb = FALSE;	/* Just make sure, since here we want fbootdb, not import */
     
     if ( ( pArea = ( db_load_area_header ( filename ) ) ) == NULL )
     {
          bugf ("No Header Found for %s!!", filename );
          return;
     }
     db_load_area_rooms		( pArea->filename, pArea );
     db_load_area_objects 	( pArea->filename, pArea );
     db_load_area_mobiles	( pArea->filename, pArea );
     db_load_area_resets	( pArea->filename, pArea );
     db_load_area_shops		( pArea->filename, pArea );
     db_load_area_specials	( pArea->filename, pArea );
     db_load_area_progs		( pArea->filename, pArea );
     //     db_load_leases		( pArea->filename, pArea );
     
     strcpy ( strArea, "" );
     return;
}

/* Manually loads an area 
 * This function does a lot of logging since importing areas is unreliable at best.
 */

void db_import_area ( CHAR_DATA *ch, char *argument )
{
     AREA_DATA		*pArea;

     fImportDb = TRUE;
     
     if ( argument[0] == '\0' )
     {
          send_to_char ( "Syntax: aimport <filename>", ch );
          return;
     }

     form_to_char ( ch, "Attempting to import area \"%s\".\n\r", argument );
     log_string ( "%s Imports area %s", ch->name, argument );          
     
     if ( ( pArea = ( db_load_area_header ( argument ) ) ) == NULL )
     {
          bugf ("No Header Found for %s!!", argument );
          fImportDb = FALSE;
          return;
     }
     log_string ( "Headers done." );
     db_load_area_rooms         ( pArea->filename, pArea );
     log_string ( "Rooms done." );
     db_load_area_objects       ( pArea->filename, pArea );
     log_string ( "Objects done." );
     db_load_area_mobiles       ( pArea->filename, pArea );
     log_string ( "Mobiles done." );
     db_load_area_resets        ( pArea->filename, pArea );
     log_string ( "Resets done." );
     db_load_area_shops         ( pArea->filename, pArea );
     log_string ( "Shops done." );
     db_load_area_specials      ( pArea->filename, pArea );
     log_string ( "Specials done." );
     db_load_area_progs         ( pArea->filename, pArea );
     log_string ( "Progs done." );
     //     db_load_leases              ( pArea->filename, pArea );
     
     /* Call the fixup routines again... just doing them globally since importation of
      * areas isn't a common event. */
     
     fImportDb = FALSE;
     
     strcpy ( strArea, "" );

     log_string ( "Fixing Exits" );
     fix_exits (  );
     log_string ( "Fixing Progs" );
     fix_mobprogs( );
     fix_roomprogs( );
     fix_objprogs( );
     
     log_string ( "Setting Racial Effects." );
     init_racial_affects (  );
     log_string ( "Updating Areas." );
     area_update ( );

     log_string ( "Import of %s complete.", argument );      
     send_to_char ( "Done.\n\r", ch );
     return;
     
}

/*
 * Saves an area HEADER file.
 */

void db_save_area_header ( char *filename, AREA_DATA *pArea )
{
     char hfilename[MSL];
     FILE *fp;

     SNP ( hfilename, "%s.header", filename );

     if ( !( fp = fopen ( hfilename, "w" ) ) )
     {
          bugf ( "Open_area: fopen (while saving an area)");
          perror ( hfilename );
     }

     /*
      * Header version MUST come first here since it can afect the construction of the rest
      * of the header, INCLUDING possibly how many version numbers there are.
      */
     fprintf ( fp, "Versions    %d %d %d %d %d %d %d %d %d\n",
               DB_HEADER_VERSION,
               DB_ROOMS_VERSION,
               DB_OBJS_VERSION,
               DB_MOBS_VERSION,
               DB_RESETS_VERSION,
               DB_PROGS_VERSION,
               DB_SHOPS_VERSION,
               DB_SPECIALS_VERSION,
               DB_LEASE_VERSION );
     fprintf ( fp, "Name        %s~\n", 	pArea->name );
     fprintf ( fp, "Zone        %d\n", 		pArea->zone );
     fprintf ( fp, "Builders    %s~\n", 	fix_string ( pArea->builders ) );
     fprintf ( fp, "Music       %s~\n", 	pArea->soundfile );
     fprintf ( fp, "VNUMs       %d %d\n", 	pArea->lvnum, pArea->uvnum );
     fprintf ( fp, "Levels      %d %d\n", 	pArea->llev, pArea->hlev );
     fprintf ( fp, "Credits     %s~\n", 	pArea->credits );
     fprintf ( fp, "Security    %d\n", 		pArea->security );
     fprintf ( fp, "End\n\n\n\n" );

     fclose ( fp );
     return;
}

/* Loads an area HEADER file */
AREA_DATA *db_load_area_header ( char *filename )
{
     bool fMatch;
     char *word;
     AREA_DATA *pArea;

     SNP ( strArea, "%s.header", filename );

     if ( !( fpArea = fopen ( strArea, "r" ) ) )
     {
          bugf ( "Open_area: fopen (while loading an area)");
          perror ( strArea );
          return NULL;
     }

     pArea = alloc_perm ( sizeof ( *pArea ), "pArea:db_load_area_header" );

     pArea->age = 15;
     pArea->nplayer = 0;
     pArea->filename = str_dup ( filename );
     pArea->vnum = top_area;
     pArea->name = str_dup ( "New Area" );
     pArea->builders = str_dup ( "" );
     pArea->credits = str_dup ( "" );
     pArea->soundfile = str_dup ( "" );
     pArea->soundfile = str_dup ( "" );
     pArea->security = 9;
     pArea->lvnum = 0;
     pArea->uvnum = 0;
     pArea->area_flags = 0;

     for ( ;; )
     {
          word = feof ( fpArea ) ? "End" : fread_word ( fpArea );

          switch ( UPPER ( word[0] ) )
          {
          case 'Z':
               KEY ( "Zone", pArea->zone, fread_number ( fpArea ) );
               break;
          case 'N':
               SKEY ( "Name", pArea->name );
               break;
          case 'S':
               KEY ( "Security", pArea->security,
                     fread_number ( fpArea ) );
               break;
          case 'V':
               if ( !str_cmp ( word, "VNUMs" ) )
               {
                    pArea->lvnum = fread_number ( fpArea );
                    pArea->uvnum = fread_number ( fpArea );
               }
               else if ( !str_cmp ( word, "Versions" ) )
               {
                    int  i;
                    for ( i = 0 ; i < 9 ; i++ )
                         versions[i] = fread_number ( fpArea );
               }
               break;
          case 'L':
               if ( !str_cmp ( word, "Levels" ) )
               {
                    pArea->llev = fread_number ( fpArea );
                    pArea->hlev = fread_number ( fpArea );
               }
          case 'E':
               if ( !str_cmp ( word, "End" ) )
               {
                    if ( area_first == NULL )
                         area_first = pArea;
                    if ( area_last != NULL )
                         area_last->next = pArea;
                    area_last = pArea;
                    pArea->next = NULL;
                    top_area++;
                    fclose ( fpArea );
                    return pArea;
               }
               break;
          case 'B':
               SKEY ( "Builders", pArea->builders );
               break;
          case 'M':
               SKEY ( "Music", pArea->soundfile );
               break;

          case 'C':
               SKEY ( "Credits", pArea->credits );
               break;

          }
          /* End of switch */
     }
     /* End of for */

     bugf ( "Premature close of %s (No End found)", strArea );
     fclose ( fpArea );
     return pArea;
}

void db_save_area_rooms ( char *filename, AREA_DATA *pArea )
{
     ROOM_INDEX_DATA    *pRoomIndex;
     EXTRA_DESCR_DATA   *pEd;
     EXIT_DATA          *pExit;
     PROG_LIST		*pRprog;
     int                 iHash;
     int                 door;
     char		 rfilename[MSL];
     FILE		 *fp;

     SNP ( rfilename, "%s%s.rooms", ROOM_DIR, filename );

     if ( !( fp = fopen ( rfilename, "w" ) ) )
     {
          bugf ( "Open_area: fopen (while saving an area)");
          perror ( rfilename );
     }

     /* Cycle through all the rooms */
     for ( iHash = 0; iHash < MAX_KEY_HASH; iHash++ )
     {
          for ( pRoomIndex = room_index_hash[iHash]; pRoomIndex; pRoomIndex = pRoomIndex->next )
          {
               if ( pRoomIndex->area == pArea )
               {
                    fprintf ( fp, "#%d\n", 	pRoomIndex->vnum );
                    fprintf ( fp, "%s~\n", 	pRoomIndex->name );
                    fprintf ( fp, "%s~\n", 	fix_string ( pRoomIndex->description ) );
                    fprintf ( fp, "%s~\n", 	fix_string ( pRoomIndex->notes ) );
                    fprintf ( fp, "%d %d\n",    pRoomIndex->room_flags, pRoomIndex->sector_type );

                    /* Save Extended Descriptions */
                    for ( pEd = pRoomIndex->extra_descr; pEd; pEd = pEd->next )
                    {
                         fprintf ( fp, "E\n%s~\n%s~\n", pEd->keyword,
                                   fix_string ( pEd->description ) );
                    }

                    /* Save the doors for the room. */

                    for ( door = 0; door < MAX_DIR; door++ )    /* I hate this! */
                    {
                         if ( ( pExit = pRoomIndex->exit[door] ) && pExit->u1.to_room )
                         {
                              int locks = 0;

                              /*
                               * Copy the flags we want to save to locks.
                               * No error checking here, we assume elsewhere has made sure that no non-doors
                               * have flags, or that it doesn't matter.
                               */

                              if ( IS_SET ( pExit->rs_flags, EX_ISDOOR ) )      SET_BIT ( locks, EX_ISDOOR );
                              if ( IS_SET ( pExit->rs_flags, EX_PICKPROOF ) )   SET_BIT ( locks, EX_PICKPROOF );
                              if ( IS_SET ( pExit->rs_flags, EX_NO_PASS ) )     SET_BIT ( locks, EX_NO_PASS );
                              if ( IS_SET ( pExit->rs_flags, EX_HIDDEN ) )      SET_BIT ( locks, EX_HIDDEN );

                              fprintf ( fp, "D%d\n", 		door );
                              fprintf ( fp, "%s~\n", 		fix_string ( pExit->description ) );
                              fprintf ( fp, "%s~\n", 		pExit->keyword );
                              fprintf ( fp, "%d %d %d\n", 	locks, pExit->key, pExit->u1.to_room->vnum );
                         }
                    }
                    for (pRprog = pRoomIndex->rprogs; pRprog; pRprog = pRprog->next)
                    {
                         fprintf(fp, "R %s %d %s~\n",
                                 prog_type_to_name(pRprog->trig_type), pRprog->vnum,
                                 pRprog->trig_phrase);
                    }
                    fprintf ( fp, "S\n" );	/* Mark the end of this room. */
               }
          }
     }
     fprintf ( fp, "#0\n\n\n\n" );		/* mark the end of the rooms file */
     fclose ( fp );
     return;
}

/* Loads an area rooms file */
void db_load_area_rooms ( char *filename, AREA_DATA *pArea )
{
     ROOM_INDEX_DATA    *pRoomIndex;
     bool		 romcvta = FALSE;
     bool		 native = TRUE;
     
     if ( versions[DB_ROOMS] < 20 )
     {
          if ( versions[DB_ROOMS] == 2 ) /* 2 = Rom 2.3 */
          {
               native = FALSE;
               romcvta = TRUE;
          }
     }

     SNP ( strArea, "%s%s.rooms", ROOM_DIR, filename );

     if ( !( fpArea = fopen ( strArea, "r" ) ) )
     {
          bugf ( "No %s found for %s", strArea, pArea->name );
          return;
     }

     /* Okay we opened the rooms file, scan rooms */

     for ( ;; )
     {
          bool		oldval;
          bool		oldival;
          int		vnum;
          char          letter;
          int           door;
          int           iHash;

          letter = fread_letter ( fpArea );
          if ( letter != '#' )
          {
               bugf ( "load_area_rooms: # not found in %s.", strArea );
               exit ( 1 );
          }

          vnum = fread_number ( fpArea );
          if ( vnum == 0 )
               break;

          oldval = fBootDb;	/* Save value of fBootDB */
          oldival = fImportDb;
          
          fBootDb = FALSE;	/* Set to false */
          fImportDb = FALSE;
          if ( get_room_index ( vnum ) != NULL )
          {
               bugf ( "load_area_rooms: vnum %d duplicated.", vnum );
               exit ( 1 );
          }
          fBootDb = oldval;	/* Restore value of fBootDb */
          fImportDb = oldival;

          pRoomIndex = alloc_perm ( sizeof ( *pRoomIndex ), "pRoomIndex:load_area_rooms" );
          
          /* Clear a few values */
          pRoomIndex->people 		= NULL;
          pRoomIndex->contents 		= NULL;
          pRoomIndex->extra_descr 	= NULL;
          pRoomIndex->area 		= area_last;
          pRoomIndex->vnum 		= vnum;
          pRoomIndex->name 		= fread_string ( fpArea );
          pRoomIndex->description 	= fread_string ( fpArea );
          if ( native )
               pRoomIndex->notes 	= fread_string ( fpArea );
          else if ( romcvta )
          {
               pRoomIndex->notes 	= str_dup ( "" );
               fread_number ( fpArea );
          }
          pRoomIndex->room_flags 	= fread_flag ( fpArea );
          pRoomIndex->sector_type 	= fread_number ( fpArea );
          pRoomIndex->light 		= 0;
          pRoomIndex->lease 		= NULL;
          
          /* Do the lettered sections */
          for ( ;; )
          {
               letter = fread_letter ( fpArea );

               if ( letter == 'S' )		/* End of Room */
                    break;

               if ( letter == 'D' )		/* A door */
               {
                    EXIT_DATA          *pexit;
                    int			locks = 0;

                    door = fread_number ( fpArea );
                    if ( door < 0 || door > 5 )
                    {
                         bugf ( "Fread_rooms: vnum %d has bad door number.", vnum );
                         exit ( 1 );
                    }

                    pexit = alloc_perm ( sizeof ( *pexit ), "pexit:load_area_rooms" );

                    pexit->description 		= fread_string ( fpArea );
                    pexit->keyword 		= fread_string ( fpArea );
                    pexit->exit_info 		= 0;
                    
                    if ( native )
                         pexit->rs_flags 	= fread_number ( fpArea );
                    else if ( romcvta )
                         locks			= fread_number ( fpArea );

                    pexit->key 			= fread_number ( fpArea );
                    pexit->u1.vnum 		= fread_number ( fpArea );
                    pexit->orig_door 	= door;
                    if ( romcvta )
                    {
                         switch ( locks )
                         {
                         case 1: pexit->rs_flags = EX_ISDOOR;                break;
                         case 2: pexit->rs_flags = EX_ISDOOR | EX_PICKPROOF; break;
                         }
                    }

                    if ( pexit->u1.vnum < 100 )
                         bugf ( "Fread_rooms (Non_Fatal): vnum %d has exit to limbo/void.", vnum);

                    pRoomIndex->exit[door] = pexit;
                    top_exit++;
               }
               else if ( letter == 'E' )
               {
                    EXTRA_DESCR_DATA   *ed;

                    ed = alloc_perm ( sizeof ( *ed ), "ed:load_area_rooms" );

                    ed->keyword 		= fread_string ( fpArea );
                    ed->description 		= fread_string ( fpArea );
                    ed->next 			= pRoomIndex->extra_descr;
                    pRoomIndex->extra_descr 	= ed;
                    top_ed++;
               }
               else if ( letter == 'R' )
               {
                    PROG_LIST *pRprog;
                    char *word;
                    int trigger = 0;

                    pRprog          = alloc_perm(sizeof(*pRprog), "roomprog" );
                    word            = fread_word( fpArea );

                    if ( !(trigger = flag_lookup( word, rprog_flags )) )
                    {
                         bugf( "ROOMprogs: invalid trigger: %s", word);
                         exit(1);
                    }

                    SET_BIT( pRoomIndex->rprog_flags, trigger );

                    pRprog->trig_type       	= trigger;
                    pRprog->vnum            	= fread_number( fpArea );
                    pRprog->trig_phrase     	= fread_string( fpArea );
                    pRprog->next            	= pRoomIndex->rprogs;
                    pRoomIndex->rprogs      	= pRprog;
               }
               else
               {
                    bugf ( "Load_rooms: vnum %d has flag not 'DESR': %c", vnum, letter );
                    exit ( 1 );
               }
          }

          iHash 		 = vnum % MAX_KEY_HASH;
          pRoomIndex->next 	 = room_index_hash[iHash];
          room_index_hash[iHash] = pRoomIndex;
          top_room++;
          top_vnum_room 	 = top_vnum_room < vnum ? vnum : top_vnum_room;
          assign_area_vnum ( vnum );
          
          /* Do necessary conversions */
          if ( romcvta )
               cvt_rom_room_a ( pRoomIndex );
          
     }
     fclose ( fpArea );
     return;
}

void db_save_area_mobiles ( char *filename, AREA_DATA *pArea )
{
     PROG_LIST 		*pMprog;
     char                buf[MAX_STRING_LENGTH];
     char                mfilename[MSL];
     FILE                *fp;
     int                 i;
     sh_int		 race;
     MOB_INDEX_DATA     *pMobIndex;

     SNP ( mfilename, "%s%s.mobiles", MOB_DIR, filename );

     if ( !( fp = fopen ( mfilename, "w" ) ) )
     {
          bugf ( "Open_area: fopen (while saving an area)");
          perror ( mfilename );
     }

     for ( i = pArea->lvnum; i <= pArea->uvnum; i++ )
     {
          if ( ( pMobIndex = get_mob_index ( i ) ) )
          {
               race = pMobIndex->race;

               fprintf ( fp, "#%d\n", pMobIndex->vnum );
               fprintf ( fp, "%s~\n", pMobIndex->player_name );
               fprintf ( fp, "%s~\n", pMobIndex->short_descr );
               fprintf ( fp, "%s~\n", fix_string ( pMobIndex->long_descr ) );
               fprintf ( fp, "%s~\n", fix_string ( pMobIndex->description ) );
               fprintf ( fp, "%s~\n", fix_string ( pMobIndex->notes ) );
               fprintf ( fp, "%s~\n", race_table[race].name );
               fprintf ( fp, "%s ",   fwrite_flag ( pMobIndex->act, buf ) );
               fprintf ( fp, "%s ",   fwrite_flag( pMobIndex->affected_by, buf ) );
               fprintf ( fp, "%s ",   fwrite_flag( pMobIndex->detections, buf ) );
               fprintf ( fp, "%s\n",  fwrite_flag( pMobIndex->protections, buf ) );
               fprintf ( fp, "%d ",   pMobIndex->alignment );
               fprintf ( fp, "%d ",   pMobIndex->level );
               fprintf ( fp, "%d ",   pMobIndex->hitroll );
               fprintf ( fp, "%dd%d+%d ",
                         pMobIndex->hit[DICE_NUMBER],
                         pMobIndex->hit[DICE_TYPE],
                         pMobIndex->hit[DICE_BONUS] );
               fprintf ( fp, "%dd%d+%d ",
                         pMobIndex->mana[DICE_NUMBER],
                         pMobIndex->mana[DICE_TYPE],
                         pMobIndex->mana[DICE_BONUS] );
               fprintf ( fp, "%dd%d+%d ",
                         pMobIndex->damage[DICE_NUMBER],
                         pMobIndex->damage[DICE_TYPE],
                         pMobIndex->damage[DICE_BONUS] );
               fprintf ( fp, "%d\n", pMobIndex->dam_type );
               fprintf ( fp, "%s ",               fwrite_flag ( pMobIndex->off_flags, buf ) );
               fprintf ( fp, "%s ",               fwrite_flag ( pMobIndex->imm_flags, buf ) );
               fprintf ( fp, "%s ",               fwrite_flag ( pMobIndex->res_flags, buf ) );
               fprintf ( fp, "%s\n",              fwrite_flag ( pMobIndex->vuln_flags, buf ) );
               fprintf ( fp, "%d %d %d %ld\n",
                         pMobIndex->start_pos,
                         pMobIndex->default_pos,
                         pMobIndex->sex,
                         pMobIndex->gold );
               fprintf ( fp, "%s ", fwrite_flag ( pMobIndex->form, buf ) );
               fprintf ( fp, "%s ", fwrite_flag ( pMobIndex->parts, buf ) );
               fprintf ( fp, "%d ", pMobIndex->size );
               fprintf ( fp, "%s\n", material_name ( pMobIndex->material ) );

               if ( IS_SET ( pMobIndex->act, ACT_SKILLMASTER ) )
               {
                    int count;
                    int total_to_write = pMobIndex->total_teach_skills;
                    fprintf ( fp, "Z %d\n", total_to_write );
                    for ( count = 0; count < total_to_write; count++ )
                         fprintf ( fp, "%s~\n", pMobIndex->teach_skills[count] );
               }
               for (pMprog = pMobIndex->mprogs; pMprog; pMprog = pMprog->next)
               {
                    fprintf(fp, "M %s %d %s~\n",
                            prog_type_to_name(pMprog->trig_type), pMprog->vnum,
                            pMprog->trig_phrase);
               }
          }
     }

     fprintf ( fp, "#0\n\n\n\n" );
     fclose ( fp );
     return;
}

/* Load Mobs file */

void db_load_area_mobiles ( char *filename, AREA_DATA *pArea )
{
     MOB_INDEX_DATA     *pMobIndex;
     bool                romcvta = FALSE;
     bool                native = TRUE;
     
     if ( versions[DB_MOBS] == 2 ) /* 2 = Rom 2.3 */
     {
          native = FALSE;
          romcvta = TRUE;
     }

     SNP ( strArea, "%s%s.mobiles", MOB_DIR, filename );

     if ( !( fpArea = fopen ( strArea, "r" ) ) )
     {
          bugf ( "No %s found for %s", strArea, pArea->name );
          return;
     }

     for ( ;; )
     {
          bool  oldval;
          bool  oldival;
          int	vnum;
          char  letter;
          int   iHash;

          letter = fread_letter ( fpArea );
          if ( letter != '#' )
          {
               bugf ( "load_area_mobiles: # not found in %s.", strArea );
               exit ( 1 );
          }

          vnum = fread_number ( fpArea );
          if ( vnum == 0 )
               break;

          oldval = fBootDb;
          oldival = fImportDb;
          
          fBootDb = FALSE;
          fImportDb = FALSE;
          if ( get_mob_index ( vnum ) != NULL )
          {
               bugf ( "load_area_mobiles: vnum %d duplicated.", vnum );
               exit ( 1 );
          }
          fImportDb = oldival;
          fBootDb = oldval;

          pMobIndex = alloc_perm ( sizeof ( *pMobIndex ), "pMobIndex:load_area_mobiles" );

          pMobIndex->new_format 	= TRUE; /* This needs to go, vestigal tail */

          pMobIndex->vnum 		= vnum;
          pMobIndex->area 		= area_last;
          newmobs++;
          pMobIndex->player_name 	= fread_string ( fpArea );
          pMobIndex->short_descr 	= fread_string ( fpArea );
          pMobIndex->long_descr 	= fread_string ( fpArea );
          pMobIndex->description 	= fread_string ( fpArea );
          if ( native )
               pMobIndex->notes 		= fread_string ( fpArea );
          pMobIndex->race 		= race_lookup ( fread_string ( fpArea ) );
          pMobIndex->long_descr[0] 	= UPPER ( pMobIndex->long_descr[0] );
          pMobIndex->description[0] 	= UPPER ( pMobIndex->description[0] );
          if ( native )
               pMobIndex->act 		= fread_flag ( fpArea ) | ACT_IS_NPC | race_table[pMobIndex->race].act;
          pMobIndex->affected_by 	= fread_flag ( fpArea );
          if ( native )
          {
               pMobIndex->detections 	= fread_flag ( fpArea );
               pMobIndex->protections 	= fread_flag ( fpArea );
          }
          pMobIndex->pShop 		= NULL;
          pMobIndex->alignment 		= fread_number ( fpArea );
          if ( romcvta )
               letter = fread_letter ( fpArea );
          pMobIndex->level 		= fread_number ( fpArea );
          pMobIndex->hitroll 		= fread_number ( fpArea );
          pMobIndex->hit[DICE_NUMBER] 	= fread_number ( fpArea );  fread_letter ( fpArea ); /* d */
          pMobIndex->hit[DICE_TYPE] 	= fread_number ( fpArea );  fread_letter ( fpArea ); /* + */
          pMobIndex->hit[DICE_BONUS] 	= fread_number ( fpArea );
          pMobIndex->mana[DICE_NUMBER]	= fread_number ( fpArea );  fread_letter ( fpArea ); /* d */
          pMobIndex->mana[DICE_TYPE] 	= fread_number ( fpArea );  fread_letter ( fpArea ); /* + */
          pMobIndex->mana[DICE_BONUS] 	= fread_number ( fpArea );
          pMobIndex->damage[DICE_NUMBER]= fread_number ( fpArea );  fread_letter ( fpArea ); /* d */
          pMobIndex->damage[DICE_TYPE]  = fread_number ( fpArea );  fread_letter ( fpArea ); /* + */
          pMobIndex->damage[DICE_BONUS] = fread_number ( fpArea );
          pMobIndex->dam_type 		= fread_number ( fpArea );
          if ( romcvta)
          {
               fread_number ( fpArea );	fread_number ( fpArea ); /* Unused AC Values */
               fread_number ( fpArea ); fread_number ( fpArea ); /* Unused AC Values */
          }
          if ( native )
          {
               pMobIndex->off_flags 		= fread_flag ( fpArea ) | race_table[pMobIndex->race].off;
               pMobIndex->imm_flags 		= fread_flag ( fpArea ) | race_table[pMobIndex->race].imm;
               pMobIndex->res_flags 		= fread_flag ( fpArea ) | race_table[pMobIndex->race].res;
               pMobIndex->vuln_flags		= fread_flag ( fpArea ) | race_table[pMobIndex->race].vuln;
          }
          else if ( romcvta )
          {
               pMobIndex->off_flags     = fread_flag ( fpArea );
               pMobIndex->imm_flags     = fread_flag ( fpArea );
               pMobIndex->res_flags     = fread_flag ( fpArea );
               pMobIndex->vuln_flags    = fread_flag ( fpArea );
          }
          pMobIndex->start_pos 		= fread_number ( fpArea );
          pMobIndex->default_pos 	= fread_number ( fpArea );
          pMobIndex->sex 		= fread_number ( fpArea );
          pMobIndex->gold 		= fread_number ( fpArea );
          if ( native )
          {
               pMobIndex->form 		= fread_flag ( fpArea ) | race_table[pMobIndex->race].form;
               pMobIndex->parts 	= fread_flag ( fpArea ) | race_table[pMobIndex->race].parts;
               pMobIndex->size 		= fread_number ( fpArea );
          }
          else if ( romcvta )
          {
               pMobIndex->form          = fread_flag ( fpArea );
               pMobIndex->parts         = fread_flag ( fpArea );
               letter                   = fread_letter( fpArea );
               switch (letter)
               {
               case ('T') :                pMobIndex->size = SIZE_TINY;    break;
               case ('S') :                pMobIndex->size = SIZE_SMALL;   break;
               case ('M') :                pMobIndex->size = SIZE_MEDIUM;  break;
               case ('L') :                pMobIndex->size = SIZE_LARGE;   break;
               case ('H') :                pMobIndex->size = SIZE_HUGE;    break;
               case ('G') :                pMobIndex->size = SIZE_GIANT;   break;
               default:                    pMobIndex->size = SIZE_MEDIUM;  break;
               }
          }
          pMobIndex->material 		= material_lookup ( fread_word ( fpArea ) );

          if ( native )
          {
               /* Skillmasters */
               pMobIndex->total_teach_skills = 0;
               {
                    int                 count = MAX_TEACH_SKILLS;
                    
                    for ( count = 0; count < MAX_TEACH_SKILLS; count++ )
                         pMobIndex->teach_skills[count] = NULL;
               }
          }

          while ( 1 )
          {
               letter = fread_letter ( fpArea );

               if ( letter == 'Z' )
               {
                    char               *tmp;
                    int                 total_to_read;
                    int                 count;

                    if ( !IS_SET ( pMobIndex->act, ACT_SKILLMASTER ) )
                         SET_BIT ( pMobIndex->act, ACT_SKILLMASTER );

                    total_to_read = fread_number ( fpArea );
                    if ( total_to_read > MAX_TEACH_SKILLS )
                         total_to_read = MAX_TEACH_SKILLS;
                    for ( count = 0; count < total_to_read; count++ )
                    {
                         tmp = fread_string ( fpArea );
                         if ( skill_lookup ( tmp ) == -1 )
                         {
                              bugf ( "Invalid skill in load_mobile for skillmaster: %s ", tmp );
                              pMobIndex->teach_skills[count] = NULL;
                         }
                         else
                         {
                              pMobIndex->teach_skills[count] = str_dup ( tmp );
                              pMobIndex->total_teach_skills++;
                         }
                    }
               }
               else if ( letter == 'M' )
               {
                    PROG_LIST *pMprog;
                    char *word;
                    int trigger = 0;

                    pMprog              = alloc_perm(sizeof(*pMprog), "pMprog:load_mobiles");
                    word                = fread_word( fpArea );

                    if ( (trigger = flag_lookup( word, mprog_flags )) == NO_FLAG )
                    {
                         bugf("MOBprogs: invalid trigger." );
                         exit(1);
                    }

                    SET_BIT( pMobIndex->mprog_flags, trigger );
                    pMprog->trig_type   = trigger;
                    pMprog->vnum        = fread_number( fpArea );
                    pMprog->trig_phrase = fread_string( fpArea );
                    pMprog->next        = pMobIndex->mprogs;
                    pMobIndex->mprogs   = pMprog;
               }
               else
               {
                    ungetc ( letter, fpArea ); break;
               }

          }
          /* end of while ( 1 ) */

          iHash = vnum % MAX_KEY_HASH;
          pMobIndex->next = mob_index_hash[iHash];
          mob_index_hash[iHash] = pMobIndex;
          top_mob_index++;
          top_vnum_mob = top_vnum_mob < vnum ? vnum : top_vnum_mob;
          assign_area_vnum ( vnum );
          kill_table[URANGE( 0, pMobIndex->level, MAX_LEVEL - 1 )].number++;
     }
     /* End of for ( ;; ) */

     fclose ( fpArea );
     return;
}

void db_save_area_objects ( char *filename, AREA_DATA *pArea )
{
     AFFECT_DATA        *pAf;
     EXTRA_DESCR_DATA   *pEd;
     PROG_LIST          *pOprog;
     char                buf[MAX_STRING_LENGTH];
     int                 i;
     OBJ_INDEX_DATA     *pObjIndex;
     char                ofilename[MSL];
     FILE                *fp;

     SNP ( ofilename, "%s%s.objects", OBJECT_DIR, filename );

     if ( !( fp = fopen ( ofilename, "w" ) ) )
     {
          bugf ( "Open_area: fopen (while saving an area)");
          perror ( ofilename );
     }

     for ( i = pArea->lvnum; i <= pArea->uvnum; i++ )
     {
          if ( ( pObjIndex = get_obj_index ( i ) ) )
          {
               fprintf ( fp, "#%d\n", pObjIndex->vnum );
               fprintf ( fp, "%s~\n", pObjIndex->name );
               fprintf ( fp, "%s~\n", pObjIndex->short_descr );
               fprintf ( fp, "%s~\n", pObjIndex->description );
               fprintf ( fp, "%s~\n", fix_string ( pObjIndex->notes) );
               fprintf ( fp, "%s~\n", material_name ( pObjIndex->material ) );
               fprintf ( fp, "%d ",   pObjIndex->item_type );
               fprintf ( fp, "%s ",   fwrite_flag ( pObjIndex->extra_flags, buf ) );
               fprintf ( fp, "%s ",   fwrite_flag ( pObjIndex->wear_flags, buf ) );
               fprintf ( fp, "%s\n",  fwrite_flag ( pObjIndex->vflags, buf ) );      /* New with this format */

               switch ( pObjIndex->item_type )
               {
               default:
                    fprintf ( fp, "%s ",  fwrite_flag ( pObjIndex->value[0], buf ) );
                    fprintf ( fp, "%s ",  fwrite_flag ( pObjIndex->value[1], buf ) );
                    fprintf ( fp, "%s ",  fwrite_flag ( pObjIndex->value[2], buf ) );
                    fprintf ( fp, "%s ",  fwrite_flag ( pObjIndex->value[3], buf ) );
                    fprintf ( fp, "%s\n", fwrite_flag ( pObjIndex->value[4], buf ) );
                    break;
               case ITEM_LIGHT:
                    fprintf ( fp, "0 0 %d 0 0\n", pObjIndex->value[2] < 1 ? 999   /* infinite */
                              : pObjIndex->value[2] );
                    break;
               case ITEM_PILL:
               case ITEM_POTION:
               case ITEM_SCROLL:
                    fprintf ( fp, "%d %d %d %d %d\n", pObjIndex->value[0] > 0 ?   /* no negative numbers */
                              pObjIndex->value[0] : 0,
                              pObjIndex->value[1] != -1 ?
                              skill_table[pObjIndex->value[1]].slot : 0,
                              pObjIndex->value[2] != -1 ?
                              skill_table[pObjIndex->value[2]].slot : 0,
                              pObjIndex->value[3] != -1 ?
                              skill_table[pObjIndex->value[3]].slot : 0,
                              0 /* unused */  );
                    break;
               case ITEM_STAFF:
               case ITEM_WAND:
                    fprintf ( fp, "%s ",
                              fwrite_flag ( pObjIndex->value[0], buf ) );
                    fprintf ( fp, "%s ",
                              fwrite_flag ( pObjIndex->value[1], buf ) );
                    fprintf ( fp, "%s %d 0\n",
                              fwrite_flag ( pObjIndex->value[2], buf ),
                              pObjIndex->value[3] != -1 ? skill_table[pObjIndex->value[3]].slot : 0 );
                    break;
               }

               fprintf ( fp, "%d ", 	pObjIndex->level );
               fprintf ( fp, "%d ", 	pObjIndex->weight );
               fprintf ( fp, "%d ", 	pObjIndex->cost );
               fprintf ( fp, "%d ", 	pObjIndex->condition );
               fprintf ( fp, "%d\n", 	pObjIndex->repop );

               /* Write out affects. */
               for ( pAf = pObjIndex->affected; pAf; pAf = pAf->next )
               {
                    if (pAf->bitvector)
                    {
                         fprintf( fp, "F\n" );
                         switch (pAf->where)
                         {
                         case TO_AFFECTS:         fprintf ( fp, "A " ); break;
                         case TO_DETECTIONS:      fprintf ( fp, "D " ); break;
                         case TO_PROTECTIONS:     fprintf ( fp, "P " ); break;
                         default:
                              bugf ( "olc_save: Invalid Affect->where");
                              break;
                         }
                         fprintf( fp, "%d %d %s\n", pAf->location, pAf->modifier,
                                  fwrite_flag( pAf->bitvector, buf ) );
                    }
                    else
                         fprintf( fp, "A\n%d %d\n",  pAf->location, pAf->modifier );
               }

               /* Write out extended descriptions */
               for ( pEd = pObjIndex->extra_descr; pEd; pEd = pEd->next )
               {
                    fprintf ( fp, "E\n%s~\n%s~\n", pEd->keyword, fix_string ( pEd->description ) );
               }
               for (pOprog = pObjIndex->oprogs; pOprog; pOprog = pOprog->next)
               {
                    fprintf(fp, "O %s %d %s~\n",
                            prog_type_to_name(pOprog->trig_type), pOprog->vnum,
                            pOprog->trig_phrase);
               }
          }
     }

     fprintf ( fp, "#0\n\n\n\n" );
     fclose ( fp );
     return;
}

void db_load_area_objects ( char *filename, AREA_DATA *pArea )
{
     OBJ_INDEX_DATA * pObjIndex;
     bool                romcvta = FALSE;
     bool                native = TRUE;
     
     if ( versions[DB_OBJS] == 2 ) /* 2 = Rom 2.3 */
     {
          native = FALSE;
          romcvta = TRUE;
     }     

     SNP ( strArea, "%s%s.objects", OBJECT_DIR, filename );

     if ( !( fpArea = fopen ( strArea, "r" ) ) )
     {
          bugf ( "No %s found for %s", strArea, pArea->name );
          return;
     }

     for ( ;; )
     {
          bool oldval;
          bool oldival;
          int  vnum;
          char letter;
          int  iHash;

          letter = fread_letter ( fpArea );
          if ( letter != '#' )
          {
               bugf ( "Load_objects: # not found in %s.", strArea );
               exit ( 1 );
          }

          vnum = fread_number ( fpArea );
          if ( vnum == 0 )
               break;

          oldval = fBootDb;
          oldival = fImportDb;
          
          fBootDb = FALSE;
          fImportDb = FALSE;
          if ( get_obj_index ( vnum ) != NULL )
          {
               bugf ( "Load_objects: vnum %d duplicated.", vnum );
               exit ( 1 );
          }
          fImportDb = oldival;
          fBootDb = oldval;
          
          pObjIndex = alloc_perm ( sizeof ( *pObjIndex ), "pObjIndex:load_area_objects" );

          pObjIndex->new_format 	= TRUE;

          pObjIndex->vnum 		= vnum;
          pObjIndex->area 		= area_last;
          pObjIndex->reset_num 		= 0;
          newobjs++;
          pObjIndex->name 		= fread_string ( fpArea );
          pObjIndex->short_descr 	= fread_string ( fpArea );
          pObjIndex->description 	= fread_string ( fpArea );
          if ( native )               
               pObjIndex->notes 		= fread_string ( fpArea );
          pObjIndex->material 		= material_lookup ( fread_string ( fpArea ) );
          pObjIndex->item_type 		= fread_number ( fpArea );
          pObjIndex->extra_flags 	= fread_flag ( fpArea );
          pObjIndex->wear_flags 	= fread_flag ( fpArea );
          if ( native )
               pObjIndex->vflags 		= fread_flag ( fpArea );
          pObjIndex->value[0] 		= fread_flag ( fpArea );
          pObjIndex->value[1] 		= fread_flag ( fpArea );
          pObjIndex->value[2] 		= fread_flag ( fpArea );
          pObjIndex->value[3] 		= fread_flag ( fpArea );
          pObjIndex->value[4] 		= fread_flag ( fpArea );
          pObjIndex->level 		= fread_number ( fpArea );
          pObjIndex->weight 		= fread_number ( fpArea );
          pObjIndex->cost 		= fread_number ( fpArea );
          if ( native )
          {
               pObjIndex->condition		= fread_number ( fpArea );
               pObjIndex->repop		= fread_number ( fpArea );
          }

          /* Get lettered values */
          for ( ;; )
          {
               char letter;
               letter = fread_letter ( fpArea );
               if ( letter == 'A' )
               {
                    AFFECT_DATA * paf;

                    paf 		= alloc_perm ( sizeof ( *paf ), "paf:load_area_objects" );
                    paf->type 		= -1;
                    paf->level 		= pObjIndex->level;
                    paf->duration 	= -1;
                    paf->location 	= fread_number ( fpArea );
                    paf->modifier 	= fread_number ( fpArea );
                    paf->bitvector 	= 0;
                    paf->next 		= pObjIndex->affected;
                    pObjIndex->affected = paf; top_affect++;
               }
               else if ( letter == 'N' )
               {
                    AFFECT_DATA * paf;

                    int slot_num;
                    paf 		= alloc_perm ( sizeof ( *paf ), "paf:load_area_objects" );
                    slot_num 		= fread_number ( fpArea );
                    paf->type 		= -1;
                    paf->level 		= pObjIndex->level;
                    paf->duration 	= -1;
                    paf->location 	= fread_number ( fpArea );
                    paf->modifier 	= fread_number ( fpArea );
                    paf->where 		= TO_AFFECTS;
                    paf->bitvector 	= fread_number ( fpArea );
                    paf->next 		= pObjIndex->affected;
                    pObjIndex->affected = paf;
                    top_affect++;
               }
               else if (letter == 'F')
               {
                    AFFECT_DATA *paf;

                    paf                     = alloc_perm( sizeof(*paf), "paf:load_area_objects" );
                    letter                  = fread_letter(fpArea);
                    switch (letter)
                    {
                    case 'A':
                         paf->where         = TO_AFFECTS;
                         break;
                    case 'D':
                         paf->where         = TO_DETECTIONS;
                         break;
                    case 'P':
                         paf->where         = TO_PROTECTIONS;
                         break;
                    default:
                         bugf ( "Load_objects: Bad where on flag set." );
                         exit( 1 );
                    }
                    paf->type               = -1;
                    paf->level              = pObjIndex->level;
                    paf->duration           = -1;
                    paf->location           = fread_number(fpArea);
                    paf->modifier           = fread_number(fpArea);
                    paf->bitvector          = fread_flag(fpArea);
                    paf->next               = pObjIndex->affected;
                    pObjIndex->affected     = paf;
                    top_affect++;
               }
               else if ( letter == 'E' )
               {
                    EXTRA_DESCR_DATA * ed;

                    ed 			= alloc_perm ( sizeof ( *ed ), "ed:load_area_objects" );
                    ed->keyword 	= fread_string ( fpArea );
                    ed->description 	= fread_string ( fpArea );
                    ed->next 		= pObjIndex->extra_descr;
                    pObjIndex->extra_descr = ed;
                    top_ed++;
               }
               else if ( letter == 'O' )
               {
                    PROG_LIST *pOprog;
                    char *word;
                    int trigger = 0;

                    pOprog                  = alloc_perm(sizeof(*pOprog), "oprogs");
                    word                    = fread_word( fpArea );
                    if ( !(trigger = flag_lookup( word, oprog_flags )) )
                    {
                         bugf( "OBJprogs: invalid trigger.");
                         exit(1);
                    }
                    SET_BIT( pObjIndex->oprog_flags, trigger );
                    pOprog->trig_type       = trigger;
                    pOprog->vnum            = fread_number( fpArea );
                    pOprog->trig_phrase     = fread_string( fpArea );
                    pOprog->next            = pObjIndex->oprogs;
                    pObjIndex->oprogs       = pOprog;
               }
               else
               {
                    ungetc ( letter, fpArea );
                    break;
               }
          }
          /* Lettered values for ( ;; ) */
          /* Translate spell "slot numbers" to internal "skill numbers." */
          switch ( pObjIndex->item_type )
          {
          case ITEM_PILL:
          case ITEM_POTION:
          case ITEM_SCROLL:
               pObjIndex->value[1] = slot_lookup ( pObjIndex->value[1] );
               pObjIndex->value[2] = slot_lookup ( pObjIndex->value[2] );
               pObjIndex->value[3] = slot_lookup ( pObjIndex->value[3] );
               break;
          case ITEM_STAFF:
          case ITEM_WAND:
               pObjIndex->value[3] = slot_lookup ( pObjIndex->value[3] );
               break;
          }
          
          /* Check the validity of some of the flags - Lotherius */
          /* Flags but no Take */
          if ( !IS_SET ( pObjIndex->wear_flags, ITEM_TAKE ) && pObjIndex->wear_flags > 0 )
               bugf ( "\nObject Vnum %d has wear flags %ld with no TAKE flag",
                      pObjIndex->vnum, pObjIndex->wear_flags );
          /* Hold flag with other flags */
          if ( IS_SET ( pObjIndex->wear_flags, ITEM_HOLD ) )
          {
               long ibid;

               ibid = pObjIndex->wear_flags;
               ibid -= ITEM_HOLD;               // Knock off the 2 flags that we know are here.
               ibid -= ITEM_TAKE;

               if ( ibid > 0 )                  // Then there shouldn't be any flags left.
               {
                    if ( ibid == ITEM_WEAR_SHIELD ) // Probably the most common occurance, fix automatically
                    {
                         bugf ( "\nObj VNUM %d has HOLD and SHIELD both set. Removing HOLD flag.\n"
                                "To make this change permanent, please do an ASAVE. If this is the wrong"
                                "change,\nthen fix it manually.", pObjIndex->vnum );
                         pObjIndex->wear_flags -= ITEM_HOLD;
                    }
                    else
                    {
                         bugf ( "\nObj VNUM %d has too many wear flags. Please check.", pObjIndex->vnum );
                    }
               }
          }
          /* Find items that are wieldable that aren't weapons */
          if ( IS_SET ( pObjIndex->wear_flags, ITEM_WIELD ) && pObjIndex->item_type != ITEM_WEAPON )
               bugf ( " Obj VNUM %d: Non-Weapon Wieldable?", pObjIndex->vnum );
          /* Find shields that aren't armor */
          if ( IS_SET ( pObjIndex->wear_flags, ITEM_WEAR_SHIELD ) && pObjIndex->item_type != ITEM_ARMOR )
               bugf ( " Obj VNUM %d: Non-Armor Shield?", pObjIndex->vnum );

          
          iHash 		= vnum % MAX_KEY_HASH;
          pObjIndex->next 	= obj_index_hash[iHash];
          obj_index_hash[iHash] = pObjIndex; top_obj_index++;
          top_vnum_obj 		= top_vnum_obj < vnum ? vnum : top_vnum_obj;
          assign_area_vnum ( vnum );
     }
     /* End of for ( ;; ) */
     fclose ( fpArea );
     return;
}

void db_save_area_resets ( char *filename, AREA_DATA *pArea )
{
     char                rfilename[MSL];
     FILE                *fp;
     int                 iHash;
     RESET_DATA         *pReset;
     MOB_INDEX_DATA     *pLastMob = NULL;
     OBJ_INDEX_DATA     *pLastObj;
     ROOM_INDEX_DATA    *pRoomIndex;
     EXIT_DATA          *pExit;
     int                 door;

     SNP ( rfilename, "%s%s.resets", RESET_DIR, filename );

     if ( !( fp = fopen ( rfilename, "w" ) ) )
     {
          bugf ( "Open_area: fopen (while saving an area)");
          perror ( rfilename );
     }

     /* Write out door resets */

     for ( iHash = 0; iHash < MAX_KEY_HASH; iHash++ )
     {
          for ( pRoomIndex = room_index_hash[iHash]; pRoomIndex; pRoomIndex = pRoomIndex->next )
          {
               if ( pRoomIndex->area == pArea )
               {
                    for ( door = 0; door < MAX_DIR; door++ )
                    {
                         int                 locks = 0;
                         if ( ( pExit = pRoomIndex->exit[door] ) && pExit->u1.to_room
                              && ( IS_SET ( pExit->rs_flags, EX_CLOSED ) || IS_SET ( pExit->rs_flags, EX_LOCKED ) ) )
                         {
                              if ( IS_SET ( pExit->rs_flags, EX_ISDOOR ) && ( !IS_SET ( pExit->rs_flags, EX_LOCKED ) ) )
                                   locks = 1;
                              if ( IS_SET ( pExit->rs_flags, EX_ISDOOR ) && ( IS_SET ( pExit->rs_flags, EX_LOCKED ) ) )
                                   locks = 2;
                              if ( pExit->key == 0 )
                                   pExit->key = -1;
                              // fprintf ( fp, "D 0 %d %d %d\n", pRoomIndex->vnum, door, locks );
                              fprintf ( fp, "D %d %d %d\n", pRoomIndex->vnum, door, locks );
                         }
                    }
               }
          }
     }

     /* Write out other resets */
     for ( iHash = 0; iHash < MAX_KEY_HASH; iHash++ )
     {
          for ( pRoomIndex = room_index_hash[iHash]; pRoomIndex; pRoomIndex = pRoomIndex->next )
          {
               if ( pRoomIndex->area == pArea )
               {
                    for ( pReset = pRoomIndex->reset_first; pReset; pReset = pReset->next )
                    {
                         /* Pulled the leading Zero off of all the following */
                         switch ( pReset->command )
                         {
                         default:
                              bugf ( "Save_resets: bad command %c.", pReset->command );
                              break;
                         case 'M':
                              pLastMob = get_mob_index ( pReset->arg1 );
                              fprintf ( fp, "M %d %d %d\n",
                                        pReset->arg1,
                                        pReset->arg2, pReset->arg3 );
                              break;
                         case 'O':
                              pLastObj = get_obj_index ( pReset->arg1 );
                              pRoomIndex = get_room_index ( pReset->arg3 );
                              fprintf ( fp, "O %d %d %d\n",
                                        pReset->arg1,
                                        pReset->arg2, pReset->arg3 );
                              break;
                         case 'P':
                              pLastObj = get_obj_index ( pReset->arg1 );
                              fprintf ( fp, "P %d %d %d\n",
                                        pReset->arg1,
                                        pReset->arg2, pReset->arg3 );
                              break;
                         case 'G':
                              fprintf ( fp, "G %d %d\n", pReset->arg1, pReset->arg2 );
                              if ( !pLastMob )
                                   bugf ( "Save_resets: !NO_MOB! in [%s]", pArea->filename );
                              break;
                         case 'E':
                              fprintf ( fp, "E %d %d %d\n", pReset->arg1, pReset->arg2, pReset->arg3 );
                              if ( !pLastMob )
                                   bugf ( "Save_resets: !NO_MOB! in [%s]", pArea->filename );
                              break;
                         case 'D':
                              /* Doors are done previously. */
                              break;
                         case 'R':
                              pRoomIndex = get_room_index ( pReset->arg1 );
                              fprintf ( fp, "R %d %d\n", pReset->arg1, pReset->arg2 );
                              break;
                         }
                         // end of switch
                    }
                    // end of for
               }
               // end of if
          }
          // end of for
     }
     // end of for
     //
     fprintf ( fp, "S\n\n\n\n" );
     fclose ( fp );
     return;
}

void db_load_area_resets ( char *filename, AREA_DATA *pArea )
{
     RESET_DATA *pReset;
     int         iLastRoom = 0;
     int         iLastObj = 0;

     SNP ( strArea, "%s%s.resets", RESET_DIR, filename );

     if ( !( fpArea = fopen ( strArea, "r" ) ) )
     {
          bugf ( "No %s found for %s", strArea, pArea->name );
          return;
     }

     for ( ;; )
     {
          EXIT_DATA          *pexit;
          ROOM_INDEX_DATA    *pRoomIndex;
          char                letter;
          bool		      fix = FALSE;

          /* The "fix" toggle is for importation of older format (Rom style) resets that don't save
           * per-reset counters and thus have pileup issues - Not used normally.. */

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

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

          pReset 		= alloc_perm ( sizeof ( *pReset ), "pReset:load_area_resets" );
          pReset->command 	= letter;
          pReset->arg1 		= fread_number ( fpArea );
          pReset->arg2 		= fread_number ( fpArea );
          if ( pReset->arg2 == -1 ) pReset->arg2 = 9999; /* Mess with infinity... this needs standardized */
          pReset->arg3 		= ( letter == 'G' || letter == 'R' ) ? 0 : fread_number ( fpArea );
          fread_to_eol ( fpArea );				 /* Skip any comments from verbose modes 	  */
          pReset->count = 0;

          /* Validate parameters.
           * We're calling the index functions for the side effect. */

          switch ( letter )
          {
          default:
               bugf ( "Load_resets: bad command '%c'.", letter );
               exit ( 1 );
               break;
          case 'M':
               get_mob_index ( pReset->arg1 );
               if ( fix == TRUE )
                    pReset->arg2 = 1;   /* reset max # to 1 */
               if ( ( pRoomIndex = get_room_index ( pReset->arg3 ) ) )
               {
                    new_reset ( pRoomIndex, pReset );
                    iLastRoom = pReset->arg3;
               }
               break;
          case 'O':
               get_obj_index ( pReset->arg1 );
               if ( ( pRoomIndex = get_room_index ( pReset->arg3 ) ) )
               {
                    new_reset ( pRoomIndex, pReset );
                    iLastObj = pReset->arg3;
               }
               break;
          case 'P':
               get_obj_index ( pReset->arg1 );
               if ( ( pRoomIndex = get_room_index ( iLastObj ) ) )
               {
                    new_reset ( pRoomIndex, pReset );
               }
               break;
          case 'G':
          case 'E':
               get_obj_index ( pReset->arg1 );
               if ( ( pRoomIndex = get_room_index ( iLastRoom ) ) )
               {
                    new_reset ( pRoomIndex, pReset );
                    iLastObj = iLastRoom;
               }
               break;
          case 'D':
               pRoomIndex = get_room_index ( pReset->arg1 );

               if ( pReset->arg2 < 0
                    || pReset->arg2 > 5
                    || !pRoomIndex
                    || !( pexit = pRoomIndex->exit[pReset->arg2] )
                    || !IS_SET ( pexit->rs_flags, EX_ISDOOR ) )
               {
                    bugf ( "Load_resets: 'D': exit %d not door.", pReset->arg2 );
                    exit ( 1 );
               }
               switch ( pReset->arg3 )
               {
               default:
                    bugf ( "Load_resets: 'D': bad 'locks': %d.", pReset->arg3 );
               case 0:
                    break;
               case 1:
                    SET_BIT ( pexit->rs_flags, EX_CLOSED );
                    break;
               case 2:
                    SET_BIT ( pexit->rs_flags, EX_LOCKED );
                    SET_BIT ( pexit->rs_flags, EX_CLOSED );
                    break;
               }
          case 'R':
               if ( pReset->arg2 < 0 || pReset->arg2 > 6 )      /* Last Door. */
               {
                    bugf ( "Load_resets: 'R': bad exit %d.", pReset->arg2 );
                    exit ( 1 );
               }
               if ( ( pRoomIndex = get_room_index ( pReset->arg1 ) ) )
                    new_reset ( pRoomIndex, pReset );
               break;
          }
          /* End of switch */

     }
     /* End of for ( ;; ) */

     fclose ( fpArea );
     return;
}

void db_save_area_shops ( char *filename, AREA_DATA *pArea )
{
     SHOP_DATA          *pShopIndex;
     MOB_INDEX_DATA     *pMobIndex;
     int                 iTrade;
     int                 iHash;
     char 		 sfilename[MSL];
     FILE 		*fp;

     SNP ( sfilename, "%s%s.shops", SHOP_DIR, filename );

     if ( !( fp = fopen ( sfilename, "w" ) ) )
     {
          bugf ( "Open_area: fopen (while saving an area)");
          perror ( sfilename );
     }

     for ( iHash = 0; iHash < MAX_KEY_HASH; iHash++ )
     {
          for ( pMobIndex = mob_index_hash[iHash]; pMobIndex; pMobIndex = pMobIndex->next )
          {
               if ( pMobIndex && pMobIndex->area == pArea && pMobIndex->pShop )
               {
                    pShopIndex = pMobIndex->pShop;
                    fprintf ( fp, "%d ", pShopIndex->keeper );
                    for ( iTrade = 0; iTrade < MAX_TRADE; iTrade++ )
                         fprintf ( fp, "%d ", pShopIndex->buy_type[iTrade] );
                    fprintf ( fp, "%d %d ", pShopIndex->profit_buy, pShopIndex->profit_sell );
                    fprintf ( fp, "%d %d\n", pShopIndex->open_hour, pShopIndex->close_hour );
               }
          }
     }

     fprintf ( fp, "0\n\n\n\n" );

     fclose ( fp );
     return;
}

void db_load_area_shops ( char *filename, AREA_DATA *pArea )
{
     SHOP_DATA  *pShop;
     
     SNP ( strArea, "%s%s.shops", SHOP_DIR, filename );

     if ( !( fpArea = fopen ( strArea, "r" ) ) )
     {
          bugf ( "No %s found for %s", strArea, pArea->name );
          return;
     }

     for ( ;; )
     {
          MOB_INDEX_DATA     *pMobIndex;
          int                 iTrade;

          pShop 		= alloc_perm ( sizeof ( *pShop ), "pShop:load_area_shops" );
          pShop->keeper 	= fread_number ( fpArea );

          if ( pShop->keeper == 0 )
               break;
          for ( iTrade = 0; iTrade < MAX_TRADE; iTrade++ )
               pShop->buy_type[iTrade] 	= fread_number ( fpArea );

          pShop->profit_buy 		= fread_number ( fpArea );
          pShop->profit_sell 		= fread_number ( fpArea );
          pShop->open_hour 		= fread_number ( fpArea );
          pShop->close_hour 		= fread_number ( fpArea );
          fread_to_eol ( fpArea );
          pMobIndex 			= get_mob_index ( pShop->keeper );
          pMobIndex->pShop 		= pShop;
          if ( shop_first == NULL )
               shop_first 		= pShop;
          if ( shop_last != NULL )
               shop_last->next 		= pShop;
          shop_last 			= pShop;
          pShop->next 			= NULL;
          top_shop++;
     }

     fclose ( fpArea );
     return;
}

void db_save_area_specials ( char *filename, AREA_DATA *pArea )
{
     int                 iHash;
     MOB_INDEX_DATA     *pMobIndex;
     char 		 sfilename[MSL];
     FILE 		 *fp;

     SNP ( sfilename, "%s%s.specials", SPEC_DIR, filename );

     if ( !( fp = fopen ( sfilename, "w" ) ) )
     {
          bugf ( "Open_area: fopen (while saving an area)");
          perror ( sfilename );
     }

     for ( iHash = 0; iHash < MAX_KEY_HASH; iHash++ )
     {
          for ( pMobIndex = mob_index_hash[iHash]; pMobIndex; pMobIndex = pMobIndex->next )
          {
               if ( pMobIndex && pMobIndex->area == pArea && pMobIndex->spec_fun )
               {
                    /* removed words "Load to:" from below as well as short_descr*/
                    fprintf ( fp, "M %d %s\n",
                              pMobIndex->vnum,
                              spec_string ( pMobIndex->spec_fun ) );
               }
          }
     }

     fprintf ( fp, "S\n\n\n\n" );

     fclose ( fp );
     return;
}

void db_load_area_specials ( char *filename, AREA_DATA *pArea )
{
     SNP ( strArea, "%s%s.specials", SPEC_DIR, filename );

     if ( !( fpArea = fopen ( strArea, "r" ) ) )
     {
          bugf ( "No %s found for %s", strArea, pArea->name );
          return;
     }

     for ( ;; )
     {
          MOB_INDEX_DATA     *pMobIndex;
          char                letter;

          switch ( letter = fread_letter ( fpArea ) )
          {
          default:
               bugf ( "Load_specials: letter '%c' not *MS.", letter );
               exit ( 1 );
          case 'S':
               return;
          case '*':
               break;
          case 'M':
               pMobIndex 		= get_mob_index ( fread_number ( fpArea ) );
               pMobIndex->spec_fun 	= spec_lookup ( fread_word ( fpArea ) );
               if ( pMobIndex->spec_fun == 0 )
               {
                    bugf ( "Load_specials: 'M': vnum %d.", pMobIndex->vnum );
                    exit ( 1 );
               }
               break;
          }
          fread_to_eol ( fpArea );
     }

     fclose ( fpArea );
     return;
}

void db_save_area_progs ( char *filename, AREA_DATA *pArea )
{
     PROG_CODE 		*pProg;
     int 		 i;
     char                pfilename[MSL];
     FILE                *fp;

     SNP ( pfilename, "%s%s.progs", PROG_DIR, filename );

     if ( !( fp = fopen ( pfilename, "w" ) ) )
     {
          bugf ( "Open_area: fopen (while saving an area)");
          perror ( pfilename );
     }

     fprintf(fp, "#MOBPROGS\n");
     for( i = pArea->lvnum; i <= pArea->uvnum; i++ )
     {
          if ( (pProg = get_prog_index(i, PRG_MPROG) ) != NULL)
          {
               fprintf(fp, "#%d\n", i);
               fprintf(fp, "%s~\n", fix_string(pProg->code));
          }
     }
     fprintf(fp,"#0\n\n");

     fprintf(fp, "#OBJPROGS\n");
     for( i = pArea->lvnum; i <= pArea->uvnum; i++ )
     {
          if ( (pProg = get_prog_index(i, PRG_OPROG) ) != NULL)
          {
               fprintf(fp, "#%d\n", i);
               fprintf(fp, "%s~\n", fix_string(pProg->code));
          }
     }
     fprintf(fp,"#0\n\n");

     fprintf(fp, "#ROOMPROGS\n");
     for( i = pArea->lvnum; i <= pArea->uvnum; i++ )
     {
          if ( (pProg = get_prog_index(i,PRG_RPROG) ) != NULL)
          {
               fprintf(fp, "#%d\n", i);
               fprintf(fp, "%s~\n", fix_string(pProg->code));
          }
     }
     fprintf(fp,"#0\n\n");

     fclose ( fp );
     return;
}

void db_load_area_progs ( char *filename, AREA_DATA *pArea )
{
     PROG_CODE  *pProg;
     char	*word;
     int	 ptype = PRG_MPROG;

     SNP ( strArea, "%s%s.progs", PROG_DIR, filename );
     
     if ( !( fpArea = fopen ( strArea, "r" ) ) )
     {
          bugf ( "No %s found for %s", strArea, pArea->name );
          return;
     }

     for ( ; ; )
     {
          bool oldval;
          bool oldival;
          int vnum;
          char letter;

          letter                  = fread_letter( fpArea );

          if ( letter != '#' )
          {
               bugf( "Load_mobprogs: # not found." );
               exit( 1 );
          }
          
          word = fread_word ( fpArea );
          
          if ( !is_number( word ) )
          {
               if ( !str_cmp ( word, "MOBPROGS" ) )          ptype = PRG_MPROG;
               else if ( !str_cmp ( word, "OBJPROGS" ) )     ptype = PRG_OPROG;
               else if ( !str_cmp ( word, "ROOMPROGS" ) )    ptype = PRG_RPROG; /* MUST BE LAST */
               else
               {
                    bugf ( "Invalid word %s in %s.", word, strArea );
                    exit ( 1 );
               }
               continue;
          }

          vnum = atol ( word );

          /* This depends on roomprogs being loaded last!!! */
          if ( vnum == 0 )
          {
               if ( ptype == PRG_RPROG )	/* Quit loading progs if all are done */
                    break;
               else				/* Get next program type if all are not done */
                    continue;
          }
          
          oldval = fBootDb;
          oldival = fImportDb;
          
          fBootDb = FALSE;
          fImportDb = FALSE;
          if ( get_prog_index( vnum, ptype ) != NULL )
          {
               bugf( "load_area_progs: vnum %d duplicated.", vnum );
               exit( 1 );
          }
          fImportDb = oldival;
          fBootDb = oldval;
          
          pProg                = alloc_perm( sizeof(*pProg), "pMprog:load_area_progs" );
          pProg->vnum          = vnum;
          pProg->code          = fread_string( fpArea );
          
          if ( ptype == PRG_MPROG )
          {
               if ( mprog_list == NULL )
                    mprog_list = pProg;
               else
               {
                    pProg->next  = mprog_list;
                    mprog_list   = pProg;
               }
               top_mprog_index++;
          }
          else if ( ptype == PRG_OPROG )
          {
               if ( oprog_list == NULL )
                    oprog_list = pProg;
               else
               {
                    pProg->next  = oprog_list;
                    oprog_list   = pProg;
               }
               top_oprog_index++;
          }
          else if ( ptype == PRG_RPROG )
          {
               if ( rprog_list == NULL )
                    rprog_list = pProg;
               else
               {
                    pProg->next  = rprog_list;
                    rprog_list   = pProg;
               }
               top_rprog_index++;               
          }
          
          else
          {
               bugf ( "Unknown ptype %d in %s????", ptype, strArea );
               exit ( 1 );
          }
     }

     fclose ( fpArea );
     return;
}