From 9d1463d7bdca2b485c5f8caa9b86782f29e30f8c Mon Sep 17 00:00:00 2001 From: dshaligram Date: Tue, 26 Jun 2007 16:57:36 +0000 Subject: Added support for a validation hook for maps to check if they're A-Ok. Tweaked savefile format (breaks saves) to allow the game to perform emergency saves if level-generation fails (followers are lost, needs to be fixed). [1743698] Re-refixed SP_ELF stub (Eino). git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@1659 c06c8d41-db1a-0410-9941-cceddc491573 --- crawl-ref/source/acr.cc | 6 ++-- crawl-ref/source/dat/clua/dungeon.lua | 57 ++++++++++++++++++++---------- crawl-ref/source/debug.cc | 2 +- crawl-ref/source/dungeon.cc | 46 +++++++++++++++++------- crawl-ref/source/effects.cc | 2 +- crawl-ref/source/effects.h | 2 +- crawl-ref/source/externs.h | 5 +++ crawl-ref/source/files.cc | 54 +++++++++++++++++----------- crawl-ref/source/files.h | 4 +-- crawl-ref/source/libutil.h | 18 ++++++---- crawl-ref/source/mapdef.cc | 66 +++++++++++++++++++++++++++++++---- crawl-ref/source/mapdef.h | 18 ++++++++-- crawl-ref/source/maps.cc | 37 ++++++++++++++------ crawl-ref/source/maps.h | 2 +- crawl-ref/source/misc.cc | 10 +++--- crawl-ref/source/misc.h | 2 +- crawl-ref/source/player.cc | 7 ++-- crawl-ref/source/tags.cc | 6 ++++ crawl-ref/source/util/levcomp.lpp | 4 +++ crawl-ref/source/util/levcomp.ypp | 28 +++++++++++++-- 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 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& 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 stair( + you.transit_stair, stair_taken, DNGN_UNSEEN); + unwind_bool ylev(you.entering_level, true, false); + std::vector 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 +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 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 @@ -807,6 +807,19 @@ std::vector map_lines::get_subst_strings() const return (substs); } +/////////////////////////////////////////////// +// 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 keyed_specs; typedef std::vector 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 *); -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 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(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 BRANCHDEF BRANCH DESC DEFAULT %token DEFAULT_DEPTH SHUFFLE SUBST TAGS KFEAT KITEM KMONS %token NAME DEPTH ORIENT PLACE CHANCE MONS ITEM -%token PRELUDE MAIN +%token PRELUDE MAIN VALIDATE VETO %token 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 */ { } -- cgit v1.2.3-54-g00ecf