OSDN Git Service

熟練度に関する数値が直接指定されていた部分を記号定数化.
[hengband/hengband.git] / src / load.c
index 4cfc7b9..24e65de 100644 (file)
@@ -1,5 +1,13 @@
 /* File: load.c */
 
+/*
+ * Copyright (c) 1997 Ben Harrison, and others
+ *
+ * This software may be copied and distributed for educational, research,
+ * and not for profit purposes provided that this copyright and statement
+ * are included in all such copies.  Other copyrights may also apply.
+ */
+
 /* Purpose: support for loading savefiles -BEN- */
 
 #include "angband.h"
@@ -232,7 +240,7 @@ static void strip_bytes(int n)
 #define OLD_MAX_MANE 22
 
 /*
- * Read an object
+ * Read an object (Old method)
  *
  * This function attempts to "repair" old savefiles, and to extract
  * the most up to date values for various object fields.
@@ -248,7 +256,7 @@ static void strip_bytes(int n)
  * a complete hack, items which are inscribed with "uncursed" will be
  * "uncursed" when imported from pre-2.7.9 savefiles.
  */
-static void rd_item(object_type *o_ptr)
+static void rd_item_old(object_type *o_ptr)
 {
        char buf[128];
 
@@ -300,7 +308,13 @@ static void rd_item(object_type *o_ptr)
        rd_u32b(&o_ptr->art_flags[1]);
        rd_u32b(&o_ptr->art_flags[2]);
        if (h_older_than(1, 3, 0, 0)) o_ptr->art_flags[3] = 0L;
-        else rd_u32b(&o_ptr->art_flags[3]);
+       else rd_u32b(&o_ptr->art_flags[3]);
+
+       if (h_older_than(1, 3, 0, 0))
+       {
+               if (o_ptr->name2 == EGO_TELEPATHY)
+                       add_flag(o_ptr->art_flags, TR_TELEPATHY);
+       }
 
        if (z_older_than(11, 0, 11))
        {
@@ -414,11 +428,11 @@ static void rd_item(object_type *o_ptr)
        else
        {
                rd_byte(&o_ptr->xtra3);
-                if (h_older_than(1, 3, 0, 1))
-                {
-                        if (o_ptr->tval > TV_CAPTURE && o_ptr->xtra3 >= 1+96)
-                                o_ptr->xtra3 += -96 + MIN_SPECIAL_ESSENCE;
-                }
+               if (h_older_than(1, 3, 0, 1))
+               {
+                       if (o_ptr->tval > TV_CAPTURE && o_ptr->xtra3 >= 1+96)
+                               o_ptr->xtra3 += -96 + MIN_SPECIAL_ESSENCE;
+               }
 
                rd_s16b(&o_ptr->xtra4);
                rd_s16b(&o_ptr->xtra5);
@@ -430,7 +444,7 @@ static void rd_item(object_type *o_ptr)
                o_ptr->pval = 0;
        }
 
-        rd_byte(&o_ptr->feeling);
+       rd_byte(&o_ptr->feeling);
 
        /* Inscription */
        rd_string(buf, sizeof(buf));
@@ -490,12 +504,132 @@ static void rd_item(object_type *o_ptr)
 }
 
 
+/*
+ * Read an object (New method)
+ */
+static void rd_item(object_type *o_ptr)
+{
+       object_kind *k_ptr;
+       u32b flags;
+       char buf[128];
+
+       if (h_older_than(1, 5, 0, 0))
+       {
+               rd_item_old(o_ptr);
+               return;
+       }
+
+       /*** Item save flags ***/
+       rd_u32b(&flags);
+
+       /*** Read un-obvious elements ***/
+       /* Kind */
+       rd_s16b(&o_ptr->k_idx);
+
+       /* Location */
+       rd_byte(&o_ptr->iy);
+       rd_byte(&o_ptr->ix);
+
+       /* Type/Subtype */
+       k_ptr = &k_info[o_ptr->k_idx];
+       o_ptr->tval = k_ptr->tval;
+       o_ptr->sval = k_ptr->sval;
+
+       /* Special pval */
+       if (flags & SAVE_ITEM_PVAL) rd_s16b(&o_ptr->pval);
+       else o_ptr->pval = 0;
+
+       if (flags & SAVE_ITEM_DISCOUNT) rd_byte(&o_ptr->discount);
+       else o_ptr->discount = 0;
+       if (flags & SAVE_ITEM_NUMBER) rd_byte(&o_ptr->number);
+       else o_ptr->number = 1;
+
+       rd_s16b(&o_ptr->weight);
+
+       if (flags & SAVE_ITEM_NAME1) rd_byte(&o_ptr->name1);
+       else o_ptr->name1 = 0;
+       if (flags & SAVE_ITEM_NAME2) rd_byte(&o_ptr->name2);
+       else o_ptr->name2 = 0;
+       if (flags & SAVE_ITEM_TIMEOUT) rd_s16b(&o_ptr->timeout);
+       else o_ptr->timeout = 0;
+
+       if (flags & SAVE_ITEM_TO_H) rd_s16b(&o_ptr->to_h);
+       else o_ptr->to_h = 0;
+       if (flags & SAVE_ITEM_TO_D) rd_s16b(&o_ptr->to_d);
+       else o_ptr->to_d = 0;
+       if (flags & SAVE_ITEM_TO_A) rd_s16b(&o_ptr->to_a);
+       else o_ptr->to_a = 0;
+
+       if (flags & SAVE_ITEM_AC) rd_s16b(&o_ptr->ac);
+       else o_ptr->ac = 0;
+
+       if (flags & SAVE_ITEM_DD) rd_byte(&o_ptr->dd);
+       else o_ptr->dd = 0;
+       if (flags & SAVE_ITEM_DS) rd_byte(&o_ptr->ds);
+       else o_ptr->ds = 0;
+
+       if (flags & SAVE_ITEM_IDENT) rd_byte(&o_ptr->ident);
+       else o_ptr->ident = 0;
+
+       if (flags & SAVE_ITEM_MARKED) rd_byte(&o_ptr->marked);
+       else o_ptr->marked = 0;
+
+       /* Object flags */
+       if (flags & SAVE_ITEM_ART_FLAGS0) rd_u32b(&o_ptr->art_flags[0]);
+       else o_ptr->art_flags[0] = 0;
+       if (flags & SAVE_ITEM_ART_FLAGS1) rd_u32b(&o_ptr->art_flags[1]);
+       else o_ptr->art_flags[1] = 0;
+       if (flags & SAVE_ITEM_ART_FLAGS2) rd_u32b(&o_ptr->art_flags[2]);
+       else o_ptr->art_flags[2] = 0;
+       if (flags & SAVE_ITEM_ART_FLAGS3) rd_u32b(&o_ptr->art_flags[3]);
+       else o_ptr->art_flags[3] = 0;
+
+       if (flags & SAVE_ITEM_CURSE_FLAGS) rd_u32b(&o_ptr->curse_flags);
+       else o_ptr->curse_flags = 0;
+
+       /* Monster holding object */
+       if (flags & SAVE_ITEM_HELD_M_IDX) rd_s16b(&o_ptr->held_m_idx);
+       else o_ptr->held_m_idx = 0;
+
+       /* Special powers */
+       if (flags & SAVE_ITEM_XTRA1) rd_byte(&o_ptr->xtra1);
+       else o_ptr->xtra1 = 0;
+       if (flags & SAVE_ITEM_XTRA2) rd_byte(&o_ptr->xtra2);
+       else o_ptr->xtra2 = 0;
+
+       if (flags & SAVE_ITEM_XTRA3) rd_byte(&o_ptr->xtra3);
+       else o_ptr->xtra3 = 0;
+
+       if (flags & SAVE_ITEM_XTRA4) rd_s16b(&o_ptr->xtra4);
+       else o_ptr->xtra4 = 0;
+       if (flags & SAVE_ITEM_XTRA5) rd_s16b(&o_ptr->xtra5);
+       else o_ptr->xtra5 = 0;
+
+       if (flags & SAVE_ITEM_FEELING) rd_byte(&o_ptr->feeling);
+       else o_ptr->feeling = 0;
+
+       if (flags & SAVE_ITEM_INSCRIPTION)
+       {
+               rd_string(buf, sizeof(buf));
+               if (buf[0]) o_ptr->inscription = quark_add(buf);
+               else o_ptr->inscription = 0;
+       }
+       else o_ptr->inscription = 0;
+
+       if (flags & SAVE_ITEM_ART_NAME)
+       {
+               rd_string(buf, sizeof(buf));
+               if (buf[0]) o_ptr->art_name = quark_add(buf);
+               else o_ptr->art_name = 0;
+       }
+       else o_ptr->art_name = 0;
+}
 
 
 /*
- * Read a monster
+ * Read a monster (Old method)
  */
-static void rd_monster(monster_type *m_ptr)
+static void rd_monster_old(monster_type *m_ptr)
 {
        byte tmp8u;
        char buf[128];
@@ -574,7 +708,7 @@ static void rd_monster(monster_type *m_ptr)
                rd_s16b(&m_ptr->target_x);
        }
 
-        rd_byte(&m_ptr->invulner);
+       rd_byte(&m_ptr->invulner);
 
        if (!(z_major == 2 && z_minor == 0 && z_patch == 6))
                rd_u32b(&m_ptr->smart);
@@ -619,6 +753,87 @@ static void rd_monster(monster_type *m_ptr)
 }
 
 
+/*
+ * Read a monster (New method)
+ */
+static void rd_monster(monster_type *m_ptr)
+{
+       u32b flags;
+       char buf[128];
+
+       if (h_older_than(1, 5, 0, 0))
+       {
+               rd_monster_old(m_ptr);
+               return;
+       }
+
+       /*** Monster save flags ***/
+       rd_u32b(&flags);
+
+       /*** Read un-obvious elements ***/
+
+       /* Read the monster race */
+       rd_s16b(&m_ptr->r_idx);
+
+       /* Read the other information */
+       rd_byte(&m_ptr->fy);
+       rd_byte(&m_ptr->fx);
+       rd_s16b(&m_ptr->hp);
+       rd_s16b(&m_ptr->maxhp);
+       rd_s16b(&m_ptr->max_maxhp);
+
+       /* Monster race index of its appearance */
+       if (flags & SAVE_MON_AP_R_IDX) rd_s16b(&m_ptr->ap_r_idx);
+       else m_ptr->ap_r_idx = m_ptr->r_idx;
+
+       if (flags & SAVE_MON_SUB_ALIGN) rd_byte(&m_ptr->sub_align);
+       else m_ptr->sub_align = 0;
+
+       if (flags & SAVE_MON_CSLEEP) rd_s16b(&m_ptr->csleep);
+       else m_ptr->csleep = 0;
+
+       rd_byte(&m_ptr->mspeed);
+
+       rd_s16b(&m_ptr->energy_need);
+
+       if (flags & SAVE_MON_FAST) rd_byte(&m_ptr->fast);
+       else m_ptr->fast = 0;
+       if (flags & SAVE_MON_SLOW) rd_byte(&m_ptr->slow);
+       else m_ptr->slow = 0;
+       if (flags & SAVE_MON_STUNNED) rd_byte(&m_ptr->stunned);
+       else m_ptr->stunned = 0;
+       if (flags & SAVE_MON_CONFUSED) rd_byte(&m_ptr->confused);
+       else m_ptr->confused = 0;
+       if (flags & SAVE_MON_MONFEAR) rd_byte(&m_ptr->monfear);
+       else m_ptr->monfear = 0;
+
+       if (flags & SAVE_MON_TARGET_Y) rd_s16b(&m_ptr->target_y);
+       else m_ptr->target_y = 0;
+       if (flags & SAVE_MON_TARGET_X) rd_s16b(&m_ptr->target_x);
+       else m_ptr->target_x = 0;
+
+       if (flags & SAVE_MON_INVULNER) rd_byte(&m_ptr->invulner);
+       else m_ptr->invulner = 0;
+
+       if (flags & SAVE_MON_SMART) rd_u32b(&m_ptr->smart);
+       else m_ptr->smart = 0;
+
+       if (flags & SAVE_MON_EXP) rd_u32b(&m_ptr->exp);
+       else m_ptr->exp = 0;
+
+       m_ptr->mflag = 0; /* Not saved */
+
+       if (flags & SAVE_MON_MFLAG2) rd_byte(&m_ptr->mflag2);
+       else m_ptr->mflag2 = 0;
+
+       if (flags & SAVE_MON_NICKNAME) 
+       {
+               rd_string(buf, sizeof(buf));
+               if (buf[0]) m_ptr->nickname = quark_add(buf);
+               else m_ptr->nickname = 0;
+       }
+       else m_ptr->nickname = 0;
+}
 
 
 
@@ -650,7 +865,7 @@ static void rd_lore(int r_idx)
        rd_byte(&r_ptr->r_drop_item);
 
        /* Count spells */
-       rd_byte(&r_ptr->r_cast_inate);
+       rd_byte(&tmp8u);
        rd_byte(&r_ptr->r_cast_spell);
 
        /* Count blows of each type */
@@ -670,10 +885,11 @@ static void rd_lore(int r_idx)
        /* Read the "Racial" monster limit per level */
        rd_byte(&r_ptr->max_num);
 
+       /* Location in saved floor */
+       rd_s16b(&r_ptr->floor_id);
+
        /* Later (?) */
        rd_byte(&tmp8u);
-       rd_byte(&tmp8u);
-       rd_byte(&tmp8u);
 
        /* Repair the lore flags */
        r_ptr->r_flags1 &= r_ptr->flags1;
@@ -959,6 +1175,7 @@ static void rd_options(void)
        cheat_xtra = (c & 0x0800) ? TRUE : FALSE;
        cheat_know = (c & 0x1000) ? TRUE : FALSE;
        cheat_live = (c & 0x2000) ? TRUE : FALSE;
+       cheat_save = (c & 0x4000) ? TRUE : FALSE;
 
        rd_byte((byte *)&autosave_l);
        rd_byte((byte *)&autosave_t);
@@ -1195,7 +1412,7 @@ static void rd_extra(void)
        for (i = 0; i < 64; i++) rd_s16b(&p_ptr->spell_exp[i]);
        if ((p_ptr->pclass == CLASS_SORCERER) && z_older_than(10, 4, 2))
        {
-               for (i = 0; i < 64; i++) p_ptr->spell_exp[i] = 1600;
+               for (i = 0; i < 64; i++) p_ptr->spell_exp[i] = SPELL_EXP_MASTER;
        }
        if (z_older_than(10, 3, 6))
                for (i = 0; i < 5; i++) for (j = 0; j < 60; j++) rd_s16b(&p_ptr->weapon_exp[i][j]);
@@ -1216,16 +1433,16 @@ static void rd_extra(void)
        {
                for (i = 0; i < 108; i++) rd_s32b(&p_ptr->magic_num1[i]);
                for (i = 0; i < 108; i++) rd_byte(&p_ptr->magic_num2[i]);
-                if (h_older_than(1, 3, 0, 1))
-                {
-                        if (p_ptr->pclass == CLASS_SMITH)
-                        {
-                                p_ptr->magic_num1[TR_ES_ATTACK] = p_ptr->magic_num1[96];
-                                p_ptr->magic_num1[96] = 0;
-                                p_ptr->magic_num1[TR_ES_AC] = p_ptr->magic_num1[97];
-                                p_ptr->magic_num1[97] = 0;
-                        }
-                }
+               if (h_older_than(1, 3, 0, 1))
+               {
+                       if (p_ptr->pclass == CLASS_SMITH)
+                       {
+                               p_ptr->magic_num1[TR_ES_ATTACK] = p_ptr->magic_num1[96];
+                               p_ptr->magic_num1[96] = 0;
+                               p_ptr->magic_num1[TR_ES_AC] = p_ptr->magic_num1[97];
+                               p_ptr->magic_num1[97] = 0;
+                       }
+               }
        }
        if ((p_ptr->pclass == CLASS_BARD) && p_ptr->magic_num1[0]) p_ptr->action = ACTION_SING;
 
@@ -1397,16 +1614,16 @@ note(format("
        }
        else
        {
-                byte max = (byte)max_d_idx;
+               byte max = (byte)max_d_idx;
 
-                rd_byte(&max);
+               rd_byte(&max);
 
-                for(i = 0; i < max; i++)
+               for(i = 0; i < max; i++)
                {
-                        rd_s16b(&max_dlv[i]);
+                       rd_s16b(&max_dlv[i]);
                        if (max_dlv[i] > d_info[i].maxdepth) max_dlv[i] = d_info[i].maxdepth;
                }
-        }
+       }
 
        /* Repair maximum player level XXX XXX XXX */
        if (p_ptr->max_plv < p_ptr->lev) p_ptr->max_plv = p_ptr->lev;
@@ -1454,6 +1671,12 @@ note(format("
                rd_s16b(&tmp16s);
                p_ptr->recall_dungeon = (byte)tmp16s;
        }
+
+       if (h_older_than(1, 5, 0, 0))
+               p_ptr->alter_reality = 0;
+       else
+               rd_s16b(&p_ptr->alter_reality);
+
        rd_s16b(&p_ptr->see_infra);
        rd_s16b(&p_ptr->tim_infra);
        rd_s16b(&p_ptr->oppose_fire);
@@ -1684,6 +1907,16 @@ note(format("
                rd_s16b(&p_ptr->riding);
        }
 
+       /* Current floor_id */
+       if (h_older_than(1, 5, 0, 0))
+       {
+               p_ptr->floor_id = 0;
+       }
+       else
+       {
+               rd_s16b(&p_ptr->floor_id);
+       }
+
        if (z_older_than(10,1,2))
        {
                playtime = 0;
@@ -1841,13 +2074,16 @@ static void rd_messages(void)
 
 
 
+/* Old hidden trap flag */
+#define CAVE_TRAP       0x8000
+
 /*
- * Read the dungeon
+ * Read the dungeon (old method)
  *
  * The monsters/objects must be loaded in the same order
  * that they were stored, since the actual indexes matter.
  */
-static errr rd_dungeon(void)
+static errr rd_dungeon_old(void)
 {
        int i, y, x;
        int ymax, xmax;
@@ -1862,7 +2098,7 @@ static errr rd_dungeon(void)
 
        /* Header info */
        rd_s16b(&dun_level);
-        if (z_older_than(10, 3, 8)) dungeon_type = DUNGEON_ANGBAND;
+       if (z_older_than(10, 3, 8)) dungeon_type = DUNGEON_ANGBAND;
        else rd_byte(&dungeon_type);
 
        /* Set the base level for old versions */
@@ -1895,12 +2131,22 @@ static errr rd_dungeon(void)
        /* Load the dungeon data */
        for (x = y = 0; y < ymax; )
        {
+               u16b info;
+
                /* Grab RLE info */
                rd_byte(&count);
                if (z_older_than(10,3,6))
+               {
                        rd_byte(&tmp8u);
+                       info = (u16b)tmp8u;
+               }
                else
-                       rd_s16b(&tmp16s);
+               {
+                       rd_u16b(&info);
+
+                       /* Decline invalid flags */
+                       info &= ~(CAVE_LITE | CAVE_VIEW | CAVE_MNLT);
+               }
 
                /* Apply the RLE info */
                for (i = count; i > 0; i--)
@@ -1909,9 +2155,7 @@ static errr rd_dungeon(void)
                        c_ptr = &cave[y][x];
 
                        /* Extract "info" */
-                       if (z_older_than(10,3,6))
-                               c_ptr->info = tmp8u;
-                       else c_ptr->info = tmp16s;
+                       c_ptr->info = info;
 
                        /* Advance/Wrap */
                        if (++x >= xmax)
@@ -1956,39 +2200,6 @@ static errr rd_dungeon(void)
                }
        }
 
-        /* Convert cave data */
-        if (z_older_than(11, 0, 99))
-        {
-                for (y = 0; y < ymax; y++) for (x = 0; x < xmax; x++)
-                {
-                       /* Wipe old unused flags */
-                       cave[y][x].info &= ~(CAVE_MASK);
-                }
-        }
-
-        if (h_older_than(1, 1, 1, 0))
-        {
-                for (y = 0; y < ymax; y++) for (x = 0; x < xmax; x++)
-                {
-                       /* Access the cave */
-                       c_ptr = &cave[y][x];
-
-                        /* Very old */
-                        if (c_ptr->feat == FEAT_INVIS)
-                        {
-                                c_ptr->feat = FEAT_FLOOR;
-                                c_ptr->info |= CAVE_TRAP;
-                        }
-                
-                        /* Older than 1.1.1 */
-                        if (c_ptr->feat == FEAT_MIRROR)
-                        {
-                                c_ptr->feat = FEAT_FLOOR;
-                                c_ptr->info |= CAVE_IN_MIRROR;
-                        }
-                }
-        }
-
        /*** Run length decoding ***/
 
        /* Load the dungeon data */
@@ -2049,13 +2260,92 @@ static errr rd_dungeon(void)
                }
        }
 
+       /* Convert cave data */
+       if (z_older_than(11, 0, 99))
+       {
+               for (y = 0; y < ymax; y++) for (x = 0; x < xmax; x++)
+               {
+                       /* Wipe old unused flags */
+                       cave[y][x].info &= ~(CAVE_MASK);
+               }
+       }
+
+       if (h_older_than(1, 1, 1, 0))
+       {
+               for (y = 0; y < ymax; y++) for (x = 0; x < xmax; x++)
+               {
+                       /* Access the cave */
+                       c_ptr = &cave[y][x];
+
+                       /* Very old */
+                       if (c_ptr->feat == FEAT_INVIS)
+                       {
+                               c_ptr->feat = FEAT_FLOOR;
+                               c_ptr->info |= CAVE_TRAP;
+                       }
+               
+                       /* Older than 1.1.1 */
+                       if (c_ptr->feat == FEAT_MIRROR)
+                       {
+                               c_ptr->feat = FEAT_FLOOR;
+                               c_ptr->info |= CAVE_OBJECT;
+                       }
+               }
+       }
+
+       if (h_older_than(1, 3, 1, 0))
+       {
+               for (y = 0; y < ymax; y++) for (x = 0; x < xmax; x++)
+               {
+                       /* Access the cave */
+                       c_ptr = &cave[y][x];
+
+                       /* Old CAVE_IN_MIRROR flag */
+                       if (c_ptr->info & CAVE_OBJECT)
+                       {
+                               c_ptr->mimic = FEAT_MIRROR;
+                       }
+
+                       /* Runes will be mimics and flags */
+                       else if (c_ptr->feat == FEAT_MINOR_GLYPH ||
+                                c_ptr->feat == FEAT_GLYPH)
+                       {
+                               c_ptr->info |= CAVE_OBJECT;
+                               c_ptr->mimic = c_ptr->feat;
+                               c_ptr->feat = FEAT_FLOOR;
+                       }
+
+                       /* Hidden traps will be trap terrains mimicing floor */
+                       else if (c_ptr->info & CAVE_TRAP)
+                       {
+                               c_ptr->info &= ~CAVE_TRAP;
+                               c_ptr->mimic = c_ptr->feat;
+                               c_ptr->feat = choose_random_trap();
+                       }
+
+                       /* Another hidden trap */
+                       else if (c_ptr->feat == FEAT_INVIS)
+                       {
+                               c_ptr->mimic = FEAT_FLOOR;
+                               c_ptr->feat = FEAT_TRAP_OPEN;
+                       }
+
+                       /* Hidden doors will be closed doors mimicing wall */
+                       else if (c_ptr->feat == FEAT_SECRET)
+                       {
+                               place_closed_door(y, x);
+                               c_ptr->mimic = FEAT_WALL_EXTRA;
+                       }
+               }
+       }
+
        /*** Objects ***/
 
        /* Read the item count */
        rd_u16b(&limit);
 
        /* Verify maximum */
-       if (limit >= max_o_idx)
+       if (limit > max_o_idx)
        {
 #ifdef JP
 note(format("¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤¬Â礭¤¹¤®¤ë(%d)¡ª", limit));
@@ -2135,7 +2425,7 @@ note(format("
        rd_u16b(&limit);
 
        /* Hack -- verify */
-       if (limit >= max_m_idx)
+       if (limit > max_m_idx)
        {
 #ifdef JP
 note(format("¥â¥ó¥¹¥¿¡¼¤ÎÇÛÎó¤¬Â礭¤¹¤®¤ë(%d)¡ª", limit));
@@ -2150,12 +2440,8 @@ note(format("
        for (i = 1; i < limit; i++)
        {
                int m_idx;
-
                monster_type *m_ptr;
 
-               monster_race *r_ptr;
-
-
                /* Get a new record */
                m_idx = m_pop();
 
@@ -2185,12 +2471,8 @@ note(format("
                /* Mark the location */
                c_ptr->m_idx = m_idx;
 
-
-               /* Access race */
-               r_ptr = &r_info[m_ptr->r_idx];
-
-               /* Count XXX XXX XXX */
-               r_ptr->cur_num++;
+               /* Count */
+               real_r_ptr(m_ptr)->cur_num++;
        }
 
        /*** Success ***/
@@ -2208,104 +2490,528 @@ note(format("
 
 
 /*
- * Actually read the savefile
+ * Read the saved floor
+ *
+ * The monsters/objects must be loaded in the same order
+ * that they were stored, since the actual indexes matter.
  */
-static errr rd_savefile_new_aux(void)
+static errr rd_saved_floor(saved_floor_type *sf_ptr)
 {
-       int i, j;
-       int town_count;
-
-       s32b wild_x_size;
-       s32b wild_y_size;
-
+       int ymax, xmax;
+       int i, y, x;
+       byte count;
        byte tmp8u;
+       s16b tmp16s;
        u16b tmp16u;
+       s32b tmp32s;
        u32b tmp32u;
+       u16b limit;
 
-#ifdef VERIFY_CHECKSUMS
-       u32b n_x_check, n_v_check;
-       u32b o_x_check, o_v_check;
-#endif
+       cave_template_type *template;
 
 
-       /* Mention the savefile version */
-        note(format(
-#ifdef JP
-                     "¥Ð¡¼¥¸¥ç¥ó %d.%d.%d ¤Î¥»¡¼¥Ö¡¦¥Õ¥¡¥¤¥ë¤ò¥í¡¼¥ÉÃæ...",
-#else
-                     "Loading a %d.%d.%d savefile...",
-#endif
-                     (z_major > 9) ? z_major - 10 : z_major, z_minor, z_patch));
+       /*** Wipe all cave ***/
+       clear_cave();
 
 
-       /* Strip the version bytes */
-       strip_bytes(4);
+       /*** Basic info ***/
 
-       /* Hack -- decrypt */
-       xor_byte = sf_extra;
+       /* Dungeon floor specific info follows */
 
+       if (!sf_ptr)
+       {
+               /*** Not a saved floor ***/
 
-       /* Clear the checksums */
-       v_check = 0L;
-       x_check = 0L;
+               rd_s16b(&dun_level);
+               base_level = dun_level;
+       }
+       else
+       {
+               /*** The saved floor ***/
 
-       /* Read the version number of the savefile */
-        /* Old savefile will be version 0.0.0.3 */
-        rd_byte(&h_ver_extra);
-        rd_byte(&h_ver_patch);
-        rd_byte(&h_ver_minor);
-        rd_byte(&h_ver_major);
+               rd_s16b(&tmp16s);
+               if (tmp16s != sf_ptr->floor_id) return 171;
 
-       /* Operating system info */
-       rd_u32b(&sf_system);
+               rd_byte(&tmp8u);
+               if (tmp8u != sf_ptr->savefile_id) return 171;
 
-       /* Time of savefile creation */
-       rd_u32b(&sf_when);
+               rd_s16b(&tmp16s);
+               if (tmp16s != sf_ptr->dun_level) return 171;
+               dun_level = sf_ptr->dun_level;
 
-       /* Number of resurrections */
-       rd_u16b(&sf_lives);
+               rd_s32b(&tmp32s);
+               if (tmp32s != sf_ptr->last_visit) return 171;
 
-       /* Number of times played */
-       rd_u16b(&sf_saves);
+               rd_u32b(&tmp32u);
+               if (tmp32u != sf_ptr->visit_mark) return 171;
 
+               rd_s16b(&tmp16s);
+               if (tmp16s != sf_ptr->upper_floor_id) return 171;
 
-       /* Later use (always zero) */
-       rd_u32b(&tmp32u);
+               rd_s16b(&tmp16s);
+               if (tmp16s != sf_ptr->lower_floor_id) return 171;
+       }
 
-       /* Later use (always zero) */
-       rd_u32b(&tmp32u);
+       rd_s16b(&base_level);
+       rd_s16b(&num_repro);
 
+       rd_u16b(&tmp16u);
+       py = (int)tmp16u;
 
-       /* Read RNG state */
-       rd_randomizer();
-#ifdef JP
-if (arg_fiddle) note("Íð¿ô¾ðÊó¤ò¥í¡¼¥É¤·¤Þ¤·¤¿");
-#else
-       if (arg_fiddle) note("Loaded Randomizer Info");
-#endif
+       rd_u16b(&tmp16u);
+       px = (int)tmp16u;
 
+       rd_s16b(&cur_hgt);
+       rd_s16b(&cur_wid);
 
+       rd_byte(&feeling);
 
-       /* Then the options */
-       rd_options();
-#ifdef JP
-if (arg_fiddle) note("¥ª¥×¥·¥ç¥ó¤ò¥í¡¼¥É¤·¤Þ¤·¤¿");
-#else
-       if (arg_fiddle) note("Loaded Option Flags");
-#endif
 
-       /*
-        * Munchkin players are marked
-        *
-        * XXX - should be replaced with a better method,
-        * after the new scorefile-handling is implemented.
-        */
-       if (munchkin_death)
+
+       /*** Read template for cave_type ***/
+
+       /* Read the template count */
+       rd_u16b(&limit);
+
+       /* Allocate the "template" array */
+       C_MAKE(template, limit, cave_template_type);
+
+       /* Read the templates */
+       for (i = 0; i < limit; i++)
+       {
+               cave_template_type *ct_ptr = &template[i];
+
+               /* Read it */
+               rd_u16b(&ct_ptr->info);
+               rd_byte(&ct_ptr->feat);
+               rd_byte(&ct_ptr->mimic);
+               rd_s16b(&ct_ptr->special);
+       }
+
+       /* Maximal size */
+       ymax = cur_hgt;
+       xmax = cur_wid;
+
+
+       /*** Run length decoding ***/
+
+       /* Load the dungeon data */
+       for (x = y = 0; y < ymax; )
+       {
+               u16b id;
+
+               /* Grab RLE info */
+               rd_byte(&count);
+
+               id = 0;
+               do 
+               {
+                       rd_byte(&tmp8u);
+                       id += tmp8u;
+               } while (tmp8u == MAX_UCHAR);
+
+               /* Apply the RLE info */
+               for (i = count; i > 0; i--)
+               {
+                       /* Access the cave */
+                       cave_type *c_ptr = &cave[y][x];
+
+                       /* Extract cave data */
+                       c_ptr->info = template[id].info;
+                       c_ptr->feat = template[id].feat;
+                       c_ptr->mimic = template[id].mimic;
+                       c_ptr->special = template[id].special;
+
+                       /* Advance/Wrap */
+                       if (++x >= xmax)
+                       {
+                               /* Wrap */
+                               x = 0;
+
+                               /* Advance/Wrap */
+                               if (++y >= ymax) break;
+                       }
+               }
+       }
+
+       /* Free the "template" array */
+       C_FREE(template, limit, cave_template_type);
+
+
+       /*** Objects ***/
+
+       /* Read the item count */
+       rd_u16b(&limit);
+
+       /* Verify maximum */
+       if (limit > max_o_idx) return 151;
+
+
+       /* Read the dungeon items */
+       for (i = 1; i < limit; i++)
        {
-               /* Mark savefile */
-               p_ptr->noscore |= 0x0001;
+               int o_idx;
+               object_type *o_ptr;
+
+
+               /* Get a new record */
+               o_idx = o_pop();
+
+               /* Oops */
+               if (i != o_idx) return 152;
+
+               /* Acquire place */
+               o_ptr = &o_list[o_idx];
+
+               /* Read the item */
+               rd_item(o_ptr);
+
+
+               /* Monster */
+               if (o_ptr->held_m_idx)
+               {
+                       monster_type *m_ptr;
+
+                       /* Monster */
+                       m_ptr = &m_list[o_ptr->held_m_idx];
+
+                       /* Build a stack */
+                       o_ptr->next_o_idx = m_ptr->hold_o_idx;
+
+                       /* Place the object */
+                       m_ptr->hold_o_idx = o_idx;
+               }
+
+               /* Dungeon */
+               else
+               {
+                       /* Access the item location */
+                       cave_type *c_ptr = &cave[o_ptr->iy][o_ptr->ix];
+
+                       /* Build a stack */
+                       o_ptr->next_o_idx = c_ptr->o_idx;
+
+                       /* Place the object */
+                       c_ptr->o_idx = o_idx;
+               }
+       }
+
+
+       /*** Monsters ***/
+
+       /* Read the monster count */
+       rd_u16b(&limit);
+
+       /* Hack -- verify */
+       if (limit > max_m_idx) return 161;
+
+       /* Read the monsters */
+       for (i = 1; i < limit; i++)
+       {
+               cave_type *c_ptr;
+               int m_idx;
+               monster_type *m_ptr;
+
+               /* Get a new record */
+               m_idx = m_pop();
+
+               /* Oops */
+               if (i != m_idx) return 162;
+
+
+               /* Acquire monster */
+               m_ptr = &m_list[m_idx];
+
+               /* Read the monster */
+               rd_monster(m_ptr);
+
+
+               /* Access grid */
+               c_ptr = &cave[m_ptr->fy][m_ptr->fx];
+
+               /* Mark the location */
+               c_ptr->m_idx = m_idx;
+
+               /* Count */
+               real_r_ptr(m_ptr)->cur_num++;
+       }
+
+       /* Success */
+       return 0;
+}
+
+
+/*
+ * Read the dungeon (new method)
+ *
+ * The monsters/objects must be loaded in the same order
+ * that they were stored, since the actual indexes matter.
+ */
+static errr rd_dungeon(void)
+{
+       errr err = 0;
+       byte num;
+       int i;
+
+       /* Initialize saved_floors array and temporal files */
+       init_saved_floors();
+
+       /* Older method */
+       if (h_older_than(1, 5, 0, 0))
+       {
+               err = rd_dungeon_old();
+
+               /* Prepare floor_id of current floor */
+               if (dungeon_type)
+               {
+                       p_ptr->floor_id = get_new_floor_id();
+                       get_sf_ptr(p_ptr->floor_id)->dun_level = dun_level;
+               }
+
+               return err;
+       }
+
+
+       /*** Meta info ***/
+
+        /* Number of floor_id used from birth */
+       rd_s16b(&max_floor_id);
+
+       /* Current dungeon type */
+       rd_byte(&dungeon_type);
+
+
+       /*** On the surface  ***/
+       if (!p_ptr->floor_id)
+       {
+               /* Number of array elements?? */
+               rd_byte(&num);
+
+               /* It should be 0 */
+               if (num) err = 181;
+
+               /* Read the current floor data */
+               err = rd_saved_floor(NULL);
+       }
+
+       /*** In the dungeon ***/
+       else
+       {
+               /* Number of array elements */
+               rd_byte(&num);
+
+               /* Read the saved_floors array */
+               for (i = 0; i < num; i++)
+               {
+                       saved_floor_type *sf_ptr = &saved_floors[i];
+
+                       rd_s16b(&sf_ptr->floor_id);
+                       rd_byte(&sf_ptr->savefile_id);
+                       rd_s16b(&sf_ptr->dun_level);
+                       rd_s32b(&sf_ptr->last_visit);
+                       rd_u32b(&sf_ptr->visit_mark);
+                       rd_s16b(&sf_ptr->upper_floor_id);
+                       rd_s16b(&sf_ptr->lower_floor_id);
+               }
+
+
+               /* Move saved floors data to temporal files */
+               for (i = 0; i < num; i++)
+               {
+                       saved_floor_type *sf_ptr = &saved_floors[i];
+                       byte tmp8u;
+               
+                       /* Unused element */
+                       if (!sf_ptr->floor_id) continue;
+
+                       /* Read the failure mark */
+                       rd_byte(&tmp8u);
+                       if (tmp8u) continue;
+
+                       /* Read from the save file */
+                       err = rd_saved_floor(sf_ptr);
+                       
+                       /* Error? */
+                       if (err) break;
+
+                       /* Re-save as temporal saved floor file */
+                       if (!save_floor(sf_ptr, SLF_SECOND)) err = 182;
+
+                       /* Error? */
+                       if (err) break;
+               }
+
+               /* Finally load current floor data from temporal file */
+               if (!err)
+               {
+                       if (!load_floor(get_sf_ptr(p_ptr->floor_id), SLF_SECOND)) err = 183;
+               }
+       }
+
+
+       /*** Error messages ***/
+       switch (err)
+       {
+       case 151:
+#ifdef JP
+               note("¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤¬Â礭¤¹¤®¤ë¡ª");
+#else
+               note("Too many object entries!");
+#endif
+               break;
+
+       case 152:
+#ifdef JP
+               note("¥¢¥¤¥Æ¥àÇÛÃÖ¥¨¥é¡¼");
+#else
+               note("Object allocation error");
+#endif
+               break;
+
+       case 161:
+#ifdef JP
+               note("¥â¥ó¥¹¥¿¡¼¤ÎÇÛÎó¤¬Â礭¤¹¤®¤ë¡ª");
+#else
+               note("Too many monster entries!");
+#endif
+               break;
+
+       case 162:
+#ifdef JP
+               note("¥â¥ó¥¹¥¿¡¼ÇÛÃÖ¥¨¥é¡¼");
+#else
+               note("Monster allocation error");
+#endif
+               break;
+
+       case 171:
+#ifdef JP
+               note("Êݸ¤µ¤ì¤¿¥Õ¥í¥¢¤Î¥À¥ó¥¸¥ç¥ó¥Ç¡¼¥¿¤¬²õ¤ì¤Æ¤¤¤Þ¤¹¡ª");
+#else
+               note("Dungeon data of saved floors are broken!");
+#endif
+               break;
+
+       case 181:
+#ifdef JP
+               note("Error 181");
+#else
+               note("Error 181");
+#endif
+               break;
+
+       case 182:
+#ifdef JP
+               note("¥Æ¥ó¥Ý¥é¥ê¡¦¥Õ¥¡¥¤¥ë¤òºîÀ®¤Ç¤­¤Þ¤»¤ó¡ª");
+#else
+               note("Failed to make temporal files!");
+#endif
+               break;
+
+       case 183:
+#ifdef JP
+               note("Error 183");
+#else
+               note("Error 183");
+#endif
+               break;
        }
 
+       /* The dungeon is ready */
+       character_dungeon = TRUE;
+
+       /* Success or Error */
+       return err;
+}
+
+
+/*
+ * Actually read the savefile
+ */
+static errr rd_savefile_new_aux(void)
+{
+       int i, j;
+       int town_count;
+
+       s32b wild_x_size;
+       s32b wild_y_size;
+
+       byte tmp8u;
+       u16b tmp16u;
+       u32b tmp32u;
+
+#ifdef VERIFY_CHECKSUMS
+       u32b n_x_check, n_v_check;
+       u32b o_x_check, o_v_check;
+#endif
+
+
+       /* Mention the savefile version */
+       note(format(
+#ifdef JP
+                    "¥Ð¡¼¥¸¥ç¥ó %d.%d.%d ¤Î¥»¡¼¥Ö¡¦¥Õ¥¡¥¤¥ë¤ò¥í¡¼¥ÉÃæ...",
+#else
+                    "Loading a %d.%d.%d savefile...",
+#endif
+                    (z_major > 9) ? z_major - 10 : z_major, z_minor, z_patch));
+
+
+       /* Strip the version bytes */
+       strip_bytes(4);
+
+       /* Hack -- decrypt */
+       xor_byte = sf_extra;
+
+
+       /* Clear the checksums */
+       v_check = 0L;
+       x_check = 0L;
+
+       /* Read the version number of the savefile */
+       /* Old savefile will be version 0.0.0.3 */
+       rd_byte(&h_ver_extra);
+       rd_byte(&h_ver_patch);
+       rd_byte(&h_ver_minor);
+       rd_byte(&h_ver_major);
+
+       /* Operating system info */
+       rd_u32b(&sf_system);
+
+       /* Time of savefile creation */
+       rd_u32b(&sf_when);
+
+       /* Number of resurrections */
+       rd_u16b(&sf_lives);
+
+       /* Number of times played */
+       rd_u16b(&sf_saves);
+
+
+       /* Later use (always zero) */
+       rd_u32b(&tmp32u);
+
+       /* Later use (always zero) */
+       rd_u32b(&tmp32u);
+
+
+       /* Read RNG state */
+       rd_randomizer();
+#ifdef JP
+if (arg_fiddle) note("Íð¿ô¾ðÊó¤ò¥í¡¼¥É¤·¤Þ¤·¤¿");
+#else
+       if (arg_fiddle) note("Loaded Randomizer Info");
+#endif
+
+
+
+       /* Then the options */
+       rd_options();
+#ifdef JP
+if (arg_fiddle) note("¥ª¥×¥·¥ç¥ó¤ò¥í¡¼¥É¤·¤Þ¤·¤¿");
+#else
+       if (arg_fiddle) note("Loaded Option Flags");
+#endif
+
        /* Then the "messages" */
        rd_messages();
 #ifdef JP
@@ -2318,9 +3024,8 @@ if (arg_fiddle) note("
 
        for (i = 0; i < max_r_idx; i++)
        {
-               monster_race *r_ptr;
                /* Access that monster */
-               r_ptr = &r_info[i];
+               monster_race *r_ptr = &r_info[i];
 
                /* Hack -- Reset the death counter */
                r_ptr->max_num = 100;
@@ -2346,13 +3051,8 @@ note(format("
        /* Read the available records */
        for (i = 0; i < tmp16u; i++)
        {
-               monster_race *r_ptr;
-
                /* Read the lore */
                rd_lore(i);
-
-               /* Access that monster */
-               r_ptr = &r_info[i];
        }
 
 #ifdef JP
@@ -2548,7 +3248,7 @@ note(format("
                                                        init_flags = INIT_ASSIGN;
                                                        p_ptr->inside_quest = i;
 
-                                                       process_dungeon_file("q_info_j.txt", 0, 0, 0, 0);
+                                                       process_dungeon_file("q_info.txt", 0, 0, 0, 0);
                                                        p_ptr->inside_quest = old_inside_quest;
                                                }
                                        }
@@ -2642,11 +3342,23 @@ note(format("
        /* Read the artifact flags */
        for (i = 0; i < tmp16u; i++)
        {
+               artifact_type *a_ptr = &a_info[i];
+
                rd_byte(&tmp8u);
-               a_info[i].cur_num = tmp8u;
-               rd_byte(&tmp8u);
-               rd_byte(&tmp8u);
-               rd_byte(&tmp8u);
+               a_ptr->cur_num = tmp8u;
+
+               if (h_older_than(1, 5, 0, 0))
+               {
+                       a_ptr->floor_id = 0;
+
+                       rd_byte(&tmp8u);
+                       rd_byte(&tmp8u);
+                       rd_byte(&tmp8u);
+               }
+               else
+               {
+                       rd_s16b(&a_ptr->floor_id);
+               }
        }
 #ifdef JP
 if (arg_fiddle) note("ÅÁÀâ¤Î¥¢¥¤¥Æ¥à¤ò¥í¡¼¥É¤·¤Þ¤·¤¿");
@@ -2928,9 +3640,15 @@ errr rd_savefile_new(void)
 {
        errr err;
 
+       /* Grab permissions */
+       safe_setuid_grab();
+
        /* The savefile is a binary file */
        fff = my_fopen(savefile, "rb");
 
+       /* Drop permissions */
+       safe_setuid_drop();
+
        /* Paranoia */
        if (!fff) return (-1);
 
@@ -2948,3 +3666,149 @@ errr rd_savefile_new(void)
 }
 
 
+/*
+ * Actually load and verify a floor save data
+ */
+static bool load_floor_aux(saved_floor_type *sf_ptr)
+{
+       byte tmp8u;
+       u32b tmp32u;
+
+#ifdef VERIFY_CHECKSUMS
+       u32b n_x_check, n_v_check;
+       u32b o_x_check, o_v_check;
+#endif
+
+       /* Hack -- decrypt (read xor_byte) */
+       xor_byte = 0;
+       rd_byte(&tmp8u);
+
+       /* Clear the checksums */
+       v_check = 0L;
+       x_check = 0L;
+
+       /* Set the version number to current version */
+       /* Never load old temporal files */
+       h_ver_extra = H_VER_EXTRA;
+       h_ver_patch = H_VER_PATCH;
+       h_ver_minor = H_VER_MINOR;
+       h_ver_major = H_VER_MAJOR;
+
+       /* Verify the sign */
+       rd_u32b(&tmp32u);
+       if (saved_floor_file_sign != tmp32u) return FALSE;
+
+       /* Read -- have error? */
+       if (rd_saved_floor(sf_ptr)) return FALSE;
+
+
+#ifdef VERIFY_CHECKSUMS
+       /* Save the checksum */
+       n_v_check = v_check;
+
+       /* Read the old checksum */
+       rd_u32b(&o_v_check);
+
+       /* Verify */
+       if (o_v_check != n_v_check) return FALSE;
+
+       /* Save the encoded checksum */
+       n_x_check = x_check;
+
+       /* Read the checksum */
+       rd_u32b(&o_x_check);
+
+       /* Verify */
+       if (o_x_check != n_x_check) return FALSE;
+#endif
+
+       /* Success */
+       return TRUE;
+}
+
+
+/*
+ * Attempt to load the temporally saved-floor data
+ */
+bool load_floor(saved_floor_type *sf_ptr, u32b mode)
+{
+       FILE *old_fff = NULL;
+       byte old_xor_byte = 0;
+       u32b old_v_check = 0;
+       u32b old_x_check = 0;
+       byte old_h_ver_major = 0;
+       byte old_h_ver_minor = 0;
+       byte old_h_ver_patch = 0;
+       byte old_h_ver_extra = 0;
+
+       bool ok = TRUE;
+       char floor_savefile[1024];
+
+       /* We have one file already opened */
+       if (mode & SLF_SECOND)
+       {
+               /* Backup original values */
+               old_fff = fff;
+               old_xor_byte = xor_byte;
+               old_v_check = v_check;
+               old_x_check = x_check;
+               old_h_ver_major = h_ver_major;
+               old_h_ver_minor = h_ver_minor;
+               old_h_ver_patch = h_ver_patch;
+               old_h_ver_extra = h_ver_extra;
+       }
+
+       /* floor savefile */
+       sprintf(floor_savefile, "%s.F%02d", savefile, (int)sf_ptr->savefile_id);
+
+       /* Grab permissions */
+       safe_setuid_grab();
+
+       /* The savefile is a binary file */
+       fff = my_fopen(floor_savefile, "rb");
+
+       /* Drop permissions */
+       safe_setuid_drop();
+
+       /* Couldn't read */
+       if (!fff) ok = FALSE;
+
+       /* Attempt to load */
+       if (ok)
+       {
+               /* Load saved floor data from file */
+               ok = load_floor_aux(sf_ptr);
+
+               /* Check for errors */
+               if (ferror(fff)) ok = FALSE;
+
+               /* Close the file */
+               my_fclose(fff);
+
+               /* Grab permissions */
+               safe_setuid_grab();
+
+               /* Delete the file */
+               if (!(mode & SLF_NO_KILL)) (void)fd_kill(floor_savefile);
+
+               /* Drop permissions */
+               safe_setuid_drop();
+       }
+
+       /* We have one file already opened */
+       if (mode & SLF_SECOND)
+       {
+               /* Restore original values */
+               fff = old_fff;
+               xor_byte = old_xor_byte;
+               v_check = old_v_check;
+               x_check = old_x_check;
+               h_ver_major = old_h_ver_major;
+               h_ver_minor = old_h_ver_minor;
+               h_ver_patch = old_h_ver_patch;
+               h_ver_extra = old_h_ver_extra;
+       }
+
+       /* Result */
+       return ok;
+}