summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorzelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573>2007-09-16 03:39:41 +0000
committerzelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573>2007-09-16 03:39:41 +0000
commitdcf7801daff4c7c76e461c5ad08749394e64466b (patch)
treeec4411652736ce6267b0a1a9c07782dd4a089497
parentcf87ca267353855c40cc29c08eb40b646693e3e2 (diff)
downloadcrawl-ref-dcf7801daff4c7c76e461c5ad08749394e64466b.tar.gz
crawl-ref-dcf7801daff4c7c76e461c5ad08749394e64466b.zip
Add dump sections for branch/area details for turns and
experience/kills, with the section names being turns_by_place and kills_by_place. Also includes a "visits" dump section (included in the "misc" section") a brief description of the number of branches/levels/areas/etc you visited. Breaks savefile compatibility. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@2102 c06c8d41-db1a-0410-9941-cceddc491573
-rw-r--r--crawl-ref/docs/crawl_options.txt5
-rw-r--r--crawl-ref/init.txt5
-rw-r--r--crawl-ref/source/acr.cc64
-rw-r--r--crawl-ref/source/chardump.cc290
-rw-r--r--crawl-ref/source/debug.cc4
-rw-r--r--crawl-ref/source/externs.h62
-rw-r--r--crawl-ref/source/files.cc37
-rw-r--r--crawl-ref/source/files.h6
-rw-r--r--crawl-ref/source/initfile.cc6
-rw-r--r--crawl-ref/source/makefile4
-rw-r--r--crawl-ref/source/makefile.unix8
-rw-r--r--crawl-ref/source/misc.cc11
-rw-r--r--crawl-ref/source/monstuff.cc56
-rw-r--r--crawl-ref/source/player.cc242
-rw-r--r--crawl-ref/source/player.h4
-rw-r--r--crawl-ref/source/tags.cc95
16 files changed, 816 insertions, 83 deletions
diff --git a/crawl-ref/docs/crawl_options.txt b/crawl-ref/docs/crawl_options.txt
index 7d280d0de4..2054c1c91a 100644
--- a/crawl-ref/docs/crawl_options.txt
+++ b/crawl-ref/docs/crawl_options.txt
@@ -1148,8 +1148,9 @@ dump_item_origin_price = 100
dump_message_count = 7
The number of last messages to be displayed in character dump files.
-dump_order = header,hiscore,stats,misc,notes,inventory,skills
-dump_order += spells,overview,mutations,messages,screenshot,kills
+dump_order = header,hiscore,stats,misc,notes,inventory,turns_by_place,
+dump_order += skills,spells,overview,mutations,messages,screenshot
+dump_order += kills_by_place,,kills
Controls the order of sections in the dump. You can use multiple
dump_order lines - all lines but the first must use dump_order +=
diff --git a/crawl-ref/init.txt b/crawl-ref/init.txt
index e18217fc73..3801452118 100644
--- a/crawl-ref/init.txt
+++ b/crawl-ref/init.txt
@@ -226,8 +226,9 @@ message_colour = lightcyan:LOW MAGIC WARNING
# dump_item_origins = all,artifacts,ego_arm,ego_weap,jewellery,runes
# dump_item_origin_price = 100
# dump_message_count = 7
-# dump_order = header,hiscore,stats,misc,notes,inventory,skills
-# dump_order += spells,overview,mutations,messages,screenshot,kills
+# dump_order = header,hiscore,stats,misc,notes,inventory,turns_by_place,
+# dump_order += skills,spells,overview,mutations,messages,screenshot
+# dump_order += kills_by_place,,kills
##### 5-b Notes #################################
#
diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc
index 1fdb6f0b92..b5d585bc6b 100644
--- a/crawl-ref/source/acr.cc
+++ b/crawl-ref/source/acr.cc
@@ -1063,6 +1063,68 @@ static void input()
}
else
viewwindow(true, false);
+
+ if (you.num_turns != -1)
+ {
+ PlaceInfo& curr_PlaceInfo = you.get_place_info();
+ PlaceInfo delta;
+
+ delta.turns_total++;
+ delta.elapsed_total += you.time_taken;
+
+ switch(you.running)
+ {
+ case RMODE_INTERLEVEL:
+ delta.turns_interlevel++;
+ delta.elapsed_interlevel += you.time_taken;
+ break;
+
+ case RMODE_EXPLORE_GREEDY:
+ case RMODE_EXPLORE:
+ delta.turns_explore++;
+ delta.elapsed_explore += you.time_taken;
+ break;
+
+ case RMODE_TRAVEL:
+ delta.turns_travel++;
+ delta.elapsed_travel += you.time_taken;
+ break;
+
+ default:
+ // prev_was_rest is needed so that the turn in which
+ // a player is interrupted from resting is counted
+ // as a resting turn, rather than "other".
+ static bool prev_was_rest = false;
+
+ if (!you.delay_queue.empty() &&
+ you.delay_queue.front().type == DELAY_REST)
+ prev_was_rest = true;
+
+ if (prev_was_rest)
+ {
+ delta.turns_resting++;
+ delta.elapsed_resting += you.time_taken;
+
+ }
+ else
+ {
+ delta.turns_other++;
+ delta.elapsed_other += you.time_taken;
+ }
+
+ if (you.delay_queue.empty() ||
+ you.delay_queue.front().type != DELAY_REST)
+ prev_was_rest = false;
+
+ break;
+ }
+
+ you.global_info += delta;
+ you.global_info.assert_validity();
+
+ curr_PlaceInfo += delta;
+ curr_PlaceInfo.assert_validity();
+ }
}
static bool toggle_flag( bool* flag, const char* flagname )
@@ -2957,7 +3019,7 @@ static bool initialise(void)
load( you.entering_level? you.transit_stair : DNGN_STONE_STAIRS_DOWN_I,
you.entering_level? LOAD_ENTER_LEVEL :
newc ? LOAD_START_GAME : LOAD_RESTART_GAME,
- true, -1, you.where_are_you );
+ NUM_LEVEL_AREA_TYPES, -1, you.where_are_you );
#if DEBUG_DIAGNOSTICS
// Debug compiles display a lot of "hidden" information, so we auto-wiz
diff --git a/crawl-ref/source/chardump.cc b/crawl-ref/source/chardump.cc
index d69ce9ce23..856d259935 100644
--- a/crawl-ref/source/chardump.cc
+++ b/crawl-ref/source/chardump.cc
@@ -73,7 +73,9 @@ static void sdump_religion(dump_params &);
static void sdump_burden(dump_params &);
static void sdump_hunger(dump_params &);
static void sdump_transform(dump_params &);
+static void sdump_visits(dump_params &);
static void sdump_misc(dump_params &);
+static void sdump_turns_by_place(dump_params &);
static void sdump_notes(dump_params &);
static void sdump_inventory(dump_params &);
static void sdump_skills(dump_params &);
@@ -81,6 +83,7 @@ static void sdump_spells(dump_params &);
static void sdump_mutations(dump_params &);
static void sdump_messages(dump_params &);
static void sdump_screenshot(dump_params &);
+static void sdump_kills_by_place(dump_params &);
static void sdump_kills(dump_params &);
static void sdump_newline(dump_params &);
static void sdump_overview(dump_params &);
@@ -115,33 +118,36 @@ struct dump_params
};
static dump_section_handler dump_handlers[] = {
- { "header", sdump_header },
- { "stats", sdump_stats },
- { "location", sdump_location },
- { "religion", sdump_religion },
- { "burden", sdump_burden },
- { "hunger", sdump_hunger },
- { "transform", sdump_transform },
- { "misc", sdump_misc },
- { "notes", sdump_notes },
- { "inventory", sdump_inventory },
- { "skills", sdump_skills },
- { "spells", sdump_spells },
- { "mutations", sdump_mutations },
- { "messages", sdump_messages },
- { "screenshot", sdump_screenshot },
- { "kills", sdump_kills },
- { "overview", sdump_overview },
- { "hiscore", sdump_hiscore },
+ { "header", sdump_header },
+ { "stats", sdump_stats },
+ { "location", sdump_location },
+ { "religion", sdump_religion },
+ { "burden", sdump_burden },
+ { "hunger", sdump_hunger },
+ { "transform", sdump_transform },
+ { "visits", sdump_visits },
+ { "misc", sdump_misc },
+ { "turns_by_place", sdump_turns_by_place},
+ { "notes", sdump_notes },
+ { "inventory", sdump_inventory },
+ { "skills", sdump_skills },
+ { "spells", sdump_spells },
+ { "mutations", sdump_mutations },
+ { "messages", sdump_messages },
+ { "screenshot", sdump_screenshot },
+ { "kills_by_place", sdump_kills_by_place},
+ { "kills", sdump_kills },
+ { "overview", sdump_overview },
+ { "hiscore", sdump_hiscore },
// Conveniences for the .crawlrc artist.
- { "", sdump_newline },
- { "-", sdump_separator },
+ { "", sdump_newline },
+ { "-", sdump_separator },
#ifdef CLUA_BINDINGS
- { NULL, sdump_lua }
+ { NULL, sdump_lua }
#else
- { NULL, NULL }
+ { NULL, NULL }
#endif
};
@@ -267,6 +273,74 @@ static void sdump_transform(dump_params &par)
}
}
+static void sdump_visits(dump_params &par)
+{
+ std::string &text(par.text);
+
+ std::vector<PlaceInfo> branches_visited =
+ you.get_all_place_info(true, true);
+
+ PlaceInfo branches_total;
+ for (unsigned int i = 0; i < branches_visited.size(); i++)
+ branches_total += branches_visited[i];
+
+ text += make_stringf("You have visited %ld branch",
+ branches_visited.size());
+ if (branches_visited.size() > 1)
+ text += "es";
+ text += make_stringf(" of the dungeon, and seen %ld of its level",
+ branches_total.levels_seen);
+ if (branches_total.levels_seen > 1)
+ text += "s";
+ text += ".\n";
+
+ PlaceInfo place_info = you.get_place_info(LEVEL_PANDEMONIUM);
+ if (place_info.num_visits > 0)
+ {
+ text += make_stringf("You have visited Pandemonium %ld time",
+ place_info.num_visits);
+ if (place_info.num_visits > 1)
+ text += "s";
+ text += make_stringf(", and seen %ld of its levels.\n",
+ place_info.levels_seen);
+ if (place_info.levels_seen > 1)
+ text += "s";
+ text += ".\n";
+ }
+
+ place_info = you.get_place_info(LEVEL_ABYSS);
+ if (place_info.num_visits > 0)
+ {
+ text += make_stringf("You have visited the Abyss %ld time",
+ place_info.num_visits);
+ if (place_info.num_visits > 1)
+ text += "s";
+ text += ".\n";
+ }
+
+ place_info = you.get_place_info(LEVEL_LABYRINTH);
+ if (place_info.num_visits > 0)
+ {
+ text += make_stringf("You have visited %ld Labyrinth",
+ place_info.num_visits);
+ if (place_info.num_visits > 1)
+ text += "s";
+ text += ".\n";
+ }
+
+ place_info = you.get_place_info(LEVEL_PORTAL_VAULT);
+ if (place_info.num_visits > 0)
+ {
+ text += make_stringf("You have visited %ld portal chamber",
+ place_info.num_visits);
+ if (place_info.num_visits > 1)
+ text += "s";
+ text += " (including bazaars).\n";
+ }
+
+ text += "\n";
+}
+
static void sdump_misc(dump_params &par)
{
sdump_location(par);
@@ -274,6 +348,82 @@ static void sdump_misc(dump_params &par)
sdump_burden(par);
sdump_hunger(par);
sdump_transform(par);
+ sdump_visits(par);
+}
+
+#define TO_PERCENT(x, y) (100.0 * ((float) (x)) / ((float) (y)))
+
+static std::string sdump_turns_place_info(PlaceInfo place_info,
+ std::string name = "")
+{
+ PlaceInfo gi = you.global_info;
+ std::string out;
+
+ if (name == "")
+ name = place_info.short_name();
+
+ float a, b, c, d, e, f;
+ unsigned int non_interlevel =
+ place_info.turns_total - place_info.turns_interlevel;
+ unsigned int global_non_interlevel =
+ gi.turns_total - gi.turns_interlevel;
+
+
+ a = TO_PERCENT(place_info.turns_total, gi.turns_total);
+ b = TO_PERCENT(non_interlevel, global_non_interlevel);
+ c = TO_PERCENT(place_info.turns_interlevel, place_info.turns_total);
+ d = TO_PERCENT(place_info.turns_resting, non_interlevel);
+ e = TO_PERCENT(place_info.turns_explore, non_interlevel);
+ f = (float) non_interlevel / (float) place_info.levels_seen;
+
+ out =
+ make_stringf("%14s | %5.1f | %5.1f | %5.1f | %5.1f | %5.1f | %13.1f\n",
+ name.c_str(), a, b, c , d, e, f);
+
+ out = replace_all(out, " nan ", " N/A ");
+
+ return out;
+}
+
+static void sdump_turns_by_place(dump_params &par)
+{
+ std::string &text(par.text);
+
+ std::vector<PlaceInfo> all_visited =
+ you.get_all_place_info(true);
+
+ text +=
+"Table legend:\n"
+" A = Turns spent in this place as a percentage of turns spent in the\n"
+" entire game.\n"
+" B = Non-inter-level travel turns spent in this place as a perecentage of\n"
+" non-inter-level travel turns spent in the entire game.\n"
+" C = Inter-level travel turns spent in this place as a perecentage of\n"
+" turns spent in this place.\n"
+" D = Turns resting spent in this place as a percentage of non-inter-level\n"
+" travel turns spent in this place.\n"
+" E = Turns spent auto-exloring this place as a percentage of\n"
+" non-inter-level travel turns spent in this place.\n"
+" F = Non-inter-level travel turns spent in this place divided by the\n"
+" number of levels of this place that you've seen.\n\n";
+
+ text += " ";
+ text += " A B C D E F\n";
+ text += " ";
+ text += "+-------+-------+-------+-------+-------+----------------------\n";
+
+ text += sdump_turns_place_info(you.global_info, "Total");
+
+ for (unsigned int i = 0; i < all_visited.size(); i++)
+ {
+ PlaceInfo pi = all_visited[i];
+ text += sdump_turns_place_info(pi);
+ }
+
+ text += " ";
+ text += "+-------+-------+-------+-------+-------+----------------------\n";
+
+ text += "\n";
}
static void sdump_newline(dump_params &par)
@@ -819,6 +969,102 @@ static void sdump_kills(dump_params &par)
par.text += you.kills->kill_info();
}
+static std::string sdump_kills_place_info(PlaceInfo place_info,
+ std::string name = "")
+{
+ PlaceInfo gi = you.global_info;
+ std::string out;
+
+ if (name == "")
+ name = place_info.short_name();
+
+ unsigned int global_total_kills = 0;
+ for (int i = 0; i < KC_NCATEGORIES; i++)
+ global_total_kills += you.global_info.mon_kill_num[i];
+
+ unsigned int total_kills = 0;
+ for (int i = 0; i < KC_NCATEGORIES; i++)
+ total_kills += place_info.mon_kill_num[i];
+
+ // Skip places where nothing was killed.
+ if (total_kills == 0)
+ return "";
+
+ float a, b, c, d, e, f, g;
+
+ a = TO_PERCENT(total_kills, global_total_kills);
+ b = TO_PERCENT(place_info.mon_kill_num[KC_YOU],
+ you.global_info.mon_kill_num[KC_YOU]);
+ c = TO_PERCENT(place_info.mon_kill_num[KC_FRIENDLY],
+ you.global_info.mon_kill_num[KC_FRIENDLY]);
+ d = TO_PERCENT(place_info.mon_kill_num[KC_OTHER],
+ you.global_info.mon_kill_num[KC_OTHER]);
+ e = TO_PERCENT(place_info.mon_kill_exp,
+ you.global_info.mon_kill_exp);
+ f = TO_PERCENT(place_info.mon_kill_exp_avail,
+ you.global_info.mon_kill_exp_avail);
+
+ g = (float) MAXIMUM(place_info.mon_kill_exp,
+ place_info.mon_kill_exp_avail) /
+ (float) place_info.levels_seen;
+
+ out =
+ make_stringf("%14s | %5.1f | %5.1f | %5.1f | %5.1f | %5.1f |"
+ " %5.1f | %13.1f\n",
+ name.c_str(), a, b, c , d, e, f, g);
+
+ out = replace_all(out, " nan ", " N/A ");
+
+ return out;
+}
+
+static void sdump_kills_by_place(dump_params &par)
+{
+ std::string &text(par.text);
+
+ std::vector<PlaceInfo> all_visited =
+ you.get_all_place_info(true);
+
+ std::string result = "";
+
+ std::string header =
+"Table legend:\n"
+" A = Kills in this place as a percentage of kills in entire the game.\n"
+" B = Kills by you in this place as a percentage of kills by you in\n"
+" the entire game.\n"
+" C = Kills by friends in this place as a percentage of kills by\n"
+" friends in the entire game.\n"
+" D = Other kills in this place as a percentage of other kills in the\n"
+" entire game.\n"
+" E = Character level experience gained in this place as a percentage of\n"
+" character level experience gained in the entire game.\n"
+" F = Skills experience gained in this place as a percentage of skills\n"
+" experience gained in the entire game.\n"
+" G = Experience gained in this place divided by the number of levels of\n"
+" this place that you have seen.\n\n";
+
+ header += " ";
+ header += " A B C D E F G\n";
+ header += " ";
+ header += "+-------+-------+-------+-------+-------+-------+--------------\n";
+
+ std::string footer = " ";
+ footer += "+-------+-------+-------+-------+-------+-------+--------------\n";
+
+ result += sdump_kills_place_info(you.global_info, "Total");
+
+ for (unsigned int i = 0; i < all_visited.size(); i++)
+ {
+ PlaceInfo pi = all_visited[i];
+ result += sdump_kills_place_info(pi);
+ }
+
+ if (result.length() > 0)
+ {
+ text += header + result + footer + "\n";
+ }
+}
+
static void sdump_overview(dump_params &par)
{
std::string overview =
diff --git a/crawl-ref/source/debug.cc b/crawl-ref/source/debug.cc
index 2dc68b3471..b63df4d115 100644
--- a/crawl-ref/source/debug.cc
+++ b/crawl-ref/source/debug.cc
@@ -644,13 +644,13 @@ static void wizard_go_to_level(const level_pos &pos)
const int old_level = you.your_level;
const branch_type old_where = you.where_are_you;
- const bool was_a_labyrinth = you.level_type == LEVEL_LABYRINTH;
+ const level_area_type old_level_type = you.level_type;
you.level_type = LEVEL_DUNGEON;
you.where_are_you = static_cast<branch_type>(pos.id.branch);
you.your_level = abs_depth;
- load(stair_taken, LOAD_ENTER_LEVEL, was_a_labyrinth, old_level, old_where);
+ load(stair_taken, LOAD_ENTER_LEVEL, old_level_type, old_level, old_where);
save_game_state();
new_level();
viewwindow(1, true);
diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h
index 20bad76b20..3c59a1ece6 100644
--- a/crawl-ref/source/externs.h
+++ b/crawl-ref/source/externs.h
@@ -416,6 +416,50 @@ private:
bool run_grids_changed() const;
};
+class PlaceInfo
+{
+public:
+ int level_type;
+ int branch;
+
+ unsigned long num_visits;
+ unsigned long levels_seen;
+
+ unsigned long mon_kill_exp;
+ unsigned long mon_kill_exp_avail;
+ unsigned long mon_kill_num[KC_NCATEGORIES];
+
+ long turns_total;
+ long turns_explore;
+ long turns_travel;
+ long turns_interlevel;
+ long turns_resting;
+ long turns_other;
+
+ double elapsed_total;
+ double elapsed_explore;
+ double elapsed_travel;
+ double elapsed_interlevel;
+ double elapsed_resting;
+ double elapsed_other;
+
+public:
+ PlaceInfo();
+
+ bool is_global() const;
+ void make_global();
+
+ void assert_validity() const;
+
+ const std::string short_name() const;
+
+ const PlaceInfo &operator += (const PlaceInfo &other);
+ const PlaceInfo &operator -= (const PlaceInfo &other);
+ PlaceInfo operator + (const PlaceInfo &other) const;
+ PlaceInfo operator - (const PlaceInfo &other) const;
+};
+
+
typedef std::vector<delay_queue_item> delay_queue_type;
class KillMaster;
@@ -618,6 +662,12 @@ public:
std::set<std::string> uniq_map_tags;
std::set<std::string> uniq_map_names;
+ PlaceInfo global_info;
+
+protected:
+ FixedVector<PlaceInfo, NUM_BRANCHES> branch_info;
+ FixedVector<PlaceInfo, NUM_LEVEL_AREA_TYPES - 1> non_branch_info;
+
public:
player();
player(const player &other);
@@ -743,6 +793,18 @@ public:
bool wearing_light_armour(bool with_skill = false) const;
void exercise(skill_type skill, int qty);
int skill(skill_type skill, bool skill_bump = false) const;
+
+ PlaceInfo& get_place_info() const ; // Current place info
+ PlaceInfo& get_place_info(branch_type branch,
+ level_area_type level_type2) const;
+ PlaceInfo& get_place_info(branch_type branch) const;
+ PlaceInfo& get_place_info(level_area_type level_type2) const;
+
+ void set_place_info(PlaceInfo info);
+ // Returns copies of the PlaceInfo; modifying the vector won't
+ // modify the player object.
+ std::vector<PlaceInfo> get_all_place_info(bool visited_only = false,
+ bool dungeon_only = false) const;
};
extern player you;
diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc
index 326d59706e..a96e9e507e 100644
--- a/crawl-ref/source/files.cc
+++ b/crawl-ref/source/files.cc
@@ -812,8 +812,10 @@ static void grab_followers()
}
}
-bool load( dungeon_feature_type stair_taken, load_mode_type load_mode,
- bool was_a_labyrinth, int old_level, branch_type old_branch )
+
+bool load( dungeon_feature_type stair_taken, int load_mode,
+ level_area_type old_level_type, char old_level,
+ branch_type where_were_you2 )
{
unwind_var<dungeon_feature_type> stair(
you.transit_stair, stair_taken, DNGN_UNSEEN);
@@ -826,7 +828,7 @@ bool load( dungeon_feature_type stair_taken, load_mode_type load_mode,
you.level_type,
false );
- if (you.level_type == LEVEL_DUNGEON)
+ if (you.level_type == LEVEL_DUNGEON && old_level_type == LEVEL_DUNGEON)
{
if (tmp_file_pairs[you.your_level][you.where_are_you] == false)
{
@@ -853,10 +855,9 @@ bool load( dungeon_feature_type stair_taken, load_mode_type load_mode,
{
grab_followers();
- if (!was_a_labyrinth)
- save_level( old_level, LEVEL_DUNGEON, old_branch );
- was_a_labyrinth = false;
+ if (old_level_type == LEVEL_DUNGEON)
+ save_level( old_level, LEVEL_DUNGEON, where_were_you2 );
}
// Try to open level savefile.
@@ -920,7 +921,7 @@ bool load( dungeon_feature_type stair_taken, load_mode_type load_mode,
if (load_mode != LOAD_RESTART_GAME)
{
if (you.level_type != LEVEL_ABYSS)
- place_player_on_stair(old_branch, stair_taken);
+ place_player_on_stair(where_were_you2, stair_taken);
else
you.moveto(45, 35);
}
@@ -989,6 +990,28 @@ bool load( dungeon_feature_type stair_taken, load_mode_type load_mode,
setup_environment_effects();
+ if (load_mode != LOAD_RESTART_GAME)
+ {
+ // Update PlaceInfo entries
+ PlaceInfo& curr_PlaceInfo = you.get_place_info();
+ PlaceInfo delta;
+
+ if (load_mode == LOAD_START_GAME ||
+ (load_mode == LOAD_ENTER_LEVEL &&
+ (where_were_you2 != you.where_are_you ||
+ old_level_type != you.level_type)))
+ delta.num_visits++;
+
+ if (just_created_level)
+ delta.levels_seen++;
+
+ you.global_info += delta;
+ you.global_info.assert_validity();
+
+ curr_PlaceInfo += delta;
+ curr_PlaceInfo.assert_validity();
+ }
+
return just_created_level;
} // end load()
diff --git a/crawl-ref/source/files.h b/crawl-ref/source/files.h
index 32bdaf1728..9e996613dc 100644
--- a/crawl-ref/source/files.h
+++ b/crawl-ref/source/files.h
@@ -60,8 +60,10 @@ void check_newer(const std::string &target,
const std::string &dependency,
void (*action)());
-bool load( dungeon_feature_type stair_taken, load_mode_type load_mode,
- bool was_a_labyrinth, int old_level, branch_type where_were_you2 );
+
+bool load( dungeon_feature_type stair_taken, int load_mode,
+ level_area_type old_level_type, char old_level,
+ branch_type where_were_you2 );
// last updated 12may2000 {dlb}
/* ***********************************************************************
diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc
index 540b10742e..1b885bddfd 100644
--- a/crawl-ref/source/initfile.cc
+++ b/crawl-ref/source/initfile.cc
@@ -752,9 +752,9 @@ void game_options::reset_options()
extra_levels.clear();
dump_order.clear();
- new_dump_fields("header,hiscore,stats,misc,inventory,skills,"
- "spells,overview,mutations,messages,screenshot,"
- "kills,notes");
+ new_dump_fields("header,hiscore,stats,misc,turns_by_place,inventory,"
+ "skills,spells,overview,mutations,messages,screenshot,"
+ "kills_by_place,kills,notes");
hp_colour.clear();
hp_colour.push_back(std::pair<int,int>(100, LIGHTGREY));
diff --git a/crawl-ref/source/makefile b/crawl-ref/source/makefile
index 5709465ae3..b21a94dfc4 100644
--- a/crawl-ref/source/makefile
+++ b/crawl-ref/source/makefile
@@ -13,8 +13,8 @@ MAKEFILE = makefile.unix
# cuts build time a lot on multi-cpu machines
#OTHER=-j2
-all:
- $(MAKE) $(OTHER) -f $(MAKEFILE)
+all: wizard
+ @echo Built wizard binary
profile:
$(MAKE) $(OTHER) -f $(MAKEFILE) EXTRA_FLAGS='-pg'
diff --git a/crawl-ref/source/makefile.unix b/crawl-ref/source/makefile.unix
index f8211891d8..281ace7259 100644
--- a/crawl-ref/source/makefile.unix
+++ b/crawl-ref/source/makefile.unix
@@ -31,16 +31,16 @@ MCHMOD := 2755
MCHMOD_SAVEDIR := 775
# The user:group to install the game as.
-INSTALL_UGRP := games:games
+INSTALL_UGRP := matt:games
-INSTALLDIR := /usr/games/crawl
+INSTALLDIR := /usr/games/crawl-svn
# If you're installing Crawl for multiple users, you *must* set this to a
# valid path before building Crawl. This is not necessary if you are building
# Crawl for a single user.
-# SAVEDIR := /usr/games/crawl/saves/
-# DATADIR := /usr/games/crawl/data/
+# SAVEDIR := /usr/games/crawl-svn/saves/
+# DATADIR := /usr/games/crawl-svn/data/
LEX := flex
YACC := bison -y
diff --git a/crawl-ref/source/misc.cc b/crawl-ref/source/misc.cc
index 4b3a6a8f4a..30f2ed3627 100644
--- a/crawl-ref/source/misc.cc
+++ b/crawl-ref/source/misc.cc
@@ -460,8 +460,8 @@ void up_stairs(dungeon_feature_type force_stair)
{
dungeon_feature_type stair_find =
force_stair? force_stair : grd[you.x_pos][you.y_pos];
- const branch_type old_where = you.where_are_you;
- const bool was_a_labyrinth = you.level_type != LEVEL_DUNGEON;
+ const branch_type old_where = you.where_are_you;
+ const level_area_type old_level_type = you.level_type;
if (stair_find == DNGN_ENTER_SHOP)
{
@@ -597,7 +597,7 @@ void up_stairs(dungeon_feature_type force_stair)
else
climb_message(stair_find, true);
- load(stair_taken, LOAD_ENTER_LEVEL, was_a_labyrinth, old_level, old_where);
+ load(stair_taken, LOAD_ENTER_LEVEL, old_level_type, old_level, old_where);
you.turn_is_over = true;
@@ -672,8 +672,7 @@ void up_stairs(dungeon_feature_type force_stair)
void down_stairs( int old_level, dungeon_feature_type force_stair )
{
int i;
- const level_area_type old_level_type = you.level_type;
- const bool was_a_labyrinth = you.level_type != LEVEL_DUNGEON;
+ const level_area_type old_level_type = you.level_type;
const dungeon_feature_type stair_find =
force_stair? force_stair : grd[you.x_pos][you.y_pos];
@@ -915,7 +914,7 @@ void down_stairs( int old_level, dungeon_feature_type force_stair )
}
const bool newlevel =
- load(stair_taken, LOAD_ENTER_LEVEL, was_a_labyrinth,
+ load(stair_taken, LOAD_ENTER_LEVEL, old_level_type,
old_level, old_where);
if (newlevel)
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc
index 35e369c353..61200ea0b6 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -364,12 +364,16 @@ static void check_kill_milestone(const monsters *mons,
#endif // DGL_MILESTONES
static void give_adjusted_experience(monsters *monster, killer_type killer,
- bool pet_kill)
+ bool pet_kill, unsigned int *exp_gain,
+ unsigned int *avail_gain)
{
- if (YOU_KILL(killer))
- gain_exp( exper_value( monster ) );
+ if (testbits(monster->flags, MF_CREATED_FRIENDLY))
+ ; // No experience if monster was created friendly
+ else if (YOU_KILL(killer))
+ gain_exp( exper_value( monster ), exp_gain, avail_gain );
else if (pet_kill)
- gain_exp( exper_value( monster ) / 2 + 1 );
+ gain_exp( exper_value( monster ) / 2 + 1,
+ exp_gain, avail_gain );
}
static bool is_pet_kill(killer_type killer, int i)
@@ -477,9 +481,6 @@ void monster_die(monsters *monster, killer_type killer, int i, bool silent)
simple_monster_message( monster, " dissipates!",
MSGCH_MONSTER_DAMAGE, MDAM_DEAD );
- if (!testbits(monster->flags, MF_CREATED_FRIENDLY))
- give_adjusted_experience(monster, killer, pet_kill);
-
if (monster->type == MONS_FIRE_VORTEX)
place_cloud(CLOUD_FIRE, monster->x, monster->y, 2 + random2(4),
monster->kill_alignment());
@@ -492,9 +493,6 @@ void monster_die(monsters *monster, killer_type killer, int i, bool silent)
monster, " vapourises!", MSGCH_MONSTER_DAMAGE,
MDAM_DEAD );
- if (!testbits(monster->flags, MF_CREATED_FRIENDLY))
- give_adjusted_experience(monster, killer, pet_kill);
-
place_cloud(CLOUD_COLD, monster->x, monster->y, 2 + random2(4),
monster->kill_alignment());
}
@@ -514,10 +512,6 @@ void monster_die(monsters *monster, killer_type killer, int i, bool silent)
place_cloud( random_smoke_type(),
monster->x, monster->y, 1 + random2(3),
monster->kill_alignment() );
-
-
- if (!testbits(monster->flags, MF_CREATED_FRIENDLY))
- give_adjusted_experience(monster, killer, pet_kill);
}
else
{
@@ -537,15 +531,8 @@ void monster_die(monsters *monster, killer_type killer, int i, bool silent)
monster->name(DESC_NOCAP_THE).c_str());
}
- if (!created_friendly)
- {
- gain_exp(exper_value( monster ));
- }
- else
- {
- if (death_message)
- mpr("That felt strangely unrewarding.");
- }
+ if (created_friendly && death_message)
+ mpr("That felt strangely unrewarding.");
// killing triggers tutorial lesson
tutorial_inspect_kill();
@@ -642,7 +629,6 @@ void monster_die(monsters *monster, killer_type killer, int i, bool silent)
{
bool notice = false;
const bool anon = (i == ANON_FRIENDLY_MONSTER);
- gain_exp(exper_value( monster ) / 2 + 1);
const mon_holy_type targ_holy = mons_holiness(monster),
attacker_holy = anon? MH_NATURAL : mons_holiness(&menv[i]);
@@ -806,6 +792,28 @@ void monster_die(monsters *monster, killer_type killer, int i, bool silent)
{
you.kills->record_kill(monster, killer, pet_kill);
+ kill_category kc =
+ (killer == KILL_YOU || killer == KILL_YOU_MISSILE) ? KC_YOU :
+ (pet_kill)? KC_FRIENDLY :
+ KC_OTHER;
+
+ unsigned int exp_gain = 0, avail_gain = 0;
+ give_adjusted_experience(monster, killer, pet_kill,
+ &exp_gain, &avail_gain);
+
+ PlaceInfo& curr_PlaceInfo = you.get_place_info();
+ PlaceInfo delta;
+
+ delta.mon_kill_num[kc]++;
+ delta.mon_kill_exp += exp_gain;
+ delta.mon_kill_exp_avail += avail_gain;
+
+ you.global_info += delta;
+ you.global_info.assert_validity();
+
+ curr_PlaceInfo += delta;
+ curr_PlaceInfo.assert_validity();
+
if (monster->has_ench(ENCH_ABJ))
{
if (mons_weight(mons_species(monster->type)))
diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc
index 6ac2ef50c9..49c0b2abc4 100644
--- a/crawl-ref/source/player.cc
+++ b/crawl-ref/source/player.cc
@@ -32,6 +32,7 @@
#include "externs.h"
+#include "branch.h"
#include "clua.h"
#include "delay.h"
#include "dgnevent.h"
@@ -2444,11 +2445,15 @@ void forget_map(unsigned char chance_forgotten)
}
} // end forget_map()
-void gain_exp( unsigned int exp_gained )
+void gain_exp( unsigned int exp_gained, unsigned int* actual_gain,
+ unsigned int* actual_avail_gain)
{
if (player_equip_ego_type( EQ_BODY_ARMOUR, SPARM_ARCHMAGI ))
exp_gained = div_rand_round( exp_gained, 4 );
+ unsigned long old_exp = you.experience;
+ int old_avail = you.exp_available;
+
#if DEBUG_DIAGNOSTICS
mprf(MSGCH_DIAGNOSTICS, "gain_exp: %d", exp_gained );
#endif
@@ -2468,6 +2473,12 @@ void gain_exp( unsigned int exp_gained )
// become useful for a longer time
if (Options.tutorial_left && you.experience_level == 7)
tutorial_finished();
+
+ if (actual_gain != NULL)
+ *actual_gain = you.experience - old_exp;
+
+ if (actual_avail_gain != NULL)
+ *actual_avail_gain = you.exp_available - old_avail;
} // end gain_exp()
void level_change(bool skip_ability_increase)
@@ -5064,6 +5075,23 @@ void player::init()
duration.init(0);
exp_available = 25;
+
+ global_info.make_global();
+ global_info.assert_validity();
+
+ for (int i = 0; i < NUM_BRANCHES; i++)
+ {
+ branch_info[i].level_type = LEVEL_DUNGEON;
+ branch_info[i].branch = i;
+ branch_info[i].assert_validity();
+ }
+
+ for (int i = 0; i < (NUM_LEVEL_AREA_TYPES - 1); i++)
+ {
+ non_branch_info[i].level_type = i + 1;
+ non_branch_info[i].branch = -1;
+ non_branch_info[i].assert_validity();
+ }
}
player::~player()
@@ -5777,3 +5805,215 @@ void player::moveto(const coord_def &c)
if (real_move)
dungeon_events.fire_position_event(DET_PLAYER_MOVED, c);
}
+
+////////////////////////////////////////////////////////////////////////////
+
+PlaceInfo::PlaceInfo()
+ : level_type(-2), branch(-2), num_visits(0),
+ levels_seen(0), mon_kill_exp(0), mon_kill_exp_avail(0),
+ turns_total(0), turns_explore(0), turns_travel(0), turns_interlevel(0),
+ turns_resting(0), turns_other(0), elapsed_total(0.0),
+ elapsed_explore(0.0), elapsed_travel(0.0), elapsed_interlevel(0.0),
+ elapsed_resting(0.0), elapsed_other(0.0)
+{
+ for (int i = 0; i < KC_NCATEGORIES; i++)
+ mon_kill_num[i] = 0;
+}
+
+bool PlaceInfo::is_global() const
+{
+ return (level_type == -1 && branch == -1);
+}
+
+void PlaceInfo::make_global()
+{
+ level_type = -1;
+ branch = -1;
+}
+
+void PlaceInfo::assert_validity() const
+{
+ // Check that level_type and branch match up
+ ASSERT(is_global() ||
+ (level_type == LEVEL_DUNGEON && branch >= BRANCH_MAIN_DUNGEON &&
+ branch < NUM_BRANCHES) ||
+ (level_type > LEVEL_DUNGEON && level_type < NUM_LEVEL_AREA_TYPES &&
+ branch == -1));
+
+ // Can't have visited a place without seeing any of its levels, and
+ // visa versa
+ ASSERT((num_visits == 0 && levels_seen == 0) ||
+ (num_visits > 0 && levels_seen > 0));
+
+ if (level_type == LEVEL_LABYRINTH || level_type == LEVEL_ABYSS)
+ ASSERT(num_visits == levels_seen);
+ else if (level_type == LEVEL_PANDEMONIUM)
+ ASSERT(num_visits <= levels_seen);
+ else if (level_type == LEVEL_DUNGEON && branches[branch].depth > 0)
+ ASSERT(levels_seen <= (unsigned long) branches[branch].depth);
+
+ ASSERT(turns_total == (turns_explore + turns_travel + turns_interlevel +
+ turns_resting + turns_other));
+
+ ASSERT(elapsed_total == (elapsed_explore + elapsed_travel +
+ elapsed_interlevel + elapsed_resting +
+ elapsed_other));
+}
+
+const std::string PlaceInfo::short_name() const
+{
+ if (level_type == LEVEL_DUNGEON)
+ return branches[branch].shortname;
+ else
+ {
+ switch (level_type)
+ {
+ case LEVEL_ABYSS:
+ return "Abyss";
+
+ case LEVEL_PANDEMONIUM:
+ return "Pandemonium";
+
+ case LEVEL_LABYRINTH:
+ return "Labyrinth";
+
+ default:
+ return "Bug";
+ }
+ }
+}
+
+const PlaceInfo &PlaceInfo::operator += (const PlaceInfo &other)
+{
+ num_visits += other.num_visits;
+ levels_seen += other.levels_seen;
+
+ mon_kill_exp += other.mon_kill_exp;
+ mon_kill_exp_avail += other.mon_kill_exp_avail;
+
+ for (int i = 0; i < KC_NCATEGORIES; i++)
+ mon_kill_num[i] += other.mon_kill_num[i];
+
+ turns_total += other.turns_total;
+ turns_explore += other.turns_explore;
+ turns_travel += other.turns_travel;
+ turns_interlevel += other.turns_interlevel;
+ turns_resting += other.turns_resting;
+ turns_other += other.turns_other;
+
+ elapsed_total += other.elapsed_total;
+ elapsed_explore += other.elapsed_explore;
+ elapsed_travel += other.elapsed_travel;
+ elapsed_interlevel += other.elapsed_interlevel;
+ elapsed_resting += other.elapsed_resting;
+ elapsed_other += other.elapsed_other;
+
+ return (*this);
+}
+
+const PlaceInfo &PlaceInfo::operator -= (const PlaceInfo &other)
+{
+ num_visits -= other.num_visits;
+ levels_seen -= other.levels_seen;
+
+ mon_kill_exp -= other.mon_kill_exp;
+ mon_kill_exp_avail -= other.mon_kill_exp_avail;
+
+ for (int i = 0; i < KC_NCATEGORIES; i++)
+ mon_kill_num[i] -= other.mon_kill_num[i];
+
+ turns_total -= other.turns_total;
+ turns_explore -= other.turns_explore;
+ turns_travel -= other.turns_travel;
+ turns_interlevel -= other.turns_interlevel;
+ turns_resting -= other.turns_resting;
+ turns_other -= other.turns_other;
+
+ elapsed_total -= other.elapsed_total;
+ elapsed_explore -= other.elapsed_explore;
+ elapsed_travel -= other.elapsed_travel;
+ elapsed_interlevel -= other.elapsed_interlevel;
+ elapsed_resting -= other.elapsed_resting;
+ elapsed_other -= other.elapsed_other;
+
+ return (*this);
+}
+
+PlaceInfo PlaceInfo::operator + (const PlaceInfo &other) const
+{
+ PlaceInfo copy = *this;
+ copy += other;
+ return copy;
+}
+
+PlaceInfo PlaceInfo::operator - (const PlaceInfo &other) const
+{
+ PlaceInfo copy = *this;
+ copy -= other;
+ return copy;
+}
+
+
+PlaceInfo& player::get_place_info() const
+{
+ return get_place_info(where_are_you, level_type);
+}
+
+PlaceInfo& player::get_place_info(branch_type branch) const
+{
+ return get_place_info(branch, LEVEL_DUNGEON);
+}
+
+PlaceInfo& player::get_place_info(level_area_type level_type2) const
+{
+ return get_place_info(NUM_BRANCHES, level_type2);
+}
+
+PlaceInfo& player::get_place_info(branch_type branch,
+ level_area_type level_type2) const
+{
+ ASSERT((level_type2 == LEVEL_DUNGEON && branch >= BRANCH_MAIN_DUNGEON &&
+ branch < NUM_BRANCHES) ||
+ (level_type2 > LEVEL_DUNGEON && level_type < NUM_LEVEL_AREA_TYPES));
+
+ if (level_type2 == LEVEL_DUNGEON)
+ return (PlaceInfo&) branch_info[branch];
+ else
+ return (PlaceInfo&) non_branch_info[level_type2 - 1];
+}
+
+void player::set_place_info(PlaceInfo place_info)
+{
+ place_info.assert_validity();
+
+ if (place_info.is_global())
+ global_info = place_info;
+ else if (place_info.level_type == LEVEL_DUNGEON)
+ branch_info[place_info.branch] = place_info;
+ else
+ non_branch_info[place_info.level_type - 1] = place_info;
+}
+
+std::vector<PlaceInfo> player::get_all_place_info(bool visited_only,
+ bool dungeon_only) const
+{
+ std::vector<PlaceInfo> list;
+
+ for (int i = 0; i < NUM_BRANCHES; i++)
+ {
+ if ((visited_only && branch_info[i].num_visits == 0) ||
+ (dungeon_only && branch_info[i].level_type != LEVEL_DUNGEON))
+ continue;
+ list.push_back(branch_info[i]);
+ }
+
+ for (int i = 0; i < (NUM_LEVEL_AREA_TYPES - 1); i++)
+ {
+ if ((visited_only && non_branch_info[i].num_visits == 0) ||
+ (dungeon_only && non_branch_info[i].level_type != LEVEL_DUNGEON))
+ continue;
+ list.push_back(non_branch_info[i]);
+ }
+
+ return list;
+}
diff --git a/crawl-ref/source/player.h b/crawl-ref/source/player.h
index 1bc1bf72bc..8f4f0e897f 100644
--- a/crawl-ref/source/player.h
+++ b/crawl-ref/source/player.h
@@ -282,8 +282,8 @@ void forget_map(unsigned char chance_forgotten);
/* ***********************************************************************
* called from: acr - fight
* *********************************************************************** */
-void gain_exp(unsigned int exp_gained);
-
+void gain_exp(unsigned int exp_gained, unsigned int* actual_gain = NULL,
+ unsigned int* actual_avail_gain = NULL);
// last updated 17dec2000 {gdl}
/* ***********************************************************************
diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc
index 057682d004..b2a5a78100 100644
--- a/crawl-ref/source/tags.cc
+++ b/crawl-ref/source/tags.cc
@@ -13,7 +13,7 @@
/* ------------------------- how tags work ----------------------------------
-1. Tag types are enumerated in enum.h, from TAG_VERSION (more a placeholder
+1. Tag types are enumerated in tags.h, from TAG_VERSION (more a placeholder
than anything else, it is not actually saved as a tag) to TAG_XXX. NUM_TAGS
is equal to the actual number of defined tags.
@@ -978,6 +978,35 @@ static void tag_construct_you_items(struct tagHeader &th)
marshallBoolean(th, does_unrandart_exist(j));
}
+static void marshallPlaceInfo(struct tagHeader &th, PlaceInfo place_info)
+{
+ marshallLong(th, place_info.level_type);
+ marshallLong(th, place_info.branch);
+
+ marshallLong(th, place_info.num_visits);
+ marshallLong(th, place_info.levels_seen);
+
+ marshallLong(th, place_info.mon_kill_exp);
+ marshallLong(th, place_info.mon_kill_exp_avail);
+
+ for (int i = 0; i < KC_NCATEGORIES; i++)
+ marshallLong(th, place_info.mon_kill_num[i]);
+
+ marshallLong(th, place_info.turns_total);
+ marshallLong(th, place_info.turns_explore);
+ marshallLong(th, place_info.turns_travel);
+ marshallLong(th, place_info.turns_interlevel);
+ marshallLong(th, place_info.turns_resting);
+ marshallLong(th, place_info.turns_other);
+
+ marshallFloat(th, place_info.elapsed_total);
+ marshallFloat(th, place_info.elapsed_explore);
+ marshallFloat(th, place_info.elapsed_travel);
+ marshallFloat(th, place_info.elapsed_interlevel);
+ marshallFloat(th, place_info.elapsed_resting);
+ marshallFloat(th, place_info.elapsed_other);
+}
+
static void tag_construct_you_dungeon(struct tagHeader &th)
{
int i,j;
@@ -1006,6 +1035,14 @@ static void tag_construct_you_dungeon(struct tagHeader &th)
marshallMap(th, portals_present,
marshall_level_pos, marshall_as_long<portal_type>);
+ marshallPlaceInfo(th, you.global_info);
+ std::vector<PlaceInfo> list = you.get_all_place_info();
+ // How many different places we have info on?
+ marshallShort(th, list.size());
+
+ for (unsigned int k = 0; k < list.size(); k++)
+ marshallPlaceInfo(th, list[k]);
+
marshall_iterator(th, you.uniq_map_tags.begin(), you.uniq_map_tags.end(),
marshallString);
marshall_iterator(th, you.uniq_map_names.begin(), you.uniq_map_names.end(),
@@ -1315,12 +1352,47 @@ static void tag_read_you_items(struct tagHeader &th, char minorVersion)
set_unrandart_exist(j, 0);
}
+static PlaceInfo unmarshallPlaceInfo(struct tagHeader &th)
+{
+ PlaceInfo place_info;
+
+ place_info.level_type = (int) unmarshallLong(th);
+ place_info.branch = (int) unmarshallLong(th);
+
+ place_info.num_visits = (unsigned long) unmarshallLong(th);
+ place_info.levels_seen = (unsigned long) unmarshallLong(th);
+
+ place_info.mon_kill_exp = (unsigned long) unmarshallLong(th);
+ place_info.mon_kill_exp_avail = (unsigned long) unmarshallLong(th);
+
+ for (int i = 0; i < KC_NCATEGORIES; i++)
+ place_info.mon_kill_num[i] = (unsigned long) unmarshallLong(th);
+
+ place_info.turns_total = unmarshallLong(th);
+ place_info.turns_explore = unmarshallLong(th);
+ place_info.turns_travel = unmarshallLong(th);
+ place_info.turns_interlevel = unmarshallLong(th);
+ place_info.turns_resting = unmarshallLong(th);
+ place_info.turns_other = unmarshallLong(th);
+
+ place_info.elapsed_total = (double) unmarshallFloat(th);
+ place_info.elapsed_explore = (double) unmarshallFloat(th);
+ place_info.elapsed_travel = (double) unmarshallFloat(th);
+ place_info.elapsed_interlevel = (double) unmarshallFloat(th);
+ place_info.elapsed_resting = (double) unmarshallFloat(th);
+ place_info.elapsed_other = (double) unmarshallFloat(th);
+
+ return place_info;
+}
+
static void tag_read_you_dungeon(struct tagHeader &th)
{
- int i,j;
- int count_c;
+ int i,j;
+ int count_c;
short count_s;
+ unsigned short count_p;
+
// how many unique creatures?
count_c = unmarshallShort(th);
you.unique_creatures.init(false);
@@ -1354,6 +1426,23 @@ static void tag_read_you_dungeon(struct tagHeader &th)
unmarshallMap(th, portals_present,
unmarshall_level_pos, unmarshall_long_as<portal_type>);
+ PlaceInfo place_info = unmarshallPlaceInfo(th);
+ ASSERT(place_info.is_global());
+ you.set_place_info(place_info);
+
+ std::vector<PlaceInfo> list = you.get_all_place_info();
+ count_p = (unsigned short) unmarshallShort(th);
+ // Use "<=" so that adding more branches or non-dungeon places
+ // won't break save-file compatibility.
+ ASSERT(count_p <= list.size());
+
+ for (i = 0; i < count_p; i++)
+ {
+ place_info = unmarshallPlaceInfo(th);
+ ASSERT(!place_info.is_global());
+ you.set_place_info(place_info);
+ }
+
typedef std::set<std::string> string_set;
typedef std::pair<string_set::iterator, bool> ssipair;
unmarshall_container(th, you.uniq_map_tags,