summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crawl-ref/source/dat/clua/ziggurat.lua10
-rw-r--r--crawl-ref/source/dungeon.cc23
-rw-r--r--crawl-ref/source/externs.h12
-rw-r--r--crawl-ref/source/files.cc3
-rw-r--r--crawl-ref/source/luadgn.cc104
-rw-r--r--crawl-ref/source/mapdef.cc13
-rw-r--r--crawl-ref/source/mapdef.h4
-rw-r--r--crawl-ref/source/mon-util.cc29
-rw-r--r--crawl-ref/source/monplace.cc247
-rw-r--r--crawl-ref/source/monplace.h12
-rw-r--r--crawl-ref/source/tags.cc9
-rw-r--r--crawl-ref/source/travel.cc11
12 files changed, 462 insertions, 15 deletions
diff --git a/crawl-ref/source/dat/clua/ziggurat.lua b/crawl-ref/source/dat/clua/ziggurat.lua
index df33ae1aa0..a022da3c27 100644
--- a/crawl-ref/source/dat/clua/ziggurat.lua
+++ b/crawl-ref/source/dat/clua/ziggurat.lua
@@ -230,7 +230,7 @@ local function monster_creator_fn(arg)
end
return mcreator(x, y)
end
- return { fn = mspec }
+ return { fn = mspec, spec = arg }
elseif atyp == "table" then
if not arg.cond or arg.cond() then
return util.cathash(monster_creator_fn(arg.spec), arg)
@@ -273,6 +273,9 @@ mset_if(depth_lt(6), "place:Pan")
local drac_creator = dgn.monster_fn("random draconian")
local function mons_drac_gen(x, y, nth)
+ if nth == 1 then
+ dgn.set_random_mon_list("random draconian")
+ end
set_random_floor_colour()
return drac_creator(x, y)
end
@@ -283,6 +286,7 @@ local pan_critter_fn = dgn.monster_fn("place:Pan")
local function mons_panlord_gen(x, y, nth)
set_random_floor_colour()
if nth == 1 then
+ dgn.set_random_mon_list("place:Pan")
return pan_lord_fn(x, y)
else
return pan_critter_fn(x, y)
@@ -591,6 +595,10 @@ end
local function ziggurat_furnish(centre, entry, exit)
local monster_generation = choose_monster_set()
+ if type(monster_generation.spec) == "string" then
+ dgn.set_random_mon_list(monster_generation.spec)
+ end
+
-- If we're going to spawn jellies, do our loot protection thing.
if monster_generation.jelly_protect then
zig().level.jelly_protect = true
diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc
index 335aba7330..3a43bfe349 100644
--- a/crawl-ref/source/dungeon.cc
+++ b/crawl-ref/source/dungeon.cc
@@ -883,6 +883,9 @@ static void _reset_level()
dgn_check_connectivity = false;
dgn_zones = 0;
+ // Forget level properties.
+ env.properties.clear();
+
// Blank level with DNGN_ROCK_WALL.
grd.init(DNGN_ROCK_WALL);
env.grid_colours.init(BLACK);
@@ -924,6 +927,26 @@ static void _reset_level()
else
env.level_flags = 0;
+ // Set default random monster generation rate (smaller is more often,
+ // except that 0 == no random monsters).
+ if (you.level_type == LEVEL_DUNGEON)
+ {
+ if (you.where_are_you == BRANCH_ECUMENICAL_TEMPLE)
+ env.spawn_random_rate = 0;
+ else
+ env.spawn_random_rate = 240;
+ }
+ else if (you.level_type == LEVEL_ABYSS
+ || you.level_type == LEVEL_PANDEMONIUM)
+ {
+ // Abyss spawn rate is set for those characters that start out in the
+ // Abyss; otherwise the number is ignored in the Abyss.
+ env.spawn_random_rate = 50;
+ }
+ else
+ // No random monsters in Labyrinths and portal vaualts.
+ env.spawn_random_rate = 0;
+
env.floor_colour = BLACK;
env.rock_colour = BLACK;
diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h
index 4be82a7c62..7cdaad0d20 100644
--- a/crawl-ref/source/externs.h
+++ b/crawl-ref/source/externs.h
@@ -491,6 +491,7 @@ public:
}
static level_id parse_level_id(const std::string &s) throw (std::string);
+ static level_id from_packed_place(const unsigned short place);
unsigned short packed_place() const;
std::string describe(bool long_name = false, bool with_number = true) const;
@@ -1685,7 +1686,16 @@ public:
FixedVector< monster_type, 20 > mons_alloc;
map_markers markers;
- double elapsed_time; // used during level load
+ // Place to associate arbitrary data with a particular level.
+ // Sort of like player::atribute
+ CrawlHashTable properties;
+
+ // Rate at which random monsters spawn, with lower numbers making
+ // them spawn more often (5 or less causes one to spawn about every
+ // 5 turns). Set to 0 to stop random generation.
+ int spawn_random_rate;
+
+ double elapsed_time; // used during level load
// Number of turns the player has spent on this level.
int turns_on_level;
diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc
index 4bdf77b5f1..17aa7aaece 100644
--- a/crawl-ref/source/files.cc
+++ b/crawl-ref/source/files.cc
@@ -9,6 +9,7 @@
#include "AppHdr.h"
#include "delay.h"
#include "files.h"
+#include "monplace.h"
#include "version.h"
#include <string.h>
@@ -1292,6 +1293,8 @@ bool load( dungeon_feature_type stair_taken, load_mode_type load_mode,
setup_environment_effects();
+ setup_vault_mon_list();
+
// Inform user of level's annotation.
if (load_mode != LOAD_VISITOR
&& !get_level_annotation().empty()
diff --git a/crawl-ref/source/luadgn.cc b/crawl-ref/source/luadgn.cc
index 79a97ed07b..e4f9096681 100644
--- a/crawl-ref/source/luadgn.cc
+++ b/crawl-ref/source/luadgn.cc
@@ -28,6 +28,7 @@
#include "maps.h"
#include "misc.h"
#include "mon-util.h"
+#include "monplace.h"
#include "spl-util.h"
#include "state.h"
#include "stuff.h"
@@ -601,6 +602,108 @@ static int dgn_change_branch_flags(lua_State *ls)
return (1);
}
+static int dgn_set_random_mon_list(lua_State *ls)
+{
+ if (you.level_type != LEVEL_PORTAL_VAULT)
+ {
+ luaL_error(ls, "Can only be used in portal vaults.");
+ return (0);
+ }
+
+ mons_list mlist = _lua_get_mlist(ls, 1);
+
+ if (mlist.size() == 0)
+ return (0);
+
+ if (mlist.size() > 1)
+ {
+ luaL_argerror(ls, 1, "Mon list must contain only one slot.");
+ return (0);
+ }
+
+ const int num_mons = mlist.slot_size(0);
+
+ if (num_mons == 0)
+ {
+ luaL_argerror(ls, 1, "Mon list is empty.");
+ return (0);
+ }
+
+ std::vector<mons_spec> mons;
+ int num_lords = 0;
+ for (int i = 0; i < num_mons; i++)
+ {
+ mons_spec mon = mlist.get_monster(0, i);
+
+ // Pandemonium lords are pseudo-unique, so don't randomly generate
+ // them.
+ if (mon.mid == MONS_PANDEMONIUM_DEMON)
+ {
+ num_lords++;
+ continue;
+ }
+
+ std::string name;
+ if (mon.place.is_valid())
+ {
+ if (mon.place.level_type == LEVEL_LABYRINTH
+ || mon.place.level_type == LEVEL_PORTAL_VAULT)
+ {
+ std::string err;
+ err = make_stringf("mon #%d: Can't use Lab or Portal as a "
+ "monster place.", i + 1);
+ luaL_argerror(ls, 1, err.c_str());
+ return(0);
+ }
+ name = mon.place.describe();
+ }
+ else
+ {
+ if (mon.mid == RANDOM_MONSTER || mon.monbase == RANDOM_MONSTER)
+ {
+ std::string err;
+ err = make_stringf("mon #%d: can't use random monster in "
+ "list specifying random monsters", i + 1);
+ luaL_argerror(ls, 1, err.c_str());
+ return(0);
+ }
+ name = mons_type_name(mon.mid, DESC_PLAIN);
+ }
+
+ mons.push_back(mon);
+
+ if (mon.number != 0)
+ mprf(MSGCH_ERROR, "dgn.set_random_mon_list() : number for %s "
+ "being discarded.",
+ name.c_str());
+
+ if (mon.band)
+ mprf(MSGCH_ERROR, "dgn.set_random_mon_list() : band request for "
+ "%s being ignored.",
+ name.c_str());
+
+ if (mon.colour != BLACK)
+ mprf(MSGCH_ERROR, "dgn.set_random_mon_list() : colour for "
+ "%s being ignored.",
+ name.c_str());
+
+ if (mon.items.size() > 0)
+ mprf(MSGCH_ERROR, "dgn.set_random_mon_list() : items for "
+ "%s being ignored.",
+ name.c_str());
+ } // for (int i = 0; i < num_mons; i++)
+
+ if (mons.size() == 0 && num_lords > 0)
+ {
+ luaL_argerror(ls, 1, "Mon list contains only pandemonium lords.");
+ return (0);
+ }
+
+ set_vault_mon_list(mons);
+
+ return (0);
+}
+
static int dgn_chance(lua_State *ls)
{
MAP(ls, 1, map);
@@ -2799,6 +2902,7 @@ static const struct luaL_reg dgn_lib[] =
{ "items_at", dgn_items_at },
{ "change_level_flags", dgn_change_level_flags },
{ "change_branch_flags", dgn_change_branch_flags },
+ { "set_random_mon_list", dgn_set_random_mon_list },
{ "get_floor_colour", dgn_get_floor_colour },
{ "get_rock_colour", dgn_get_rock_colour },
{ "change_floor_colour", dgn_change_floor_colour },
diff --git a/crawl-ref/source/mapdef.cc b/crawl-ref/source/mapdef.cc
index 7266116331..446583ef5c 100644
--- a/crawl-ref/source/mapdef.cc
+++ b/crawl-ref/source/mapdef.cc
@@ -1990,6 +1990,19 @@ mons_spec mons_list::get_monster(int index)
return (pick_monster( mons[index] ));
}
+mons_spec mons_list::get_monster(int slot_index, int list_index) const
+{
+ if (slot_index < 0 || slot_index >= (int) mons.size())
+ return mons_spec(RANDOM_MONSTER);
+
+ const mons_spec_list &list = mons[slot_index].mlist;
+
+ if (list_index < 0 || list_index >= (int) list.size())
+ return mons_spec(RANDOM_MONSTER);
+
+ return list[list_index];
+}
+
void mons_list::clear()
{
mons.clear();
diff --git a/crawl-ref/source/mapdef.h b/crawl-ref/source/mapdef.h
index 8b2a40260e..68d62b5851 100644
--- a/crawl-ref/source/mapdef.h
+++ b/crawl-ref/source/mapdef.h
@@ -447,12 +447,14 @@ public:
void clear();
mons_spec get_monster(int index);
+ mons_spec get_monster(int slot_index, int list_index) const;
// Returns an error string if the monster is unrecognised.
std::string add_mons(const std::string &s, bool fix_slot = false);
std::string set_mons(int slot, const std::string &s);
- size_t size() const { return mons.size(); }
+ size_t size() const { return mons.size(); }
+ size_t slot_size(int slot) const { return mons[slot].mlist.size(); }
private:
typedef std::vector<mons_spec> mons_spec_list;
diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc
index 38be768b2f..f0e7e8ea33 100644
--- a/crawl-ref/source/mon-util.cc
+++ b/crawl-ref/source/mon-util.cc
@@ -2105,7 +2105,34 @@ std::string mons_type_name(int type, description_level_type desc )
}
}
- result += get_monster_data(type)->name;
+ switch(type)
+ {
+ case RANDOM_MONSTER:
+ result += "random monster";
+ return (result);
+ case RANDOM_DRACONIAN:
+ result += "random draconian";
+ return (result);
+ case RANDOM_BASE_DRACONIAN:
+ result += "random base draconian";
+ return (result);
+ case RANDOM_NONBASE_DRACONIAN:
+ result += "random nonbase draconian";
+ return (result);
+ case WANDERING_MONSTER:
+ result += "wandering monster";
+ return (result);
+ }
+
+ const monsterentry *me = get_monster_data(type);
+ ASSERT(me != NULL);
+ if (me == NULL)
+ {
+ result += make_stringf("invalid type %d", type);
+ return (result);
+ }
+
+ result += me->name;
// Vowel fix: Change 'a orc' to 'an orc'.
if (result.length() >= 3
diff --git a/crawl-ref/source/monplace.cc b/crawl-ref/source/monplace.cc
index 753095e6b3..a95a26a04f 100644
--- a/crawl-ref/source/monplace.cc
+++ b/crawl-ref/source/monplace.cc
@@ -29,6 +29,14 @@
#include "traps.h"
#include "view.h"
+static std::vector<int> vault_mon_types;
+static std::vector<int> vault_mon_bases;
+static std::vector<int> vault_mon_weights;
+
+#define VAULT_MON_TYPES_KEY "vault_mon_types"
+#define VAULT_MON_BASES_KEY "vault_mon_bases"
+#define VAULT_MON_WEIGHTS_KEY "vault_mon_weights"
+
// NEW place_monster -- note that power should be set to:
// 51 for abyss
// 52 for pandemonium
@@ -41,6 +49,14 @@
#define BIG_BAND 20
+static monster_type _resolve_monster_type(monster_type mon_type,
+ proximity_type proximity,
+ monster_type &base_type,
+ coord_def &pos,
+ unsigned mmask,
+ dungeon_char_type *stair_type,
+ int *lev_mons);
+
static void _define_zombie( int mid, monster_type ztype,
monster_type cs, int power, coord_def pos );
static monster_type _band_member(band_type band, int power);
@@ -219,10 +235,19 @@ void spawn_random_monsters()
return;
}
+ if (env.spawn_random_rate == 0)
+ {
+#ifdef DEBUG_MON_CREATION
+ mpr("random monster gen turned off", MSGCH_DIAGNOSTICS);
+#endif
+ return;
+ }
+
+ const int rate = (you.char_direction == GDT_DESCENDING) ?
+ env.spawn_random_rate : 8;
+
// Place normal dungeon monsters, but not in player LOS.
- if (you.level_type == LEVEL_DUNGEON
- && !player_in_branch( BRANCH_ECUMENICAL_TEMPLE )
- && x_chance_in_y(5, (you.char_direction == GDT_DESCENDING) ? 240 : 8))
+ if (you.level_type == LEVEL_DUNGEON && x_chance_in_y(5, rate))
{
#ifdef DEBUG_MON_CREATION
mpr("Create wandering monster...", MSGCH_DIAGNOSTICS);
@@ -245,7 +270,8 @@ void spawn_random_monsters()
// look a bit strange for a place as chaotic as the Abyss. Then again,
// the player is unlikely to meet all of them and notice this.)
if (you.level_type == LEVEL_ABYSS
- && (you.char_direction != GDT_GAME_START || one_chance_in(10)))
+ && (you.char_direction != GDT_GAME_START
+ || x_chance_in_y(5, rate)))
{
mons_place(mgen_data(WANDERING_MONSTER));
viewwindow(true, false);
@@ -253,28 +279,58 @@ void spawn_random_monsters()
}
// Place Pandemonium monsters.
- if (you.level_type == LEVEL_PANDEMONIUM && one_chance_in(10))
+ if (you.level_type == LEVEL_PANDEMONIUM && x_chance_in_y(5, rate))
{
pandemonium_mons();
viewwindow(true, false);
+ return;
+ }
+
+ // A portal vault *might* decide to turn on random monster spawning,
+ // but it's off by default.
+ if (you.level_type == LEVEL_PORTAL_VAULT && x_chance_in_y(5, rate))
+ {
+ mons_place(mgen_data(WANDERING_MONSTER));
+ viewwindow(true, false);
}
- // No monsters in the Labyrinth, or the Ecumenical Temple, or in Bazaars.
+ // No random monsters in the Labyrinth.
}
monster_type pick_random_monster(const level_id &place)
{
- int level = place.absdepth();
+ int level;
+ if (place.level_type == LEVEL_PORTAL_VAULT)
+ level = you.your_level;
+ else
+ level = place.absdepth();
return pick_random_monster(place, level, level);
}
monster_type pick_random_monster(const level_id &place, int power,
int &lev_mons)
{
- if (place.level_type == LEVEL_LABYRINTH
- || place.level_type == LEVEL_PORTAL_VAULT)
- {
+ if (place.level_type == LEVEL_LABYRINTH)
+ return (MONS_PROGRAM_BUG);
+
+ if (place == BRANCH_ECUMENICAL_TEMPLE)
return (MONS_PROGRAM_BUG);
+
+ if (place.level_type == LEVEL_PORTAL_VAULT)
+ {
+ monster_type base_type = (monster_type) 0;
+ coord_def dummy1;
+ dungeon_char_type dummy2;
+ monster_type type =
+ _resolve_monster_type(RANDOM_MONSTER, PROX_ANYWHERE, base_type,
+ dummy1, 0, &dummy2, &lev_mons);
+
+#if DEBUG || DEBUG_DIAGNOSTICS
+ if (base_type != 0 && base_type != MONS_PROGRAM_BUG)
+ mpr("Random portal vault mon discarding base type.",
+ MSGCH_ERROR);
+#endif
+ return (type);
}
monster_type mon_type = MONS_PROGRAM_BUG;
@@ -395,7 +451,7 @@ bool drac_colour_incompatible(int drac, int colour)
static monster_type _resolve_monster_type(monster_type mon_type,
proximity_type proximity,
- monster_type base_type,
+ monster_type &base_type,
coord_def &pos,
unsigned mmask,
dungeon_char_type *stair_type,
@@ -495,6 +551,44 @@ static monster_type _resolve_monster_type(monster_type mon_type,
mon_type = MONS_DANCING_WEAPON;
else
{
+ if (you.level_type == LEVEL_PORTAL_VAULT)
+ {
+ if (vault_mon_types.size() == 0)
+ return (MONS_PROGRAM_BUG);
+
+ int i = choose_random_weighted(vault_mon_weights.begin(),
+ vault_mon_weights.end());
+ int type = vault_mon_types[i];
+ int base = vault_mon_bases[i];
+
+ if (type == -1)
+ {
+ place = level_id::from_packed_place(base);
+ // If lev_mons is set to you.your_level, it was probably
+ // set as a default meaning "the current dungeon depth",
+ // which for a portal vault using it's own definition
+ // of random monsters means "the depth of whatever place
+ // we're using for picking the random monster".
+ if (*lev_mons == you.your_level)
+ *lev_mons = place.absdepth();
+ // pick_random_monster() is called below
+ }
+ else
+ {
+ base_type = (monster_type) base;
+ mon_type = (monster_type) type;
+ if (mon_type == RANDOM_DRACONIAN
+ || mon_type == RANDOM_BASE_DRACONIAN
+ || mon_type == RANDOM_NONBASE_DRACONIAN)
+ {
+ mon_type =
+ _resolve_monster_type(mon_type, proximity,
+ base_type, pos, mmask,
+ stair_type, lev_mons);
+ }
+ return (mon_type);
+ }
+ }
// Now pick a monster of the given branch and level.
mon_type = pick_random_monster(place, *lev_mons, *lev_mons);
}
@@ -2836,3 +2930,134 @@ void monster_pathfind::update_pos(coord_def npos, int total)
add_new_pos(npos, total);
}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Random monsters for portal vaults.
+//
+/////////////////////////////////////////////////////////////////////////////
+
+void set_vault_mon_list(const std::vector<mons_spec> &list)
+{
+ CrawlHashTable &props = env.properties;
+
+ props.erase(VAULT_MON_TYPES_KEY);
+ props.erase(VAULT_MON_BASES_KEY);
+ props.erase(VAULT_MON_WEIGHTS_KEY);
+
+ unsigned int size = list.size();
+ if (size == 0)
+ {
+ setup_vault_mon_list();
+ return;
+ }
+
+ props[VAULT_MON_TYPES_KEY].new_vector(SV_LONG).resize(size);
+ props[VAULT_MON_BASES_KEY].new_vector(SV_LONG).resize(size);
+ props[VAULT_MON_WEIGHTS_KEY].new_vector(SV_LONG).resize(size);
+
+ CrawlVector &type_vec = props[VAULT_MON_TYPES_KEY];
+ CrawlVector &base_vec = props[VAULT_MON_BASES_KEY];
+ CrawlVector &weight_vec = props[VAULT_MON_WEIGHTS_KEY];
+
+ for (unsigned int i = 0; i < size; i++)
+ {
+ const mons_spec &spec = list[i];
+
+ if (spec.place.is_valid())
+ {
+ ASSERT(spec.place.level_type != LEVEL_LABYRINTH
+ && spec.place.level_type != LEVEL_PORTAL_VAULT);
+ type_vec[i] = (long) -1;
+ base_vec[i] = (long) spec.place.packed_place();
+ }
+ else
+ {
+ ASSERT(spec.mid != RANDOM_MONSTER
+ && spec.monbase != RANDOM_MONSTER);
+ type_vec[i] = (long) spec.mid;
+ base_vec[i] = (long) spec.monbase;
+ }
+ weight_vec[i] = (long) spec.genweight;
+ }
+
+ setup_vault_mon_list();
+}
+
+void get_vault_mon_list(std::vector<mons_spec> &list)
+{
+ list.clear();
+
+ CrawlHashTable &props = env.properties;
+
+ if (!props.exists(VAULT_MON_TYPES_KEY))
+ return;
+
+ ASSERT(props.exists(VAULT_MON_BASES_KEY));
+ ASSERT(props.exists(VAULT_MON_WEIGHTS_KEY));
+
+ CrawlVector &type_vec = props[VAULT_MON_TYPES_KEY];
+ CrawlVector &base_vec = props[VAULT_MON_BASES_KEY];
+ CrawlVector &weight_vec = props[VAULT_MON_WEIGHTS_KEY];
+
+ ASSERT(type_vec.size() == base_vec.size());
+ ASSERT(type_vec.size() == weight_vec.size());
+
+ unsigned int size = type_vec.size();
+ for (unsigned int i = 0; i < size; i++)
+ {
+ int type = (long) type_vec[i];
+ int base = (long) base_vec[i];
+
+ mons_spec spec;
+
+ if (type == -1)
+ {
+ spec.place = level_id::from_packed_place(base);
+ ASSERT(spec.place.is_valid());
+ ASSERT(spec.place.level_type != LEVEL_LABYRINTH
+ && spec.place.level_type != LEVEL_PORTAL_VAULT);
+ }
+ else
+ {
+ spec.mid = type;
+ spec.monbase = (monster_type) base;
+ ASSERT(spec.mid != RANDOM_MONSTER
+ && spec.monbase != RANDOM_MONSTER);
+ }
+ spec.genweight = (long) weight_vec[i];
+
+ list.push_back(spec);
+ }
+}
+
+void setup_vault_mon_list()
+{
+ vault_mon_types.clear();
+ vault_mon_bases.clear();
+ vault_mon_weights.clear();
+
+ std::vector<mons_spec> list;
+ get_vault_mon_list(list);
+
+ unsigned int size = list.size();
+
+ vault_mon_types.resize(size);
+ vault_mon_bases.resize(size);
+ vault_mon_weights.resize(size);
+
+ for (unsigned int i = 0; i < size; i++)
+ {
+ if (list[i].place.is_valid())
+ {
+ vault_mon_types[i] = -1;
+ vault_mon_bases[i] = list[i].place.packed_place();
+ }
+ else
+ {
+ vault_mon_types[i] = list[i].mid;
+ vault_mon_bases[i] = list[i].monbase;
+ }
+ vault_mon_weights[i] = list[i].genweight;
+ }
+}
diff --git a/crawl-ref/source/monplace.h b/crawl-ref/source/monplace.h
index 2b4529e59f..24be04f149 100644
--- a/crawl-ref/source/monplace.h
+++ b/crawl-ref/source/monplace.h
@@ -340,6 +340,18 @@ coord_def find_newmons_square_contiguous(monster_type mons_class,
void spawn_random_monsters();
+/* ***********************************************************************
+ * called from: luadgn
+ * *********************************************************************** */
+void set_vault_mon_list(const std::vector<mons_spec> &list);
+
+void get_vault_mon_list(std::vector<mons_spec> &list);
+
+/* ***********************************************************************
+ * called from: files
+ * *********************************************************************** */
+void setup_vault_mon_list();
+
class monster_pathfind
{
public:
diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc
index 9f1bae2103..ce8154f240 100644
--- a/crawl-ref/source/tags.cc
+++ b/crawl-ref/source/tags.cc
@@ -1726,7 +1726,10 @@ static void tag_construct_level(writer &th)
marshallCoord(th, env.sanctuary_pos);
marshallByte(th, env.sanctuary_time);
+ marshallLong(th, env.spawn_random_rate);
+
env.markers.write(th);
+ env.properties.write(th);
}
void marshallItem(writer &th, const item_def &item)
@@ -2003,6 +2006,7 @@ void tag_construct_level_tiles(writer &th)
static void tag_read_level( reader &th, char minorVersion )
{
+
env.floor_colour = unmarshallByte(th);
env.rock_colour = unmarshallByte(th);
@@ -2070,7 +2074,12 @@ static void tag_read_level( reader &th, char minorVersion )
unmarshallCoord(th, env.sanctuary_pos);
env.sanctuary_time = unmarshallByte(th);
+ env.spawn_random_rate = unmarshallLong(th);
+
env.markers.read(th, minorVersion);
+
+ env.properties.clear();
+ env.properties.read(th);
}
static void tag_read_level_items(reader &th, char minorVersion)
diff --git a/crawl-ref/source/travel.cc b/crawl-ref/source/travel.cc
index ea38dd925a..ecef971888 100644
--- a/crawl-ref/source/travel.cc
+++ b/crawl-ref/source/travel.cc
@@ -3118,6 +3118,17 @@ level_id level_id::parse_level_id(const std::string &s) throw (std::string)
return level_id(br, dep);
}
+level_id level_id::from_packed_place(const unsigned short place)
+{
+ level_id id;
+
+ id.branch = (branch_type) place_branch(place);
+ id.depth = place_depth(place);
+ id.level_type = (level_area_type) place_type(place);
+
+ return (id);
+}
+
// NOTE: see also marshall_level_id
void level_id::save(writer& outf) const
{