summaryrefslogtreecommitdiff
path: root/src/loadsave.cc
diff options
context:
space:
mode:
authorManoj Srivastava <srivasta@debian.org>2020-05-23 00:33:19 -0700
committerManoj Srivastava <srivasta@debian.org>2020-05-23 00:33:19 -0700
commitd6b913d3ca2e84b75f3675fd6e9f5246c100cf27 (patch)
tree5fc28b7efc737bf2c79dc7d799e0a6013957fe11 /src/loadsave.cc
parentc42f029316c0c004a795ca170bdb50644a800534 (diff)
parent73a0259be1d44fdb2ab34266ae0ff63f0d8f0b60 (diff)
Merge branch 'master' into dgit/siddebian/2.4.0-ah-1archive/debian/2.4.0-ah-1
Diffstat (limited to 'src/loadsave.cc')
-rw-r--r--src/loadsave.cc2451
1 files changed, 1053 insertions, 1398 deletions
diff --git a/src/loadsave.cc b/src/loadsave.cc
index 1806d7c8..3c843a36 100644
--- a/src/loadsave.cc
+++ b/src/loadsave.cc
@@ -1,12 +1,12 @@
#include "loadsave.hpp"
#include "loadsave.h"
-#include "ability_type.hpp"
#include "artifact_type.hpp"
#include "birth.hpp"
#include "cave_type.hpp"
#include "dungeon_info_type.hpp"
#include "ego_item_type.hpp"
+#include "game.hpp"
#include "init1.hpp"
#include "init2.hpp"
#include "levels.hpp"
@@ -18,18 +18,18 @@
#include "object1.hpp"
#include "object2.hpp"
#include "object_kind.hpp"
+#include "options.hpp"
#include "player_class.hpp"
+#include "player_level_flag.hpp"
#include "player_race.hpp"
#include "player_race_mod.hpp"
#include "player_type.hpp"
-#include "quark.hpp"
#include "hooks.hpp"
#include "skill_type.hpp"
#include "store_type.hpp"
#include "tables.hpp"
#include "timer_type.hpp"
#include "town_type.hpp"
-#include "trap_type.hpp"
#include "util.hpp"
#include "util.h"
#include "wilderness_map.hpp"
@@ -38,12 +38,33 @@
#include "xtra2.hpp"
#include "z-rand.hpp"
+#include <boost/filesystem.hpp>
#include <cassert>
+#include <fmt/format.h>
#include <memory>
static u32b vernum; /* Version flag */
static FILE *fff; /* Local savefile ptr */
+/*
+ * Show information on the screen, one line at a time.
+ *
+ * Avoid the top two lines, to avoid interference with "msg_print()".
+ */
+static void note(cptr msg)
+{
+ static int y = 2;
+
+ /* Draw the message */
+ prt(msg, y, 0);
+
+ /* Advance one line (wrap if needed) */
+ if (++y >= 24) y = 2;
+
+ /* Flush it */
+ Term_fresh();
+}
+
/**
* Load/save flag
*/
@@ -52,22 +73,23 @@ enum class ls_flag_t {
SAVE = 7
};
-/*
- * Basic byte-level reading from savefile. This provides a single point
- * of interface to the pseudoencryption that ToME (and Angband)
- * uses. I'm thinking about if it might be faster/better to modify all
- * the do_* functions to directly do this stuff -- it'd make the code
- * somewhat uglier to maintain, but concievably might be much faster. Or
- * is it better maybe to scrap the pseudoencryption entirely and adopt
- * some other means of obfuscation, should it still prove useful in any
- * way? -- Improv
- *
- * What's the point of encryption on savefiles anyway? If I wanted to
- * make a cheater savefile, I'd activate debug mode, and hack the game
- * not to save it. There's no point. -- takkaria
+/**
+ * Structure for loading/saving option values
*/
+namespace {
+
+struct option_value {
+ std::string name;
+ bool_ value;
+};
-static byte sf_get(void)
+} // namespace (anonymous)
+
+
+/*
+ * Basic byte-level reading from savefile.
+ */
+static byte sf_get()
{
byte c;
@@ -81,7 +103,7 @@ static byte sf_get(void)
static void sf_put(byte v)
{
- (void)putc((int)v, fff);
+ putc((int)v, fff);
}
/*
@@ -106,6 +128,11 @@ static void do_byte(byte *v, ls_flag_t flag)
}
}
+static void do_char(char *c, ls_flag_t flag)
+{
+ do_byte((byte *) c, flag);
+}
+
static void do_bool(bool_ *f, ls_flag_t flag)
{
byte b = *f;
@@ -116,6 +143,24 @@ static void do_bool(bool_ *f, ls_flag_t flag)
}
}
+static void do_std_bool(bool *x, ls_flag_t flag)
+{
+ switch (flag)
+ {
+ case ls_flag_t::LOAD:
+ {
+ *x = (sf_get() != 0);
+ return;
+ }
+ case ls_flag_t::SAVE:
+ {
+ byte val = (*x) ? 1 : 0;
+ sf_put(val);
+ return;
+ }
+ }
+}
+
static void do_u16b(u16b *v, ls_flag_t flag)
{
switch (flag)
@@ -171,95 +216,145 @@ static void do_s32b(s32b *ip, ls_flag_t flag)
do_u32b((u32b *)ip, flag);
}
-/*
- * Do object memory and similar stuff
- */
-static void do_xtra(int k_idx, ls_flag_t flag)
+static void save_std_string(std::string const *s)
{
- byte tmp8u = 0;
- object_kind *k_ptr = &k_info[k_idx];
-
- switch(flag)
+ // Length prefix.
+ u32b saved_size = s->size();
+ do_u32b(&saved_size, ls_flag_t::SAVE);
+ // Save each character
+ for (auto c: *s)
{
- case ls_flag_t::SAVE:
- {
- if (k_ptr->aware) tmp8u |= 0x01;
- if (k_ptr->tried) tmp8u |= 0x02;
- if (k_ptr->artifact) tmp8u |= 0x80;
-
- do_byte(&tmp8u, flag);
- return;
+ sf_put(c);
}
- case ls_flag_t::LOAD:
+}
+
+static std::string load_std_string()
+{
+ // Length prefix.
+ u32b saved_size;
+ do_u32b(&saved_size, ls_flag_t::LOAD);
+ // Convert to size_t
+ std::size_t n = saved_size;
+ // Make sure we reserve space rather than resizing as we go.
+ std::string s;
+ s.reserve(n);
+ // Read each character
+ for (std::size_t i = 0; i < n; i++)
+ {
+ s += sf_get();
+ }
+ // Done
+ return s;
+}
+
+
+static void do_std_string(std::string &s, ls_flag_t flag)
+{
+ switch (flag)
{
- do_byte(&tmp8u, flag);
- k_ptr->aware = ((tmp8u & 0x01) ? TRUE : FALSE);
- k_ptr->tried = ((tmp8u & 0x02) ? TRUE : FALSE);
- k_ptr->artifact = ((tmp8u & 0x80) ? TRUE : FALSE);
- return;
- }
+ case ls_flag_t::LOAD:
+ s = load_std_string();
+ break;
+ case ls_flag_t::SAVE:
+ save_std_string(&s);
+ break;
}
}
-static void save_string(const char *str)
+static void do_option_value(option_value *option_value, ls_flag_t flag)
{
- while (*str)
+ do_std_string(option_value->name, flag);
+ do_bool(&option_value->value, flag);
+}
+
+
+namespace {
+
+/**
+ * Load/save flag set
+ */
+template<std::size_t Tiers> void do_flag_set(flag_set<Tiers> *flags, ls_flag_t flag)
+{
+ for (std::size_t i = 0; i < flags->size(); i++)
{
- do_byte((byte*)str, ls_flag_t::SAVE);
- str++;
+ do_u32b(&(*flags)[i], flag);
}
- do_byte((byte*)str, ls_flag_t::SAVE);
}
-static void load_string(char *str, int max)
+template<typename T, typename F> void do_vector(ls_flag_t flag, std::vector<T> &v, F f)
{
- int i;
+ u32b n = v.size();
- /* Read the string */
- for (i = 0; TRUE; i++)
+ do_u32b(&n, flag);
+
+ if (flag == ls_flag_t::LOAD)
{
- byte tmp8u;
+ v.clear(); // Make sure it's empty
+ v.reserve(n);
+ std::fill_n(std::back_inserter(v), n, T());
+ }
- /* Read a byte */
- do_byte(&tmp8u, ls_flag_t::LOAD);
+ for (std::size_t i = 0; i < n; i++)
+ {
+ f(&v[i], flag);
+ }
+}
- /* Collect string while legal */
- if (i < max) str[i] = tmp8u;
+template<typename A, typename F> void do_array(std::string const &what, ls_flag_t flag, A &array, std::size_t size, F f)
+{
+ // Save/load size.
+ u32b n = size;
+ do_u32b(&n, flag);
- /* End of string */
- if (!tmp8u) break;
+ // Check that we don't overflow the array.
+ if (flag == ls_flag_t::LOAD)
+ {
+ if (n > size)
+ {
+ note(fmt::format("Too many {:s}: {:d} > {:d}! Game may act strangely or crash.", what, n, size).c_str());
+ }
+ }
+
+ // Load/save the contents of the array.
+ for (std::size_t i = 0; i < n; i++)
+ {
+ f(&array[i], flag);
}
- /* Terminate */
- str[max - 1] = '\0';
}
-static void do_string(char *str, int max, ls_flag_t flag)
-/* Max is ignored for writing */
+static void do_bytes(ls_flag_t flag, std::uint8_t *buf, std::size_t n)
{
- switch(flag) {
- case ls_flag_t::LOAD:
+ for (std::size_t i = 0; i < n; i++)
{
- load_string(str, max);
- return;
+ do_byte(&buf[i], flag);
}
- case ls_flag_t::SAVE:
+};
+
+static void do_seed(seed_t *seed, ls_flag_t flag)
+{
+ uint8_t buf[seed_t::n_bytes];
+
+ if (flag == ls_flag_t::SAVE)
{
- save_string(str);
- return;
+ seed->to_bytes(buf);
}
+
+ do_bytes(flag, buf, sizeof(buf));
+
+ if (flag == ls_flag_t::LOAD)
+ {
+ *seed = seed_t::from_bytes(buf);
}
}
+} // namespace (anonymous)
+
+
/*
* Load/Save quick start data
*/
-static void do_quick_start(ls_flag_t flag)
+static void do_quick_start(ls_flag_t flag, birther &previous_char)
{
- s16b tmp16s;
- u32b tmp32u;
- int i;
-
- do_s16b(&previous_char.sex, flag);
do_s16b(&previous_char.race, flag);
do_s16b(&previous_char.rmod, flag);
do_s16b(&previous_char.pclass, flag);
@@ -267,20 +362,34 @@ static void do_quick_start(ls_flag_t flag)
do_byte(&previous_char.quests, flag);
do_byte(&previous_char.god, flag);
do_s32b(&previous_char.grace, flag);
- do_s16b(&previous_char.age, flag);
- do_s16b(&previous_char.wt, flag);
- do_s16b(&previous_char.ht, flag);
- do_s16b(&previous_char.sc, flag);
do_s32b(&previous_char.au, flag);
- for (i = 0; i < 6; i++) do_s16b(&(previous_char.stat[i]), flag);
+ for (std::size_t i = 0; i < 6; i++)
+ {
+ do_s16b(&(previous_char.stat[i]), flag);
+ }
do_s16b(&previous_char.luck, flag);
- do_s16b(&tmp16s, flag);
- do_u32b(&tmp32u, flag);
- do_byte((byte*)&previous_char.quick_ok, flag);
+ do_bool(&previous_char.quick_ok, flag);
+}
+
+static void do_skill_modifier(skill_modifier *s, ls_flag_t flag)
+{
+ do_char(&s->basem, flag);
+ do_u32b(&s->base, flag);
+ do_char(&s->modm, flag);
+ do_s16b(&s->mod, flag);
+}
+
+static void do_skill_modifiers(skill_modifiers *skill_modifiers, ls_flag_t flag)
+{
+ do_vector(flag, skill_modifiers->modifiers, do_skill_modifier);
+}
- for (i = 0; i < 4; i++) do_string(previous_char.history[i], 60, flag);
+static void do_player_level_flag(player_level_flag *lflag, ls_flag_t flag)
+{
+ do_flag_set(&lflag->oflags, flag);
+ do_s16b(&lflag->pval, flag);
}
/*
@@ -288,106 +397,52 @@ static void do_quick_start(ls_flag_t flag)
*/
static void do_subrace(ls_flag_t flag)
{
+ auto &race_mod_info = game->edit_data.race_mod_info;
+
player_race_mod *sr_ptr = &race_mod_info[SUBRACE_SAVE];
int i;
- char buf[81];
- buf[80] = '\0'; // Make sure string is always NUL terminated
+ do_std_string(sr_ptr->title, flag);
+ do_std_string(sr_ptr->description, flag);
- if (flag == ls_flag_t::SAVE)
- {
- strncpy(buf, sr_ptr->title, 80);
- }
- do_string(buf, 80, flag);
- if (flag == ls_flag_t::LOAD)
- {
- set_subrace_title(sr_ptr, buf);
- }
+ do_bool(&sr_ptr->place, flag);
- if (flag == ls_flag_t::SAVE)
- {
- strncpy(buf, sr_ptr->desc, 80);
- }
- do_string(buf, 80, flag);
- if (flag == ls_flag_t::LOAD)
+ for (i = 0; i < 6; i++)
{
- set_subrace_description(sr_ptr, buf);
+ do_s16b(&sr_ptr->ps.adj[i], flag);
}
- do_byte((byte*)&sr_ptr->place, flag);
-
- for (i = 0; i < 6; i++)
- do_s16b(&sr_ptr->r_adj[i], flag);
-
- do_byte((byte*)&sr_ptr->luck, flag);
+ do_char(&sr_ptr->luck, flag);
do_s16b(&sr_ptr->mana, flag);
- do_s16b(&sr_ptr->r_dis, flag);
- do_s16b(&sr_ptr->r_dev, flag);
- do_s16b(&sr_ptr->r_sav, flag);
- do_s16b(&sr_ptr->r_stl, flag);
- do_s16b(&sr_ptr->r_srh, flag);
- do_s16b(&sr_ptr->r_fos, flag);
- do_s16b(&sr_ptr->r_thn, flag);
- do_s16b(&sr_ptr->r_thb, flag);
+ do_s16b(&sr_ptr->ps.mhp, flag);
+ do_s16b(&sr_ptr->ps.exp, flag);
- do_byte((byte*)&sr_ptr->r_mhp, flag);
- do_s16b(&sr_ptr->r_exp, flag);
+ do_char(&sr_ptr->infra, flag);
- do_byte((byte*)&sr_ptr->b_age, flag);
- do_byte((byte*)&sr_ptr->m_age, flag);
-
- do_byte((byte*)&sr_ptr->m_b_ht, flag);
- do_byte((byte*)&sr_ptr->m_m_ht, flag);
- do_byte((byte*)&sr_ptr->f_b_ht, flag);
- do_byte((byte*)&sr_ptr->f_m_ht, flag);
-
- do_byte((byte*)&sr_ptr->m_b_wt, flag);
- do_byte((byte*)&sr_ptr->m_m_wt, flag);
- do_byte((byte*)&sr_ptr->f_b_wt, flag);
- do_byte((byte*)&sr_ptr->f_m_wt, flag);
-
- do_byte((byte*)&sr_ptr->infra, flag);
-
- for (i = 0; i < 4; i++)
- do_s16b(&sr_ptr->powers[i], flag);
+ do_vector(flag, sr_ptr->ps.powers, do_s16b);
for (i = 0; i < BODY_MAX; i++)
- do_byte((byte*)&sr_ptr->body_parts[i], flag);
+ {
+ do_char(&sr_ptr->body_parts[i], flag);
+ }
- do_u32b(&sr_ptr->flags1, flag);
- do_u32b(&sr_ptr->flags2, flag);
+ do_flag_set(&sr_ptr->flags, flag);
for (i = 0; i < PY_MAX_LEVEL + 1; i++)
{
- do_u32b(&sr_ptr->oflags1[i], flag);
- do_u32b(&sr_ptr->oflags2[i], flag);
- do_u32b(&sr_ptr->oflags3[i], flag);
- do_u32b(&sr_ptr->oflags4[i], flag);
- do_u32b(&sr_ptr->oflags5[i], flag);
- do_u32b(&sr_ptr->oesp[i], flag);
- do_s16b(&sr_ptr->opval[i], flag);
+ do_player_level_flag(&sr_ptr->lflags[i], flag);
}
do_byte(&sr_ptr->g_attr, flag);
- do_byte((byte*)&sr_ptr->g_char, flag);
+ do_char(&sr_ptr->g_char, flag);
- for (i = 0; i < MAX_SKILLS; i++)
- {
- do_byte((byte*)&sr_ptr->skill_basem[i], flag);
- do_u32b(&sr_ptr->skill_base[i], flag);
- do_byte((byte*)&sr_ptr->skill_modm[i], flag);
- do_s16b(&sr_ptr->skill_mod[i], flag);
- }
+ do_skill_modifiers(&sr_ptr->skill_modifiers, flag);
}
-/* Load/Save the random spells info */
-static void do_spells(int i, ls_flag_t flag)
+static void do_random_spell(random_spell *s_ptr, ls_flag_t flag)
{
- random_spell *s_ptr = &random_spells[i];
- do_string(s_ptr->name, 30, flag);
- do_string(s_ptr->desc, 30, flag);
do_s16b(&s_ptr->mana, flag);
do_s16b(&s_ptr->fail, flag);
do_u32b(&s_ptr->proj_flags, flag);
@@ -396,113 +451,82 @@ static void do_spells(int i, ls_flag_t flag)
do_byte(&s_ptr->dam_sides, flag);
do_byte(&s_ptr->dam_dice, flag);
do_byte(&s_ptr->level, flag);
- do_byte((byte*)&s_ptr->untried, flag);
+ do_std_bool(&s_ptr->untried, flag);
}
-
-/*
- * Show information on the screen, one line at a time.
- *
- * Avoid the top two lines, to avoid interference with "msg_print()".
- */
-static void note(cptr msg)
+static void do_level_marker(level_marker *marker, ls_flag_t flag)
{
- static int y = 2;
-
- /* Draw the message */
- prt(msg, y, 0);
-
- /* Advance one line (wrap if needed) */
- if (++y >= 24) y = 2;
-
- /* Flush it */
- Term_fresh();
-}
+ std::string v;
-
-static void skip_ver_byte(u32b version, ls_flag_t flag)
-/* Reads and discards a byte if the savefile is as old as/older than version */
-{
- if ((flag == ls_flag_t::LOAD) && (vernum <= version))
+ if (flag == ls_flag_t::SAVE)
{
- byte forget;
- do_byte(&forget, flag);
+ v = level_marker_values().stringify(*marker);
}
- return;
-}
-static void do_ver_s16b(s16b *v, u32b version, s16b defval, ls_flag_t flag)
-{
- if ((flag == ls_flag_t::LOAD) && (vernum < version))
+ do_std_string(v, flag);
+
+ if (flag == ls_flag_t::LOAD)
{
- *v = defval;
- return;
+ bool valid = level_marker_values().parse(v.c_str(), marker);
+ if (!valid)
+ {
+ note(fmt::format("Bad level marker: {}!", v).c_str());
+ abort();
+ }
}
- do_s16b(v, flag);
}
/*
* Misc. other data
*/
-static char loaded_game_module[80];
static bool_ do_extra(ls_flag_t flag)
{
- int i, j;
- byte tmp8u = 0;
- s16b tmp16s = 0;
- u32b tmp32u = 0;
- s32b tmp32s = 0;
- u16b tmp16b = 0;
- u32b dummy32u = 0;
+ auto const &d_info = game->edit_data.d_info;
+ auto &s_info = game->s_info;
- do_string(player_name, 32, flag);
+ do_std_string(game->player_name, flag);
- do_string(died_from, 80, flag);
-
- for (i = 0; i < 4; i++)
- {
- do_string(history[i], 60, flag);
- }
+ do_std_string(game->died_from, flag);
/* Handle the special levels info */
- if (flag == ls_flag_t::SAVE)
{
- tmp8u = max_d_idx;
- tmp16s = MAX_DUNGEON_DEPTH;
- }
- do_byte(&tmp8u, flag);
+ byte tmp8u = d_info.size();
+ u16b tmp16u = MAX_DUNGEON_DEPTH;
- if (flag == ls_flag_t::LOAD)
- {
- if (tmp8u > max_d_idx)
+ do_byte(&tmp8u, flag);
+
+ if (flag == ls_flag_t::LOAD)
{
- note(format("Too many (%d) dungeon types!", tmp8u));
+ if (tmp8u > d_info.size())
+ {
+ note(format("Too many dungeon types!", static_cast<int>(tmp8u)));
+ }
}
- }
- do_s16b(&tmp16s, flag);
+ do_u16b(&tmp16u, flag);
- if (flag == ls_flag_t::LOAD)
- {
- if (tmp16s > MAX_DUNGEON_DEPTH)
+ if (flag == ls_flag_t::LOAD)
{
- note(format("Too many (%d) max level by dungeon type!", tmp16s));
+ if (tmp16u > MAX_DUNGEON_DEPTH)
+ {
+ note(format("Too many (%d) max level by dungeon type!", static_cast<int>(tmp16u)));
+ }
}
- }
- /* Load the special levels history */
- for (i = 0; i < tmp8u; i++)
- {
- for (j = 0; j < tmp16s; j++)
+ /* Load the special levels history */
+ for (std::size_t i = 0; i < tmp8u; i++)
{
- do_byte((byte*)&special_lvl[j][i], flag);
+ for (std::size_t j = 0; j < tmp16u; j++)
+ {
+ do_level_marker(&game->level_markers[j][i], flag);
+ }
}
}
- do_byte((byte*)&generate_special_feeling, flag);
+ do_std_bool(&game->generate_special_feeling, flag);
/* Load the quick start data */
- do_quick_start(flag);
+ do_quick_start(flag, game->previous_char);
/* Load/save the special subrace */
do_subrace(flag);
@@ -513,75 +537,39 @@ static bool_ do_extra(ls_flag_t flag)
do_byte(&p_ptr->pracem, flag);
do_byte(&p_ptr->pclass, flag);
do_byte(&p_ptr->pspec, flag);
- do_byte(&p_ptr->psex, flag);
- do_u16b(&tmp16b, flag);
- do_u16b(&tmp16b, flag);
do_byte(&p_ptr->mimic_form, flag);
do_s16b(&p_ptr->mimic_level, flag);
- if (flag == ls_flag_t::SAVE) tmp8u = 0;
do_byte(&p_ptr->hitdie, flag);
do_u16b(&p_ptr->expfact, flag);
- do_s16b(&p_ptr->age, flag);
- do_s16b(&p_ptr->ht, flag);
- do_s16b(&p_ptr->wt, flag);
-
/* Dump the stats (maximum and current) */
- for (i = 0; i < 6; ++i) do_s16b(&p_ptr->stat_max[i], flag);
- for (i = 0; i < 6; ++i) do_s16b(&p_ptr->stat_cur[i], flag);
- for (i = 0; i < 6; ++i) do_s16b(&p_ptr->stat_cnt[i], flag);
- for (i = 0; i < 6; ++i) do_s16b(&p_ptr->stat_los[i], flag);
-
- /* Dump the skills */
- do_s16b(&p_ptr->skill_points, flag);
- do_s16b(&p_ptr->skill_last_level, flag);
- do_s16b(&p_ptr->melee_style, flag);
- do_s16b(&p_ptr->use_piercing_shots, flag);
-
- tmp16s = MAX_SKILLS;
- do_s16b(&tmp16s, flag);
-
- if ((flag == ls_flag_t::LOAD) && (tmp16s > MAX_SKILLS))
- {
- quit("Too many skills");
- }
-
- if (flag == ls_flag_t::SAVE) old_max_s_idx = max_s_idx;
- do_u16b(&old_max_s_idx, flag);
- for (i = 0; i < tmp16s; ++i)
- {
- if (i < old_max_s_idx)
- {
- do_s32b(&s_info[i].value, flag);
- do_s32b(&s_info[i].mod, flag);
- do_byte((byte*)&s_info[i].dev, flag);
- do_byte((byte*)&s_info[i].hidden, flag);
- do_u32b(&s_info[i].uses, flag);
- }
- else
- {
- do_u32b(&tmp32u, flag);
- do_s16b(&tmp16s, flag);
- do_byte(&tmp8u, flag);
- do_byte(&tmp8u, flag);
- do_u32b(&tmp32u, flag);
- }
- }
-
- tmp16s = max_ab_idx;
- do_s16b(&tmp16s, flag);
-
- if ((flag == ls_flag_t::LOAD) && (tmp16s > max_ab_idx))
- {
- quit("Too many abilities");
+ for (std::size_t i = 0; i < 6; ++i) do_s16b(&p_ptr->stat_max[i], flag);
+ for (std::size_t i = 0; i < 6; ++i) do_s16b(&p_ptr->stat_cur[i], flag);
+ for (std::size_t i = 0; i < 6; ++i) do_s16b(&p_ptr->stat_cnt[i], flag);
+ for (std::size_t i = 0; i < 6; ++i) do_s16b(&p_ptr->stat_los[i], flag);
+
+ // Skills
+ {
+ do_s16b(&p_ptr->skill_points, flag);
+ do_s16b(&p_ptr->skill_last_level, flag);
+ do_s16b(&p_ptr->melee_style, flag);
+ do_s16b(&p_ptr->use_piercing_shots, flag);
+
+ do_array("skills", flag, s_info, s_info.size(),
+ [](auto skill, auto flag) -> void {
+ do_s32b(&skill->value, flag);
+ do_s32b(&skill->mod, flag);
+ do_std_bool(&skill->dev, flag);
+ do_std_bool(&skill->hidden, flag);
+ }
+ );
}
- for (i = 0; i < tmp16s; ++i)
- {
- do_byte((byte*)&ab_info[i].acquired, flag);
- }
+ // Abilities
+ do_vector(flag, p_ptr->abilities, do_u16b);
+ // Miscellaneous
do_s16b(&p_ptr->luck_base, flag);
do_s16b(&p_ptr->luck_max, flag);
@@ -595,48 +583,28 @@ static bool_ do_extra(ls_flag_t flag)
do_s16b(&p_ptr->town_num, flag); /* -KMW- */
/* Write arena and rewards information -KMW- */
- do_s16b(&tmp16s, flag);
- do_s16b(&tmp16s, flag);
do_s16b(&p_ptr->inside_quest, flag);
- do_byte(&tmp8u, flag);
/* Save/load spellbinder */
- do_byte(&p_ptr->spellbinder_num, flag);
- do_byte(&p_ptr->spellbinder_trigger, flag);
- for (i = 0; i < 4; i++)
- do_u32b(&p_ptr->spellbinder[i], flag);
+ do_byte(&p_ptr->spellbinder.trigger, flag);
+ do_vector(flag, p_ptr->spellbinder.spell_idxs, do_u32b);
-
- do_byte(&tmp8u, flag); /* tmp8u should be 0 at this point */
-
- if (flag == ls_flag_t::SAVE) tmp8u = MAX_PLOTS;
- do_byte(&tmp8u, flag);
-
- if ((flag == ls_flag_t::LOAD) && (tmp8u > MAX_PLOTS))
- {
- quit(format("Too many plots, %d %d", tmp8u, MAX_PLOTS));
- }
-
- for (i = 0; i < tmp8u; i++)
- {
- do_s16b(&plots[i], flag);
- }
-
- if (flag == ls_flag_t::SAVE)
- {
- tmp8u = MAX_RANDOM_QUEST;
- }
- do_byte(&tmp8u, flag);
-
- if ((flag == ls_flag_t::LOAD) &&
- (tmp8u > MAX_RANDOM_QUEST)) quit("Too many random quests");
- for (i = 0; i < tmp8u; i++)
- {
- do_byte(&random_quests[i].type, flag);
- do_s16b(&random_quests[i].r_idx, flag);
- do_byte((byte*)&random_quests[i].done, flag);
- }
+ // Quest status
+ do_array("plot quests", flag, plots, MAX_PLOTS,
+ [](auto plot, auto flag) -> void {
+ do_s16b(plot, flag);
+ }
+ );
+
+ // Random quests
+ do_array("random quests", flag, random_quests, MAX_RANDOM_QUEST,
+ [](auto q, auto flag) -> void {
+ do_byte(&q->type, flag);
+ do_s16b(&q->r_idx, flag);
+ do_std_bool(&q->done, flag);
+ }
+ );
do_s16b(&p_ptr->oldpx, flag);
do_s16b(&p_ptr->oldpy, flag);
@@ -654,49 +622,48 @@ static bool_ do_extra(ls_flag_t flag)
do_s16b(&p_ptr->csp, flag);
do_u16b(&p_ptr->csp_frac, flag);
- /* XXX
- Here's where tank points were.
- Those who run the estate of you-know-who is really stupid.
- I'll never even consider reading her books now. -- neil */
- do_s16b(&tmp16s, flag);
- do_s16b(&tmp16s, flag);
- do_s16b(&tmp16s, flag);
- do_s16b(&tmp16s, flag);
-
/* Gods */
do_s32b(&p_ptr->grace, flag);
do_s32b(&p_ptr->grace_delay, flag);
- do_byte((byte*)&p_ptr->praying, flag);
+ do_bool(&p_ptr->praying, flag);
do_s16b(&p_ptr->melkor_sacrifice, flag);
do_byte(&p_ptr->pgod, flag);
- /* Max Player and Dungeon Levels */
do_s16b(&p_ptr->max_plv, flag);
- if (flag == ls_flag_t::SAVE)
- tmp8u = max_d_idx;
- do_byte(&tmp8u, flag);
- for (i = 0; i < tmp8u; i++)
+ // Max dungeon levels
{
- if (flag == ls_flag_t::SAVE)
- tmp16s = max_dlv[i];
- do_s16b(&tmp16s, flag);
- if ((flag == ls_flag_t::LOAD) && (i <= max_d_idx))
- max_dlv[i] = tmp16s;
+ byte tmp8u = d_info.size();
+
+ do_byte(&tmp8u, flag);
+
+ for (std::size_t i = 0; i < tmp8u; i++)
+ {
+ s16b tmp16s = max_dlv[i];
+
+ do_s16b(&tmp16s, flag);
+
+ if ((flag == ls_flag_t::LOAD) && (i <= d_info.size()))
+ {
+ max_dlv[i] = tmp16s;
+ }
+ }
}
+
/* Repair max player level??? */
if ((flag == ls_flag_t::LOAD) && (p_ptr->max_plv < p_ptr->lev))
+ {
p_ptr->max_plv = p_ptr->lev;
+ }
- do_byte((byte*)&(p_ptr->help.enabled), flag);
- for (i = 0; i < HELP_MAX; i++)
+ /* Help */
+ do_std_bool(&p_ptr->help.enabled, flag);
+ for (std::size_t i = 0; i < HELP_MAX; i++)
{
- do_bool(&(p_ptr->help.activated[i]), flag);
+ do_std_bool(&p_ptr->help.activated[i], flag);
}
/* More info */
- tmp16s = 0;
- do_s16b(&p_ptr->sc, flag);
do_s16b(&p_ptr->blind, flag);
do_s16b(&p_ptr->paralyzed, flag);
do_s16b(&p_ptr->confused, flag);
@@ -711,7 +678,6 @@ static bool_ do_extra(ls_flag_t flag)
do_s16b(&p_ptr->poisoned, flag);
do_s16b(&p_ptr->image, flag);
do_s16b(&p_ptr->protevil, flag);
- do_s16b(&p_ptr->protundead, flag);
do_s16b(&p_ptr->invuln, flag);
do_s16b(&p_ptr->hero, flag);
do_s16b(&p_ptr->shero, flag);
@@ -742,7 +708,7 @@ static bool_ do_extra(ls_flag_t flag)
do_s16b(&p_ptr->tim_invis, flag);
do_s16b(&p_ptr->word_recall, flag);
- do_s16b(&p_ptr->recall_dungeon, flag);
+ do_byte(&p_ptr->recall_dungeon, flag);
do_s16b(&p_ptr->see_infra, flag);
do_s16b(&p_ptr->tim_infra, flag);
do_s16b(&p_ptr->oppose_fire, flag);
@@ -750,182 +716,97 @@ static bool_ do_extra(ls_flag_t flag)
do_s16b(&p_ptr->oppose_acid, flag);
do_s16b(&p_ptr->oppose_elec, flag);
do_s16b(&p_ptr->oppose_pois, flag);
- do_s16b(&p_ptr->oppose_ld, flag);
do_s16b(&p_ptr->oppose_cc, flag);
- do_s16b(&p_ptr->oppose_ss, flag);
- do_s16b(&p_ptr->oppose_nex, flag);
do_s16b(&p_ptr->tim_esp, flag);
do_s16b(&p_ptr->tim_wraith, flag);
do_s16b(&p_ptr->tim_ffall, flag);
- do_ver_s16b(&p_ptr->tim_fly, SAVEFILE_VERSION, 0, flag);
- do_s16b(&tmp16s, flag);
- do_ver_s16b(&p_ptr->tim_poison, SAVEFILE_VERSION, 0, flag);
- do_s16b(&tmp16s, flag);
+ do_s16b(&p_ptr->tim_fly, flag);
+ do_s16b(&p_ptr->tim_poison, flag);
do_s16b(&p_ptr->tim_invisible, flag);
do_s16b(&p_ptr->tim_inv_pow, flag);
do_s16b(&p_ptr->tim_mimic, flag);
do_s16b(&p_ptr->lightspeed, flag);
do_s16b(&p_ptr->tim_lite, flag);
- do_ver_s16b(&p_ptr->tim_regen, SAVEFILE_VERSION, 0, flag);
- do_ver_s16b(&p_ptr->tim_regen_pow, SAVEFILE_VERSION, 0, flag);
+ do_s16b(&p_ptr->tim_regen, flag);
+ do_s16b(&p_ptr->tim_regen_pow, flag);
do_s16b(&p_ptr->holy, flag);
- do_s16b(&tmp16s, flag);
- do_s16b(&tmp16s, flag);
do_s16b(&p_ptr->immov_cntr, flag);
do_s16b(&p_ptr->strike, flag);
- do_s16b(&tmp16s, flag);
do_s16b(&p_ptr->tim_reflect, flag);
- do_s16b(&tmp16s, flag);
do_s16b(&p_ptr->tim_deadly, flag);
do_s16b(&p_ptr->prob_travel, flag);
do_s16b(&p_ptr->disrupt_shield, flag);
do_s16b(&p_ptr->parasite, flag);
do_s16b(&p_ptr->parasite_r_idx, flag);
- do_s32b(&tmp32s, flag);
- do_s32b(&tmp32s, flag);
do_s16b(&p_ptr->absorb_soul, flag);
do_s32b(&p_ptr->inertia_controlled_spell, flag);
do_s16b(&p_ptr->last_rewarded_level, flag);
- do_s16b(&tmp16s, flag); /* compat */
-
- if (flag == ls_flag_t::SAVE) { tmp16s = CORRUPTIONS_MAX; }
- do_s16b(&tmp16s, flag);
- if (tmp16s > CORRUPTIONS_MAX) {
- quit("Too many corruptions");
- }
-
- for (i = 0; i < tmp16s; i++)
- {
- if (flag == ls_flag_t::SAVE)
- tmp8u = p_ptr->corruptions[i];
-
- do_byte(&tmp8u, flag);
-
- if (flag == ls_flag_t::LOAD)
- p_ptr->corruptions[i] = tmp8u;
- }
+ do_array("corruptions", flag, p_ptr->corruptions, CORRUPTIONS_MAX,
+ [](auto corruption, auto flag) -> void {
+ do_bool(corruption, flag);
+ }
+ );
- do_byte((byte*)&p_ptr->corrupt_anti_teleport_stopped, flag);
+ do_bool(&p_ptr->corrupt_anti_teleport_stopped, flag);
do_byte(&p_ptr->confusing, flag);
- do_byte((byte*)&p_ptr->black_breath, flag);
- do_byte((byte*)&fate_flag, flag);
- do_byte(&p_ptr->searching, flag);
- do_byte(&tmp8u, flag);
- do_byte(&p_ptr->preserve, flag);
- do_byte(&p_ptr->special, flag);
- do_byte((byte*)&ambush_flag, flag);
+ do_bool(&p_ptr->black_breath, flag);
+ do_bool(&fate_flag, flag);
+ do_bool(&ambush_flag, flag);
do_byte(&p_ptr->allow_one_death, flag);
- do_s16b(&tmp16s, flag);
-
- do_byte(&tmp8u, flag);
do_s16b(&no_breeds, flag);
- do_s16b(&p_ptr->protgood, flag);
/* Auxilliary variables */
do_u32b(&p_ptr->mimic_extra, flag);
do_u32b(&p_ptr->antimagic_extra, flag);
- do_u32b(&tmp32u, flag);
- do_u32b(&tmp32u, flag);
- do_u32b(&tmp32u, flag);
do_u32b(&p_ptr->music_extra, flag);
- do_u32b(&tmp32u, flag);
do_u32b(&p_ptr->necro_extra, flag);
do_u32b(&p_ptr->necro_extra2, flag);
- do_u32b(&tmp32u, flag);
- do_u32b(&tmp32u, flag);
- do_u32b(&tmp32u, flag);
- do_u32b(&tmp32u, flag);
- do_u32b(&tmp32u, flag);
- do_u32b(&tmp32u, flag);
- do_u32b(&tmp32u, flag);
-
do_u16b(&p_ptr->body_monster, flag);
- do_byte((byte*)&p_ptr->disembodied, flag);
+ do_bool(&p_ptr->disembodied, flag);
/* Are we in astral mode? */
- do_byte((byte*)&p_ptr->astral, flag);
-
- if (flag == ls_flag_t::SAVE) tmp16s = POWER_MAX;
- do_s16b(&tmp16s, flag);
- if ((flag == ls_flag_t::LOAD) && (tmp16s > POWER_MAX))
- note(format("Too many (%u) powers!", tmp16s));
- for (i = 0; i < POWER_MAX; i++)
- do_byte((byte*)&p_ptr->powers_mod[i], flag);
+ do_bool(&p_ptr->astral, flag);
- skip_ver_byte(100, flag);
+ // Powers
+ do_array("powers", flag, p_ptr->powers_mod, POWER_MAX,
+ [](auto pwr, auto flag) -> void {
+ do_bool(pwr, flag);
+ }
+ );
/* The tactic */
- do_byte((byte*)&p_ptr->tactic, flag);
+ do_char(&p_ptr->tactic, flag);
/* The movement */
- do_byte((byte*)&p_ptr->movement, flag);
+ do_char(&p_ptr->movement, flag);
/* The comapnions killed */
do_s16b(&p_ptr->companion_killed, flag);
/* The fate */
- do_byte((byte*)&p_ptr->no_mortal, flag);
-
- /* The bounties -- kept only for load-compatibility with old savefiles. */
- for (i = 0; i < 24; i++) {
- tmp16s = 0; do_s16b(&tmp16s, flag);
- tmp16s = 0; do_s16b(&tmp16s, flag);
- }
- tmp32u = 0; do_u32b(&tmp32u, flag);
+ do_bool(&p_ptr->no_mortal, flag);
- /* Spells */
- do_s16b(&spell_num, flag);
- for (i = 0; i < MAX_SPELLS; i++)
- do_spells(i, flag);
- do_s16b(&rune_num, flag);
- for (i = 0; i < MAX_RUNES; i++)
- {
- do_string(rune_spells[i].name, 30, flag);
- do_s16b(&rune_spells[i].type, flag);
- do_s16b(&rune_spells[i].rune2, flag);
- do_s16b(&rune_spells[i].mana, flag);
- }
+ /* Random spells */
+ do_vector(flag, p_ptr->random_spells, do_random_spell);
- /* Load random seeds */
- do_u32b(&dummy32u, flag); /* Load-compatibility with old savefiles. */
- do_u32b(&seed_flavor, flag); /* For consistent object flavors. */
- do_u32b(&dummy32u, flag); /* Load-compatibility with old savefiles. */
+ /* Random seed for object flavors. */
+ do_seed(&seed_flavor(), flag);
/* Special stuff */
- do_u16b(&tmp16b, flag); /* Dummy */
do_u16b(&total_winner, flag);
do_u16b(&has_won, flag);
do_u16b(&noscore, flag);
/* Write death */
- if (flag == ls_flag_t::SAVE) tmp8u = death;
- do_byte(&tmp8u, flag);
- if (flag == ls_flag_t::LOAD) death = tmp8u;
-
- /* Incompatible module? */
- if (flag == ls_flag_t::LOAD)
- {
- s32b ok;
-
- ok = module_savefile_loadable(loaded_game_module);
-
- /* Argh bad game module! */
- if (!ok)
- {
- note(format("Bad game module. Savefile was saved with module '%s' but game is '%s'.", loaded_game_module, game_module));
- return (FALSE);
- }
- }
+ do_bool(&death, flag);
- /* Write feeling */
- if (flag == ls_flag_t::SAVE) tmp8u = feeling;
- do_byte(&tmp8u, flag);
- if (flag == ls_flag_t::LOAD) feeling = tmp8u;
+ /* Level feeling */
+ do_s16b(&feeling, flag);
/* Turn of last "feeling" */
do_s32b(&old_turn, flag);
@@ -942,8 +823,6 @@ static bool_ do_extra(ls_flag_t flag)
*/
static void do_monster(monster_type *m_ptr, ls_flag_t flag)
{
- int i;
-
/* Read the monster race */
do_s16b(&m_ptr->r_idx, flag);
@@ -976,16 +855,20 @@ static void do_monster(monster_type *m_ptr, ls_flag_t flag)
do_s32b(&m_ptr->mflag, flag);
- if (flag == ls_flag_t::LOAD) m_ptr->mflag &= PERM_MFLAG_MASK;
-
- /* Attacks */
- for (i = 0; i < 4; i++)
+ if (flag == ls_flag_t::LOAD)
{
- do_byte(&m_ptr->blow[i].method, flag);
- do_byte(&m_ptr->blow[i].effect, flag);
- do_byte(&m_ptr->blow[i].d_dice, flag);
- do_byte(&m_ptr->blow[i].d_side, flag);
+ m_ptr->mflag &= PERM_MFLAG_MASK;
}
+
+ /* Attacks */
+ do_array("attacks", flag, m_ptr->blow, 4,
+ [](auto blow, auto flag) {
+ do_byte(&blow->method, flag);
+ do_byte(&blow->effect, flag);
+ do_byte(&blow->d_dice, flag);
+ do_byte(&blow->d_side, flag);
+ }
+ );
}
@@ -1031,7 +914,6 @@ static bool_ wearable_p(object_type *o_ptr)
case TV_HYPNOS:
case TV_INSTRUMENT:
case TV_DAEMON_BOOK:
- case TV_TRAPKIT:
case TV_TOOL:
{
return (TRUE);
@@ -1045,19 +927,16 @@ static bool_ wearable_p(object_type *o_ptr)
/*
* rd/wr an object
- *
- * FIXME! This code probably has a lot of cruft from the old Z/V codebase.
- *
*/
static void do_item(object_type *o_ptr, ls_flag_t flag)
{
+ auto &k_info = game->edit_data.k_info;
+ auto &a_info = game->edit_data.a_info;
+ auto &e_info = game->edit_data.e_info;
+
byte old_dd;
byte old_ds;
- u32b f1, f2, f3, f4, f5, esp;
-
- object_kind *k_ptr;
-
/* Kind */
do_s16b(&o_ptr->k_idx, flag);
@@ -1110,20 +989,10 @@ static void do_item(object_type *o_ptr, ls_flag_t flag)
do_byte(&o_ptr->marked, flag);
/* flags */
- do_u32b(&o_ptr->art_flags1, flag);
- do_u32b(&o_ptr->art_flags2, flag);
- do_u32b(&o_ptr->art_flags3, flag);
- do_u32b(&o_ptr->art_flags4, flag);
- do_u32b(&o_ptr->art_flags5, flag);
- do_u32b(&o_ptr->art_esp, flag);
+ do_flag_set(&o_ptr->art_flags, flag);
/* obvious flags */
- do_u32b(&o_ptr->art_oflags1, flag);
- do_u32b(&o_ptr->art_oflags2, flag);
- do_u32b(&o_ptr->art_oflags3, flag);
- do_u32b(&o_ptr->art_oflags4, flag);
- do_u32b(&o_ptr->art_oflags5, flag);
- do_u32b(&o_ptr->art_oesp, flag);
+ do_flag_set(&o_ptr->art_oflags, flag);
/* Monster holding object */
do_s16b(&o_ptr->held_m_idx, flag);
@@ -1145,50 +1014,22 @@ static void do_item(object_type *o_ptr, ls_flag_t flag)
do_s16b(&o_ptr->found_aux3, flag);
do_s16b(&o_ptr->found_aux4, flag);
- if (flag == ls_flag_t::LOAD)
- {
- char buf[128];
- /* Inscription */
- load_string(buf, 128);
- if (buf[0])
- {
- o_ptr->note = quark_add(buf);
- }
- /* Artifact name */
- load_string(buf, 128);
- if (buf[0])
- {
- o_ptr->art_name = quark_add(buf);
- }
- }
- if (flag == ls_flag_t::SAVE)
- {
- /* Save the inscription (if any) */
- if (o_ptr->note)
- {
- save_string(quark_str(o_ptr->note));
- }
- else
- {
- save_string("");
- }
- if (o_ptr->art_name)
- {
- save_string(quark_str(o_ptr->art_name));
- }
- else
- {
- save_string("");
- }
- }
+ // Inscription
+ do_std_string(o_ptr->inscription, flag);
+
+ // Artifact name
+ do_std_string(o_ptr->artifact_name, flag);
+
+ /* Stick any more shared code before this. The rest
+ of this function is reserved for ls_flag_t::LOAD's
+ cleanup functions */
+
+ if (flag == ls_flag_t::SAVE) return;
- if (flag == ls_flag_t::SAVE) return ; /* Stick any more shared code before this. The rest
- of this function is reserved for ls_flag_t::LOAD's
- cleanup functions */
/*********** END OF ls_flag_t::SAVE ***************/
/* Obtain the "kind" template */
- k_ptr = &k_info[o_ptr->k_idx];
+ object_kind *k_ptr = &k_info[o_ptr->k_idx];
/* Obtain tval/sval from k_info */
o_ptr->tval = k_ptr->tval;
@@ -1213,16 +1054,11 @@ static void do_item(object_type *o_ptr, ls_flag_t flag)
}
- /* Extract the flags */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
-
/* Paranoia */
if (o_ptr->name1)
{
- artifact_type *a_ptr;
-
/* Obtain the artifact info */
- a_ptr = &a_info[o_ptr->name1];
+ auto a_ptr = &a_info[o_ptr->name1];
/* Verify that artifact */
if (!a_ptr->name) o_ptr->name1 = 0;
@@ -1270,7 +1106,7 @@ static void do_item(object_type *o_ptr, ls_flag_t flag)
o_ptr->ds = old_ds;
}
- if (o_ptr->art_name) /* A random artifact */
+ if (!o_ptr->artifact_name.empty()) /* A random artifact */
{
o_ptr->dd = old_dd;
o_ptr->ds = old_ds;
@@ -1284,7 +1120,6 @@ static void do_cave_type(cave_type *c_ptr, ls_flag_t flag)
do_byte(&c_ptr->mimic, flag);
do_s16b(&c_ptr->special, flag);
do_s16b(&c_ptr->special2, flag);
- do_s16b(&c_ptr->t_idx, flag);
do_s16b(&c_ptr->inscription, flag);
do_byte(&c_ptr->mana, flag);
do_s16b(&c_ptr->effect, flag);
@@ -1301,307 +1136,287 @@ static void do_grid(ls_flag_t flag)
}
}
-static void my_sentinel(const char *place, u16b value, ls_flag_t flag)
-/* This function lets us know exactly where a savefile is
- broken by reading/writing conveniently a sentinel at this
- spot */
+static bool do_objects(ls_flag_t flag, bool no_companions)
{
if (flag == ls_flag_t::SAVE)
{
- do_u16b(&value, flag);
- return;
+ // Compact everything before saving
+ compact_objects(0);
+ compact_monsters(0);
}
- if (flag == ls_flag_t::LOAD)
- {
- u16b found;
- do_u16b(&found, flag);
- if (found == value) /* All is good */
- return;
- /* All is bad */
- note(format("Savefile broken %s", place));
- return;
- }
- note(format("Impossible has occurred")); /* Programmer error */
- exit(0);
-}
-
+ u16b n_objects = o_max;
-/*
- * Handle dungeon
- *
- * The monsters/objects must be loaded in the same order
- * that they were stored, since the actual indexes matter.
- */
-static bool_ do_dungeon(ls_flag_t flag, bool_ no_companions)
-{
- int i;
-
- cave_type *c_ptr;
-
- /* Read specific */
- u16b tmp16b = 0;
-
- my_sentinel("Before do_dungeon", 324, flag);
-
- /* Header info */
- do_s16b(&dun_level, flag);
- do_byte(&dungeon_type, flag);
- do_s16b(&num_repro, flag);
- do_s16b(&p_ptr->py, flag);
- do_s16b(&p_ptr->px, flag);
- do_s16b(&cur_hgt, flag);
- do_s16b(&cur_wid, flag);
- do_s16b(&max_panel_rows, flag);
- do_s16b(&max_panel_cols, flag);
-
- do_u32b(&dungeon_flags1, flag);
- do_u32b(&dungeon_flags2, flag);
-
- /* Last teleportation */
- do_s16b(&last_teleportation_y, flag);
- do_s16b(&last_teleportation_y, flag);
-
- /* Spell effects */
- tmp16b = MAX_EFFECTS;
- do_u16b(&tmp16b, flag);
-
- if ((flag == ls_flag_t::LOAD) && (tmp16b > MAX_EFFECTS))
- {
- quit("Too many spell effects");
- }
-
- for (i = 0; i < tmp16b; ++i)
- {
- do_s16b(&effects[i].type, flag);
- do_s16b(&effects[i].dam, flag);
- do_s16b(&effects[i].time, flag);
- do_u32b(&effects[i].flags, flag);
- do_s16b(&effects[i].cx, flag);
- do_s16b(&effects[i].cy, flag);
- do_s16b(&effects[i].rad, flag);
- }
-
- /* TO prevent bugs with evolving dungeons */
- for (i = 0; i < 100; i++)
- {
- do_s16b(&floor_type[i], flag);
- do_s16b(&fill_type[i], flag);
- }
-
- if ((flag == ls_flag_t::LOAD) && (!dun_level && !p_ptr->inside_quest))
- {
- int xstart = 0;
- int ystart = 0;
- /* Init the wilderness */
- process_dungeon_file("w_info.txt", &ystart, &xstart, cur_hgt, cur_wid,
- TRUE, FALSE);
-
- /* Init the town */
- xstart = 0;
- ystart = 0;
- init_flags = 0;
- process_dungeon_file("t_info.txt", &ystart, &xstart, cur_hgt, cur_wid,
- TRUE, FALSE);
- }
-
- do_grid(flag);
-
- /*** Objects ***/
-
- if (flag == ls_flag_t::SAVE) compact_objects(0);
- if (flag == ls_flag_t::SAVE) compact_monsters(0);
if (flag == ls_flag_t::SAVE)
{
- tmp16b = o_max;
+ u16b tmp16u = n_objects;
if (no_companions)
{
- for (i = 1; i < o_max; i++)
+ for (int i = 1; i < o_max; i++)
{
object_type *o_ptr = &o_list[i];
- if (o_ptr->held_m_idx && (m_list[o_ptr->held_m_idx].status == MSTATUS_COMPANION)) tmp16b--;
+ if (o_ptr->held_m_idx && (m_list[o_ptr->held_m_idx].status == MSTATUS_COMPANION))
+ {
+ tmp16u--;
+ }
}
}
- /* Item count */
- do_u16b(&tmp16b, flag);
-
- tmp16b = o_max;
+ do_u16b(&tmp16u, flag);
}
else
- /* Read item count */
- do_u16b(&tmp16b, flag);
+ {
+ do_u16b(&n_objects, flag);
+ }
/* Verify maximum */
- if ((flag == ls_flag_t::LOAD) && (tmp16b > max_o_idx))
+ if ((flag == ls_flag_t::LOAD) && (n_objects > max_o_idx))
{
- note(format("Too many (%d) object entries!", tmp16b));
- return (FALSE);
+ note("Too many object entries!");
+ return false;
}
/* Dungeon items */
- for (i = 1; i < tmp16b; i++)
+ if (flag == ls_flag_t::SAVE)
{
- int o_idx;
-
- object_type *o_ptr;
-
- if (flag == ls_flag_t::SAVE)
+ for (std::size_t i = 1; i < n_objects; i++)
{
- o_ptr = &o_list[i];
- /* Don't save objects held by companions when no_companions is set */
- if (no_companions && o_ptr->held_m_idx && (m_list[o_ptr->held_m_idx].status == MSTATUS_COMPANION)) continue;
+ auto o_ptr = &o_list[i];
+ // Skip objects held by companions when no_companions is set
+ if (no_companions && o_ptr->held_m_idx && (m_list[o_ptr->held_m_idx].status == MSTATUS_COMPANION))
+ {
+ continue;
+ }
do_item(o_ptr, ls_flag_t::SAVE);
- continue; /* Saving is easy */
}
- /* Until the end of the loop, this is all ls_flag_t::LOAD */
-
- /* Get a new record */
- o_idx = o_pop();
-
- /* Oops */
- if (i != o_idx)
+ }
+ else if (flag == ls_flag_t::LOAD)
+ {
+ for (int i = 1; i < n_objects; i++)
{
- note(format("Object allocation error (%d <> %d)", i, o_idx));
- return (FALSE);
- }
+ /* Get a new record */
+ int o_idx = o_pop();
+ /* Oops */
+ if (i != o_idx)
+ {
+ note(format("Object allocation error (%d <> %d)", i, o_idx));
+ return false;
+ }
- /* Acquire place */
- o_ptr = &o_list[o_idx];
+ /* Acquire place */
+ auto o_ptr = &o_list[o_idx];
- /* Read the item */
- do_item(o_ptr, ls_flag_t::LOAD);
+ /* Read the item */
+ do_item(o_ptr, ls_flag_t::LOAD);
- /* Monster */
- if (o_ptr->held_m_idx)
- {
/* Monster */
- monster_type *m_ptr = &m_list[o_ptr->held_m_idx];
+ if (o_ptr->held_m_idx)
+ {
+ /* Monster */
+ monster_type *m_ptr = &m_list[o_ptr->held_m_idx];
- /* Place the object */
- m_ptr->hold_o_idxs.push_back(o_idx);
- }
+ /* Place the object */
+ m_ptr->hold_o_idxs.push_back(o_idx);
+ }
- /* Dungeon */
- else
- {
- /* Access the item location */
- c_ptr = &cave[o_ptr->iy][o_ptr->ix];
+ /* Dungeon */
+ else
+ {
+ /* Access the item location */
+ auto c_ptr = &cave[o_ptr->iy][o_ptr->ix];
- /* Place the object */
- c_ptr->o_idxs.push_back(o_idx);
+ /* Place the object */
+ c_ptr->o_idxs.push_back(o_idx);
+ }
}
}
- /*** Monsters ***/
+ return true;
+}
+
+
+static bool do_monsters(ls_flag_t flag, bool no_companions)
+{
+ auto &r_info = game->edit_data.r_info;
+
+ u16b n_monsters = m_max;
if (flag == ls_flag_t::SAVE)
{
- tmp16b = m_max;
+ u16b tmp16u = m_max;
if (no_companions)
{
- for (i = 1; i < m_max; i++)
+ for (int i = 1; i < m_max; i++)
{
monster_type *m_ptr = &m_list[i];
- if (m_ptr->status == MSTATUS_COMPANION) tmp16b--;
+ if (m_ptr->status == MSTATUS_COMPANION)
+ {
+ tmp16u--;
+ }
}
}
- /* Write the monster count */
- do_u16b(&tmp16b, flag);
-
- tmp16b = m_max;
+ do_u16b(&tmp16u, flag);
}
else
- /* Read the monster count */
- do_u16b(&tmp16b, flag);
+ {
+ do_u16b(&n_monsters, flag);
+ }
/* Validate */
- if ((flag == ls_flag_t::LOAD) && (tmp16b > max_m_idx))
+ if ((flag == ls_flag_t::LOAD) && (n_monsters > max_m_idx))
{
- note(format("Too many (%d) monster entries!", tmp16b));
- return (FALSE);
+ note("Too many monster entries!");
+ return false;
}
- /* Read the monsters */
- for (i = 1; i < tmp16b; i++)
- {
- int m_idx;
- monster_type *m_ptr;
- monster_race *r_ptr;
+ /* Load/save the monsters */
- if (flag == ls_flag_t::SAVE)
+ if (flag == ls_flag_t::SAVE)
+ {
+ for (std::size_t i = 1; i < n_monsters; i++)
{
- m_ptr = &m_list[i];
+ auto m_ptr = &m_list[i];
- /* Don't save companions when no_companions is set */
- if (no_companions && m_ptr->status == MSTATUS_COMPANION) continue;
+ // Skip companions when no_companions is set
+ if (no_companions && m_ptr->status == MSTATUS_COMPANION)
+ {
+ continue;
+ }
do_monster(m_ptr, ls_flag_t::SAVE);
- continue; /* Easy to save a monster */
}
- /* From here on, it's all ls_flag_t::LOAD */
- /* Get a new record */
- m_idx = m_pop();
-
- /* Oops */
- if (i != m_idx)
+ }
+ else if (flag == ls_flag_t::LOAD)
+ {
+ for (int i = 1; i < n_monsters; i++)
{
- note(format("Monster allocation error (%d <> %d)", i, m_idx));
- return (FALSE);
- }
+ /* Get a new record */
+ int m_idx = m_pop();
+
+ /* Oops */
+ if (i != m_idx)
+ {
+ note(format("Monster allocation error (%d <> %d)", i, m_idx));
+ return false;
+ }
- /* Acquire monster */
- m_ptr = &m_list[m_idx];
+ /* Acquire monster */
+ auto m_ptr = &m_list[m_idx];
- /* Read the monster */
- do_monster(m_ptr, ls_flag_t::LOAD);
+ /* Read the monster */
+ do_monster(m_ptr, ls_flag_t::LOAD);
- /* Access grid */
- c_ptr = &cave[m_ptr->fy][m_ptr->fx];
+ /* Place in grid */
+ auto c_ptr = &cave[m_ptr->fy][m_ptr->fx];
+ c_ptr->m_idx = m_idx;
- /* Mark the location */
- c_ptr->m_idx = m_idx;
+ /* Controlled? */
+ if (m_ptr->mflag & MFLAG_CONTROL)
+ {
+ p_ptr->control = m_idx;
+ }
- /* Controlled ? */
- if (m_ptr->mflag & MFLAG_CONTROL)
- p_ptr->control = m_idx;
+ /* Count as an alive member of race */
+ auto r_ptr = &r_info[m_ptr->r_idx];
+ r_ptr->cur_num++;
+ }
+ }
- /* Access race */
- r_ptr = &r_info[m_ptr->r_idx];
+ /* Save/load pets */
+ {
+ const std::size_t sz =
+ (flag == ls_flag_t::SAVE && !no_companions) ? max_m_idx : 0;
- /* Count XXX XXX XXX */
- r_ptr->cur_num++;
+ do_array("pets", flag, km_list, sz,
+ [](auto m_ptr, auto flag) {
+ do_monster(m_ptr, flag);
+ }
+ );
}
- /* Read the kept monsters */
+ return true;
+}
- tmp16b = (flag == ls_flag_t::SAVE && !no_companions) ? max_m_idx : 0;
+/*
+ * Handle dungeon
+ *
+ * The monsters/objects must be loaded in the same order
+ * that they were stored, since the actual indexes matter.
+ */
+static bool_ do_dungeon(ls_flag_t flag, bool no_companions)
+{
+ /* Header info */
+ do_s16b(&dun_level, flag);
+ do_byte(&dungeon_type, flag);
+ do_s16b(&num_repro, flag);
+ do_s16b(&p_ptr->py, flag);
+ do_s16b(&p_ptr->px, flag);
+ do_s16b(&cur_hgt, flag);
+ do_s16b(&cur_wid, flag);
+ do_s16b(&max_panel_rows, flag);
+ do_s16b(&max_panel_cols, flag);
+
+ do_flag_set(&dungeon_flags, flag);
- /* Read the monster count */
- do_u16b(&tmp16b, flag);
+ /* Last teleportation */
+ do_s16b(&last_teleportation_y, flag);
+ do_s16b(&last_teleportation_y, flag);
+
+ /* Spell effects */
+ do_array("spell effects", flag, effects, MAX_EFFECTS,
+ [](auto effect, auto flag) -> void {
+ do_s16b(&effect->type, flag);
+ do_s16b(&effect->dam, flag);
+ do_s16b(&effect->time, flag);
+ do_u32b(&effect->flags, flag);
+ do_s16b(&effect->cx, flag);
+ do_s16b(&effect->cy, flag);
+ do_s16b(&effect->rad, flag);
+ }
+ );
- /* Hack -- verify */
- if ((flag == ls_flag_t::LOAD) && (tmp16b > max_m_idx))
+ /* To prevent bugs with evolving dungeons */
+ for (std::size_t i = 0; i < 100; i++)
{
- note(format("Too many (%d) monster entries!", tmp16b));
- return (FALSE);
+ do_s16b(&floor_type[i], flag);
+ do_s16b(&fill_type[i], flag);
}
- for (i = 1; i < tmp16b; i++)
+
+ if ((flag == ls_flag_t::LOAD) && (!dun_level && !p_ptr->inside_quest))
{
- monster_type *m_ptr;
+ int xstart = 0;
+ int ystart = 0;
+ /* Init the wilderness */
+ process_dungeon_file("w_info.txt", &ystart, &xstart, cur_hgt, cur_wid,
+ TRUE, FALSE);
+
+ /* Init the town */
+ xstart = 0;
+ ystart = 0;
+ init_flags = 0;
+ process_dungeon_file("t_info.txt", &ystart, &xstart, cur_hgt, cur_wid,
+ TRUE, FALSE);
+ }
+
+ do_grid(flag);
- /* Acquire monster */
- m_ptr = &km_list[i];
+ /*** Objects ***/
+ if (!do_objects(flag, no_companions))
+ {
+ return FALSE;
+ }
- /* Read the monster */
- do_monster(m_ptr, flag);
+ /*** Monsters ***/
+ if (!do_monsters(flag, no_companions))
+ {
+ return FALSE;
}
/*** Success ***/
@@ -1614,7 +1429,7 @@ static bool_ do_dungeon(ls_flag_t flag, bool_ no_companions)
}
/* Save the current persistent dungeon -SC- */
-void save_dungeon(void)
+void save_dungeon()
{
char tmp[16];
char name[1024], buf[5];
@@ -1623,145 +1438,58 @@ void save_dungeon(void)
if (!get_dungeon_save(buf) || (!dun_level)) return;
/* Construct filename */
- sprintf(tmp, "%s.%s", player_base, buf);
+ sprintf(tmp, "%s.%s", game->player_base.c_str(), buf);
path_build(name, 1024, ANGBAND_DIR_SAVE, tmp);
/* Open the file */
fff = my_fopen(name, "wb");
/* Save the dungeon */
- do_dungeon(ls_flag_t::SAVE, TRUE);
+ do_dungeon(ls_flag_t::SAVE, true);
my_fclose(fff);
}
-bool_ file_exist(cptr buf)
-{
- int fd;
- bool_ result;
-
- /* Open savefile */
- fd = fd_open(buf, O_RDONLY);
-
- /* File exists */
- if (fd >= 0)
- {
- fd_close(fd);
- result = TRUE;
- }
- else
- result = FALSE;
-
- return result;
-}
-
-
-/*
- * Handle monster lore
- */
-static void do_lore(int r_idx, ls_flag_t flag)
-{
- monster_race *r_ptr = &r_info[r_idx];
-
- /* Count sights/deaths/kills */
- do_s16b(&r_ptr->r_sights, flag);
- do_s16b(&r_ptr->r_deaths, flag);
- do_s16b(&r_ptr->r_pkills, flag);
- do_s16b(&r_ptr->r_tkills, flag);
-
- /* Count wakes and ignores */
- do_byte(&r_ptr->r_wake, flag);
- do_byte(&r_ptr->r_ignore, flag);
-
- /* Extra stuff */
- do_byte(&r_ptr->r_xtra1, flag);
- do_byte(&r_ptr->r_xtra2, flag);
-
- /* Count drops */
- do_byte(&r_ptr->r_drop_gold, flag);
- do_byte(&r_ptr->r_drop_item, flag);
-
- /* Count spells */
- do_byte(&r_ptr->r_cast_inate, flag);
- do_byte(&r_ptr->r_cast_spell, flag);
-
- /* Count blows of each type */
- do_byte(&r_ptr->r_blows[0], flag);
- do_byte(&r_ptr->r_blows[1], flag);
- do_byte(&r_ptr->r_blows[2], flag);
- do_byte(&r_ptr->r_blows[3], flag);
-
- /* Memorize flags */
- do_u32b(&r_ptr->r_flags1, flag); /* Just to remind you */
- do_u32b(&r_ptr->r_flags2, flag); /* flag is unrelated to */
- do_u32b(&r_ptr->r_flags3, flag); /* the other argument */
- do_u32b(&r_ptr->r_flags4, flag);
- do_u32b(&r_ptr->r_flags5, flag);
- do_u32b(&r_ptr->r_flags6, flag);
- do_u32b(&r_ptr->r_flags7, flag);
- do_u32b(&r_ptr->r_flags8, flag);
- do_u32b(&r_ptr->r_flags9, flag);
-
- /* Read the "Racial" monster tmp16b per level */
- do_s16b(&r_ptr->max_num, flag);
-
- do_byte((byte*)&r_ptr->on_saved, flag);
-
- if (flag == ls_flag_t::LOAD)
- {
- /* Lore flag repair? */
- r_ptr->r_flags1 &= r_ptr->flags1;
- r_ptr->r_flags2 &= r_ptr->flags2;
- r_ptr->r_flags3 &= r_ptr->flags3;
- r_ptr->r_flags4 &= r_ptr->flags4;
- r_ptr->r_flags5 &= r_ptr->flags5;
- r_ptr->r_flags6 &= r_ptr->flags6;
- }
-}
-
-
-
/*
* Read a store
*/
static void do_store(store_type *str, ls_flag_t flag)
{
- byte store_inven_max = STORE_INVEN_MAX;
-
- /* Some basic info */
+ // Store state
do_s32b(&str->store_open, flag);
do_u16b(&str->owner, flag);
-
- /* Could be cleaner, done this way for benefit of the for loop later on */
- byte num;
- if (flag == ls_flag_t::SAVE) num = str->stock_num;
- do_byte(&num, flag);
-
- /* Last visit */
do_s32b(&str->last_visit, flag);
- /* Items */
- for (int j = 0; j < num; j++)
+ // Items in store
{
- if (flag == ls_flag_t::LOAD)
- /* Can't this be cleaner? */
+ byte num = str->stock.size();
+
+ do_byte(&num, flag);
+
+ if (flag == ls_flag_t::SAVE)
{
- object_type forge;
- /* Wipe the object */
- object_wipe(&forge);
- /* Read the item */
- do_item(&forge, ls_flag_t::LOAD);
- /* Acquire valid items */
- if ((str->stock_num < store_inven_max) && (str->stock_num < str->stock_size))
+ for (std::size_t i = 0; i < num; i++)
{
- int k = str->stock_num++;
+ do_item(&str->stock[i], ls_flag_t::SAVE);
+ }
+ }
+ else if (flag == ls_flag_t::LOAD)
+ {
+ for (std::size_t i = 0; i < num; i++)
+ {
+ object_type forge;
+ object_wipe(&forge);
+ do_item(&forge, ls_flag_t::LOAD);
- /* Acquire the item */
- object_copy(&str->stock[k], &forge);
+ if ((str->stock.size() < STORE_INVEN_MAX) && (str->stock.size() < str->stock_size))
+ {
+ object_type stock_obj;
+ object_copy(&stock_obj, &forge);
+ str->stock.push_back(stock_obj);
+ }
}
}
- if (flag == ls_flag_t::SAVE) do_item(&str->stock[j], flag);
}
}
@@ -1770,26 +1498,24 @@ static void do_store(store_type *str, ls_flag_t flag)
*/
static void do_randomizer(ls_flag_t flag)
{
- int i;
-
- u16b tmp16u = 0;
+ std::string state;
- /* Tmp */
- do_u16b(&tmp16u, flag);
+ if (flag == ls_flag_t::SAVE)
+ {
+ state = get_complex_rng_state();
+ }
- /* Place */
- do_u16b(&Rand_place, flag);
+ do_std_string(state, flag);
- /* State */
- for (i = 0; i < RAND_DEG; i++)
+ if (flag == ls_flag_t::LOAD)
{
- do_u32b(&Rand_state[i], flag);
+ set_complex_rng_state(state);
}
/* Accept */
if (flag == ls_flag_t::LOAD)
{
- Rand_quick = FALSE;
+ set_complex_rng();
}
}
@@ -1815,90 +1541,92 @@ static void do_options(ls_flag_t flag)
/*** Special info */
/* Read "delay_factor" */
- do_byte(&delay_factor, flag);
+ do_byte(&options->delay_factor, flag);
/* Read "hitpoint_warn" */
- do_byte(&hitpoint_warn, flag);
+ do_byte(&options->hitpoint_warn, flag);
/*** Cheating options ***/
- if (flag == ls_flag_t::LOAD) /* There *MUST* be some nice way to unify this! */
- {
- u16b c;
- do_u16b(&c, ls_flag_t::LOAD);
- if (c & 0x0002) wizard = TRUE;
- cheat_peek = (c & 0x0100) ? TRUE : FALSE;
- cheat_hear = (c & 0x0200) ? TRUE : FALSE;
- cheat_room = (c & 0x0400) ? TRUE : FALSE;
- cheat_xtra = (c & 0x0800) ? TRUE : FALSE;
- cheat_know = (c & 0x1000) ? TRUE : FALSE;
- cheat_live = (c & 0x2000) ? TRUE : FALSE;
- }
- if (flag == ls_flag_t::SAVE)
- {
- u16b c = 0;
- if (wizard) c |= 0x0002;
- if (cheat_peek) c |= 0x0100;
- if (cheat_hear) c |= 0x0200;
- if (cheat_room) c |= 0x0400;
- if (cheat_xtra) c |= 0x0800;
- if (cheat_know) c |= 0x1000;
- if (cheat_live) c |= 0x2000;
- do_u16b(&c, ls_flag_t::SAVE);
- }
+ do_bool(&wizard, flag);
+ do_bool(&options->cheat_peek, flag);
+ do_bool(&options->cheat_hear, flag);
+ do_bool(&options->cheat_room, flag);
+ do_bool(&options->cheat_xtra, flag);
+ do_bool(&options->cheat_live, flag);
- do_byte((byte*)&autosave_l, flag);
- do_byte((byte*)&autosave_t, flag);
- do_s16b(&autosave_freq, flag);
+ /*** Autosave options */
+ do_bool(&options->autosave_l, flag);
+ do_bool(&options->autosave_t, flag);
+ do_s16b(&options->autosave_freq, flag);
- if (flag == ls_flag_t::LOAD)
+ // Standard options
{
- /* Read the option flags */
- for (n = 0; n < 8; n++) do_u32b(&oflag[n], flag);
+ std::vector<option_value> option_values;
- /* Read the option masks */
- for (n = 0; n < 8; n++) do_u32b(&mask[n], flag);
+ // If we're saving we need to map to a vector of key-value pairs.
+ if (flag == ls_flag_t::SAVE)
+ {
+ for (auto const &option: options->standard_options)
+ {
+ option_values.emplace_back(
+ option_value {
+ option.o_text,
+ *option.o_var
+ }
+ );
+ }
+ }
- /* Analyze the options */
- for (n = 0; n < 8; n++)
+ // Read/write the option values
+ do_vector(flag, option_values, do_option_value);
+
+ // If we're loading we need to set options based of the key-value pairs.
+ if (flag == ls_flag_t::LOAD)
{
- /* Analyze the options */
- for (i = 0; i < 32; i++)
+ // Go through all the options that were loaded.
+ for (auto const &option_value: option_values)
{
- /* Process valid flags */
- if (mask[n] & (1L << i))
+ // We need to search through all the options
+ // that are actually in the game; we'll ignore
+ // saved options that are now gone.
+ const option_type *found_option;
+ for (auto const &option: options->standard_options)
{
- /* Process valid flags */
- if (option_mask[n] & (1L << i))
+ if (option_value.name == option.o_text)
{
- /* Set */
- if (oflag[n] & (1L << i))
- {
- /* Set */
- option_flag[n] |= (1L << i);
- }
-
- /* Clear */
- else
- {
- /* Clear */
- option_flag[n] &= ~(1L << i);
- }
+ found_option = &option;
+ break;
}
}
+
+ // If we found the option, we'll set the value.
+ if (found_option)
+ {
+ *(*found_option).o_var = option_value.value;
+ }
}
}
+ }
+ if (flag == ls_flag_t::LOAD)
+ {
/*** Window Options ***/
/* Read the window flags */
- for (n = 0; n < 8; n++) do_u32b(&oflag[n], flag);
+ for (n = 0; n < ANGBAND_TERM_MAX; n++)
+ {
+ do_u32b(&oflag[n], flag);
+ }
/* Read the window masks */
- for (n = 0; n < 8; n++) do_u32b(&mask[n], flag);
+ for (n = 0; n < ANGBAND_TERM_MAX; n++)
+ {
+ do_u32b(&mask[n], flag);
+ }
/* Analyze the options */
- for (n = 0; n < 8; n++)
+ for (n = 0; n < ANGBAND_TERM_MAX; n++)
{
/* Analyze the options */
for (i = 0; i < 32; i++)
@@ -1927,61 +1655,34 @@ static void do_options(ls_flag_t flag)
}
}
}
+
if (flag == ls_flag_t::SAVE)
{
- /* Analyze the options */
- for (i = 0; option_info[i].o_desc; i++)
- {
- int os = option_info[i].o_page;
- int ob = option_info[i].o_bit;
-
- /* Process real entries */
- if (option_info[i].o_var)
- {
- /* Set */
- if (*option_info[i].o_var)
- {
- /* Set */
- option_flag[os] |= (1L << ob);
- }
-
- /* Clear */
- else
- {
- /* Clear */
- option_flag[os] &= ~(1L << ob);
- }
- }
- }
-
-
- /*** Normal options ***/
-
- /* Dump the flags */
- for (i = 0; i < 8; i++) do_u32b(&option_flag[i], flag);
-
- /* Dump the masks */
- for (i = 0; i < 8; i++) do_u32b(&option_mask[i], flag);
-
/*** Window options ***/
/* Dump the flags */
- for (i = 0; i < 8; i++) do_u32b(&window_flag[i], flag);
+ for (i = 0; i < ANGBAND_TERM_MAX; i++)
+ {
+ do_u32b(&window_flag[i], flag);
+ }
/* Dump the masks */
- for (i = 0; i < 8; i++) do_u32b(&window_mask[i], flag);
+ for (i = 0; i < ANGBAND_TERM_MAX; i++)
+ {
+ do_u32b(&window_mask[i], flag);
+ }
}
}
/*
- * Handle player inventory
- *
- * FIXME! This function probably could be unified better
- * Note that the inventory is "re-sorted" later by "dungeon()".
+ * Handle player inventory. Note that the inventory is
+ * "re-sorted" later by "dungeon()".
*/
static bool_ do_inventory(ls_flag_t flag)
{
+ auto const &a_info = game->edit_data.a_info;
+
if (flag == ls_flag_t::LOAD)
{
int slot = 0;
@@ -2058,63 +1759,56 @@ static bool_ do_inventory(ls_flag_t flag)
}
if (flag == ls_flag_t::SAVE)
{
- u16b i;
- u16b sent = 0xFFFF;
- for (i = 0; i < INVEN_TOTAL; i++)
+ for (u16b i = 0; i < INVEN_TOTAL; i++)
{
object_type *o_ptr = &p_ptr->inventory[i];
if (!o_ptr->k_idx) continue;
do_u16b(&i, flag);
do_item(o_ptr, flag);
}
- do_u16b(&sent, ls_flag_t::SAVE); /* Sentinel */
+ // Sentinel
+ u16b sent = 0xFFFF;
+ do_u16b(&sent, ls_flag_t::SAVE);
}
/* Success */
return (TRUE);
}
+static void do_message(message &msg, ls_flag_t flag)
+{
+ do_std_string(msg.text, flag);
+ do_u32b(&msg.count, flag);
+ do_byte(&msg.color, flag);
+}
+
/*
* Read the saved messages
*/
-static void do_messages(ls_flag_t flag) /* FIXME! We should be able to unify this better */
+static void do_messages(ls_flag_t flag)
{
- int i;
- char buf[128];
- byte color;
+ auto &messages = game->messages;
- s16b num;
-
- /* Total */
- if (flag == ls_flag_t::SAVE) num = message_num();
+ /* Save/load number of messages */
+ s16b num = messages.size();
do_s16b(&num, flag);
/* Read the messages */
- if (flag == ls_flag_t::LOAD)
+ for (int i = 0; i < num; i++)
{
- byte tmp8u = 0;
- for (i = 0; i < num; i++)
- {
- /* Read the message */
- do_string(buf, 128, ls_flag_t::LOAD);
- do_byte(&color, flag);
- do_byte(&tmp8u, flag);
+ message message;
- /* Save the message */
- message_add(buf, color);
+ if (flag == ls_flag_t::SAVE)
+ {
+ message = messages.at(i);
}
- }
- if (flag == ls_flag_t::SAVE)
- {
- byte holder;
- byte zero = 0;
- for (i = num - 1; i >= 0; i--)
+
+ do_message(message, flag);
+
+ if (flag == ls_flag_t::LOAD)
{
- do_string((char *)message_str((s16b)i), 0, ls_flag_t::SAVE);
- holder = message_color((s16b)i);
- do_byte(&holder, flag);
- do_byte(&zero, flag);
+ messages.add(message);
}
}
}
@@ -2128,7 +1822,7 @@ bool_ load_dungeon(char *ext)
s16b old_dun = dun_level;
/* Construct name */
- sprintf(tmp, "%s.%s", player_base, ext);
+ sprintf(tmp, "%s.%s", game->player_base.c_str(), ext);
path_build(name, 1024, ANGBAND_DIR_SAVE, tmp);
/* Open the file */
@@ -2144,7 +1838,7 @@ bool_ load_dungeon(char *ext)
}
/* Read the dungeon */
- if (!do_dungeon(ls_flag_t::LOAD, FALSE))
+ if (!do_dungeon(ls_flag_t::LOAD, false))
{
dun_level = old_dun;
dungeon_type = old_dungeon_type;
@@ -2161,35 +1855,16 @@ bool_ load_dungeon(char *ext)
return (TRUE);
}
-void do_fate(int i, ls_flag_t flag)
-{
- if ((flag == ls_flag_t::LOAD) && (i >= MAX_FATES)) i = MAX_FATES - 1;
-
- do_byte(&fates[i].fate, flag);
- do_byte(&fates[i].level, flag);
- do_byte(&fates[i].serious, flag);
- do_s16b(&fates[i].o_idx, flag);
- do_s16b(&fates[i].e_idx, flag);
- do_s16b(&fates[i].a_idx, flag);
- do_s16b(&fates[i].v_idx, flag);
- do_s16b(&fates[i].r_idx, flag);
- do_s16b(&fates[i].count, flag);
- do_s16b(&fates[i].time, flag);
- do_byte((byte*)&fates[i].know, flag);
-}
-
/*
* Load/save timers.
*/
static void do_timers(ls_flag_t flag)
{
- timer_type *t_ptr;
-
- for (t_ptr = gl_timers; t_ptr != NULL; t_ptr = t_ptr->next)
+ for (auto &&t_ptr: game->timers)
{
- do_bool(&t_ptr->enabled, flag);
- do_s32b(&t_ptr->delay, flag);
- do_s32b(&t_ptr->countdown, flag);
+ do_std_bool(&t_ptr->m_enabled, flag);
+ do_s32b(&t_ptr->m_delay, flag);
+ do_s32b(&t_ptr->m_countdown, flag);
}
}
@@ -2198,41 +1873,41 @@ static void do_timers(ls_flag_t flag)
*/
static void do_stores(ls_flag_t flag)
{
- u16b tmp16u;
- u16b real_max = 0;
+ auto const &st_info = game->edit_data.st_info;
- /* Note that this forbids max_towns from shrinking, but that is fine */
- std::unique_ptr<byte[]> reals(new byte[max_towns]);
+ // Indexes for "real" towns.
+ std::vector<byte> reals;
+ reals.reserve(max_towns);
- /* Find the real towns */
+ // Fill in the "real" towns if necessary.
if (flag == ls_flag_t::SAVE)
{
for (int i = 1; i < max_towns; i++)
{
- if (!(town_info[i].flags & (TOWN_REAL))) continue;
- reals[real_max++] = i;
+ if (!(town_info[i].flags & TOWN_REAL))
+ {
+ continue;
+ }
+ reals.emplace_back(i);
}
}
- do_u16b(&real_max, flag);
- for (int i = 0; i < real_max; i++)
- {
- do_byte((byte*)&reals[i], flag);
- }
+
+ // Load/save
+ do_vector(flag, reals, do_byte);
/* Read the stores */
- if (flag == ls_flag_t::SAVE) tmp16u = max_st_idx;
- do_u16b(&tmp16u, flag);
- assert(tmp16u <= max_st_idx);
+ u16b n_stores = st_info.size();
+ do_u16b(&n_stores, flag);
+ assert(n_stores <= st_info.size());
- /* Ok now read the real towns */
- for (int i = 0; i < real_max; i++)
+ for (auto const z: reals)
{
- int z = reals[i];
-
- /* Ultra paranoia */
- if (!town_info[z].stocked) create_stores_stock(z);
+ if (!town_info[z].stocked)
+ {
+ create_stores_stock(z);
+ }
- for (int j = 0; j < tmp16u; j++)
+ for (int j = 0; j < n_stores; j++)
{
do_store(&town_info[z].store[j], flag);
}
@@ -2240,395 +1915,398 @@ static void do_stores(ls_flag_t flag)
}
/*
- * Note that this function may not be needed at all.
- * It was taken out of load_player_aux(). Do we need it?
+ * Monster memory
*/
-static void junkinit(void)
+static bool do_monster_lore(ls_flag_t flag)
{
- int i, j;
- p_ptr->inside_quest = 0;
- p_ptr->town_num = 1;
- p_ptr->wilderness_x = 4;
- p_ptr->wilderness_y = 4;
- for (i = 0; i < max_wild_x; i++)
- {
- for (j = 0; j < max_wild_y; j++)
- {
- wild_map[j][i].seed = rand_int(0x10000000);
+ auto &r_info = game->edit_data.r_info;
+
+ do_array("monster races", flag, r_info, r_info.size(),
+ [](auto r_ptr, auto flag) -> void {
+ do_s16b(&r_ptr->r_pkills, flag);
+ do_s16b(&r_ptr->max_num, flag);
+ do_bool(&r_ptr->on_saved, flag);
}
- }
-}
+ );
-static void morejunk(void)
-{
- sp_ptr = &sex_info[p_ptr->psex]; /* Sex */
- rp_ptr = &race_info[p_ptr->prace]; /* Raceclass */
- rmp_ptr = &race_mod_info[p_ptr->pracem];
- cp_ptr = &class_info[p_ptr->pclass];
- spp_ptr = &class_info[p_ptr->pclass].spec[p_ptr->pspec];
+ return true;
}
/*
- * Actually read the savefile
+ * Object memory
*/
-static bool_ do_savefile_aux(ls_flag_t flag)
+static bool do_object_lore(ls_flag_t flag)
{
- int i, j;
+ auto &k_info = game->edit_data.k_info;
- byte tmp8u;
- u16b tmp16u;
+ do_array("object kinds", flag, k_info, k_info.size(),
+ [](auto k_ptr, auto flag) -> void {
+ do_bool(&k_ptr->aware, flag);
+ do_bool(&k_ptr->tried, flag);
+ do_bool(&k_ptr->artifact, flag);
+ }
+ );
- /* Mention the savefile version */
- if (flag == ls_flag_t::LOAD)
+ return true;
+}
+
+
+static bool do_towns(ls_flag_t flag)
+{
+ auto &d_info = game->edit_data.d_info;
+
+ u16b max_towns_ldsv = max_towns;
+
+ do_u16b(&max_towns_ldsv, flag);
+
+ if ((flag == ls_flag_t::LOAD) && (max_towns_ldsv > max_towns))
{
- if (vernum < 100)
- {
- note(format("Savefile version %lu too old! ", vernum));
- return FALSE;
- }
- else
- {
- note(format("Loading version %lu savefile... ", vernum));
- }
+ note("Too many towns!");
+ return false;
}
+
if (flag == ls_flag_t::SAVE)
{
- sf_when = time((time_t *) 0); /* Note when file was saved */
- sf_saves++; /* Increment the saves ctr */
+ max_towns_ldsv = TOWN_RANDOM;
}
- /* Handle version bytes. FIXME! DG wants me to change this all around */
- if (flag == ls_flag_t::LOAD)
- {
- u32b mt32b;
- byte mtbyte;
+ do_u16b(&max_towns_ldsv, flag);
- /* Discard all this, we've already read it */
- do_u32b(&mt32b, flag);
- do_byte(&mtbyte, flag);
- }
- if (flag == ls_flag_t::SAVE)
+ if ((flag == ls_flag_t::LOAD) && (max_towns_ldsv != TOWN_RANDOM))
{
- u32b saver;
- saver = SAVEFILE_VERSION;
- do_u32b(&saver, flag);
- tmp8u = (byte)rand_int(256);
- do_byte(&tmp8u, flag); /* 'encryption' */
+ note("Different random towns base!");
+ return false;
}
- /* Kept only for compatibility; always set to 0 */
+ for (std::size_t i = 0; i < max_towns; i++)
{
- u32b tmp32u = 0;
- do_u32b(&tmp32u, flag);
- }
+ auto town = &town_info[i];
- /* Time of last save */
- do_u32b(&sf_when, flag);
+ do_bool(&town->destroyed, flag);
- /* Number of past lives */
- do_u16b(&sf_lives, flag);
+ if (i >= TOWN_RANDOM)
+ {
+ do_seed(&town->seed, flag);
+ do_byte(&town->flags, flag);
- /* Number of times saved */
- do_u16b(&sf_saves, flag);
+ // Create stock if necessary
+ if ((town_info->flags & TOWN_REAL) && (flag == ls_flag_t::LOAD))
+ {
+ create_stores_stock(i);
+ }
+ }
+ }
- /* Game module */
if (flag == ls_flag_t::SAVE)
- strcpy(loaded_game_module, game_module);
- do_string(loaded_game_module, 80, flag);
-
- /* Timers */
- do_timers(flag);
-
- /* Read RNG state */
- do_randomizer(flag);
-
- /* Automatizer state */
- do_byte((byte*)&automatizer_enabled, flag);
+ {
+ max_towns_ldsv = d_info.size();
+ }
- /* Then the options */
- do_options(flag);
+ do_u16b(&max_towns_ldsv, flag);
- /* Then the "messages" */
- do_messages(flag);
+ if ((flag == ls_flag_t::LOAD) && (max_towns_ldsv > d_info.size()))
+ {
+ note("Too many dungeon types!");
+ return false;
+ }
- /* Monster Memory */
- if (flag == ls_flag_t::SAVE) tmp16u = max_r_idx;
- do_u16b(&tmp16u, flag);
+ // Town quest entrances
+ u16b max_quests_ldsv = TOWN_DUNGEON;
+ do_u16b(&max_quests_ldsv, flag);
- /* Incompatible save files */
- if ((flag == ls_flag_t::LOAD) && (tmp16u > max_r_idx))
+ if ((flag == ls_flag_t::LOAD) && (max_quests_ldsv > TOWN_DUNGEON))
{
- note(format("Too many (%u) monster races!", tmp16u));
- return (FALSE);
+ note("Too many town per dungeons!");
+ return false;
}
- /* Read the available records */
- for (i = 0; i < tmp16u; i++)
+ for (std::size_t i = 0; i < max_towns_ldsv; i++)
{
- /* Read the lore */
- do_lore(i, flag);
+ for (std::size_t j = 0; j < max_quests_ldsv; j++)
+ {
+ do_s16b(&(d_info[i].t_idx[j]), flag);
+ do_s16b(&(d_info[i].t_level[j]), flag);
+ }
+ do_s16b(&(d_info[i].t_num), flag);
}
- /* Object Memory */
- if (flag == ls_flag_t::SAVE) tmp16u = max_k_idx;
- do_u16b(&tmp16u, flag);
+ return true;
+}
- /* Incompatible save files */
- if ((flag == ls_flag_t::LOAD) && (tmp16u > max_k_idx))
- {
- note(format("Too many (%u) object kinds!", tmp16u));
- return (FALSE);
- }
+static bool do_quests(ls_flag_t flag)
+{
+ do_array("quests", flag, quest, MAX_Q_IDX,
+ [](auto q, auto flag) {
+ // Load/save the data
+ do_s16b(&q->status, flag);
+ for (auto &quest_data : q->data)
+ {
+ do_s32b(&quest_data, flag);
+ }
+ // Initialize if necessary
+ if ((flag == ls_flag_t::LOAD) && (q->init != NULL))
+ {
+ q->init();
+ }
+ }
+ );
+
+ return true;
+}
+
+static bool do_wilderness(ls_flag_t flag)
+{
+ auto &wilderness = game->wilderness;
+
+ // Player position and "mode" wrt. wilderness
+ do_s32b(&p_ptr->wilderness_x, flag);
+ do_s32b(&p_ptr->wilderness_y, flag);
+ do_bool(&p_ptr->wild_mode, flag);
+ do_bool(&p_ptr->old_wild_mode, flag);
- /* Read the object memory */
- for (i = 0; i < tmp16u; i++) do_xtra(i, flag);
- if (flag == ls_flag_t::LOAD) junkinit();
+ // Size of the wilderness
+ u16b wild_x_size = wilderness.width();
+ u16b wild_y_size = wilderness.height();
+ do_u16b(&wild_x_size, flag);
+ do_u16b(&wild_y_size, flag);
+ if (flag == ls_flag_t::LOAD)
{
- u16b max_towns_ldsv;
- u16b max_quests_ldsv;
- if (flag == ls_flag_t::SAVE) max_towns_ldsv = max_towns;
- /* Number of towns */
- do_u16b(&max_towns_ldsv, flag);
- /* Incompatible save files */
- if ((flag == ls_flag_t::LOAD) && (max_towns_ldsv > max_towns))
+ if ((wild_x_size > wilderness.width()) || (wild_y_size > wilderness.height()))
{
- note(format("Too many (%u) towns!", max_towns_ldsv));
- return (FALSE);
+ note("Wilderness is too big!");
+ return false;
}
- /* Min of random towns */
- if (flag == ls_flag_t::SAVE) max_towns_ldsv = TOWN_RANDOM;
- do_u16b(&max_towns_ldsv, flag);
- /* Incompatible save files */
- if ((flag == ls_flag_t::LOAD) && (max_towns_ldsv != TOWN_RANDOM))
+ }
+
+ // Save/load wilderness tile state
+ for (std::size_t x = 0; x < wild_x_size; x++)
+ {
+ for (std::size_t y = 0; y < wild_y_size; y++)
{
- note(format("Different random towns base (%u)!", max_towns_ldsv));
- return (FALSE);
+ auto w = &wilderness(x, y);
+ do_seed(&w->seed, flag);
+ do_u16b(&w->entrance, flag);
+ do_bool(&w->known, flag);
}
+ }
- for (i = 0; i < max_towns; i++)
- {
- do_byte((byte*)&town_info[i].destroyed, flag);
+ return true;
+}
- if (i >= TOWN_RANDOM)
- {
- do_u32b(&town_info[i].seed, flag);
- do_byte(&town_info[i].numstores, flag);
- do_byte(&town_info[i].flags, flag);
+static void do_randart(random_artifact *ra_ptr, ls_flag_t flag)
+{
+ do_std_string(ra_ptr->name_full, flag);
+ do_std_string(ra_ptr->name_short, flag);
+ do_byte(&ra_ptr->level, flag);
+ do_byte(&ra_ptr->attr, flag);
+ do_u32b(&ra_ptr->cost, flag);
+ do_byte(&ra_ptr->activation, flag);
+ do_byte(&ra_ptr->generated, flag);
+}
- /* If the town is realy used create a sock */
- if ((town_info[i].flags & (TOWN_REAL)) && (flag == ls_flag_t::LOAD))
- {
- create_stores_stock(i);
- }
- }
+static bool do_randarts(ls_flag_t flag)
+{
+ do_vector(flag, game->random_artifacts, do_randart);
+ return true;
+}
+
+static bool do_artifacts(ls_flag_t flag)
+{
+ auto &a_info = game->edit_data.a_info;
+
+ do_array("artifacts", flag, a_info, a_info.size(),
+ [](auto a_ptr, auto flag) {
+ do_byte(&a_ptr->cur_num, flag);
}
+ );
- /* Number of dungeon */
- if (flag == ls_flag_t::SAVE) max_towns_ldsv = max_d_idx;
- do_u16b(&max_towns_ldsv, flag);
+ return true;
+}
- /* Incompatible save files */
- if ((flag == ls_flag_t::LOAD) && (max_towns_ldsv > max_d_idx))
- {
- note(format("Too many dungeon types (%u)!", max_towns_ldsv));
- return (FALSE);
+static bool do_fates(ls_flag_t flag)
+{
+ do_array("fates", flag, fates, MAX_FATES,
+ [](auto fate, auto flag) {
+ do_byte(&fate->fate, flag);
+ do_byte(&fate->level, flag);
+ do_byte(&fate->serious, flag);
+ do_s16b(&fate->o_idx, flag);
+ do_s16b(&fate->e_idx, flag);
+ do_s16b(&fate->a_idx, flag);
+ do_s16b(&fate->v_idx, flag);
+ do_s16b(&fate->r_idx, flag);
+ do_s16b(&fate->count, flag);
+ do_s16b(&fate->time, flag);
+ do_bool(&fate->know, flag);
}
+ );
- /* Number of towns per dungeon */
- if (flag == ls_flag_t::SAVE) max_quests_ldsv = TOWN_DUNGEON;
- do_u16b(&max_quests_ldsv, flag);
- /* Incompatible save files */
- if ((flag == ls_flag_t::LOAD) && (max_quests_ldsv > TOWN_DUNGEON))
- {
- note(format("Too many town per dungeons (%u)!", max_quests_ldsv));
- return (FALSE);
+ return true;
+}
+
+static bool do_floor_inscriptions(ls_flag_t flag)
+{
+ do_array("inscriptions", flag, p_ptr->inscriptions, MAX_INSCRIPTIONS,
+ [](auto i_ptr, auto flag) {
+ do_std_bool(i_ptr, flag);
}
+ );
- for (i = 0; i < max_towns_ldsv; i++)
- {
- for (j = 0; j < max_quests_ldsv; j++)
- {
- do_s16b(&(d_info[i].t_idx[j]), flag);
- do_s16b(&(d_info[i].t_level[j]), flag);
- }
- do_s16b(&(d_info[i].t_num), flag);
+ return true;
+}
+
+static bool do_player_hd(ls_flag_t flag)
+{
+ auto &player_hp = game->player_hp;
+
+ do_array("hit dice entries", flag, player_hp, PY_MAX_LEVEL,
+ [](auto hp_ptr, auto flag) {
+ do_s16b(hp_ptr, flag);
}
+ );
- /* Sanity check number of quests */
- if (flag == ls_flag_t::SAVE) max_quests_ldsv = MAX_Q_IDX;
- do_u16b(&max_quests_ldsv, flag);
+ return true;
+}
+
+
+/*
+ * Actually read the savefile
+ */
+static bool_ do_savefile_aux(ls_flag_t flag)
+{
+ auto &class_info = game->edit_data.class_info;
+ auto const &race_info = game->edit_data.race_info;
+ auto const &race_mod_info = game->edit_data.race_mod_info;
- /* Incompatible save files */
- if ((flag == ls_flag_t::LOAD) && (max_quests_ldsv != MAX_Q_IDX))
+ /* Mention the savefile version */
+ if (flag == ls_flag_t::LOAD)
+ {
+ if (vernum != SAVEFILE_VERSION)
{
- note(format("Invalid number of quests (%u)!", max_quests_ldsv));
- return (FALSE);
+ note("Incompatible save file version");
+ return FALSE;
}
+ }
- for (i = 0; i < MAX_Q_IDX; i++)
- {
- do_s16b(&quest[i].status, flag);
- for (auto &quest_data : quest[i].data)
- {
- do_s32b(&quest_data, flag);
- }
+ /* Handle version bytes */
+ if (flag == ls_flag_t::LOAD)
+ {
+ /* Discard all this, we've already read it */
+ u32b mt32b;
+ do_u32b(&mt32b, flag);
+ }
+ if (flag == ls_flag_t::SAVE)
+ {
+ u32b saver;
+ saver = SAVEFILE_VERSION;
+ do_u32b(&saver, flag);
+ }
- /* Init the hooks */
- if ((flag == ls_flag_t::LOAD) && (quest[i].init != NULL))
- {
- quest[i].init(i);
- }
- }
+ /* Game module */
+ {
+ std::string loaded_game_module;
- /* Position in the wilderness */
- do_s32b(&p_ptr->wilderness_x, flag);
- do_s32b(&p_ptr->wilderness_y, flag);
- do_byte((byte*)&p_ptr->wild_mode, flag);
- do_byte((byte*)&p_ptr->old_wild_mode, flag);
+ if (flag == ls_flag_t::SAVE)
+ {
+ loaded_game_module = game_module;
+ }
+ do_std_string(loaded_game_module, flag);
+ // Check for incompatible module
+ if (flag == ls_flag_t::LOAD)
{
- s32b wild_x_size, wild_y_size;
- if (flag == ls_flag_t::SAVE)
+ if (!module_savefile_loadable(loaded_game_module))
{
- wild_x_size = max_wild_x;
- wild_y_size = max_wild_y;
- }
- /* Size of the wilderness */
- do_s32b(&wild_x_size, flag);
- do_s32b(&wild_y_size, flag);
- /* Incompatible save files */
- if ((flag == ls_flag_t::LOAD) &&
- ((wild_x_size > max_wild_x) || (wild_y_size > max_wild_y)))
- {
- note(format("Wilderness is too big (%u/%u)!",
- wild_x_size, wild_y_size));
- return (FALSE);
- }
- /* Wilderness seeds */
- for (i = 0; i < wild_x_size; i++)
- {
- for (j = 0; j < wild_y_size; j++)
- {
- do_u32b(&wild_map[j][i].seed, flag);
- do_u16b(&wild_map[j][i].entrance, flag);
- do_byte((byte*)&wild_map[j][i].known, flag);
- }
+ note(fmt::format("Bad game module. Savefile was saved with module '{:s}' but game is '{:s}'.",
+ loaded_game_module,
+ game_module).c_str());
+ return FALSE;
}
}
}
- /* Load the random artifacts. */
- if (flag == ls_flag_t::SAVE) tmp16u = MAX_RANDARTS;
- do_u16b(&tmp16u, flag);
- if ((flag == ls_flag_t::LOAD) && (tmp16u > MAX_RANDARTS))
+ /* Timers */
+ do_timers(flag);
+
+ /* Read RNG state */
+ do_randomizer(flag);
+
+ /* Automatizer state */
+ do_bool(&automatizer_enabled, flag);
+
+ /* Then the options */
+ do_options(flag);
+
+ /* Then the "messages" */
+ do_messages(flag);
+
+ if (!do_monster_lore(flag))
{
- note(format("Too many (%u) random artifacts!", tmp16u));
- return (FALSE);
+ return FALSE;
}
- for (i = 0; i < tmp16u; i++)
- {
- random_artifact *ra_ptr = &random_artifacts[i];
- do_string(ra_ptr->name_full, 80, flag);
- do_string(ra_ptr->name_short, 80, flag);
- do_byte(&ra_ptr->level, flag);
- do_byte(&ra_ptr->attr, flag);
- do_u32b(&ra_ptr->cost, flag);
- do_byte(&ra_ptr->activation, flag);
- do_byte(&ra_ptr->generated, flag);
+ if (!do_object_lore(flag))
+ {
+ return FALSE;
}
- /* Load the Artifacts */
- if (flag == ls_flag_t::SAVE) tmp16u = max_a_idx;
- do_u16b(&tmp16u, flag);
- /* Incompatible save files */
- if ((flag == ls_flag_t::LOAD) && (tmp16u > max_a_idx))
+ if (!do_towns(flag))
{
- note(format("Too many (%u) artifacts!", tmp16u));
- return (FALSE);
+ return FALSE;
}
- /* Read the artifact flags */
- for (i = 0; i < tmp16u; i++)
+ if (!do_quests(flag))
{
- do_byte(&(&a_info[i])->cur_num, flag);
+ return FALSE;
}
- /* Fates */
- if (flag == ls_flag_t::SAVE) tmp16u = MAX_FATES;
- do_u16b(&tmp16u, flag);
-
- /* Incompatible save files */
- if ((flag == ls_flag_t::LOAD) && (tmp16u > MAX_FATES))
+ if (!do_wilderness(flag))
{
- note(format("Too many (%u) fates!", tmp16u));
- return (FALSE);
+ return FALSE;
}
- /* Read the fate flags */
- for (i = 0; i < tmp16u; i++)
+ if (!do_randarts(flag))
{
- do_fate(i, flag);
+ return FALSE;
}
- /* Load the Traps */
- if (flag == ls_flag_t::SAVE) tmp16u = max_t_idx;
- do_u16b(&tmp16u, flag);
-
- /* Incompatible save files */
- if ((flag == ls_flag_t::LOAD) && (tmp16u > max_t_idx))
+ if (!do_artifacts(flag))
{
- note(format("Too many (%u) traps!", tmp16u));
- return (FALSE);
+ return FALSE;
}
- /* fate flags */
- for (i = 0; i < tmp16u; i++)
+ if (!do_fates(flag))
{
- do_byte((byte*)&t_info[i].ident, flag);
+ return FALSE;
}
- /* inscription knowledge */
- if (flag == ls_flag_t::SAVE) tmp16u = MAX_INSCRIPTIONS;
- do_u16b(&tmp16u, flag);
-
- /* Incompatible save files */
- if ((flag == ls_flag_t::LOAD) && (tmp16u > MAX_INSCRIPTIONS))
+ if (!do_floor_inscriptions(flag))
{
- note(format("Too many (%u) inscriptions!", tmp16u));
- return (FALSE);
+ return FALSE;
}
- /* Read the inscription flag */
- for (i = 0; i < tmp16u; i++)
- do_byte((byte*)&inscription_info[i].know, flag);
-
-
- /* Read the extra stuff */
if (!do_extra(flag))
+ {
return FALSE;
+ }
-
- /* player_hp array */
- if (flag == ls_flag_t::SAVE) tmp16u = PY_MAX_LEVEL;
- do_u16b(&tmp16u, flag);
- /* Incompatible save files */
- if ((flag == ls_flag_t::LOAD) && (tmp16u > PY_MAX_LEVEL))
+ if (!do_player_hd(flag))
{
- note(format("Too many (%u) hitpoint entries!", tmp16u));
- return (FALSE);
+ return FALSE;
}
- /* Read the player_hp array */
- for (i = 0; i < tmp16u; i++)
+ if (flag == ls_flag_t::LOAD)
{
- do_s16b(&player_hp[i], flag);
+ // Make sure that the auxiliary pointers for player
+ // class, race, etc. point to the right places.
+ rp_ptr = &race_info[p_ptr->prace];
+ rmp_ptr = &race_mod_info[p_ptr->pracem];
+ cp_ptr = &class_info[p_ptr->pclass];
+ spp_ptr = &class_info[p_ptr->pclass].spec[p_ptr->pspec];
}
- if (flag == ls_flag_t::LOAD) morejunk();
-
/* Read the pet command settings */
do_byte(&p_ptr->pet_follow_distance, flag);
do_byte(&p_ptr->pet_open_doors, flag);
@@ -2638,10 +2316,13 @@ static bool_ do_savefile_aux(ls_flag_t flag)
do_s16b(&p_ptr->dripping_tread, flag);
/* Read the inventory */
- if (!do_inventory(flag) && (flag == ls_flag_t::LOAD)) /* do NOT reverse this ordering */
+ if (!do_inventory(flag))
{
- note("Unable to read inventory");
- return (FALSE);
+ if (flag == ls_flag_t::LOAD)
+ {
+ note("Unable to read inventory");
+ return FALSE;
+ }
}
/* Stores */
@@ -2651,35 +2332,25 @@ static bool_ do_savefile_aux(ls_flag_t flag)
if (!death)
{
/* Dead players have no dungeon */
- if (flag == ls_flag_t::LOAD) note("Restoring Dungeon...");
- if ((flag == ls_flag_t::LOAD) && (!do_dungeon(ls_flag_t::LOAD, FALSE)))
+ if (flag == ls_flag_t::LOAD)
+ {
+ note("Restoring Dungeon...");
+ }
+
+ if ((flag == ls_flag_t::LOAD) && (!do_dungeon(ls_flag_t::LOAD, false)))
{
note("Error reading dungeon data");
- return (FALSE);
+ return FALSE;
}
- if (flag == ls_flag_t::SAVE) do_dungeon(ls_flag_t::SAVE, FALSE);
- my_sentinel("Before ghost data", 435, flag);
- my_sentinel("After ghost data", 320, flag);
- }
- {
- byte foo = 0;
if (flag == ls_flag_t::SAVE)
{
- /*
- * Safety Padding. It's there
- * for a good reason. Trust me on
- * this. Keep this at the *END*
- * of the file, and do *NOT* try to
- * read it. Insert any new stuff before
- * this position.
- */
- do_byte(&foo, ls_flag_t::SAVE);
+ do_dungeon(ls_flag_t::SAVE, false);
}
}
/* Success */
- return (TRUE);
+ return TRUE;
}
@@ -2687,7 +2358,7 @@ static bool_ do_savefile_aux(ls_flag_t flag)
/*
* Actually read the savefile
*/
-static errr rd_savefile(void)
+static errr rd_savefile()
{
errr err = 0;
@@ -2725,10 +2396,8 @@ static errr rd_savefile(void)
* Note that we always try to load the "current" savefile, even if
* there is no such file, so we must check for "empty" savefile names.
*/
-bool_ load_player(void)
+bool_ load_player()
{
- int fd = -1;
-
errr err = 0;
cptr what = "generic";
@@ -2747,7 +2416,7 @@ bool_ load_player(void)
/* XXX XXX XXX Fix this */
/* Verify the existance of the savefile */
- if (!file_exist(savefile))
+ if (!boost::filesystem::exists(savefile))
{
/* Give a message */
msg_format("Savefile does not exist: %s", savefile);
@@ -2761,45 +2430,34 @@ bool_ load_player(void)
if (!err)
{
/* Open the savefile */
- fd = fd_open(savefile, O_RDONLY);
+ int fd = fd_open(savefile, O_RDONLY);
/* No file */
if (fd < 0) err = -1;
/* Message (below) */
if (err) what = "Cannot open savefile";
+
+ /* Close the file */
+ if (!err) fd_close(fd);
}
/* Process file */
if (!err)
{
- byte tmp8u = 0;
-
/* Open the file XXX XXX XXX XXX Should use Angband file interface */
fff = my_fopen(savefile, "rb");
-/* fff = fdopen(fd, "r"); */
/* Read the first four bytes */
do_u32b(&vernum, ls_flag_t::LOAD);
- do_byte(&tmp8u, ls_flag_t::LOAD); // For comatibility with old savefiles
- /* XXX XXX XXX XXX Should use Angband file interface */
my_fclose(fff);
- /* fclose(fff) */
- /* Close the file */
- fd_close(fd);
}
/* Process file */
if (!err)
{
-
- /* Extract version */
- sf_major = VERSION_MAJOR;
- sf_minor = VERSION_MINOR;
- sf_patch = VERSION_PATCH;
-
/* Clear screen */
Term_clear();
@@ -2840,9 +2498,6 @@ bool_ load_player(void)
return (TRUE);
}
- /* Count lives */
- sf_lives++;
-
/* Forget turns */
turn = old_turn = 0;
@@ -2857,7 +2512,7 @@ bool_ load_player(void)
if (p_ptr->chp >= 0)
{
/* Reset cause of death */
- (void)strcpy(died_from, "(alive and well)");
+ game->died_from = "(alive and well)";
}
/* Success */
@@ -2866,8 +2521,8 @@ bool_ load_player(void)
/* Message */
- msg_format("Error (%s) reading %d.%d.%d savefile.",
- what, sf_major, sf_minor, sf_patch);
+ msg_format("Error (%s) reading savefile (version " FMTu32b ").",
+ what, vernum);
msg_print(NULL);
/* Oops */
@@ -2895,7 +2550,7 @@ static bool_ save_player_aux(char *name)
if (fd >= 0)
{
/* Close the "fd" */
- (void)fd_close(fd);
+ fd_close(fd);
/* Open the savefile */
fff = my_fopen(name, "wb");
@@ -2914,7 +2569,7 @@ static bool_ save_player_aux(char *name)
if (!ok)
{
/* Remove "broken" files */
- (void)fd_kill(name);
+ fd_kill(name);
}
}
@@ -2928,7 +2583,7 @@ static bool_ save_player_aux(char *name)
/*
* Attempt to save the player in a savefile
*/
-bool_ save_player(void)
+bool_ save_player()
{
int result = FALSE;
char safe[1024];