summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-02-09 09:11:41 +0000
committerdshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-02-09 09:11:41 +0000
commit8c1ca155f86b9828efa8b10d703c2fd523d1e0d9 (patch)
treee04bc9f0fa9b7bde98412f7afbb5de895caa4830
parent19c9624157d17b27641120d0e5aac81d67168c55 (diff)
downloadcrawl-ref-8c1ca155f86b9828efa8b10d703c2fd523d1e0d9.tar.gz
crawl-ref-8c1ca155f86b9828efa8b10d703c2fd523d1e0d9.zip
Interlevel travel now handles branch stairs more intelligently:
Travel knows that all branch exits of the same type share the same destination, and will use the nearest branch exit, even if you've never used it before. The same applies to multiple branch entries, the portals to Zot:1 for instance. This does mean that the first visit to Zot is likely to generate a bad Zot-exit guess (Zot has many entries and many exits), but that'll be fixed the first time the player leaves Zot. .tc version updated. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@945 c06c8d41-db1a-0410-9941-cceddc491573
-rw-r--r--crawl-ref/source/travel.cc53
-rw-r--r--crawl-ref/source/travel.h11
2 files changed, 56 insertions, 8 deletions
diff --git a/crawl-ref/source/travel.cc b/crawl-ref/source/travel.cc
index 1ad2b3be59..2c1e89e070 100644
--- a/crawl-ref/source/travel.cc
+++ b/crawl-ref/source/travel.cc
@@ -31,6 +31,7 @@
#include "view.h"
#include <algorithm>
+#include <set>
#include <cstdarg>
#include <cctype>
#include <cstdio>
@@ -40,7 +41,7 @@
#endif
#define TC_MAJOR_VERSION ((unsigned char) 4)
-#define TC_MINOR_VERSION ((unsigned char) 5)
+#define TC_MINOR_VERSION ((unsigned char) 6)
enum IntertravelDestination
{
@@ -2600,6 +2601,7 @@ void level_pos::load(FILE *file)
void stair_info::save(FILE *file) const
{
writeCoord(file, position);
+ writeShort(file, grid);
destination.save(file);
writeByte(file, guessed_pos? 1 : 0);
}
@@ -2607,6 +2609,7 @@ void stair_info::save(FILE *file) const
void stair_info::load(FILE *file)
{
readCoord(file, position);
+ grid = readShort(file);
destination.load(file);
guessed_pos = readByte(file) != 0;
}
@@ -2658,6 +2661,7 @@ void LevelInfo::update()
// Make sure our stair list is correct.
correct_stair_list(stair_positions);
+ sync_all_branch_stairs();
update_stair_distances();
}
@@ -2711,6 +2715,45 @@ void LevelInfo::update_stair(int x, int y, const level_pos &p, bool guess)
if (!guess && p.id.branch == BRANCH_VESTIBULE_OF_HELL
&& id.branch == BRANCH_MAIN_DUNGEON)
travel_hell_entry = p;
+
+ // All branch stairs land on the same place on the destination level,
+ // update the cache accordingly (but leave guessed_pos = true). This
+ // applies for both branch exits (the usual case) and branch entrances.
+ if (si->destination.id.branch != id.branch)
+ sync_branch_stairs(si);
+ }
+}
+
+// If a stair leading out of or into a branch has a known destination, all
+// stairs of the same type on this level should have the same destination set
+// as guessed_pos == true.
+void LevelInfo::sync_all_branch_stairs()
+{
+ std::set<int> synced;
+
+ for (int i = 0, size = stairs.size(); i < size; ++i)
+ {
+ const stair_info &si = stairs[i];
+ if (si.destination.id.branch != id.branch && si.destination.is_valid()
+ && synced.find(si.grid) == synced.end())
+ {
+ synced.insert( si.grid );
+ sync_branch_stairs( &si );
+ }
+ }
+}
+
+void LevelInfo::sync_branch_stairs(const stair_info *si)
+{
+ for (int i = 0, size = stairs.size(); i < size; ++i)
+ {
+ stair_info &sother = stairs[i];
+ if (si == &sother || !sother.guessed_pos || si->grid != sother.grid
+ || sother.destination.is_valid())
+ {
+ continue;
+ }
+ sother.destination = si->destination;
}
}
@@ -2820,6 +2863,7 @@ void LevelInfo::correct_stair_list(const std::vector<coord_def> &s)
{
stair_info si;
si.position = s[i];
+ si.grid = grd(si.position);
si.destination.id = level_id::get_next_level_id(s[i]);
if (si.destination.id.branch == BRANCH_VESTIBULE_OF_HELL
&& id.branch == BRANCH_MAIN_DUNGEON
@@ -2856,8 +2900,8 @@ void LevelInfo::get_stairs(std::vector<coord_def> &st)
{
for (int x = 0; x < GXM - 1; ++x)
{
- unsigned char grid = grd[x + 1][y + 1];
- unsigned char envc = (unsigned char) env.map[x][y];
+ int grid = grd[x + 1][y + 1];
+ int envc = (unsigned char) env.map[x][y];
if ((x + 1 == you.x_pos && y + 1 == you.y_pos)
|| (envc
@@ -3159,6 +3203,9 @@ void TravelCache::save(FILE *file) const
levels.begin();
for ( ; i != levels.end(); ++i)
{
+ // LevelInfos will also be created for levels in the Abyss and
+ // Pandemonium, but they shouldn't be saved because the
+ // information in them is useless.
if (i->first.level_type != LEVEL_DUNGEON)
continue;
diff --git a/crawl-ref/source/travel.h b/crawl-ref/source/travel.h
index 97491884c1..e0e24d790f 100644
--- a/crawl-ref/source/travel.h
+++ b/crawl-ref/source/travel.h
@@ -260,18 +260,17 @@ private:
struct stair_info
{
coord_def position; // Position of stair
-
+ int 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_info() : destination(), distance(-1), guessed_pos(true)
+ stair_info()
+ : position(-1, -1), grid(DNGN_FLOOR), destination(),
+ distance(-1), guessed_pos(true)
{
- position.x = position.y = -1;
}
void reset_distance()
@@ -341,6 +340,8 @@ private:
void correct_stair_list(const std::vector<coord_def> &s);
void update_stair_distances();
+ void sync_all_branch_stairs();
+ void sync_branch_stairs(const stair_info *si);
void fixup();
private: