From 97f93f7d2dd30fee884ee4eeb8a16dcb51cf4a7c Mon Sep 17 00:00:00 2001 From: dshaligram Date: Tue, 25 Nov 2008 00:01:38 +0000 Subject: Allow ziggurats placed in Pandemonium to return to the same Pan level when the player leaves the ziggurat. Breaks saves. Cleaned up up_stairs() and down_stairs() to remove spurious depth changes when changing you.level_type - depth (you.your_level) now changes only for stairs with both ends in LEVEL_DUNGEON. All levels are now saved on exit, including non LEVEL_DUNGEON levels. Re-entering non-dungeon levels from down_stairs will still delete the old level. Re-entering non-dungeon levels from up_stairs (i.e. returning to a non-dungeon level from some other place, like a ziggurat) will reload the old level. Fixed bogus marker trashing when player attempts to use a Zot entrance with insufficient runes. Delete .msg files when game ends. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@7598 c06c8d41-db1a-0410-9941-cceddc491573 --- crawl-ref/source/dat/clua/ziggurat.lua | 7 +- crawl-ref/source/externs.h | 101 ++++++++++ crawl-ref/source/files.cc | 42 ++-- crawl-ref/source/files.h | 4 +- crawl-ref/source/luadgn.cc | 8 + crawl-ref/source/misc.cc | 359 ++++++++++++++++++++------------- crawl-ref/source/newgame.cc | 2 +- crawl-ref/source/ouch.cc | 22 +- crawl-ref/source/player.cc | 5 +- crawl-ref/source/tags.cc | 55 ++--- crawl-ref/source/travel.h | 101 ---------- 11 files changed, 405 insertions(+), 301 deletions(-) diff --git a/crawl-ref/source/dat/clua/ziggurat.lua b/crawl-ref/source/dat/clua/ziggurat.lua index f3981c731d..65927e7b1f 100644 --- a/crawl-ref/source/dat/clua/ziggurat.lua +++ b/crawl-ref/source/dat/clua/ziggurat.lua @@ -23,7 +23,8 @@ function cleanup_ziggurat() return one_way_stair { onclimb = function(...) dgn.persist.ziggurat = { } - end + end, + dstplace = zig().origin_level } end @@ -43,6 +44,8 @@ function initialise_ziggurat(z) z.colour = ziggurat_wall_colour() z.level = { } + + z.origin_level = dgn.level_name(dgn.level_id()) end function ziggurat_initialiser() @@ -409,8 +412,6 @@ local function ziggurat_rectangle_builder(e) end dgn.colour_map(needs_colour, zig().colour) - - crawl.mpr("Ziggurat depth is now " .. zig_depth(), "diagnostic") end ---------------------------------------------------------------------- diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h index 6c75be735d..ef22c4eb6d 100644 --- a/crawl-ref/source/externs.h +++ b/crawl-ref/source/externs.h @@ -434,6 +434,107 @@ struct delay_queue_item }; +// Identifies a level. Should never include virtual methods or +// dynamically allocated memory (see code to push level_id onto Lua +// stack in luadgn.cc) +class level_id +{ +public: + branch_type branch; // The branch in which the level is. + int depth; // What depth (in this branch - starting from 1) + level_area_type level_type; + +public: + // Returns the level_id of the current level. + static level_id current(); + + // Returns the level_id of the level that the stair/portal/whatever at + // 'pos' on the current level leads to. + static level_id get_next_level_id(const coord_def &pos); + + level_id() + : branch(BRANCH_MAIN_DUNGEON), depth(-1), + level_type(LEVEL_DUNGEON) + { + } + level_id(branch_type br, int dep, level_area_type ltype = LEVEL_DUNGEON) + : branch(br), depth(dep), level_type(ltype) + { + } + level_id(const level_id &ot) + : branch(ot.branch), depth(ot.depth), level_type(ot.level_type) + { + } + level_id(level_area_type ltype) + : branch(BRANCH_MAIN_DUNGEON), depth(-1), level_type(ltype) + { + } + + static level_id parse_level_id(const std::string &s) throw (std::string); + + unsigned short packed_place() const; + std::string describe(bool long_name = false, bool with_number = true) const; + + void clear() + { + branch = BRANCH_MAIN_DUNGEON; + depth = -1; + level_type = LEVEL_DUNGEON; + } + + int absdepth() const; + + bool is_valid() const + { + return (branch != NUM_BRANCHES && depth != -1) + || level_type != LEVEL_DUNGEON; + } + + const level_id &operator = (const level_id &id) + { + branch = id.branch; + depth = id.depth; + level_type = id.level_type; + return (*this); + } + + bool operator == ( const level_id &id ) const + { + return (level_type == id.level_type + && (level_type != LEVEL_DUNGEON + || (branch == id.branch && depth == id.depth))); + } + + bool operator != ( const level_id &id ) const + { + return !operator == (id); + } + + bool operator <( const level_id &id ) const + { + if (level_type != id.level_type) + return (level_type < id.level_type); + + if (level_type != LEVEL_DUNGEON) + return (false); + + return (branch < id.branch) || (branch==id.branch && depth < id.depth); + } + + bool operator == ( const branch_type _branch ) const + { + return (branch == _branch && level_type == LEVEL_DUNGEON); + } + + bool operator != ( const branch_type _branch ) const + { + return !operator == (_branch); + } + + void save(writer&) const; + void load(reader&); +}; + struct item_def { object_class_type base_type; // basic class (ie OBJ_WEAPON) diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index d2085cc678..057a3a32bc 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -827,15 +827,7 @@ static void _place_player_on_stair(level_area_type old_level_type, bool find_first = true; // Order is important here. - if (you.level_type == LEVEL_DUNGEON - && old_branch == BRANCH_VESTIBULE_OF_HELL - && stair_taken == DNGN_STONE_STAIRS_UP_I) - { - // Leaving hell - look for entry portal first. - stair_taken = DNGN_ENTER_HELL; - find_first = false; - } - else if (stair_taken == DNGN_EXIT_PANDEMONIUM) + if (stair_taken == DNGN_EXIT_PANDEMONIUM) { stair_taken = DNGN_ENTER_PANDEMONIUM; find_first = false; @@ -845,6 +837,10 @@ static void _place_player_on_stair(level_area_type old_level_type, stair_taken = DNGN_ENTER_ABYSS; find_first = false; } + else if (stair_taken == DNGN_EXIT_HELL) + { + stair_taken = DNGN_ENTER_HELL; + } else if (stair_taken == DNGN_ENTER_HELL) { // The vestibule and labyrinth always start from this stair. @@ -885,9 +881,15 @@ static void _place_player_on_stair(level_area_type old_level_type, - DNGN_ENTER_FIRST_BRANCH); } else if (stair_taken >= DNGN_ENTER_DIS - && stair_taken <= DNGN_TRANSIT_PANDEMONIUM) + && stair_taken <= DNGN_ENTER_TARTARUS) + { + // Only when entering a hell - when exiting, go back to the + // entry stair. + if (player_in_hell()) + stair_taken = DNGN_STONE_STAIRS_UP_I; + } + else if (stair_taken == DNGN_EXIT_ABYSS) { - // When entering a hell or pandemonium. stair_taken = DNGN_STONE_STAIRS_UP_I; } else if (stair_taken == DNGN_ENTER_PORTAL_VAULT) @@ -1078,13 +1080,14 @@ bool load( dungeon_feature_type stair_taken, load_mode_type load_mode, if (you.level_type == LEVEL_DUNGEON && old_level_type == LEVEL_DUNGEON || load_mode == LOAD_START_GAME && you.char_direction != GDT_GAME_START) { - if (tmp_file_pairs[you.your_level][you.where_are_you] == false) + const level_id current(level_id::current()); + if (Generated_Levels.find(current) == Generated_Levels.end()) { // Make sure the old file is gone. unlink(cha_fil.c_str()); // Save the information for later deletion -- DML 6/11/99 - tmp_file_pairs[you.your_level][you.where_are_you] = true; + Generated_Levels.insert(current); } } @@ -1104,8 +1107,7 @@ bool load( dungeon_feature_type stair_taken, load_mode_type load_mode, { _grab_followers(); - if (old_level_type == LEVEL_DUNGEON) - _save_level( old_level, LEVEL_DUNGEON, old_branch ); + _save_level( old_level, old_level_type, old_branch ); } if (make_changes) @@ -1135,7 +1137,7 @@ bool load( dungeon_feature_type stair_taken, load_mode_type load_mode, // generation. you.your_level = 0; you.char_direction = GDT_DESCENDING; - tmp_file_pairs[you.your_level][you.where_are_you] = true; + Generated_Levels.insert(level_id::current()); } _clear_env_map(); @@ -1657,13 +1659,11 @@ static void _restore_level(const level_id &original) you.level_type, you.your_level, you.where_are_you ); } -// Given a level in the dungeon (i.e. level_type == LEVEL_DUNGEON), -// returns true if the level has been created already in this game. -// Asserts if the level_type is not LEVEL_DUNGEON. +// Given a level returns true if the level has been created already +// in this game. bool is_existing_level(const level_id &level) { - ASSERT(level.level_type == LEVEL_DUNGEON); - return (tmp_file_pairs[level.absdepth()][level.branch]); + return (Generated_Levels.find(level) != Generated_Levels.end()); } // Applies an operation (applicator) after switching to the specified level. diff --git a/crawl-ref/source/files.h b/crawl-ref/source/files.h index f2e8c006a1..2a60fbeb77 100644 --- a/crawl-ref/source/files.h +++ b/crawl-ref/source/files.h @@ -15,6 +15,7 @@ #include #include #include +#include enum load_mode_type { @@ -28,7 +29,8 @@ enum load_mode_type #define MAX_LEVELS 50 // referenced in files - newgame - ouch: -extern FixedArray tmp_file_pairs; +typedef std::set level_id_set; +extern level_id_set Generated_Levels; bool file_exists(const std::string &name); bool dir_exists(const std::string &dir); diff --git a/crawl-ref/source/luadgn.cc b/crawl-ref/source/luadgn.cc index 0e81370fbe..53194de4ea 100644 --- a/crawl-ref/source/luadgn.cc +++ b/crawl-ref/source/luadgn.cc @@ -2225,6 +2225,13 @@ LUAFN(dgn_level_id) return (1); } +LUAFN(dgn_level_name) +{ + const level_id lid(_lua_level_id(ls, 1)); + lua_pushstring(ls, lid.describe().c_str()); + return (1); +} + LUAFN(dgn_set_level_type_origin) { if (you.level_type != LEVEL_PORTAL_VAULT) @@ -2484,6 +2491,7 @@ static const struct luaL_reg dgn_lib[] = { "br_parent_branch", dgn_br_parent_branch }, { "level_id", dgn_level_id }, + { "level_name", dgn_level_name }, { "set_level_type_origin", dgn_set_level_type_origin }, { "map_by_tag", dgn_map_by_tag }, { "map_in_depth", dgn_map_in_depth }, diff --git a/crawl-ref/source/misc.cc b/crawl-ref/source/misc.cc index 810b708294..91545ab67e 100644 --- a/crawl-ref/source/misc.cc +++ b/crawl-ref/source/misc.cc @@ -1512,6 +1512,102 @@ bool check_annotation_exclusion_warning() return (true); } +static void _player_change_level_reset() +{ + you.prev_targ = MHITNOT; + if (you.pet_target != MHITYOU) + you.pet_target = MHITNOT; + + you.prev_grd_targ = coord_def(0, 0); +} + +static level_id _stair_destination_override() +{ + const std::string force_place = + env.markers.property_at(you.pos(), MAT_ANY, "dstplace"); + if (!force_place.empty()) + { + try + { + const level_id place = level_id::parse_level_id(force_place); + return (place); + } + catch (const std::string &err) + { + end(1, false, "Marker set with invalid level name: %s", + force_place.c_str()); + } + } + + const level_id invalid; + return (invalid); +} + +static bool _stair_force_destination(const level_id &override) +{ + if (override.is_valid()) + { + if (override.level_type == LEVEL_DUNGEON) + { + you.where_are_you = override.branch; + you.your_level = override.absdepth(); + you.level_type = override.level_type; + } + else + { + you.level_type = override.level_type; + } + return (true); + } + return (false); +} + +static void _player_change_level_upstairs(dungeon_feature_type stair_find, + const level_id &place_override) +{ + if (_stair_force_destination(place_override)) + return; + + if (you.level_type == LEVEL_DUNGEON) + you.your_level--; + + // Make sure we return to our main dungeon level... labyrinth entrances + // in the abyss or pandemonium are a bit trouble (well the labyrinth does + // provide a way out of those places, its really not that bad I suppose). + if (level_type_exits_up(you.level_type)) + you.level_type = LEVEL_DUNGEON; + + if (player_in_branch( BRANCH_VESTIBULE_OF_HELL )) + { + you.where_are_you = BRANCH_MAIN_DUNGEON; + you.your_level = you.hell_exit; + } + + if (player_in_hell()) + { + you.where_are_you = BRANCH_VESTIBULE_OF_HELL; + you.your_level = 27; + } + + // Did we take a branch stair? + for (int i = 0; i < NUM_BRANCHES; ++i) + { + if (branches[i].exit_stairs == stair_find + && you.where_are_you == i) + { + you.where_are_you = branches[i].parent_branch; + + // If leaving a branch which wasn't generated in this + // particular game (like the Swamp or Shoals), then + // its startdepth is set to -1; compensate for that, + // so we don't end up on "level -1". + if (branches[i].startdepth == -1) + you.your_level += 2; + break; + } + } +} + void up_stairs(dungeon_feature_type force_stair, entry_cause_type entry_cause) { @@ -1536,9 +1632,6 @@ void up_stairs(dungeon_feature_type force_stair, return; } - level_id old_level_id = level_id::current(); - LevelInfo &old_level_info = travel_cache.get_level_info(old_level_id); - // Since the overloaded message set turn_is_over, I'm assuming that // the overloaded character makes an attempt... so we're doing this // check before that one. -- bwr @@ -1566,7 +1659,12 @@ void up_stairs(dungeon_feature_type force_stair, return; } - if (you.your_level == 0 + const level_id destination_override(_stair_destination_override()); + const bool leaving_dungeon = + level_id::current() == level_id(BRANCH_MAIN_DUNGEON, 1) + && !destination_override.is_valid(); + + if (leaving_dungeon && !yesno("Are you sure you want to leave the Dungeon?", false, 'n')) { mpr("Alright, then stay!"); @@ -1576,29 +1674,25 @@ void up_stairs(dungeon_feature_type force_stair, // Checks are done, the character is committed to moving between levels. leaving_level_now(); - int old_level = you.your_level; + const int old_level = you.your_level; // Interlevel travel data. const bool collect_travel_data = can_travel_interlevel(); + level_id old_level_id = level_id::current(); + LevelInfo &old_level_info = travel_cache.get_level_info(old_level_id); + if (collect_travel_data) old_level_info.update(); - // Make sure we return to our main dungeon level... labyrinth entrances - // in the abyss or pandemonium are a bit trouble (well the labyrinth does - // provide a way out of those places, its really not that bad I suppose). - if (level_type_exits_up(you.level_type)) - you.level_type = LEVEL_DUNGEON; - - you.your_level--; - - int i = 0; + _player_change_level_reset(); + _player_change_level_upstairs(stair_find, destination_override); if (you.your_level < 0) { mpr("You have escaped!"); - for (i = 0; i < ENDOFPACK; i++) + for (int i = 0; i < ENDOFPACK; i++) { if (is_valid_item( you.inv[i] ) && you.inv[i].base_type == OBJ_ORBS) @@ -1610,39 +1704,30 @@ void up_stairs(dungeon_feature_type force_stair, ouch(INSTANT_DEATH, NON_MONSTER, KILLED_BY_LEAVING); } - you.prev_targ = MHITNOT; - if (you.pet_target != MHITYOU) - you.pet_target = MHITNOT; - - you.prev_grd_targ = coord_def(0, 0); - - if (player_in_branch( BRANCH_VESTIBULE_OF_HELL )) + if (old_level_id.branch == BRANCH_VESTIBULE_OF_HELL + && !player_in_branch( BRANCH_VESTIBULE_OF_HELL )) { mpr("Thank you for visiting Hell. Please come again soon."); - you.where_are_you = BRANCH_MAIN_DUNGEON; - you.your_level = you.hell_exit; - stair_find = DNGN_STONE_STAIRS_UP_I; } - if (player_in_hell()) - { - you.where_are_you = BRANCH_VESTIBULE_OF_HELL; - you.your_level = 27; - } - - // Did we take a branch stair? - for (i = 0; i < NUM_BRANCHES; ++i) + // Fixup exits from the Hell branches. + if (player_in_branch(BRANCH_VESTIBULE_OF_HELL)) { - if (branches[i].exit_stairs == stair_find) + switch (old_level_id.branch) { - you.where_are_you = branches[i].parent_branch; - - // If leaving a branch which wasn't generated in this - // particular game (like the Swamp or Shoals), then - // its startdepth is set to -1; compensate for that, - // so we don't end up on "level -1". - if (branches[i].startdepth == -1) - you.your_level += 2; + case BRANCH_COCYTUS: + stair_find = DNGN_ENTER_COCYTUS; + break; + case BRANCH_DIS: + stair_find = DNGN_ENTER_DIS; + break; + case BRANCH_GEHENNA: + stair_find = DNGN_ENTER_GEHENNA; + break; + case BRANCH_TARTARUS: + stair_find = DNGN_ENTER_TARTARUS; + break; + default: break; } } @@ -1789,17 +1874,79 @@ static void _mark_portal_return_point(const coord_def &pos) } } +// All changes to you.level_type, you.where_are_you and you.your_level +// for descending stairs should happen here. +static void _player_change_level_downstairs( + dungeon_feature_type stair_find, + const level_id &place_override, + bool shaft, + int shaft_level, + const level_id &shaft_dest) +{ + if (_stair_force_destination(place_override)) + return; + + const level_area_type original_level_type(you.level_type); + + if (you.level_type != LEVEL_DUNGEON + && (you.level_type != LEVEL_PANDEMONIUM + || stair_find != DNGN_TRANSIT_PANDEMONIUM) + && (you.level_type != LEVEL_PORTAL_VAULT + || !grid_is_stone_stair(stair_find))) + { + you.level_type = LEVEL_DUNGEON; + } + + if (stair_find == DNGN_ENTER_HELL) + { + you.where_are_you = BRANCH_VESTIBULE_OF_HELL; + you.hell_exit = you.your_level; + + you.your_level = 26; + } + + // Welcome message. + // Try to find a branch stair. + for (int i = 0; i < NUM_BRANCHES; ++i) + { + if (branches[i].entry_stairs == stair_find) + { + you.where_are_you = branches[i].id; + break; + } + } + + if (stair_find == DNGN_ENTER_LABYRINTH) + you.level_type = LEVEL_LABYRINTH; + else if (stair_find == DNGN_ENTER_ABYSS) + you.level_type = LEVEL_ABYSS; + else if (stair_find == DNGN_ENTER_PANDEMONIUM) + you.level_type = LEVEL_PANDEMONIUM; + else if (stair_find == DNGN_ENTER_PORTAL_VAULT) + you.level_type = LEVEL_PORTAL_VAULT; + + if (shaft) + { + you.your_level = shaft_level; + you.where_are_you = shaft_dest.branch; + } + else if (original_level_type == LEVEL_DUNGEON + && you.level_type == LEVEL_DUNGEON) + { + you.your_level++; + } +} + void down_stairs( int old_level, dungeon_feature_type force_stair, entry_cause_type entry_cause ) { - int i; const level_area_type old_level_type = you.level_type; const dungeon_feature_type stair_find = force_stair? force_stair : grd(you.pos()); branch_type old_where = you.where_are_you; - bool shaft = (!force_stair + const bool shaft = (!force_stair && get_trap_type(you.pos()) == TRAP_SHAFT || force_stair == DNGN_TRAP_NATURAL); level_id shaft_dest; @@ -1836,6 +1983,7 @@ void down_stairs( int old_level, dungeon_feature_type force_stair, return; } + if (shaft) { const bool known_trap = (grd(you.pos()) != DNGN_UNDISCOVERED_TRAP @@ -1883,33 +2031,6 @@ void down_stairs( int old_level, dungeon_feature_type force_stair, mpr("You fall through a shaft!"); } - // All checks are done, the player is on the move now. - - // Fire level-leaving trigger. - leaving_level_now(); - -#ifdef DGL_MILESTONES - if (!force_stair) - { - // Not entirely accurate - the player could die before - // reaching the Abyss. - if (grd(you.pos()) == DNGN_ENTER_ABYSS) - mark_milestone("abyss.enter", "entered the Abyss!"); - else if (grd(you.pos()) == DNGN_EXIT_ABYSS - && you.char_direction != GDT_GAME_START) - { - mark_milestone("abyss.exit", "escaped from the Abyss!"); - } - } -#endif - - // [ds] Descending into the Labyrinth increments your_level. Going - // downstairs from a labyrinth implies that you've been banished (or been - // sent to Pandemonium somehow). Decrementing your_level here is needed - // to fix this buggy sequence: D:n -> Labyrinth -> Abyss -> D:(n+1). - if (level_type_exits_up(you.level_type)) - you.your_level--; - if (stair_find == DNGN_ENTER_ZOT) { const int num_runes = runes_in_pack(); @@ -1930,6 +2051,27 @@ void down_stairs( int old_level, dungeon_feature_type force_stair, } } + const level_id destination_override(_stair_destination_override()); + + // All checks are done, the player is on the move now. + // Fire level-leaving trigger. + leaving_level_now(); + +#ifdef DGL_MILESTONES + if (!force_stair) + { + // Not entirely accurate - the player could die before + // reaching the Abyss. + if (grd(you.pos()) == DNGN_ENTER_ABYSS) + mark_milestone("abyss.enter", "entered the Abyss!"); + else if (grd(you.pos()) == DNGN_EXIT_ABYSS + && you.char_direction != GDT_GAME_START) + { + mark_milestone("abyss.exit", "escaped from the Abyss!"); + } + } +#endif + // Interlevel travel data. const bool collect_travel_data = can_travel_interlevel(); @@ -1943,42 +2085,6 @@ void down_stairs( int old_level, dungeon_feature_type force_stair, if (you.level_type == LEVEL_ABYSS) save_abyss_uniques(); - if (you.level_type != LEVEL_DUNGEON - && (you.level_type != LEVEL_PANDEMONIUM - || stair_find != DNGN_TRANSIT_PANDEMONIUM) - && (you.level_type != LEVEL_PORTAL_VAULT - || !grid_is_stone_stair(stair_find))) - { - you.level_type = LEVEL_DUNGEON; - } - - you.prev_targ = MHITNOT; - if (you.pet_target != MHITYOU) - you.pet_target = MHITNOT; - - you.prev_grd_targ = coord_def(0, 0); - - if (stair_find == DNGN_ENTER_HELL) - { - you.where_are_you = BRANCH_VESTIBULE_OF_HELL; - you.hell_exit = you.your_level; - - you.your_level = 26; - } - - // Welcome message. - // Try to find a branch stair. - bool entered_branch = false; - for (i = 0; i < NUM_BRANCHES; ++i) - { - if (branches[i].entry_stairs == stair_find) - { - entered_branch = true; - you.where_are_you = branches[i].id; - break; - } - } - if (stair_find == DNGN_ENTER_LABYRINTH) dungeon_terrain_changed(you.pos(), DNGN_STONE_ARCH); @@ -1988,14 +2094,9 @@ void down_stairs( int old_level, dungeon_feature_type force_stair, _mark_portal_return_point(you.pos()); } - if (stair_find == DNGN_ENTER_LABYRINTH) - you.level_type = LEVEL_LABYRINTH; - else if (stair_find == DNGN_ENTER_ABYSS) - you.level_type = LEVEL_ABYSS; - else if (stair_find == DNGN_ENTER_PANDEMONIUM) - you.level_type = LEVEL_PANDEMONIUM; - else if (stair_find == DNGN_ENTER_PORTAL_VAULT) - you.level_type = LEVEL_PORTAL_VAULT; + _player_change_level_reset(); + _player_change_level_downstairs(stair_find, destination_override, shaft, + shaft_level, shaft_dest); // When going downstairs into a special level, delete any previous // instances of it. @@ -2005,11 +2106,16 @@ void down_stairs( int old_level, dungeon_feature_type force_stair, you.where_are_you, you.level_type, false); #if DEBUG_DIAGNOSTICS - mprf( MSGCH_DIAGNOSTICS, "Deleting: %s", lname.c_str() ); + mprf( MSGCH_WARN, "Deleting: %s", lname.c_str() ); #endif unlink(lname.c_str()); } + // Did we enter a new branch. + const bool entered_branch( + you.where_are_you != old_level_id.branch + && branches[you.where_are_you].parent_branch == old_level_id.branch); + if (stair_find == DNGN_EXIT_ABYSS || stair_find == DNGN_EXIT_PANDEMONIUM) { mpr("You pass through the gate."); @@ -2045,14 +2151,6 @@ void down_stairs( int old_level, dungeon_feature_type force_stair, KILLED_BY_FALLING_DOWN_STAIRS); } - if (shaft) - { - you.your_level = shaft_level; - you.where_are_you = shaft_dest.branch; - } - else if (you.level_type == LEVEL_DUNGEON) - you.your_level++; - dungeon_feature_type stair_taken = stair_find; if (you.level_type == LEVEL_ABYSS) @@ -2196,19 +2294,6 @@ void down_stairs( int old_level, dungeon_feature_type force_stair, unsigned char pc = 0; unsigned char pt = random2avg(28, 3); - if (shaft) - { - you.your_level = shaft_level; - you.where_are_you = shaft_dest.branch; - } - else if (level_type_exits_up(you.level_type)) - you.your_level++; - else if (level_type_exits_down(you.level_type) - && !level_type_exits_down(old_level_type)) - { - you.your_level--; - } - switch (you.level_type) { diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index 6f2dbccc15..8f62376770 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -1267,7 +1267,7 @@ game_start: set_mp( you.max_magic_points, false ); // tmpfile purging removed in favour of marking - tmp_file_pairs.init(false); + Generated_Levels.clear(); _initialise_branch_depths(); init_level_connectivity(); diff --git a/crawl-ref/source/ouch.cc b/crawl-ref/source/ouch.cc index 8d797a1e31..a00a296e8d 100644 --- a/crawl-ref/source/ouch.cc +++ b/crawl-ref/source/ouch.cc @@ -1007,18 +1007,16 @@ void end_game( scorefile_entry &se ) } // clean all levels that we think we have ever visited - for (int level = 0; level < MAX_LEVELS; level++) + for (level_id_set::const_iterator i = Generated_Levels.begin(); + i != Generated_Levels.end(); ++i) { - for (int dungeon = 0; dungeon < NUM_BRANCHES; dungeon++) - { - if (tmp_file_pairs[level][dungeon]) - { - unlink( - make_filename( you.your_name, level, - static_cast(dungeon), - LEVEL_DUNGEON, false ).c_str() ); - } - } + const level_id &place(*i); + unlink( + make_filename( you.your_name, + place.absdepth(), + place.branch, + place.level_type, + false ).c_str() ); } // temp levels, if any @@ -1041,7 +1039,7 @@ void end_game( scorefile_entry &se ) #ifdef PACKAGE_SUFFIX PACKAGE_SUFFIX , #endif - ".st", ".kil", ".tc", ".nts", ".tut", ".sav" + ".st", ".kil", ".tc", ".nts", ".tut", ".sav", ".msg" }; const int num_suffixes = sizeof(suffixes) / sizeof(const char*); diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index 7fcace5605..b386f0f4cb 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -6957,7 +6957,10 @@ void PlaceInfo::assert_validity() const 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); + // Ziggurats can allow a player to return to the same + // Pandemonium level. + // ASSERT(num_visits <= levels_seen); + ; else if (level_type == LEVEL_DUNGEON && branches[branch].depth > 0) ASSERT(levels_seen <= (unsigned long) branches[branch].depth); diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc index 3e6c484140..409b35f06a 100644 --- a/crawl-ref/source/tags.cc +++ b/crawl-ref/source/tags.cc @@ -96,7 +96,8 @@ extern std::map portal_vault_colours; extern std::map level_annotations; // temp file pairs used for file level cleanup -FixedArray < bool, MAX_LEVELS, NUM_BRANCHES > tmp_file_pairs; + +level_id_set Generated_Levels; // The minor version for the tag currently being read. static int _tag_minor_version = -1; @@ -292,6 +293,16 @@ void marshall_as_long(writer& th, const T& t) marshallLong( th, static_cast(t) ); } +template +void marshallSet(writer &th, const std::set &s, + void (*marshall)(writer &, const data &)) +{ + marshallLong( th, s.size() ); + typename std::set::const_iterator i = s.begin(); + for ( ; i != s.end(); ++i) + marshall(th, *i); +} + template void marshallMap(writer &th, const std::map& data, void (*key_marshall)(writer&, const key&), @@ -354,6 +365,16 @@ void marshall_level_pos( writer& th, const level_pos& lpos ) marshall_level_id(th, lpos.id); } +template +void unmarshallSet(reader &th, set &dset, + data (*data_unmarshall)(reader &)) +{ + dset.clear(); + long len = unmarshallLong(th); + for (long i = 0L; i < len; ++i) + dset.insert(data_unmarshall(th)); +} + template void unmarshallMap(reader& th, map& data, key (*key_unmarshall) (reader&), @@ -1096,25 +1117,20 @@ static void marshallPlaceInfo(writer &th, PlaceInfo place_info) static void tag_construct_you_dungeon(writer &th) { - int i,j; - // how many unique creatures? marshallShort(th, NUM_MONSTERS); - for (j = 0; j < NUM_MONSTERS; ++j) + for (int j = 0; j < NUM_MONSTERS; ++j) marshallByte(th,you.unique_creatures[j]); // unique beasties // how many branches? marshallByte(th, NUM_BRANCHES); - for (j = 0; j < NUM_BRANCHES; ++j) + for (int j = 0; j < NUM_BRANCHES; ++j) { marshallLong(th, branches[j].startdepth); marshallLong(th, branches[j].branch_flags); } - marshallShort(th, MAX_LEVELS); - for (i = 0; i < MAX_LEVELS; ++i) - for (j = 0; j < NUM_BRANCHES; ++j) - marshallBoolean(th, tmp_file_pairs[i][j]); + marshallSet(th, Generated_Levels, marshall_level_id); marshallMap(th, stair_level, marshall_as_long, marshall_level_id); @@ -1542,16 +1558,10 @@ static PlaceInfo unmarshallPlaceInfo(reader &th) static void tag_read_you_dungeon(reader &th) { - int i,j; - int count_c; - short count_s; - - unsigned short count_p; - // how many unique creatures? - count_c = unmarshallShort(th); + int count_c = unmarshallShort(th); you.unique_creatures.init(false); - for (j = 0; j < count_c; ++j) + for (int j = 0; j < count_c; ++j) { const bool created = static_cast(unmarshallByte(th)); @@ -1561,16 +1571,13 @@ static void tag_read_you_dungeon(reader &th) // how many branches? count_c = unmarshallByte(th); - for (j = 0; j < count_c; ++j) + for (int j = 0; j < count_c; ++j) { branches[j].startdepth = unmarshallLong(th); branches[j].branch_flags = (unsigned long) unmarshallLong(th); } - count_s = unmarshallShort(th); - for (i = 0; i < count_s; ++i) - for (j = 0; j < count_c; ++j) - tmp_file_pairs[i][j] = unmarshallBoolean(th); + unmarshallSet(th, Generated_Levels, unmarshall_level_id); unmarshallMap(th, stair_level, unmarshall_long_as, @@ -1593,12 +1600,12 @@ static void tag_read_you_dungeon(reader &th) you.set_place_info(place_info); std::vector list = you.get_all_place_info(); - count_p = (unsigned short) unmarshallShort(th); + unsigned short 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++) + for (int i = 0; i < count_p; i++) { place_info = unmarshallPlaceInfo(th); ASSERT(!place_info.is_global()); diff --git a/crawl-ref/source/travel.h b/crawl-ref/source/travel.h index 65e2bcd08a..419d0e3a32 100644 --- a/crawl-ref/source/travel.h +++ b/crawl-ref/source/travel.h @@ -179,107 +179,6 @@ enum explore_stop_type //////////////////////////////////////////////////////////////////////////// // Structs for interlevel travel. -// Identifies a level. Should never include virtual methods or -// dynamically allocated memory (see code to push level_id onto Lua -// stack in luadgn.cc) -class level_id -{ -public: - branch_type branch; // The branch in which the level is. - int depth; // What depth (in this branch - starting from 1) - level_area_type level_type; - -public: - // Returns the level_id of the current level. - static level_id current(); - - // Returns the level_id of the level that the stair/portal/whatever at - // 'pos' on the current level leads to. - static level_id get_next_level_id(const coord_def &pos); - - level_id() - : branch(BRANCH_MAIN_DUNGEON), depth(-1), - level_type(LEVEL_DUNGEON) - { - } - level_id(branch_type br, int dep, level_area_type ltype = LEVEL_DUNGEON) - : branch(br), depth(dep), level_type(ltype) - { - } - level_id(const level_id &ot) - : branch(ot.branch), depth(ot.depth), level_type(ot.level_type) - { - } - level_id(level_area_type ltype) - : branch(BRANCH_MAIN_DUNGEON), depth(-1), level_type(ltype) - { - } - - static level_id parse_level_id(const std::string &s) throw (std::string); - - unsigned short packed_place() const; - std::string describe(bool long_name = false, bool with_number = true) const; - - void clear() - { - branch = BRANCH_MAIN_DUNGEON; - depth = -1; - level_type = LEVEL_DUNGEON; - } - - int absdepth() const; - - bool is_valid() const - { - return (branch != NUM_BRANCHES && depth != -1) - || level_type != LEVEL_DUNGEON; - } - - const level_id &operator = (const level_id &id) - { - branch = id.branch; - depth = id.depth; - level_type = id.level_type; - return (*this); - } - - bool operator == ( const level_id &id ) const - { - return (level_type == id.level_type - && (level_type != LEVEL_DUNGEON - || (branch == id.branch && depth == id.depth))); - } - - bool operator != ( const level_id &id ) const - { - return !operator == (id); - } - - bool operator <( const level_id &id ) const - { - if (level_type != id.level_type) - return (level_type < id.level_type); - - if (level_type != LEVEL_DUNGEON) - return (false); - - return (branch < id.branch) || (branch==id.branch && depth < id.depth); - } - - bool operator == ( const branch_type _branch ) const - { - return (branch == _branch && level_type == LEVEL_DUNGEON); - } - - bool operator != ( const branch_type _branch ) const - { - return !operator == (_branch); - } - - - void save(writer&) const; - void load(reader&); -}; // A position on a particular level. struct level_pos -- cgit v1.2.3-54-g00ecf