From b27a757b68bf8a1dcbcb9b3a5cfea5c1278c9bb4 Mon Sep 17 00:00:00 2001 From: dshaligram Date: Fri, 20 Jul 2007 11:40:25 +0000 Subject: Updated travel to allow it to use rock stairs. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@1898 c06c8d41-db1a-0410-9941-cceddc491573 --- crawl-ref/source/direct.cc | 22 +++++++++- crawl-ref/source/dungeon.cc | 27 +++++++------ crawl-ref/source/misc.cc | 6 +-- crawl-ref/source/travel.cc | 97 +++++++++++++++++++++++++++++++++++++-------- crawl-ref/source/travel.h | 26 +++++++++--- 5 files changed, 139 insertions(+), 39 deletions(-) (limited to 'crawl-ref') diff --git a/crawl-ref/source/direct.cc b/crawl-ref/source/direct.cc index b2c3382803..745f662aea 100644 --- a/crawl-ref/source/direct.cc +++ b/crawl-ref/source/direct.cc @@ -1526,6 +1526,21 @@ static void describe_monster_weapon(monsters *mons) mpr(msg.str().c_str()); } +#ifdef DEBUG_DIAGNOSTICS +static std::string stair_destination_description(const coord_def &pos) +{ + if (LevelInfo *linf = travel_cache.find_level_info(level_id::current())) + { + const stair_info *si = linf->get_stair(pos); + if (si) + return (" " + si->describe()); + else if (is_stair(grd(pos))) + return (" (unknown stair)"); + } + return (""); +} +#endif + static void describe_cell(int mx, int my) { bool mimic_item = false; @@ -1648,10 +1663,13 @@ static void describe_cell(int mx, int my) std::string marker; if (map_marker *mark = env.find_marker(coord_def(mx, my), MAT_ANY)) marker = " (" + mark->describe() + ")"; - mprf("(%d,%d): %s - %s%s", mx, my, + const std::string traveldest = + stair_destination_description(coord_def(mx, my)); + mprf("(%d,%d): %s - %s%s%s", mx, my, stringize_glyph(get_screen_glyph(mx, my)).c_str(), feature_desc.c_str(), - marker.c_str()); + marker.c_str(), + traveldest.c_str()); #else mpr(feature_desc.c_str()); #endif diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index f46559ba58..311ea74805 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -294,12 +294,17 @@ static inline bool dgn_grid_is_passable(dungeon_feature_type grid) && grid != DNGN_SECRET_DOOR)); } +static inline bool dgn_square_is_passable(const coord_def &c) +{ + return (dgn_map_mask(c) && dgn_grid_is_passable(grd(c))); +} + static inline void dgn_point_record_stub(const coord_def &) { } template static void dgn_fill_zone( const coord_def &c, int zone, point_record &prec, - bool (*passable)(dungeon_feature_type) = dgn_grid_is_passable) + bool (*passable)(const coord_def &) = dgn_square_is_passable) { // No bounds checks, assuming the level has at least one layer of // rock border. @@ -312,12 +317,8 @@ static void dgn_fill_zone( continue; const coord_def cp(c.x + xi, c.y + yi); - if (travel_point_distance[cp.x][cp.y] - || dgn_map_mask(cp) - || !passable(grd(cp))) - { + if (travel_point_distance[cp.x][cp.y] || !passable(cp)) continue; - } prec(cp); dgn_fill_zone(cp, zone, prec); @@ -6448,6 +6449,13 @@ struct nearest_point } }; +inline static bool dgn_square_travel_ok(const coord_def &c) +{ + const dungeon_feature_type feat = grd(c); + return (is_traversable(feat) || grid_is_trap(feat) + || feat == DNGN_SECRET_DOOR); +} + // Fill travel_point_distance out from all stone stairs on the level. static coord_def dgn_find_closest_to_stone_stairs() { @@ -6457,17 +6465,12 @@ static coord_def dgn_find_closest_to_stone_stairs() for (int y = 0; y < GYM; ++y) for (int x = 0; x < GXM; ++x) if (!travel_point_distance[x][y] && grid_is_stone_stair(grd[x][y])) - dgn_fill_zone(coord_def(x, y), 1, np, is_traversable); + dgn_fill_zone(coord_def(x, y), 1, np, dgn_square_travel_ok); return (np.nearest); } coord_def dgn_find_nearby_stair(int stair_to_find, bool find_closest) { -#ifdef DEBUG_DIAGNOSTICS - mprf(MSGCH_DIAGNOSTICS, "Placing PC on %s", - dungeon_feature_name( - static_cast(stair_to_find))); -#endif if (stair_to_find == DNGN_ROCK_STAIRS_UP || stair_to_find == DNGN_ROCK_STAIRS_DOWN) { diff --git a/crawl-ref/source/misc.cc b/crawl-ref/source/misc.cc index 0a83963b72..be7d8d1e1f 100644 --- a/crawl-ref/source/misc.cc +++ b/crawl-ref/source/misc.cc @@ -601,9 +601,9 @@ void up_stairs(void) int old_level = you.your_level; // Interlevel travel data: - bool collect_travel_data = you.level_type != LEVEL_LABYRINTH - && you.level_type != LEVEL_ABYSS - && you.level_type != LEVEL_PANDEMONIUM; + const bool collect_travel_data = you.level_type != LEVEL_LABYRINTH + && you.level_type != LEVEL_ABYSS + && you.level_type != LEVEL_PANDEMONIUM; level_id old_level_id = level_id::current(); LevelInfo &old_level_info = travel_cache.get_level_info(old_level_id); diff --git a/crawl-ref/source/travel.cc b/crawl-ref/source/travel.cc index b5c6b48b04..3bdd1219db 100644 --- a/crawl-ref/source/travel.cc +++ b/crawl-ref/source/travel.cc @@ -44,7 +44,7 @@ #endif #define TC_MAJOR_VERSION ((unsigned char) 4) -#define TC_MINOR_VERSION ((unsigned char) 7) +#define TC_MINOR_VERSION ((unsigned char) 9) enum IntertravelDestination { @@ -2393,6 +2393,11 @@ static int find_transtravel_stair( const level_id &cur, for (int i = 0, count = stairs.size(); i < count; ++i) { stair_info &si = stairs[i]; + + // Skip placeholders, since there are no real stairs there. + if (!si.can_travel()) + continue; + int deltadist = li.distance_between(this_stair, &si); if (!this_stair) { @@ -2461,9 +2466,7 @@ static int find_transtravel_stair( const level_id &cur, // We need to get the stairs at the new location and set the // distance on them as well. LevelInfo &lo = travel_cache.get_level_info(dest.id); - stair_info *so = lo.get_stair(dest.pos); - - if (so) + if (stair_info *so = lo.get_stair(dest.pos)) { if (so->distance == -1 || so->distance > dist2stair) so->distance = dist2stair; @@ -2472,7 +2475,8 @@ static int find_transtravel_stair( const level_id &cur, } // Okay, take these stairs and keep going. - int newdist = find_transtravel_stair(dest.id, target, + const int newdist = + find_transtravel_stair(dest.id, target, dist2stair, dest.pos, closest_level, best_level_distance, best_stair, target_has_excludes); @@ -2789,14 +2793,36 @@ void stair_info::save(FILE *file) const writeShort(file, grid); destination.save(file); writeByte(file, guessed_pos? 1 : 0); + writeByte(file, type); } void stair_info::load(FILE *file) { readCoord(file, position); - grid = readShort(file); + grid = static_cast(readShort(file)); destination.load(file); guessed_pos = readByte(file) != 0; + type = static_cast(readByte(file)); +} + +std::string stair_info::describe() const +{ + if (destination.is_valid()) + { + const level_pos &lp(destination); + return + make_stringf( + " (-> %s@(%d,%d)%s%s)", lp.id.describe().c_str(), + lp.pos.x, lp.pos.y, + guessed_pos? " guess" : "", + type == PLACEHOLDER? " placeholder" : ""); + } + else if (destination.id.is_valid()) + { + return make_stringf( + " (->%s (?))", destination.id.describe().c_str()); + } + return (" (?)"); } void LevelInfo::set_level_excludes() @@ -2882,6 +2908,34 @@ void LevelInfo::update_stair(int x, int y, const level_pos &p, bool guess) if (si->destination.id.branch != id.branch) sync_branch_stairs(si); } + else if (!si && guess) + { + create_placeholder_stair(coord_def(x, y), p); + } +} + +void LevelInfo::create_placeholder_stair(const coord_def &stair, + const level_pos &dest) +{ + // If there are any existing placeholders with the same 'dest', zap them. + for (int i = 0, size = stairs.size(); i < size; ++i) + { + if (stairs[i].type == stair_info::PLACEHOLDER + && stairs[i].destination == dest) + { + stairs.erase( stairs.begin() + i ); + break; + } + } + + stair_info placeholder; + placeholder.position = stair; + placeholder.grid = DNGN_FLOOR; + placeholder.destination = dest; + placeholder.type = stair_info::PLACEHOLDER; + stairs.push_back(placeholder); + + resize_stair_distances(); } // If a stair leading out of or into a branch has a known destination, all @@ -2940,7 +2994,7 @@ stair_info *LevelInfo::get_stair(const coord_def &pos) int LevelInfo::get_stair_index(const coord_def &pos) const { - for (int i = stairs.size() - 1; i >= 0; --i) + for (int i = static_cast(stairs.size()) - 1; i >= 0; --i) { if (stairs[i].position == pos) return i; @@ -2955,6 +3009,9 @@ void LevelInfo::correct_stair_list(const std::vector &s) // First we kill any stairs in 'stairs' that aren't there in 's'. for (int i = ((int) stairs.size()) - 1; i >= 0; --i) { + if (stairs[i].type != stair_info::PHYSICAL) + continue; + bool found = false; for (int j = s.size() - 1; j >= 0; --j) { @@ -2973,17 +3030,17 @@ void LevelInfo::correct_stair_list(const std::vector &s) // in 'stairs'. for (int i = 0, sz = s.size(); i < sz; ++i) { - bool found = false; + int found = -1; for (int j = stairs.size() - 1; j >= 0; --j) { if (s[i] == stairs[j].position) { - found = true; + found = j; break; } } - if (!found) + if (found == -1) { stair_info si; si.position = s[i]; @@ -2999,11 +3056,20 @@ void LevelInfo::correct_stair_list(const std::vector &s) // in whenever the player takes these stairs. stairs.push_back(si); } + else + { + stairs[found].type = stair_info::PHYSICAL; + } } + resize_stair_distances(); +} + +void LevelInfo::resize_stair_distances() +{ const int nstairs = stairs.size(); stair_distances.reserve( nstairs * nstairs ); - stair_distances.resize( nstairs * nstairs, 0 ); + stair_distances.resize( nstairs * nstairs, 0 ); } int LevelInfo::distance_between(const stair_info *s1, const stair_info *s2) @@ -3028,11 +3094,10 @@ void LevelInfo::get_stairs(std::vector &st) dungeon_feature_type grid = grd[x][y]; int envc = env.map[x][y].object; - if ((x == you.x_pos && y == you.y_pos) - || (envc - && is_travelable_stair(grid) - && (is_terrain_seen(x, y) - || !is_branch_stair(x, y)))) + if (((x == you.x_pos && y == you.y_pos) + || envc) + && is_travelable_stair(grid) + && (is_terrain_seen(x, y) || !is_branch_stair(x, y))) { // Convert to grid coords, because that's what we use // everywhere else. diff --git a/crawl-ref/source/travel.h b/crawl-ref/source/travel.h index 7f234ca7da..a4e4317220 100644 --- a/crawl-ref/source/travel.h +++ b/crawl-ref/source/travel.h @@ -344,27 +344,37 @@ private: struct stair_info { +public: + enum stair_type + { + PHYSICAL, + PLACEHOLDER + }; + +public: coord_def position; // Position of stair - int grid; // Grid feature of the stair. + dungeon_feature_type grid; // Grid feature of the stair. level_pos destination; // The level and the position on the level this // stair leads to. This may be a guess. int distance; // The distance traveled to reach this stair. bool guessed_pos; // true if we're not sure that 'destination' is // correct. + stair_type type; stair_info() : position(-1, -1), grid(DNGN_FLOOR), destination(), - distance(-1), guessed_pos(true) + distance(-1), guessed_pos(true), type(PHYSICAL) { } - void clear_distance() - { - distance = -1; - } + void clear_distance() { distance = -1; } void save(FILE *) const; void load(FILE *); + + std::string describe() const; + + bool can_travel() const { return (type == PHYSICAL); } }; struct travel_exclude @@ -447,6 +457,10 @@ private: level_id id; friend class TravelCache; + +private: + void create_placeholder_stair(const coord_def &, const level_pos &); + void resize_stair_distances(); }; const int TRAVEL_WAYPOINT_COUNT = 10; -- cgit v1.2.3-54-g00ecf