summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crawl-ref/source/acr.cc6
-rw-r--r--crawl-ref/source/dat/clua/dungeon.lua57
-rw-r--r--crawl-ref/source/debug.cc2
-rw-r--r--crawl-ref/source/dungeon.cc46
-rw-r--r--crawl-ref/source/effects.cc2
-rw-r--r--crawl-ref/source/effects.h2
-rw-r--r--crawl-ref/source/externs.h5
-rw-r--r--crawl-ref/source/files.cc54
-rw-r--r--crawl-ref/source/files.h4
-rw-r--r--crawl-ref/source/libutil.h18
-rw-r--r--crawl-ref/source/mapdef.cc66
-rw-r--r--crawl-ref/source/mapdef.h18
-rw-r--r--crawl-ref/source/maps.cc37
-rw-r--r--crawl-ref/source/maps.h2
-rw-r--r--crawl-ref/source/misc.cc10
-rw-r--r--crawl-ref/source/misc.h2
-rw-r--r--crawl-ref/source/player.cc7
-rw-r--r--crawl-ref/source/tags.cc6
-rw-r--r--crawl-ref/source/util/levcomp.lpp4
-rw-r--r--crawl-ref/source/util/levcomp.ypp28
20 files changed, 283 insertions, 93 deletions
diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc
index f9c123c31c..4480cf7c45 100644
--- a/crawl-ref/source/acr.cc
+++ b/crawl-ref/source/acr.cc
@@ -3023,8 +3023,10 @@ static bool initialise(void)
calc_hp();
calc_mp();
- load( 82, (newc ? LOAD_START_GAME : LOAD_RESTART_GAME), false, 0,
- you.where_are_you );
+ 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 );
#if DEBUG_DIAGNOSTICS
// Debug compiles display a lot of "hidden" information, so we auto-wiz
diff --git a/crawl-ref/source/dat/clua/dungeon.lua b/crawl-ref/source/dat/clua/dungeon.lua
index 28084beaa8..7fe2b30a22 100644
--- a/crawl-ref/source/dat/clua/dungeon.lua
+++ b/crawl-ref/source/dat/clua/dungeon.lua
@@ -3,39 +3,60 @@
-- Dungeoneering functions.
------------------------------------------------------------------------------
--- Given an object and a table (dgn), returns a table with functions
--- that translate into method calls on the object. This table is
--- suitable for setfenv() on a function that expects to directly
--- address a map object.
-function dgn_map_meta_wrap(obj, tab)
- local meta = { }
+-- Wraps a map_def into a Lua environment (a table) such that
+-- functions run in the environment (with setfenv) can directly
+-- address the map with function calls such as name(), tags(), etc.
+--
+-- This function caches the environments it creates, so that successive runs
+-- of Lua chunks from the same map will use the same environment.
+function dgn_map_meta_wrap(map, tab)
+ if not dgn._map_envs then
+ dgn._map_envs = { }
+ end
+
+ local name = dgn.name(map)
+ local meta = dgn._map_envs[name]
+
+ if not meta then
+ meta = { }
+
+ local meta_meta = { __index = _G }
+ setmetatable(meta, meta_meta)
+ dgn._map_envs[name] = meta
+ end
+
+ -- We must set this each time - the map may have the same name, but
+ -- be a different C++ object.
for fn, val in pairs(tab) do
meta[fn] = function (...)
- return crawl.err_trace(val, obj, ...)
+ return crawl.err_trace(val, map, ...)
end
end
- meta.wrapped_instance = obj
-
- local meta_meta = { __index = _G }
- setmetatable(meta, meta_meta)
+ meta.wrapped_instance = map
return meta
end
+-- Discards accumulated map environments.
+function dgn_flush_map_environments()
+ dgn._map_envs = nil
+end
+
function dgn_set_map(map)
g_dgn_curr_map = map
end
function dgn_run_map(prelude, main)
if prelude or main then
- env = dgn_map_meta_wrap(g_dgn_curr_map, dgn)
+ local env = dgn_map_meta_wrap(g_dgn_curr_map, dgn)
if prelude then
- setfenv(prelude, env)()
+ local fn = setfenv(prelude, env)
+ if not main then
+ return fn()
+ end
+ fn()
end
if main then
- setfenv(main, env)()
+ return setfenv(main, env)()
end
- -- Return the environment in case we want to chain further
- -- calls.
- return env
end
-end
+end \ No newline at end of file
diff --git a/crawl-ref/source/debug.cc b/crawl-ref/source/debug.cc
index 4f7badcd30..0ca57b4a3a 100644
--- a/crawl-ref/source/debug.cc
+++ b/crawl-ref/source/debug.cc
@@ -424,7 +424,7 @@ void level_travel( int delta )
static void wizard_go_to_level(const level_pos &pos)
{
const int abs_depth = absdungeon_depth(pos.id.branch, pos.id.depth);
- const int stair_taken =
+ const dungeon_feature_type stair_taken =
abs_depth > you.your_level? DNGN_STONE_STAIRS_DOWN_I
: DNGN_STONE_STAIRS_UP_I;
diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc
index 8ed6a9b652..e566927fb7 100644
--- a/crawl-ref/source/dungeon.cc
+++ b/crawl-ref/source/dungeon.cc
@@ -38,6 +38,7 @@
#include "externs.h"
#include "direct.h"
#include "dungeon.h"
+#include "files.h"
#include "itemname.h"
#include "itemprop.h"
#include "items.h"
@@ -205,7 +206,7 @@ static dgn_region_list no_door_fixup_zones;
static dgn_region_list vault_zones;
static std::vector<vault_placement> level_vaults;
static int minivault_chance = 3;
-
+static bool dgn_level_vetoed = false;
static std::string level_name(int subdepth)
{
@@ -243,9 +244,27 @@ static void place_altars()
*********************************************************************/
void builder(int level_number, int level_type)
{
- do
+ // 15 tries to build the level, after which we bail with a capital B.
+ int tries = 10;
+ while (tries-- > 0)
+ {
+ dgn_level_vetoed = false;
build_dungeon_level(level_number, level_type);
- while (!valid_dungeon_level(level_number, level_type));
+
+ if (!dgn_level_vetoed && valid_dungeon_level(level_number, level_type))
+ return;
+ }
+
+ save_game(true,
+ make_stringf("Unable to generate level for '%s'!",
+ level_id::current().describe().c_str()).c_str());
+}
+
+static bool ensure_vault_placed(bool vault_success)
+{
+ if (!vault_success)
+ dgn_level_vetoed = true;
+ return (vault_success);
}
static coord_def find_level_feature(int feat)
@@ -413,21 +432,21 @@ static void build_layout_skeleton(int level_number, int level_type,
{
skip_build = builder_by_branch(level_number);
- if (skip_build == BUILD_QUIT)
+ if (skip_build == BUILD_QUIT || dgn_level_vetoed)
return;
}
- if (skip_build == BUILD_CONTINUE)
+ if (!dgn_level_vetoed && skip_build == BUILD_CONTINUE)
{
// do 'normal' building. Well, except for the swamp.
if (!player_in_branch(BRANCH_SWAMP) &&
!player_in_branch(BRANCH_SHOALS))
skip_build = builder_normal(level_number, level_type, sr);
- if (skip_build == BUILD_CONTINUE)
+ if (!dgn_level_vetoed && skip_build == BUILD_CONTINUE)
{
skip_build = builder_basic(level_number);
- if (skip_build == BUILD_CONTINUE)
+ if (!dgn_level_vetoed && skip_build == BUILD_CONTINUE)
builder_extras(level_number, level_type);
}
}
@@ -548,7 +567,7 @@ static void build_dungeon_level(int level_number, int level_type)
reset_level();
build_layout_skeleton(level_number, level_type, sr);
- if (you.level_type == LEVEL_LABYRINTH)
+ if (you.level_type == LEVEL_LABYRINTH || dgn_level_vetoed)
return;
// Try to place minivaults that really badly want to be placed. Still
@@ -572,6 +591,9 @@ static void build_dungeon_level(int level_number, int level_type)
place_branch_entrances( level_number, level_type );
+ if (dgn_level_vetoed)
+ return;
+
check_doors();
if (!player_in_branch( BRANCH_DIS ) && !player_in_branch( BRANCH_VAULTS ))
@@ -1117,7 +1139,7 @@ static builder_rc_type builder_by_type(int level_number, char level_type)
end(1, false, "Failed to find Pandemonium level %s!\n",
pandemon_level_names[which_demon]);
- build_vaults(level_number, vault);
+ ensure_vault_placed( build_vaults(level_number, vault) );
}
else
{
@@ -1187,7 +1209,7 @@ static builder_rc_type builder_by_branch(int level_number)
if (vault != -1)
{
- build_vaults(level_number, vault);
+ ensure_vault_placed( build_vaults(level_number, vault) );
return BUILD_SKIP;
}
@@ -1267,7 +1289,7 @@ static builder_rc_type builder_normal(int level_number, char level_type,
if (vault != -1)
{
- build_vaults(level_number, vault);
+ ensure_vault_placed( build_vaults(level_number, vault) );
return BUILD_SKIP;
}
@@ -3037,7 +3059,7 @@ static bool build_vaults(int level_number, int force_vault, int rune_subst,
const int gluggy = vault_main(vgrid, place, force_vault, &level_vaults);
- if (gluggy == MAP_NONE)
+ if (gluggy == MAP_NONE || !gluggy)
return (false);
int vx, vy;
diff --git a/crawl-ref/source/effects.cc b/crawl-ref/source/effects.cc
index f3661b0f4c..9c96fa5a35 100644
--- a/crawl-ref/source/effects.cc
+++ b/crawl-ref/source/effects.cc
@@ -136,7 +136,7 @@ static std::string who_banished(const std::string &who)
return (who.empty()? who : " (" + who + ")");
}
-void banished(int gate_type, const std::string &who)
+void banished(dungeon_feature_type gate_type, const std::string &who)
{
#ifdef DGL_MILESTONES
if (gate_type == DNGN_ENTER_ABYSS)
diff --git a/crawl-ref/source/effects.h b/crawl-ref/source/effects.h
index 21aa5bdd24..19714869d1 100644
--- a/crawl-ref/source/effects.h
+++ b/crawl-ref/source/effects.h
@@ -22,7 +22,7 @@
/* ***********************************************************************
* called from: ability - acr - beam - decks - fight - religion - spells
* *********************************************************************** */
-void banished(int gate_type, const std::string &who = "");
+void banished(dungeon_feature_type gate_type, const std::string &who = "");
// last updated 12may2000 {dlb}
diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h
index 07457b8d12..a2ee9c7f01 100644
--- a/crawl-ref/source/externs.h
+++ b/crawl-ref/source/externs.h
@@ -759,6 +759,11 @@ public:
int old_hunger; // used for hunger delta-meter (see output.cc)
+ // Set when the character is going to a new level, to guard against levgen
+ // failures
+ dungeon_feature_type transit_stair;
+ bool entering_level;
+
// Warning: these two are quite different.
//
// The spell table is an index to a specific spell slot (you.spells).
diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc
index aa14cfe8a8..fdbc137f94 100644
--- a/crawl-ref/source/files.cc
+++ b/crawl-ref/source/files.cc
@@ -939,9 +939,13 @@ static void grab_followers(std::vector<follower>& followers)
}
}
-bool load( int 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, load_mode_type load_mode,
+ bool was_a_labyrinth, int old_level, branch_type old_branch )
{
+ unwind_var<dungeon_feature_type> stair(
+ you.transit_stair, stair_taken, DNGN_UNSEEN);
+ unwind_bool ylev(you.entering_level, true, false);
+
std::vector<follower> followers;
bool just_created_level = false;
@@ -971,7 +975,7 @@ bool load( int stair_taken, load_mode_type load_mode, bool was_a_labyrinth,
clear_clouds();
// This block is to grab followers and save the old level to disk.
- if (load_mode == LOAD_ENTER_LEVEL)
+ if (load_mode == LOAD_ENTER_LEVEL && old_level != -1)
{
grab_followers(followers);
@@ -1039,13 +1043,12 @@ bool load( int stair_taken, load_mode_type load_mode, bool was_a_labyrinth,
if (load_mode != LOAD_RESTART_GAME)
clear_clouds();
- if (load_mode != LOAD_RESTART_GAME && you.level_type != LEVEL_ABYSS)
- {
- place_player_on_stair(old_branch, stair_taken);
- }
- else if (load_mode != LOAD_RESTART_GAME && you.level_type == LEVEL_ABYSS)
+ if (load_mode != LOAD_RESTART_GAME)
{
- you.moveto(45, 35);
+ if (you.level_type != LEVEL_ABYSS)
+ place_player_on_stair(old_branch, stair_taken);
+ else
+ you.moveto(45, 35);
}
crawl_view.set_player_at(you.pos(), true);
@@ -1149,7 +1152,8 @@ void save_game(bool leave_game, const char *farewellmsg)
/* Stashes */
std::string stashFile = get_savedir_filename( you.your_name, "", "st" );
FILE *stashf = fopen(stashFile.c_str(), "wb");
- if (stashf) {
+ if (stashf)
+ {
stashes.save(stashf);
fclose(stashf);
DO_CHMOD_PRIVATE(stashFile.c_str());
@@ -1166,7 +1170,8 @@ void save_game(bool leave_game, const char *farewellmsg)
/* kills */
std::string killFile = get_savedir_filename( you.your_name, "", "kil" );
FILE *killf = fopen(killFile.c_str(), "wb");
- if (killf) {
+ if (killf)
+ {
you.kills.save(killf);
fclose(killf);
DO_CHMOD_PRIVATE(killFile.c_str());
@@ -1175,7 +1180,8 @@ void save_game(bool leave_game, const char *farewellmsg)
/* travel cache */
std::string travelCacheFile = get_savedir_filename(you.your_name,"","tc");
FILE *travelf = fopen(travelCacheFile.c_str(), "wb");
- if (travelf) {
+ if (travelf)
+ {
travel_cache.save(travelf);
fclose(travelf);
DO_CHMOD_PRIVATE(travelCacheFile.c_str());
@@ -1184,7 +1190,8 @@ void save_game(bool leave_game, const char *farewellmsg)
/* notes */
std::string notesFile = get_savedir_filename(you.your_name, "", "nts");
FILE *notesf = fopen(notesFile.c_str(), "wb");
- if (notesf) {
+ if (notesf)
+ {
save_notes(notesf);
fclose(notesf);
DO_CHMOD_PRIVATE(notesFile.c_str());
@@ -1194,7 +1201,8 @@ void save_game(bool leave_game, const char *farewellmsg)
std::string tutorFile = get_savedir_filename(you.your_name, "", "tut");
FILE *tutorf = fopen(tutorFile.c_str(), "wb");
- if (tutorf) {
+ if (tutorf)
+ {
save_tutorial(tutorf);
fclose(tutorf);
DO_CHMOD_PRIVATE(tutorFile.c_str());
@@ -1216,7 +1224,8 @@ void save_game(bool leave_game, const char *farewellmsg)
return;
// must be exiting -- save level & goodbye!
- save_level(you.your_level, you.level_type, you.where_are_you);
+ if (!you.entering_level)
+ save_level(you.your_level, you.level_type, you.where_are_you);
clrscr();
@@ -1347,7 +1356,8 @@ void restore_game(void)
std::string stashFile = get_savedir_filename( you.your_name, "", "st" );
FILE *stashf = fopen(stashFile.c_str(), "rb");
- if (stashf) {
+ if (stashf)
+ {
stashes.load(stashf);
fclose(stashf);
}
@@ -1359,21 +1369,24 @@ void restore_game(void)
std::string killFile = get_savedir_filename( you.your_name, "", "kil" );
FILE *killf = fopen(killFile.c_str(), "rb");
- if (killf) {
+ if (killf)
+ {
you.kills.load(killf);
fclose(killf);
}
std::string travelCacheFile = get_savedir_filename(you.your_name,"","tc");
FILE *travelf = fopen(travelCacheFile.c_str(), "rb");
- if (travelf) {
+ if (travelf)
+ {
travel_cache.load(travelf);
fclose(travelf);
}
std::string notesFile = get_savedir_filename(you.your_name, "", "nts");
FILE *notesf = fopen(notesFile.c_str(), "rb");
- if (notesf) {
+ if (notesf)
+ {
load_notes(notesf);
fclose(notesf);
}
@@ -1382,7 +1395,8 @@ void restore_game(void)
std::string tutorFile = get_savedir_filename(you.your_name, "", "tut");
FILE *tutorf = fopen(tutorFile.c_str(), "rb");
- if (tutorf) {
+ if (tutorf)
+ {
load_tutorial(tutorf);
fclose(tutorf);
}
diff --git a/crawl-ref/source/files.h b/crawl-ref/source/files.h
index c210a1d534..d3defbf8d0 100644
--- a/crawl-ref/source/files.h
+++ b/crawl-ref/source/files.h
@@ -53,8 +53,8 @@ void check_newer(const std::string &target,
const std::string &dependency,
void (*action)());
-bool load( int 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, load_mode_type load_mode,
+ bool was_a_labyrinth, int old_level, branch_type where_were_you2 );
// last updated 12may2000 {dlb}
/* ***********************************************************************
diff --git a/crawl-ref/source/libutil.h b/crawl-ref/source/libutil.h
index 1191ca6312..e327ab6d74 100644
--- a/crawl-ref/source/libutil.h
+++ b/crawl-ref/source/libutil.h
@@ -116,23 +116,29 @@ void usleep( unsigned long time );
int snprintf( char *str, size_t size, const char *format, ... );
#endif
-// Sets a boolean to a new value in the scope of the object instance.
-class unwind_bool
+template <typename T>
+class unwind_var
{
public:
- unwind_bool(bool &val_, bool newval) : val(val_), oldval(val_)
+ unwind_var(T &val_, T newval, T reset_to) : val(val_), oldval(reset_to)
{
val = newval;
}
- ~unwind_bool()
+ unwind_var(T &val_, T newval) : val(val_), oldval(val_)
+ {
+ val = newval;
+ }
+ ~unwind_var()
{
val = oldval;
}
private:
- bool &val;
- bool oldval;
+ T &val;
+ T oldval;
};
+typedef unwind_var<bool> unwind_bool;
+
class base_pattern
{
public:
diff --git a/crawl-ref/source/mapdef.cc b/crawl-ref/source/mapdef.cc
index edae6afa9f..a2615f9b7b 100644
--- a/crawl-ref/source/mapdef.cc
+++ b/crawl-ref/source/mapdef.cc
@@ -808,6 +808,19 @@ std::vector<std::string> map_lines::get_subst_strings() const
}
///////////////////////////////////////////////
+// dlua_set_map
+
+dlua_set_map::dlua_set_map(map_def *map)
+{
+ dlua.callfn("dgn_set_map", "m", map);
+}
+
+dlua_set_map::~dlua_set_map()
+{
+ dlua.callfn("dgn_set_map", 0, 0);
+}
+
+///////////////////////////////////////////////
// map_def
//
@@ -828,6 +841,8 @@ void map_def::init()
depths.clear();
prelude.clear();
main.clear();
+ validate.clear();
+ veto.clear();
reinit();
}
@@ -851,6 +866,8 @@ void map_def::write_full(FILE *outf)
writeString(outf, name);
prelude.write(outf);
main.write(outf);
+ validate.write(outf);
+ veto.write(outf);
}
void map_def::read_full(FILE *inf)
@@ -871,6 +888,8 @@ void map_def::read_full(FILE *inf)
prelude.read(inf);
main.read(inf);
+ validate.read(inf);
+ veto.read(inf);
}
void map_def::load()
@@ -939,7 +958,8 @@ void map_def::set_file(const std::string &s)
std::string map_def::run_lua(bool run_main)
{
- dlua.callfn("dgn_set_map", "m", this);
+ dlua_set_map mset(this);
+
int err = prelude.load(dlua);
if (err == -1000)
lua_pushnil(dlua);
@@ -960,22 +980,56 @@ std::string map_def::run_lua(bool run_main)
if (!dlua.callfn("dgn_run_map", 2, 0))
return rewrite_chunk_errors(dlua.error);
- // Clear the map setting.
- dlua.callfn("dgn_set_map", 0, 0);
-
return (dlua.error);
}
+bool map_def::test_lua_boolchunk(dlua_chunk &chunk)
+{
+ bool result = true;
+ dlua_set_map mset(this);
+
+ int err = chunk.load(dlua);
+ if (err == -1000)
+ return (true);
+ else if (err)
+ {
+ mprf(MSGCH_WARN, "Lua error: %s", validate.orig_error().c_str());
+ return (true);
+ }
+
+ if (dlua.callfn("dgn_run_map", 1, 1))
+ dlua.fnreturns("b", &result);
+ else
+ mprf(MSGCH_WARN, "Lua error: %s",
+ rewrite_chunk_errors(dlua.error).c_str());
+
+ return (result);
+}
+
+bool map_def::test_lua_validate()
+{
+ return test_lua_boolchunk(validate);
+}
+
+bool map_def::test_lua_veto()
+{
+ return test_lua_boolchunk(veto);
+}
+
std::string map_def::rewrite_chunk_errors(const std::string &s) const
{
std::string res = s;
if (prelude.rewrite_chunk_errors(res))
return (res);
- main.rewrite_chunk_errors(res);
+ if (main.rewrite_chunk_errors(res))
+ return (res);
+ if (validate.rewrite_chunk_errors(res))
+ return (res);
+ veto.rewrite_chunk_errors(res);
return (res);
}
-std::string map_def::validate()
+std::string map_def::validate_map_def()
{
std::string err = run_lua(true);
if (!err.empty())
diff --git a/crawl-ref/source/mapdef.h b/crawl-ref/source/mapdef.h
index 8e1db25209..307b9bfd3e 100644
--- a/crawl-ref/source/mapdef.h
+++ b/crawl-ref/source/mapdef.h
@@ -394,6 +394,13 @@ typedef std::map<int, keyed_mapspec> keyed_specs;
typedef std::vector<level_range> depth_ranges;
+class map_def;
+struct dlua_set_map
+{
+ dlua_set_map(map_def *map);
+ ~dlua_set_map();
+};
+
class map_def
{
public:
@@ -411,7 +418,7 @@ public:
keyed_specs keyspecs;
- dlua_chunk prelude, main;
+ dlua_chunk prelude, main, validate, veto;
private:
// This map has been loaded from an index, and not fully realised.
@@ -435,7 +442,13 @@ public:
void set_file(const std::string &s);
std::string run_lua(bool skip_main);
- std::string validate();
+ // Returns true if the validation passed.
+ bool test_lua_validate();
+
+ // Returns true if *not* vetoed, i.e., the map is good to go.
+ bool test_lua_veto();
+
+ std::string validate_map_def();
void add_prelude_line(int line, const std::string &s);
void add_main_line(int line, const std::string &s);
@@ -476,6 +489,7 @@ public:
private:
void write_depth_ranges(FILE *) const;
void read_depth_ranges(FILE *);
+ bool test_lua_boolchunk(dlua_chunk &);
std::string rewrite_chunk_errors(const std::string &s) const;
std::string add_key_field(
diff --git a/crawl-ref/source/maps.cc b/crawl-ref/source/maps.cc
index ccff83396e..011bbe45df 100644
--- a/crawl-ref/source/maps.cc
+++ b/crawl-ref/source/maps.cc
@@ -37,7 +37,7 @@ static int apply_vault_definition(
vault_placement &,
std::vector<vault_placement> *);
-static void resolve_map(map_def &def);
+static bool resolve_map(map_def &def, const map_def &original);
//////////////////////////////////////////////////////////////////////////
@@ -87,25 +87,35 @@ static int write_vault(map_def &mdef, map_type map,
// Copy the map so we can monkey with it.
place.map = mdef;
-
+
// Try so many times to place the map. This will always succeed
- // unless there are conflicting map placements in 'avoid'.
- int tries = 10;
- do
- resolve_map(place.map);
- while ((place.orient =
- apply_vault_definition(place.map, map, place, avoid)) == MAP_NONE
- && tries-- > 0);
+ // unless there are conflicting map placements in 'avoid', or there
+ // is a map validate Lua hook that keeps rejecting the map.
+ int tries = 25;
+
+ while (tries-- > 0)
+ {
+ if (!resolve_map(place.map, mdef))
+ continue;
+
+ place.orient = apply_vault_definition(place.map, map,
+ place, avoid);
+ if (place.orient != MAP_NONE)
+ break;
+ }
return (place.orient);
}
// Mirror the map if appropriate, resolve substitutable symbols (?),
-static void resolve_map(map_def &map)
+static bool resolve_map(map_def &map, const map_def &original)
{
map.reinit();
map.run_lua(true);
map.resolve();
+
+ if (!map.test_lua_validate())
+ return (false);
// Mirroring is possible for any map that does not explicitly forbid it.
// Note that mirroring also flips the orientation.
@@ -118,6 +128,8 @@ static void resolve_map(map_def &map)
// The map may also refuse to be rotated.
if (coinflip())
map.rotate( coinflip() );
+
+ return (true);
}
static bool is_grid_clobbered(int sx, int sy, int width, int height)
@@ -385,7 +397,7 @@ void reset_map_parser()
static bool checked_des_index_dir = false;
-#define DESCACHE_VER 1001
+#define DESCACHE_VER 1002
static void check_des_index_dir()
{
@@ -577,6 +589,9 @@ void read_maps()
parse_maps( lc_desfile );
}
+
+ // Clean up cached environments.
+ dlua.callfn("dgn_flush_map_environments", 0, 0);
}
void add_parsed_map( const map_def &md )
diff --git a/crawl-ref/source/maps.h b/crawl-ref/source/maps.h
index 91de437ffe..87b3c933cd 100644
--- a/crawl-ref/source/maps.h
+++ b/crawl-ref/source/maps.h
@@ -28,7 +28,7 @@ struct vault_placement
std::vector<coord_def> exits;
vault_placement()
- : x(-1), y(-1), width(0), height(0), map(),
+ : x(-1), y(-1), width(0), height(0), orient(0), map(),
exits()
{
}
diff --git a/crawl-ref/source/misc.cc b/crawl-ref/source/misc.cc
index 1fc91fe7f7..e526b1d43f 100644
--- a/crawl-ref/source/misc.cc
+++ b/crawl-ref/source/misc.cc
@@ -533,7 +533,7 @@ void merfolk_start_swimming(void)
void up_stairs(void)
{
- int stair_find = grd[you.x_pos][you.y_pos];
+ dungeon_feature_type stair_find = 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;
@@ -653,7 +653,7 @@ void up_stairs(void)
}
}
- const unsigned char stair_taken = stair_find;
+ const dungeon_feature_type stair_taken = stair_find;
if (player_is_levitating())
{
@@ -739,12 +739,12 @@ void up_stairs(void)
}
} // end up_stairs()
-void down_stairs( int old_level, int force_stair )
+void down_stairs( int old_level, dungeon_feature_type force_stair )
{
int i;
char old_level_type = you.level_type;
const bool was_a_labyrinth = you.level_type != LEVEL_DUNGEON;
- const int stair_find =
+ const dungeon_feature_type stair_find =
force_stair? force_stair : grd[you.x_pos][you.y_pos];
bool leave_abyss_pan = false;
@@ -955,7 +955,7 @@ void down_stairs( int old_level, int force_stair )
if (you.level_type == LEVEL_DUNGEON)
you.your_level++;
- int stair_taken = stair_find;
+ dungeon_feature_type stair_taken = stair_find;
if (you.level_type == LEVEL_LABYRINTH || you.level_type == LEVEL_ABYSS)
stair_taken = DNGN_FLOOR;
diff --git a/crawl-ref/source/misc.h b/crawl-ref/source/misc.h
index ef30f7d1a2..ce8b9ccd0c 100644
--- a/crawl-ref/source/misc.h
+++ b/crawl-ref/source/misc.h
@@ -43,7 +43,7 @@ void disarm_trap(struct dist &disa);
/* ***********************************************************************
* called from: acr - effects - spells3
* *********************************************************************** */
-void down_stairs(int old_level, int force_stair = 0);
+void down_stairs(int old_level, dungeon_feature_type force_stair = DNGN_UNSEEN);
// last updated 12may2000 {dlb}
diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc
index cba3505d0f..d31130824b 100644
--- a/crawl-ref/source/player.cc
+++ b/crawl-ref/source/player.cc
@@ -4040,10 +4040,10 @@ void set_mp(int new_amount, bool max_too)
static const char * Species_Abbrev_List[ NUM_SPECIES ] =
- { "XX", "Hu", "El", "HE", "GE", "DE", "SE", "HD", "MD", "Ha",
+ { "XX", "Hu", "HE", "GE", "DE", "SE", "HD", "MD", "Ha",
"HO", "Ko", "Mu", "Na", "Gn", "Og", "Tr", "OM", "Dr", "Dr",
"Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Dr",
- "Ce", "DG", "Sp", "Mi", "DS", "Gh", "Ke", "Mf" };
+ "Ce", "DG", "Sp", "Mi", "DS", "Gh", "Ke", "Mf", "El" };
int get_species_index_by_abbrev( const char *abbrev )
{
@@ -4488,6 +4488,9 @@ void player::init()
banished = false;
banished_by.clear();
+
+ entering_level = false;
+ transit_stair = DNGN_UNSEEN;
just_autoprayed = false;
berserk_penalty = 0;
diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc
index 2986016cc5..55b4433fe3 100644
--- a/crawl-ref/source/tags.cc
+++ b/crawl-ref/source/tags.cc
@@ -830,6 +830,9 @@ static void tag_construct_you(struct tagHeader &th)
marshallLong( th, you.num_turns );
marshallShort(th, you.magic_contamination);
+
+ marshallShort(th, you.transit_stair);
+ marshallByte(th, you.entering_level);
}
static void tag_construct_you_items(struct tagHeader &th)
@@ -1118,6 +1121,9 @@ static void tag_read_you(struct tagHeader &th, char minorVersion)
you.num_turns = unmarshallLong(th);
you.magic_contamination = unmarshallShort(th);
+
+ you.transit_stair = static_cast<dungeon_feature_type>(unmarshallShort(th));
+ you.entering_level = unmarshallByte(th);
}
static void tag_read_you_items(struct tagHeader &th, char minorVersion)
diff --git a/crawl-ref/source/util/levcomp.lpp b/crawl-ref/source/util/levcomp.lpp
index 4cc718855a..6df93afa7c 100644
--- a/crawl-ref/source/util/levcomp.lpp
+++ b/crawl-ref/source/util/levcomp.lpp
@@ -161,6 +161,10 @@ NSPACE [^\ \t\r\n]
^prelude[ \t]*\{\{ { BEGIN(LUA); return PRELUDE; }
^lua[ \t]*\{\{ { BEGIN(LUA); return MAIN; }
^[ \t]*\{\{ { BEGIN(LUA); return MAIN; }
+^validate[ \t]*\{\{ { BEGIN(LUA); return VALIDATE; }
+^veto[ \t]*\{\{ { BEGIN(LUA); return VETO; }
+
+
NAME: { BEGIN(ARGUMENT); return NAME; }
default-depth: { BEGIN(ARGUMENT); return DEFAULT_DEPTH; }
DEPTH: { BEGIN(ARGUMENT); return DEPTH; }
diff --git a/crawl-ref/source/util/levcomp.ypp b/crawl-ref/source/util/levcomp.ypp
index 0a3cb8ada1..aec084fb22 100644
--- a/crawl-ref/source/util/levcomp.ypp
+++ b/crawl-ref/source/util/levcomp.ypp
@@ -65,7 +65,7 @@ level_range set_range(const char *s, int start, int end)
%token <i> BRANCHDEF BRANCH DESC DEFAULT
%token <i> DEFAULT_DEPTH SHUFFLE SUBST TAGS KFEAT KITEM KMONS
%token <i> NAME DEPTH ORIENT PLACE CHANCE MONS ITEM
-%token <i> PRELUDE MAIN
+%token <i> PRELUDE MAIN VALIDATE VETO
%token <i> CHARACTER
@@ -114,7 +114,7 @@ level : name map_specs
yyerror( lc_global_prelude.orig_error().c_str() );
}
- std::string err = lc_map.validate();
+ std::string err = lc_map.validate_map_def();
if (!err.empty())
yyerror(err.c_str());
if (!lc_map.has_depth() && !lc_default_depths.empty())
@@ -172,6 +172,8 @@ metaline : place
| kmons
| main_lua
| prelude_lua
+ | validate_lua
+ | veto_lua
;
global_lua : MAIN global_lua_lines { }
@@ -196,6 +198,28 @@ main_lua_line : LUA_LINE
lc_map.main.add(yylineno, $1);
}
+validate_lua : VALIDATE validate_lua_lines { }
+
+validate_lua_lines : /* empty */ { }
+ | validate_lua_lines validate_lua_line { }
+ ;
+
+validate_lua_line : LUA_LINE
+ {
+ lc_map.validate.add(yylineno, $1);
+ }
+
+veto_lua : VETO veto_lua_lines { }
+
+veto_lua_lines : /* empty */ { }
+ | veto_lua_lines veto_lua_line { }
+ ;
+
+veto_lua_line : LUA_LINE
+ {
+ lc_map.veto.add(yylineno, $1);
+ }
+
prelude_lua : PRELUDE prelude_lua_lines { }
prelude_lua_lines : /* empty */ { }