diff -uprN -x *.o ../src/.cvsignore ./.cvsignore
--- ../src/.cvsignore	Tue Oct 28 23:16:17 1997
+++ ./.cvsignore	Wed Dec 31 18:00:00 1969
@@ -1,3 +0,0 @@
-conf.h
-.accepted
-Makefile
diff -uprN -x *.o ../src/act.comm.c ./act.comm.c
--- ../src/act.comm.c	Sat Jun 13 20:13:10 1998
+++ ./act.comm.c	Sat Jan  2 04:07:32 1999
@@ -307,6 +307,7 @@ ACMD(do_write)
     act("$n begins to jot down a note.", TRUE, ch, 0, 0, TO_ROOM);
     ch->desc->str = &paper->action_description;
     ch->desc->max_str = MAX_NOTE_LENGTH;
+    SET_BIT(GET_OBJ_EXTRA(paper),ITEM_UNIQUE_SAVE);
   }
 }
 
diff -uprN -x *.o ../src/act.other.c ./act.other.c
--- ../src/act.other.c	Tue Jun 16 17:08:57 1998
+++ ./act.other.c	Sat Jan  2 04:09:21 1999
@@ -37,6 +37,7 @@ extern int max_filesize;
 extern int nameserver_is_slow;
 extern int top_of_world;
 extern int auto_save;
+extern int xap_objs;
 
 /* extern procedures */
 void list_skills(struct char_data * ch);
@@ -859,7 +860,9 @@ ACMD(do_gen_tog)
     {"Nameserver_is_slow changed to NO; IP addresses will now be resolved.\r\n",
     "Nameserver_is_slow changed to YES; sitenames will no longer be resolved.\r\n"},
     {"Autoexits disabled.\r\n",
-    "Autoexits enabled.\r\n"}
+    "Autoexits enabled.\r\n"},
+    {"Ascii objects turned off.\r\n",
+    "Ascii objects turned on.\r\n"}
   };
 
 
@@ -914,6 +917,10 @@ ACMD(do_gen_tog)
     break;
   case SCMD_AUTOEXIT:
     result = PRF_TOG_CHK(ch, PRF_AUTOEXIT);
+    break;
+  case SCMD_XAP_OBJS:
+ /* I guess we'll have interesing results if xap objs aren't 1 or 0 */
+    result = (xap_objs = !xap_objs);   
     break;
   default:
     log("SYSERR: Unknown subcmd %d in do_gen_toggle.", subcmd);
diff -uprN -x *.o ../src/act.wizard.c ./act.wizard.c
--- ../src/act.wizard.c	Wed Jun 24 23:59:20 1998
+++ ./act.wizard.c	Sat Jan  2 04:13:05 1999
@@ -2566,3 +2566,122 @@ ACMD(do_set)
     free_char(cbuf);
 }
 
+void out_rent(char *name) {
+  FILE *fl,*fp;
+  char fname[MAX_INPUT_LENGTH], buf[MAX_STRING_LENGTH],fname2[MAX_INPUT_LENGTH];
+  struct obj_file_elem object;
+  struct obj_data *obj;
+  struct rent_info rent;
+
+  if (!get_filename(name, fname, CRASH_FILE))
+    return;
+  if (!(fl = fopen(fname, "rb"))) {
+    return;
+  }
+
+  sprintf(buf, "%s\r\n", fname);
+  if (!feof(fl))
+    fread(&rent, sizeof(struct rent_info), 1, fl);
+
+  if (!get_filename(name, fname2, NEW_OBJ_FILES)) {
+    log("Unable to complete conversion - unable to get new object filename.\r\n");
+    return;
+  }
+  if (!(fp = fopen(fname2, "w+"))) {
+    log("Unable to open new object file.\r\n");
+    return;
+  }
+
+  fprintf(fp,"%d %d %d %d %d %d\r\n",rent.rentcode,rent.time,
+       rent.net_cost_per_diem,rent.gold,rent.account,rent.nitems);
+  /* for rent code */
+
+  while (!feof(fl)) {
+    fread(&object, sizeof(struct obj_file_elem), 1, fl);
+
+    if (ferror(fl) || ferror(fp)) {
+      fclose(fl);
+      fclose(fp);
+      log("Error in conversion of rent files.");
+      return;
+    }
+
+    if (!feof(fl)) {
+      if (real_object(object.item_number) > 0) {
+       /* none of these will be unique items. just can't happen */
+          obj = read_object(object.item_number, VIRTUAL);
+          my_obj_save_to_disk(fp, obj,0);
+          extract_obj(obj);
+      }
+    }
+  }
+  fclose(fl);
+
+  /* write final line - this is never actually read.. but hey! */
+  fprintf(fp, "$~\n");
+  fclose(fp);
+}
+
+/* Xap - To keep old rent files (binary) and not loose all objects, you'll
+   have to convert to ascii files.  Guess what?  This doesn't work as well
+   as you'd think.  Well, It works, but here's some limitations:
+    1. Sucks up memory. I don't know why. Maybe its specific to my mud,
+        but I'm pretty sure I'm freeing all that needs it.
+    2. It takes time.  You'll notice I use the process output command
+        a few times.  This is because with something like 2500 rent files,
+        it can take up to 2 or 3 minutes.
+                I guess, use at your own risk. */
+
+ACMD(do_objconv) {
+  int counter;
+  float percent;
+  struct char_data *victim;
+  extern struct player_index_element *player_table;
+  struct char_file_u tmp_store;
+  int flag25=0,flag50=0,flag75=0,flag100=0;
+  int process_output(struct descriptor_data *t);
+  struct descriptor_data *d;
+
+  send_to_all("Please hold on - object conversion taking place.\r\n");
+
+  for (d = descriptor_list; d; d = d->next) {
+    process_output(d);
+  }
+
+  if(GET_LEVEL(ch) != LVL_IMPL && !IS_NPC(ch)) {
+    send_to_char("You may not.\r\n",ch);
+    return;
+  }
+  /* okay, this is where we load every char, apparently.. but we'll
+     do it one at a time, thank you very much */
+  for (counter = 0; counter <= top_of_p_table; counter++) {
+    CREATE(victim, struct char_data, 1);
+    clear_char(victim);
+    if (load_char((player_table + counter)->name, &tmp_store) > -1)
+      store_to_char(&tmp_store, victim);
+    out_rent(GET_NAME(victim));
+    free_char(victim);
+    percent = (float)((float) counter/(float) top_of_p_table);
+    if(percent > .25 && flag25==0) {
+      send_to_char("25%...",ch);
+      flag25=1;
+      process_output(ch->desc);
+    }
+    if(percent > .50 && flag50==0) {
+      send_to_char("50%...",ch);
+      flag50=1;
+      process_output(ch->desc);
+    }
+    if(percent > .75 && flag75==0) {
+      send_to_char("75%...",ch);
+      flag75=1;
+      process_output(ch->desc);
+    }
+    if(percent > .90 && flag100==0) {
+      send_to_char("90%...",ch);
+      flag100=1;
+      process_output(ch->desc);
+    }
+  }
+  send_to_char("100%. Done.\r\n",ch);
+}
diff -uprN -x *.o ../src/comm.c ./comm.c
--- ../src/comm.c	Fri Jul  3 14:07:39 1998
+++ ./comm.c	Sat Jan  2 04:15:56 1999
@@ -99,6 +99,7 @@ int max_players = 0;		/* max descriptors
 int tics = 0;			/* for extern checkpointing */
 int scheck = 0;			/* for syntax checking mode */
 extern int nameserver_is_slow;	/* see config.c */
+extern int xap_objs;		/* ascii objects. */
 extern int auto_save;		/* see config.c */
 extern int autosave_time;	/* see config.c */
 struct timeval null_time;	/* zero-valued time structure */
@@ -259,6 +260,10 @@ int main(int argc, char **argv)
     case 's':
       no_specials = 1;
       log("Suppressing assignment of special routines.");
+      break;
+    case 'o':
+      xap_objs = 1;
+      log("Loading player objects from secondary (ascii) files.");
       break;
     default:
       log("SYSERR: Unknown option -%c in argument string.", *(argv[pos] + 1));
diff -uprN -x *.o ../src/constants.c ./constants.c
--- ../src/constants.c	Wed Jun 24 16:56:58 1998
+++ ./constants.c	Sat Jan  2 04:16:18 1999
@@ -359,6 +359,7 @@ const char *extra_bits[] = {
   "!THIEF",
   "!WARRIOR",
   "!SELL",
+  "UNIQUE",
   "\n"
 };
 
diff -uprN -x *.o ../src/db.c ./db.c
--- ../src/db.c	Wed Jun 24 23:44:38 1998
+++ ./db.c	Sat Jan  2 04:25:42 1999
@@ -57,6 +57,7 @@ int mini_mud = 0;		/* mini-mud mode?		 *
 int no_rent_check = 0;		/* skip rent check on boot?	 */
 time_t boot_time = 0;		/* time of mud boot		 */
 int circle_restrict = 0;	/* level of game restriction	 */
+int xap_objs = 0;		/* Xap objs			 */
 sh_int r_mortal_start_room;	/* rnum of mortal start room	 */
 sh_int r_immort_start_room;	/* rnum of immort start room	 */
 sh_int r_frozen_start_room;	/* rnum of frozen start room	 */
@@ -2566,3 +2567,219 @@ int real_object(int vnum)
       bot = mid + 1;
   }
 }
+
+int my_obj_save_to_disk(FILE *fp, struct obj_data *obj, int locate)
+{
+  int counter2;
+  struct extra_descr_data *ex_desc;
+  char buf1[MAX_STRING_LENGTH +1];
+
+      if (obj->action_description) {
+        strcpy(buf1, obj->action_description);
+        strip_string(buf1);
+      } else
+        *buf1 = 0;
+
+        fprintf(fp,
+              "#%d\n"
+             "%d %d %d %d %d %d\n",
+              GET_OBJ_VNUM(obj),
+              locate,
+              GET_OBJ_VAL(obj, 0),
+              GET_OBJ_VAL(obj, 1),
+              GET_OBJ_VAL(obj, 2),
+              GET_OBJ_VAL(obj, 3),
+              GET_OBJ_EXTRA(obj));
+
+  if(!(IS_OBJ_STAT(obj,ITEM_UNIQUE_SAVE))) {
+    return 1;
+  }
+       fprintf(fp,
+             "XAP\n"
+              "%s~\n"
+              "%s~\n"
+              "%s~\n"
+              "%s~\n"
+              "%d %d %d %d %d\n",
+              obj->name ? obj->name : "undefined",
+              obj->short_description ? obj->short_description : "undefined",
+              obj->description ? obj->description : "undefined",
+              buf1,
+              GET_OBJ_TYPE(obj),
+              GET_OBJ_WEAR(obj),
+              GET_OBJ_WEIGHT(obj),
+              GET_OBJ_COST(obj),
+              GET_OBJ_RENT(obj)
+        );
+      /* Do we have affects? */
+      for (counter2 = 0; counter2 < MAX_OBJ_AFFECT; counter2++)
+        if (obj->affected[counter2].modifier)
+          fprintf(fp, "A\n"
+                  "%d %d\n",
+                  obj->affected[counter2].location,
+                  obj->affected[counter2].modifier
+            );
+
+      /* Do we have extra descriptions? */
+      if (obj->ex_description) {        /*. Yep, save them too . */
+        for (ex_desc = obj->ex_description; ex_desc; ex_desc = ex_desc->next) {
+          /*. Sanity check to prevent nasty protection faults . */
+          if (!*ex_desc->keyword || !*ex_desc->description) {
+            continue;
+          }
+          strcpy(buf1, ex_desc->description);
+          strip_string(buf1);
+          fprintf(fp, "E\n"
+                  "%s~\n"
+                  "%s~\n",
+                  ex_desc->keyword,
+                  buf1
+            );
+        }
+      }
+  return 1;
+}
+
+/* This procedure removes the '\r\n' from a string so that it may be
+  saved to a file.  Use it only on buffers, not on the orginal
+  strings. */
+
+void strip_string(char *buffer)
+{
+  register char *ptr, *str;
+
+  ptr = buffer;
+  str = ptr;
+
+  while ((*str = *ptr)) {
+    str++;
+    ptr++;
+    if (*ptr == '\r')
+      ptr++;
+  }
+}
+
+int read_xap_objects(FILE *fl,struct char_data *ch) {
+  char line[MAX_STRING_LENGTH];
+  int t[10],nr,danger,j,k,zwei;
+  struct obj_data *temp=NULL;
+  struct extra_descr_data *new_descr;
+  int num_of_objs=0;
+
+  if(!feof(fl))
+    get_line(fl, line);
+  while (!feof(fl) && line != NULL) {
+       /* first, we get the number. Not too hard. */
+    if(*line == '#') {
+      num_of_objs++;
+      if (sscanf(line, "#%d", &nr) != 1) {
+        continue;
+      }
+      /* we have the number, check it, load obj. */
+      if (nr == -1) {  /* then its unique */
+        temp = create_obj();
+        temp->item_number=NOTHING;
+        SET_BIT(GET_OBJ_EXTRA(temp), ITEM_UNIQUE_SAVE);
+      } else if ( nr < 0) {
+         continue;
+      } else  {
+        temp=read_object(nr,VIRTUAL);
+        if (nr >= 99999 || !temp) {
+          continue;
+        }
+      }
+      /* now we read locate. - this is for autoeq, will be 0 elsewise */
+      /* only the rest of the vals, and extra flags will be read */
+      get_line(fl,line);
+      sscanf(line,"%d %d %d %d %d %d",t, t + 1, t+2, t + 3, t + 4,t+5);
+      GET_OBJ_VAL(temp,0) = t[1];
+      GET_OBJ_VAL(temp,1) = t[2];
+      GET_OBJ_VAL(temp,2) = t[3];
+      GET_OBJ_VAL(temp,3) = t[4];
+      GET_OBJ_EXTRA(temp) = t[5];
+
+      get_line(fl,line);
+       /* read line check for xap. */
+      if(!strcasecmp("XAP",line)) {  /* then this is a Xap Obj, requires
+                                       special care */
+        if ((temp->name = fread_string(fl, buf2)) == NULL) {
+          temp->name = "undefined";
+        }
+
+        if ((temp->short_description = fread_string(fl, buf2)) == NULL) {
+          temp->short_description = "undefined";
+        }
+
+        if ((temp->description = fread_string(fl, buf2)) == NULL) {
+          temp->description = "undefined";
+        }
+
+        if ((temp->action_description = fread_string(fl, buf2)) == NULL) {
+          temp->action_description=0;
+        }
+        if (!get_line(fl, line) ||
+           (sscanf(line, "%d %d %d %d %d", t,t+1,t+2,t+3,t+4) != 5)) {
+          fprintf(stderr, "Format error in first numeric line (expecting _x_ args)");
+          return 0;
+        }
+        temp->obj_flags.type_flag = t[0];
+        temp->obj_flags.wear_flags = t[1];
+        temp->obj_flags.weight = t[2];
+        temp->obj_flags.cost = t[3];
+        temp->obj_flags.cost_per_day = t[4];
+
+       /* buf2 is error codes pretty much */
+        strcat(buf2, ", after numeric constants (expecting E/#xxx)");
+
+       /* we're clearing these for good luck */
+
+        for (j = 0; j < MAX_OBJ_AFFECT; j++) {
+          temp->affected[j].location = APPLY_NONE;
+          temp->affected[j].modifier = 0;
+        }
+
+
+        for (k=j=zwei=0;!zwei && !feof(fl);) {
+          switch (*line) {
+            case 'E':
+              CREATE(new_descr, struct extra_descr_data, 1);
+              new_descr->keyword = fread_string(fl, buf2);
+              new_descr->description = fread_string(fl, buf2);
+              new_descr->next = temp->ex_description;
+              temp->ex_description = new_descr;
+              get_line(fl,line);
+              break;
+           case 'A':
+              if (j >= MAX_OBJ_AFFECT) {
+                log("Too many object affectations in loading rent file");
+                danger=1;
+              }
+              get_line(fl, line);
+              sscanf(line, "%d %d", t, t + 1);
+
+              temp->affected[j].location = t[0];
+              temp->affected[j].modifier = t[1];  
+              j++;
+              get_line(fl,line);
+              break;
+
+            case '$':
+            case '#':
+              zwei=1;
+              break;
+            default:
+              zwei=1;
+              break;
+          }
+        }      /* exit our for loop */
+        get_line(fl,line);
+      }   /* exit our xap loop */
+      IN_ROOM(ch)=1;
+      if(temp != NULL) {
+        obj_to_char(temp,ch);
+      }
+    }
+  }  /* exit our while loop */
+  return num_of_objs;
+}
+
diff -uprN -x *.o ../src/db.h ./db.h
--- ../src/db.h	Sat Jun 13 12:51:20 1998
+++ ./db.h	Sat Jan  2 04:26:47 1999
@@ -118,6 +118,7 @@ void	free_obj(struct obj_data *obj);
 int	real_object(int vnum);
 struct obj_data *read_object(int nr, int type);
 int	vnum_object(char *searchname, struct char_data *ch);
+int my_obj_save_to_disk(FILE *fp, struct obj_data *obj, int locate);
 
 #define REAL 0
 #define VIRTUAL 1
@@ -232,3 +233,7 @@ extern char	*OK;
 extern char	*NOPERSON;
 extern char	*NOEFFECT;
 #endif
+
+void strip_string(char *buffer);
+int read_xap_objects(FILE *fl,struct char_data *ch);
+
diff -uprN -x *.o ../src/handler.h ./handler.h
--- ../src/handler.h	Wed Jun 24 18:03:32 1998
+++ ./handler.h	Sat Jan  2 06:46:29 1999
@@ -101,6 +101,7 @@ int	Crash_load(struct char_data *ch);
 void	Crash_crashsave(struct char_data *ch);
 void	Crash_idlesave(struct char_data *ch);
 void	Crash_save_all(void);
+int     Crash_load_xapobjs(struct char_data *ch);
 
 /* prototypes from fight.c */
 void	set_fighting(struct char_data *ch, struct char_data *victim);
diff -uprN -x *.o ../src/interpreter.c ./interpreter.c
--- ../src/interpreter.c	Sat Jan  2 03:13:03 1999
+++ ./interpreter.c	Sat Jan  2 04:29:41 1999
@@ -44,6 +44,7 @@ extern int max_bad_pws;
 extern struct index_data *mob_index;
 extern struct index_data *obj_index;
 extern struct room_data *world;
+extern int xap_objs;
 
 /* external functions */
 void echo_on(struct descriptor_data *d);
@@ -125,6 +126,7 @@ ACMD(do_load);
 ACMD(do_look);
 /* ACMD(do_move); -- interpreter.h */
 ACMD(do_not_here);
+ACMD(do_objconv);
 ACMD(do_offer);
 ACMD(do_olc);
 ACMD(do_order);
@@ -381,6 +383,7 @@ cpp_extern const struct command_info cmd
   { "nudge"    , POS_RESTING , do_action   , 0, 0 },
   { "nuzzle"   , POS_RESTING , do_action   , 0, 0 },
 
+  { "objconv"  , POS_DEAD    , do_objconv  , LVL_IMPL, 0 },
   { "olc"      , POS_DEAD    , do_olc      , LVL_IMPL, 0 },
   { "order"    , POS_RESTING , do_order    , 1, 0 },
   { "offer"    , POS_STANDING, do_not_here , 1, 0 },
@@ -538,6 +541,8 @@ cpp_extern const struct command_info cmd
   { "wizlock"  , POS_DEAD    , do_wizlock  , LVL_IMPL, 0 },
   { "worship"  , POS_RESTING , do_action   , 0, 0 },
   { "write"    , POS_STANDING, do_write    , 1, 0 },
+
+  { "xapobjs"  , POS_DEAD,     do_gen_tog  , LVL_IMPL, SCMD_XAP_OBJS },
 
   { "yawn"     , POS_RESTING , do_action   , 0, 0 },
   { "yodel"    , POS_RESTING , do_action   , 0, 0 },
diff -uprN -x *.o ../src/interpreter.h ./interpreter.h
--- ../src/interpreter.h	Sun Jun  7 22:38:14 1998
+++ ./interpreter.h	Sat Jan  2 04:29:57 1999
@@ -113,6 +113,7 @@ struct alias {
 #define SCMD_HOLYLIGHT	13
 #define SCMD_SLOWNS	14
 #define SCMD_AUTOEXIT	15
+#define SCMD_XAP_OBJS   16
 
 /* do_wizutil */
 #define SCMD_REROLL	0
diff -uprN -x *.o ../src/mail.c ./mail.c
--- ../src/mail.c	Tue Jun 16 15:57:12 1998
+++ ./mail.c	Sat Jan  2 04:30:40 1999
@@ -589,6 +589,10 @@ void postmaster_receive_mail(struct char
       obj->action_description =
 	str_dup("Mail system error - please report.  Error #11.\r\n");
 
+	       /* so it saves */
+    SET_BIT(GET_OBJ_EXTRA(obj), ITEM_UNIQUE_SAVE);
+
+
     obj_to_char(obj, ch);
 
     act("$n gives you a piece of mail.", FALSE, mailman, 0, ch, TO_VICT);
diff -uprN -x *.o ../src/objsave.c ./objsave.c
--- ../src/objsave.c	Sat Jan  2 03:53:10 1999
+++ ./objsave.c	Sat Jan  2 07:15:21 1999
@@ -37,6 +37,7 @@ extern int rent_file_timeout, crash_file
 extern int free_rent;
 extern int min_rent_cost;
 extern int max_obj_save;	/* change in config.c */
+extern int xap_objs;
 
 /* Extern functions */
 ACMD(do_action);
@@ -64,7 +65,7 @@ void Crash_calculate_rent(struct obj_dat
 void Crash_rentsave(struct char_data * ch, int cost);
 void Crash_cryosave(struct char_data * ch, int cost);
 
-
+/* skipped with xap objs */
 struct obj_data *Obj_from_store_to(struct obj_file_elem object, int *locate)
 {
   struct obj_data *obj;
@@ -107,22 +108,26 @@ int Obj_to_store_from(struct obj_data * 
   int j;
   struct obj_file_elem object;
 
-  object.item_number = GET_OBJ_VNUM(obj);
-  object.locate = (sh_int) locate; /* where worn or inventory? */
-  object.value[0] = GET_OBJ_VAL(obj, 0);
-  object.value[1] = GET_OBJ_VAL(obj, 1);
-  object.value[2] = GET_OBJ_VAL(obj, 2);
-  object.value[3] = GET_OBJ_VAL(obj, 3);
-  object.extra_flags = GET_OBJ_EXTRA(obj);
-  object.weight = GET_OBJ_WEIGHT(obj);
-  object.timer = GET_OBJ_TIMER(obj);
-  object.bitvector = obj->obj_flags.bitvector;
-  for (j = 0; j < MAX_OBJ_AFFECT; j++)
-    object.affected[j] = obj->affected[j];
+  if(!xap_objs) {
+    object.item_number = GET_OBJ_VNUM(obj);
+    object.locate = (sh_int) locate; /* where worn or inventory? */
+    object.value[0] = GET_OBJ_VAL(obj, 0);
+    object.value[1] = GET_OBJ_VAL(obj, 1);
+    object.value[2] = GET_OBJ_VAL(obj, 2);
+    object.value[3] = GET_OBJ_VAL(obj, 3);
+    object.extra_flags = GET_OBJ_EXTRA(obj);
+    object.weight = GET_OBJ_WEIGHT(obj);
+    object.timer = GET_OBJ_TIMER(obj);
+    object.bitvector = obj->obj_flags.bitvector;
+    for (j = 0; j < MAX_OBJ_AFFECT; j++)
+      object.affected[j] = obj->affected[j];
 
-  if (fwrite(&object, sizeof(struct obj_file_elem), 1, fl) < 1) {
-    perror("SYSERR: error writing object in Obj_to_store");
-    return 0;
+    if (fwrite(&object, sizeof(struct obj_file_elem), 1, fl) < 1) {
+      perror("SYSERR: error writing object in Obj_to_store");
+      return 0;
+    }
+  } else {
+    my_obj_save_to_disk(fl, obj, locate);
   }
   return 1;
 }
@@ -141,8 +146,14 @@ int Crash_delete_file(char *name)
   char filename[50];
   FILE *fl;
 
-  if (!get_filename(name, filename, CRASH_FILE))
-    return 0;
+  if(!xap_objs) {
+    if (!get_filename(name, filename, CRASH_FILE))
+      return 0;
+  } else {
+    if(!get_filename(name,filename,NEW_OBJ_FILES))
+      return 0;
+  }
+
   if (!(fl = fopen(filename, "rb"))) {
     if (errno != ENOENT) {	/* if it fails but NOT because of no file */
       sprintf(buf1, "SYSERR: deleting crash file %s (1)", filename);
@@ -167,9 +178,17 @@ int Crash_delete_crashfile(struct char_d
   char fname[MAX_INPUT_LENGTH];
   struct rent_info rent;
   FILE *fl;
+  int rentcode,timed,netcost,gold,account,nitems;
+  char line[MAX_INPUT_LENGTH];
+
+  if(!xap_objs) {
+    if (!get_filename(GET_NAME(ch), fname, CRASH_FILE))
+      return 0;
+  } else {
+    if(!get_filename(GET_NAME(ch), fname,NEW_OBJ_FILES))
+      return 0;
+  }
 
-  if (!get_filename(GET_NAME(ch), fname, CRASH_FILE))
-    return 0;
   if (!(fl = fopen(fname, "rb"))) {
     if (errno != ENOENT) {	/* if it fails, NOT because of no file */
       sprintf(buf1, "SYSERR: checking for crash file %s (3)", fname);
@@ -177,12 +196,26 @@ int Crash_delete_crashfile(struct char_d
     }
     return 0;
   }
-  if (!feof(fl))
-    fread(&rent, sizeof(struct rent_info), 1, fl);
-  fclose(fl);
 
-  if (rent.rentcode == RENT_CRASH)
-    Crash_delete_file(GET_NAME(ch));
+  if(!xap_objs) {
+    if (!feof(fl))
+      fread(&rent, sizeof(struct rent_info), 1, fl);
+    fclose(fl);
+  } else {
+    if (!feof(fl))
+      get_line(fl,line);
+    sscanf(line,"%d %d %d %d %d %d",&rentcode,&timed,&netcost,&gold,
+        &account,&nitems);
+    fclose(fl);
+  }
+
+  if(!xap_objs) {
+    if (rent.rentcode == RENT_CRASH)
+      Crash_delete_file(GET_NAME(ch));
+  } else {
+    if (rentcode == RENT_CRASH)
+      Crash_delete_file(GET_NAME(ch));
+  }
 
   return 1;
 }
@@ -193,9 +226,16 @@ int Crash_clean_file(char *name)
   char fname[MAX_STRING_LENGTH], filetype[20];
   struct rent_info rent;
   FILE *fl;
+  int rentcode,timed,netcost,gold,account,nitems;
+  char line[MAX_STRING_LENGTH];
 
-  if (!get_filename(name, fname, CRASH_FILE))
-    return 0;
+  if(!xap_objs) {
+    if (!get_filename(name, fname, CRASH_FILE))
+      return 0;
+  } else {
+    if (!get_filename(name, fname, NEW_OBJ_FILES))
+      return 0;
+  }
   /*
    * open for write so that permission problems will be flagged now, at boot
    * time.
@@ -207,15 +247,28 @@ int Crash_clean_file(char *name)
     }
     return 0;
   }
-  if (!feof(fl))
-    fread(&rent, sizeof(struct rent_info), 1, fl);
-  fclose(fl);
+  if(!xap_objs) {
+    if (!feof(fl))
+      fread(&rent, sizeof(struct rent_info), 1, fl);
+    fclose(fl);
+  } else {
+    if (!feof(fl))
+      get_line(fl,line);
+      sscanf(line, "%d %d %d %d %d %d",&rentcode,&timed,&netcost,
+        &gold,&account,&nitems);
+    fclose(fl);
+  }
+
+  if(!xap_objs) {
+    rentcode=rent.rentcode;
+    timed=rent.time;
+  }
 
-  if ((rent.rentcode == RENT_CRASH) ||
-      (rent.rentcode == RENT_FORCED) || (rent.rentcode == RENT_TIMEDOUT)) {
-    if (rent.time < time(0) - (crash_file_timeout * SECS_PER_REAL_DAY)) {
+  if ((rentcode == RENT_CRASH) ||
+      (rentcode == RENT_FORCED) || (rentcode == RENT_TIMEDOUT)) {
+    if (timed < time(0) - (crash_file_timeout * SECS_PER_REAL_DAY)) {
       Crash_delete_file(name);
-      switch (rent.rentcode) {
+      switch (rentcode) {
       case RENT_CRASH:
 	strcpy(filetype, "crash");
 	break;
@@ -233,8 +286,8 @@ int Crash_clean_file(char *name)
       return 1;
     }
     /* Must retrieve rented items w/in 30 days */
-  } else if (rent.rentcode == RENT_RENTED)
-    if (rent.time < time(0) - (rent_file_timeout * SECS_PER_REAL_DAY)) {
+  } else if (rentcode == RENT_RENTED)
+    if (timed < time(0) - (rent_file_timeout * SECS_PER_REAL_DAY)) {
       Crash_delete_file(name);
       log("    Deleting %s's rent file.", name);
       return 1;
@@ -262,19 +315,41 @@ void Crash_listrent(struct char_data * c
   struct obj_file_elem object;
   struct obj_data *obj;
   struct rent_info rent;
-  int offset = 0;
+  int rentcode,timed,netcost,gold,account,nitems;
+  int offset = 0,t[10],nr;
+  char line[MAX_STRING_LENGTH];
+  char *sdesc;
+
+  if(!xap_objs) {
+    if (!get_filename(name, fname, CRASH_FILE))
+      return;
+  } else {
+    if (!get_filename(name, fname, NEW_OBJ_FILES))
+      return;
+  }
 
-  if (!get_filename(name, fname, CRASH_FILE))
-    return;
   if (!(fl = fopen(fname, "rb"))) {
     sprintf(buf, "%s has no rent file.\r\n", name);
     send_to_char(buf, ch);
     return;
   }
   sprintf(buf, "%s\r\n", fname);
-  if (!feof(fl))
-    fread(&rent, sizeof(struct rent_info), 1, fl);
-  switch (rent.rentcode) {
+
+  if (!feof(fl)) {
+    if(!xap_objs) {
+      fread(&rent, sizeof(struct rent_info), 1, fl);
+    } else {
+      get_line(fl,line);
+      sscanf(line,"%d %d %d %d %d %d",&rentcode,&timed,&netcost,
+                &gold,&account,&nitems);
+    }
+  }
+
+  if(!xap_objs) {
+    rentcode=rent.rentcode;
+  }
+
+  switch (rentcode) {
   case RENT_RENTED:
     strcat(buf, "Rent\r\n");
     break;
@@ -292,26 +367,60 @@ void Crash_listrent(struct char_data * c
     strcat(buf, "Undef\r\n");
     break;
   }
-  while (!feof(fl)) {
-    fread(&object, sizeof(struct obj_file_elem), 1, fl);
-    if (ferror(fl)) {
-      fclose(fl);
-      return;
+
+  if(!xap_objs) {
+    while (!feof(fl)) {
+      fread(&object, sizeof(struct obj_file_elem), 1, fl);
+      if (ferror(fl)) {
+        fclose(fl);
+        return;
+      }
+      if (!feof(fl))
+        if (real_object(object.item_number) > -1) {
+          obj = read_object(object.item_number, VIRTUAL);
+          offset += sprintf(buf + offset, " [%5d] (%5dau) %-20s\r\n",
+                  object.item_number, GET_OBJ_RENT(obj),
+                  obj->short_description);
+          extract_obj(obj);
+          if (offset > MAX_STRING_LENGTH - 80) {
+            strcat(buf, "** Excessive rent listing. **\r\n");
+            break;
+          }
+        }
     }
-    if (!feof(fl))
-      if (real_object(object.item_number) > -1) {
-	obj = read_object(object.item_number, VIRTUAL);
-        sprintf(buf, "%s [%5d] (%5dau) <%2d> %-20s\r\n", buf,
-              object.item_number, GET_OBJ_RENT(obj),
-              object.locate, obj->short_description);
-	extract_obj(obj);
-	if (offset > MAX_STRING_LENGTH - 80) {
-	  strcat(buf, "** Excessive rent listing. **\r\n");
-	  break;
-	}
+  } else {      /* else we have xap objs */
+    while(!feof(fl)) {
+      get_line(fl,line);
+      if(*line == '#') { /* swell - its an item */
+        sscanf(line,"#%d",&nr);
+        if(nr != NOTHING) {  /* then we can dispense with it easily */
+          obj=read_object(nr,VIRTUAL);
+          sprintf(buf,"%s[%5d] (%5dau) %-20s\r\n",buf,
+                  nr, GET_OBJ_RENT(obj),
+                  obj->short_description);
+          free_obj(obj);
+        } else { /* its nothing, and a unique item. bleh. partial parse.*/
+          get_line(fl,line);    /* this is obj+val */
+          get_line(fl,line);    /* this is XAP */
+          sprintf(buf2,"xap objects in listrent");
+          fread_string(fl,buf2);  /* screw the name */
+          sdesc=fread_string(fl,buf2);
+          fread_string(fl,buf2); /* screw the long desc */
+          fread_string(fl,buf2); /* screw the action desc. */
+          get_line(fl,line);    /* this is an important line.rent..*/
+          sscanf(line,"%d %d %d %d %d",t,t+1,t+2,t+3,t+4);
+          /* great we got it all, make the buf */
+          sprintf(buf,"%s[%5d] (%5dau) %-20s\r\n",buf,
+                  nr, t[4],sdesc);
+        /* best of all, we don't care if there's descs, or stuff..*/
+        /* since we're only doing operations on lines beginning in # */
+        /* i suppose you don't want to make exdescs start with # .:) */
+        }
       }
+    }
   }
-  send_to_char(buf, ch);
+        /* why would you have send_to_char here anyway?!?! */
+  page_string(ch->desc,buf,0);
   fclose(fl);
 }
 
@@ -319,9 +428,17 @@ void Crash_listrent(struct char_data * c
 
 int Crash_write_rentcode(struct char_data * ch, FILE * fl, struct rent_info * rent)
 {
-  if (fwrite(rent, sizeof(struct rent_info), 1, fl) < 1) {
-    perror("SYSERR: writing rent code");
-    return 0;
+  if(!xap_objs) {
+    if (fwrite(rent, sizeof(struct rent_info), 1, fl) < 1) {
+      perror("SYSERR: writing rent code");
+      return 0;
+    }
+  } else {
+    if(fprintf(fl,"%d %d %d %d %d %d\r\n",rent->rentcode, rent->time,
+        rent->net_cost_per_diem,rent->gold,rent->account,rent->nitems) < 1) {
+      perror("Syserr: Writing rent code");
+      return 0;
+    }
   }
   return 1;
 }
@@ -439,6 +556,10 @@ int Crash_load(struct char_data * ch)
   int locate, j;
   struct obj_data *obj1;
   struct obj_data *cont_row[MAX_BAG_ROW];
+  
+  if(xap_objs) {
+    return (Crash_load_xapobjs(ch));
+  }
 
   if (!get_filename(GET_NAME(ch), fname, CRASH_FILE))
     return 1;
@@ -675,9 +796,15 @@ int Crash_is_unrentable(struct obj_data 
   if (!obj)
     return 0;
 
-  if (IS_OBJ_STAT(obj, ITEM_NORENT) || GET_OBJ_RENT(obj) < 0 ||
+  if(!xap_objs) {
+    if (IS_OBJ_STAT(obj, ITEM_NORENT) || GET_OBJ_RENT(obj) < 0 ||
       GET_OBJ_RNUM(obj) <= NOTHING || GET_OBJ_TYPE(obj) == ITEM_KEY)
-    return 1;
+      return 1;
+  } else {
+    if (IS_OBJ_STAT(obj, ITEM_NORENT) || GET_OBJ_RENT(obj) < 0 ||
+        GET_OBJ_TYPE(obj) == ITEM_KEY)
+      return 1;
+  }
 
   return 0;
 }
@@ -747,17 +874,29 @@ void Crash_crashsave(struct char_data * 
   if (IS_NPC(ch))
     return;
 
-  if (!get_filename(GET_NAME(ch), buf, CRASH_FILE))
-    return;
+  if(!xap_objs) {
+    if (!get_filename(GET_NAME(ch), buf, CRASH_FILE))
+      return;
+  } else {
+    if (!get_filename(GET_NAME(ch), buf, NEW_OBJ_FILES))
+      return;
+  }
+
   if (!(fp = fopen(buf, "wb")))
     return;
 
   rent.rentcode = RENT_CRASH;
   rent.time = time(0);
-  if (!Crash_write_rentcode(ch, fp, &rent)) {
-    fclose(fp);
-    return;
+  if(!xap_objs) {
+    if (!Crash_write_rentcode(ch, fp, &rent)) {
+      fclose(fp);
+      return;
+    }
+  } else {
+    fprintf(fp,"%d %d %d %d %d %d\r\n",rent.rentcode,rent.time,
+    rent.net_cost_per_diem,rent.gold,rent.account,rent.nitems);
   }
+
   for (j = 0; j < NUM_WEARS; j++)
     if (GET_EQ(ch,j)) {
       if (!Crash_save(GET_EQ(ch,j), fp, j+1)) {
@@ -783,14 +922,20 @@ void Crash_idlesave(struct char_data * c
   char buf[MAX_INPUT_LENGTH];
   struct rent_info rent;
   int j;
-  int cost, cost_eq;
+  int cost;
   FILE *fp;
 
   if (IS_NPC(ch))
     return;
 
-  if (!get_filename(GET_NAME(ch), buf, CRASH_FILE))
-    return;
+  if(!xap_objs) {
+    if (!get_filename(GET_NAME(ch), buf, CRASH_FILE))
+      return;
+  } else {
+    if (!get_filename(GET_NAME(ch), buf, NEW_OBJ_FILES))
+      return;
+  }
+
   if (!(fp = fopen(buf, "wb")))
     return;
 
@@ -821,11 +966,16 @@ void Crash_idlesave(struct char_data * c
   rent.time = time(0);
   rent.gold = GET_GOLD(ch);
   rent.account = GET_BANK_GOLD(ch);
-  if (!Crash_write_rentcode(ch, fp, &rent)) {
-    fclose(fp);
-    return;
-  }
 
+  if(!xap_objs) {
+    if (!Crash_write_rentcode(ch, fp, &rent)) {
+      fclose(fp);
+      return;
+    }
+  } else {
+    fprintf(fp,"%d %d %d %d %d %d\r\n",rent.rentcode,rent.time,
+        rent.net_cost_per_diem,rent.gold,rent.account,rent.nitems);
+  }
   for (j = 0; j < NUM_WEARS; j++)
     if (GET_EQ(ch,j)) {
       if (!Crash_save(GET_EQ(ch,j), fp, j+1)) {
@@ -855,8 +1005,14 @@ void Crash_rentsave(struct char_data * c
   if (IS_NPC(ch))
     return;
 
-  if (!get_filename(GET_NAME(ch), buf, CRASH_FILE))
-    return;
+  if(!xap_objs) {
+    if (!get_filename(GET_NAME(ch), buf, CRASH_FILE))
+      return;
+  } else {
+    if (!get_filename(GET_NAME(ch), buf, NEW_OBJ_FILES))
+      return;
+  }
+
   if (!(fp = fopen(buf, "wb")))
     return;
 
@@ -869,10 +1025,17 @@ void Crash_rentsave(struct char_data * c
   rent.time = time(0);
   rent.gold = GET_GOLD(ch);
   rent.account = GET_BANK_GOLD(ch);
-  if (!Crash_write_rentcode(ch, fp, &rent)) {
-    fclose(fp);
-    return;
+
+  if(!xap_objs) {
+    if (!Crash_write_rentcode(ch, fp, &rent)) {
+      fclose(fp);
+      return;
+    }
+  } else {
+    fprintf(fp,"%d %d %d %d %d %d\r\n",rent.rentcode,rent.time,
+        rent.net_cost_per_diem,rent.gold,rent.account,rent.nitems);
   }
+
   for (j = 0; j < NUM_WEARS; j++)
     if (GET_EQ(ch,j)) {
       if (!Crash_save(GET_EQ(ch,j), fp, j+1)) {
@@ -902,8 +1065,14 @@ void Crash_cryosave(struct char_data * c
   if (IS_NPC(ch))
     return;
 
-  if (!get_filename(GET_NAME(ch), buf, CRASH_FILE))
-    return;
+  if(!xap_objs) {
+    if (!get_filename(GET_NAME(ch), buf, CRASH_FILE))
+      return;
+  } else {
+    if (!get_filename(GET_NAME(ch), buf, NEW_OBJ_FILES))
+      return;
+  }
+
   if (!(fp = fopen(buf, "wb")))
     return;
 
@@ -918,9 +1087,15 @@ void Crash_cryosave(struct char_data * c
   rent.gold = GET_GOLD(ch);
   rent.account = GET_BANK_GOLD(ch);
   rent.net_cost_per_diem = 0;
-  if (!Crash_write_rentcode(ch, fp, &rent)) {
-    fclose(fp);
-    return;
+  if(!xap_objs) {
+    if (!Crash_write_rentcode(ch, fp, &rent)) {
+      fclose(fp);
+      return;
+    }
+  } else {
+    fprintf(fp,"%d %d %d %d %d %d\r\n",rent.rentcode,rent.time,
+        rent.net_cost_per_diem,rent.gold,rent.account,rent.nitems);
+
   }
   for (j = 0; j < NUM_WEARS; j++)
     if (GET_EQ(ch,j)) {
@@ -1154,4 +1329,302 @@ void Crash_save_all(void)
       }
     }
   }
+}
+
+int Crash_load_xapobjs(struct char_data *ch) {
+  FILE *fl;
+  char fname[MAX_STRING_LENGTH];
+  char line[256];
+  int t[10],danger,zwei=0,num_of_days;
+  int orig_rent_code;
+  struct obj_data *temp;
+  int locate=0, j, nr,k,cost,num_objs=0;
+  struct obj_data *obj1;
+  struct obj_data *cont_row[MAX_BAG_ROW];
+  struct extra_descr_data *new_descr;
+  int rentcode,timed,netcost,gold,account,nitems;
+
+  if (!get_filename(GET_NAME(ch), fname, NEW_OBJ_FILES))
+    return 1;
+
+  if (!(fl = fopen(fname, "r+b"))) {
+    if (errno != ENOENT) {	/* if it fails, NOT because of no file */
+      sprintf(buf1, "SYSERR: READING OBJECT FILE %s (5)", fname);
+      perror(buf1);
+      send_to_char("\r\n********************* NOTICE *********************\r\n"
+		   "There was a problem loading your objects from disk.\r\n"
+		   "Contact a God for assistance.\r\n", ch);
+    }
+    sprintf(buf, "%s entering game with no equipment.", GET_NAME(ch));
+    mudlog(buf, NRM, MAX(LVL_IMMORT, GET_INVIS_LEV(ch)), TRUE);
+    return 1;
+  }
+  if (!feof(fl))
+    get_line(fl,line);
+
+  sscanf(line,"%d %d %d %d %d %d",&rentcode, &timed,
+        &netcost,&gold,&account,&nitems);
+
+  if (rentcode == RENT_RENTED || rentcode == RENT_TIMEDOUT) {
+    num_of_days = (float) (time(0) - timed) / SECS_PER_REAL_DAY;
+    cost = (int) (netcost * num_of_days);
+    if (cost > GET_GOLD(ch) + GET_BANK_GOLD(ch)) {
+      fclose(fl);
+      sprintf(buf, "%s entering game, rented equipment lost (no $).",
+	      GET_NAME(ch));
+      mudlog(buf, BRF, MAX(LVL_IMMORT, GET_INVIS_LEV(ch)), TRUE);
+      Crash_crashsave(ch);
+      return 2;
+    } else {
+      GET_BANK_GOLD(ch) -= MAX(cost - GET_GOLD(ch), 0);
+      GET_GOLD(ch) = MAX(GET_GOLD(ch) - cost, 0);
+      save_char(ch, NOWHERE);
+    }
+  }
+  switch (orig_rent_code = rentcode) {
+  case RENT_RENTED:
+    sprintf(buf, "%s un-renting and entering game.", GET_NAME(ch));
+    mudlog(buf, NRM, MAX(LVL_IMMORT, GET_INVIS_LEV(ch)), TRUE);
+    break;
+  case RENT_CRASH:
+    sprintf(buf, "%s retrieving crash-saved items and entering game.", GET_NAME(ch));
+    mudlog(buf, NRM, MAX(LVL_IMMORT, GET_INVIS_LEV(ch)), TRUE);
+    break;
+  case RENT_CRYO:
+    sprintf(buf, "%s un-cryo'ing and entering game.", GET_NAME(ch));
+    mudlog(buf, NRM, MAX(LVL_IMMORT, GET_INVIS_LEV(ch)), TRUE);
+    break;
+  case RENT_FORCED:
+  case RENT_TIMEDOUT:
+    sprintf(buf, "%s retrieving force-saved items and entering game.", GET_NAME(ch));
+    mudlog(buf, NRM, MAX(LVL_IMMORT, GET_INVIS_LEV(ch)), TRUE);
+    break;
+  default:
+    sprintf(buf, "WARNING: %s entering game with undefined rent code.", GET_NAME(ch));
+    mudlog(buf, BRF, MAX(LVL_IMMORT, GET_INVIS_LEV(ch)), TRUE);
+    break;
+  }
+
+  for (j = 0;j < MAX_BAG_ROW;j++)
+    cont_row[j] = NULL; /* empty all cont lists (you never know ...) */
+
+  if(!feof(fl))
+    get_line(fl, line);
+  while (!feof(fl)) {
+        temp=NULL;
+        /* first, we get the number. Not too hard. */
+    if(*line == '#') {
+      if (sscanf(line, "#%d", &nr) != 1) {
+        continue;
+      }
+      /* we have the number, check it, load obj. */
+      if (nr == NOTHING) {   /* then it is unique */
+        temp = create_obj();
+        temp->item_number=NOTHING;
+      } else if (nr < 0) {
+        continue;
+      } else {
+        temp=read_object(nr,VIRTUAL);
+        if (nr >= 999999 || !temp) {
+          continue;
+        }
+      }
+
+      get_line(fl,line);
+      sscanf(line,"%d %d %d %d %d %d",t, t + 1, t+2, t + 3, t + 4,t+5);
+      locate=t[0];
+      GET_OBJ_VAL(temp,0) = t[1];
+      GET_OBJ_VAL(temp,1) = t[2];
+      GET_OBJ_VAL(temp,2) = t[3];
+      GET_OBJ_VAL(temp,3) = t[4];
+      GET_OBJ_EXTRA(temp) = t[5];
+
+      get_line(fl,line);
+       /* read line check for xap. */
+      if(!strcasecmp("XAP",line)) {  /* then this is a Xap Obj, requires
+                                       special care */
+        if ((temp->name = fread_string(fl, buf2)) == NULL) {
+          temp->name = "undefined";
+        }
+
+        if ((temp->short_description = fread_string(fl, buf2)) == NULL) {
+          temp->short_description = "undefined";
+        }
+
+        if ((temp->description = fread_string(fl, buf2)) == NULL) {
+          temp->description = "undefined";
+        }
+
+        if ((temp->action_description = fread_string(fl, buf2)) == NULL) {
+          temp->action_description=0;
+        }
+        if (!get_line(fl, line) ||
+           (sscanf(line, "%d %d %d %d %d", t,t+1,t+2,t+3,t+4) != 5)) {
+          fprintf(stderr, "Format error in first numeric line (expecting _x_ args)");
+          return 0;
+        }
+        temp->obj_flags.type_flag = t[0];
+        temp->obj_flags.wear_flags = t[1];
+        temp->obj_flags.weight = t[2];
+        temp->obj_flags.cost = t[3];
+        temp->obj_flags.cost_per_day = t[4];
+
+        /* buf2 is error codes pretty much */
+        strcat(buf2, ", after numeric constants (expecting E/#xxx)");
+
+        /* we're clearing these for good luck */
+
+        for (j = 0; j < MAX_OBJ_AFFECT; j++) {
+          temp->affected[j].location = APPLY_NONE;
+          temp->affected[j].modifier = 0;
+        }
+
+        get_line(fl,line);
+        for (k=j=zwei=0;!zwei && !feof(fl);) {
+          switch (*line) {
+            case 'E':
+              CREATE(new_descr, struct extra_descr_data, 1);
+              new_descr->keyword = fread_string(fl, buf2);
+              new_descr->description = fread_string(fl, buf2);
+              new_descr->next = temp->ex_description;
+              temp->ex_description = new_descr;
+              get_line(fl,line);
+              break;
+            case 'A':
+               log("here");
+              if (j >= MAX_OBJ_AFFECT) {
+                log("Too many object affectations in loading rent file");
+                danger=1;
+              }
+              get_line(fl, line);
+              sscanf(line, "%d %d", t, t + 1);
+
+              temp->affected[j].location = t[0];
+              temp->affected[j].modifier = t[1];  
+              j++;
+              get_line(fl,line);
+              break;
+
+            case '$':
+            case '#':
+              zwei=1;
+              break;
+            default:
+              zwei=1;
+              break;
+          }
+        }      /* exit our for loop */
+      }   /* exit our xap loop */
+      if(temp != NULL) {
+        num_objs++;
+        auto_equip(ch, temp, locate);
+      } else {
+        continue;
+      }
+ /* 
+   what to do with a new loaded item:
+
+   if there's a list with <locate> less than 1 below this:
+     (equipped items are assumed to have <locate>==0 here) then its
+     container has disappeared from the file   *gasp*
+      -> put all the list back to ch's inventory
+   if there's a list of contents with <locate> 1 below this:
+     check if it's a container
+     - if so: get it from ch, fill it, and give it back to ch (this way the
+         container has its correct weight before modifying ch)
+     - if not: the container is missing -> put all the list to ch's inventory
+
+   for items with negative <locate>:
+     if there's already a list of contents with the same <locate> put obj to it
+     if not, start a new list
+
+ Confused? Well maybe you can think of some better text to be put here ...
+
+ since <locate> for contents is < 0 the list indices are switched to
+ non-negative
+ */
+
+        if (locate > 0) { /* item equipped */
+          for (j = MAX_BAG_ROW-1;j > 0;j--)
+            if (cont_row[j]) { /* no container -> back to ch's inventory */
+              for (;cont_row[j];cont_row[j] = obj1) {
+                obj1 = cont_row[j]->next_content;
+                obj_to_char(cont_row[j], ch);
+              }
+              cont_row[j] = NULL;
+            }
+          if (cont_row[0]) { /* content list existing */
+            if (GET_OBJ_TYPE(temp) == ITEM_CONTAINER) {
+              /* rem item ; fill ; equip again */
+              temp = unequip_char(ch, locate-1);
+              temp->contains = NULL; /* should be empty - but who knows */
+              for (;cont_row[0];cont_row[0] = obj1) {
+                obj1 = cont_row[0]->next_content;
+                obj_to_obj(cont_row[0], temp);
+              }
+              equip_char(ch, temp, locate-1);
+            } else { /* object isn't container -> empty content list */
+              for (;cont_row[0];cont_row[0] = obj1) {
+                obj1 = cont_row[0]->next_content;
+                obj_to_char(cont_row[0], ch);
+              }
+              cont_row[0] = NULL;
+            }
+          }
+        } else { /* locate <= 0 */
+          for (j = MAX_BAG_ROW-1;j > -locate;j--)
+            if (cont_row[j]) { /* no container -> back to ch's inventory */
+              for (;cont_row[j];cont_row[j] = obj1) {
+                obj1 = cont_row[j]->next_content;
+                obj_to_char(cont_row[j], ch);
+              } 
+              cont_row[j] = NULL;
+            }
+
+          if (j == -locate && cont_row[j]) { /* content list existing */
+            if (GET_OBJ_TYPE(temp) == ITEM_CONTAINER) {
+              /* take item ; fill ; give to char again */
+              obj_from_char(temp);
+              temp->contains = NULL;
+              for (;cont_row[j];cont_row[j] = obj1) {
+                obj1 = cont_row[j]->next_content;
+                obj_to_obj(cont_row[j], temp);
+              }
+              obj_to_char(temp, ch); /* add to inv first ... */
+            } else { /* object isn't container -> empty content list */
+              for (;cont_row[j];cont_row[j] = obj1) {
+                obj1 = cont_row[j]->next_content;
+                obj_to_char(cont_row[j], ch);
+              }
+              cont_row[j] = NULL;
+            }
+          }
+
+          if (locate < 0 && locate >= -MAX_BAG_ROW) {
+               /* let obj be part of content list
+                  but put it at the list's end thus having the items
+                  in the same order as before renting */
+            obj_from_char(temp);
+            if ((obj1 = cont_row[-locate-1])) {
+              while (obj1->next_content)
+                obj1 = obj1->next_content;
+              obj1->next_content = temp;
+            } else
+              cont_row[-locate-1] = temp;
+          }
+        } /* locate less than zero */
+      }
+    }
+
+  /* Little hoarding check. -gg 3/1/98 */
+  sprintf(fname, "%s (level %d) has %d objects (max %d).",
+	GET_NAME(ch), GET_LEVEL(ch), num_objs, max_obj_save);
+  mudlog(fname, NRM, LVL_GOD, TRUE);
+
+  fclose(fl);
+
+  if ((orig_rent_code == RENT_RENTED) || (orig_rent_code == RENT_CRYO))
+    return 0;
+  else
+    return 1;
 }
diff -uprN -x *.o ../src/spells.c ./spells.c
--- ../src/spells.c	Thu Jun 18 14:11:21 1998
+++ ./spells.c	Sat Jan  2 06:41:13 1999
@@ -370,7 +370,7 @@ ASPELL(spell_identify)
 
 ASPELL(spell_enchant_weapon)
 {
-  int i;
+  int i,flag;
 
   if (ch == NULL || obj == NULL)
     return;
@@ -378,17 +378,19 @@ ASPELL(spell_enchant_weapon)
   if ((GET_OBJ_TYPE(obj) == ITEM_WEAPON) &&
       !OBJ_FLAGGED(obj, ITEM_MAGIC)) {
 
-    for (i = 0; i < MAX_OBJ_AFFECT; i++)
-      if (obj->affected[i].location != APPLY_NONE)
-	return;
+    for (i = flag = 0; i+1 < MAX_OBJ_AFFECT && !flag; i++) {
+      if (obj->affected[i].location == APPLY_NONE)
+        flag=1;
+    }
 
     SET_BIT(GET_OBJ_EXTRA(obj), ITEM_MAGIC);
+    SET_BIT(GET_OBJ_EXTRA(obj), ITEM_UNIQUE_SAVE);
 
-    obj->affected[0].location = APPLY_HITROLL;
-    obj->affected[0].modifier = 1 + (level >= 18);
+    obj->affected[i].location = APPLY_HITROLL;
+    obj->affected[i].modifier = 1 + (level >= 18);
 
-    obj->affected[1].location = APPLY_DAMROLL;
-    obj->affected[1].modifier = 1 + (level >= 20);
+    obj->affected[i+1].location = APPLY_DAMROLL;
+    obj->affected[i+1].modifier = 1 + (level >= 20);
 
     if (IS_GOOD(ch)) {
       SET_BIT(GET_OBJ_EXTRA(obj), ITEM_ANTI_EVIL);
diff -uprN -x *.o ../src/structs.h ./structs.h
--- ../src/structs.h	Sat Jan  2 03:47:39 1999
+++ ./structs.h	Sat Jan  2 06:41:47 1999
@@ -321,6 +321,7 @@
 #define ITEM_ANTI_THIEF	   (1 << 14)	/* Not usable by thieves	*/
 #define ITEM_ANTI_WARRIOR  (1 << 15)	/* Not usable by warriors	*/
 #define ITEM_NOSELL	   (1 << 16)	/* Shopkeepers won't touch it	*/
+#define ITEM_UNIQUE_SAVE   (1 << 17)	/* unique object save		*/
 
 
 /* Modifier constants used with obj affects ('A' fields) */
diff -uprN -x *.o ../src/utils.c ./utils.c
--- ../src/utils.c	Sat Jun 20 23:08:44 1998
+++ ./utils.c	Sat Jan  2 06:42:08 1999
@@ -443,6 +443,10 @@ int get_filename(char *orig_name, char *
     prefix = LIB_PLRTEXT;
     suffix = SUF_TEXT;
     break;
+  case NEW_OBJ_FILES:
+    prefix = LIB_PLROBJS;
+    suffix = "new";
+    break;
   default:
     return 0;
   }
diff -uprN -x *.o ../src/utils.h ./utils.h
--- ../src/utils.h	Sat Jun 20 23:19:07 1998
+++ ./utils.h	Sat Jan  2 06:42:17 1999
@@ -90,6 +90,7 @@ void	update_pos(struct char_data *victim
 /* get_filename() */
 #define CRASH_FILE	0
 #define ETEXT_FILE	1
+#define NEW_OBJ_FILES  2
 
 /* breadth-first searching */
 #define BFS_ERROR		-1
