summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crawl-ref/source/acr.cc16
-rw-r--r--crawl-ref/source/misc.cc6
-rw-r--r--crawl-ref/source/travel.cc190
-rw-r--r--crawl-ref/source/travel.h14
-rw-r--r--crawl-ref/source/view.cc15
5 files changed, 116 insertions, 125 deletions
diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc
index bc615905ce..9654654652 100644
--- a/crawl-ref/source/acr.cc
+++ b/crawl-ref/source/acr.cc
@@ -3245,12 +3245,7 @@ static void _open_door(coord_def move, bool check_confused)
excludes.push_back(dc);
}
- if (!excludes.empty())
- {
- mark_all_excludes_non_updated();
- for (unsigned int i = 0; i < excludes.size(); ++i)
- update_exclusion_los(excludes[i]);
- }
+ update_exclusion_los(excludes);
you.turn_is_over = true;
}
@@ -3407,12 +3402,9 @@ static void _close_door(coord_def move)
if (is_excluded(dc))
excludes.push_back(dc);
}
- if (!excludes.empty())
- {
- mark_all_excludes_non_updated();
- for (unsigned int i = 0; i < excludes.size(); ++i)
- update_exclusion_los(excludes[i]);
- }
+
+ update_exclusion_los(excludes);
+
you.turn_is_over = true;
}
else if (you.confused())
diff --git a/crawl-ref/source/misc.cc b/crawl-ref/source/misc.cc
index e1e726cbc6..ec3806caa1 100644
--- a/crawl-ref/source/misc.cc
+++ b/crawl-ref/source/misc.cc
@@ -2780,7 +2780,7 @@ void set_auto_exclude(const monsters *mon)
{
if (need_auto_exclude(mon) && !is_exclude_root(mon->pos()))
{
- toggle_exclude(mon->pos(), true);
+ set_exclude(mon->pos(), true);
#ifdef USE_TILE
viewwindow(true, false);
#endif
@@ -2792,9 +2792,9 @@ void set_auto_exclude(const monsters *mon)
// player in sight. If sleepy is true, stationary monsters are ignored.
void remove_auto_exclude(const monsters *mon, bool sleepy)
{
- if (need_auto_exclude(mon, sleepy) && is_exclude_root(mon->pos()))
+ if (need_auto_exclude(mon, sleepy))
{
- toggle_exclude(mon->pos());
+ del_exclude(mon->pos());
#ifdef USE_TILE
viewwindow(true, false);
#endif
diff --git a/crawl-ref/source/travel.cc b/crawl-ref/source/travel.cc
index 0775a16c29..ca7f5bd946 100644
--- a/crawl-ref/source/travel.cc
+++ b/crawl-ref/source/travel.cc
@@ -278,7 +278,18 @@ bool is_traversable(dungeon_feature_type grid)
struct los_param_excl : public los_param_trans
{
- los_param_excl(const coord_def& c) : los_param_trans(c) {}
+ int radius_sq;
+
+ los_param_excl(const coord_def& c, int r)
+ : los_param_trans(c), radius_sq(r)
+ {
+ }
+
+ bool los_bounds(const coord_def& p) const
+ {
+ return (p.abs() <= radius_sq &&
+ los_param_trans::los_bounds(p));
+ }
unsigned appearance(const coord_def& p) const
{
@@ -310,44 +321,67 @@ struct los_param_excl : public los_param_trans
}
};
+int travel_exclude::radius_sq() const
+{
+ return (radius > 0 ? radius*radius + 1 : 0);
+}
+
void travel_exclude::set_exclude_show()
{
- losight(show, los_param_excl(pos));
+ losight(show, los_param_excl(pos, radius_sq()));
uptodate = true;
}
+bool travel_exclude::affects(const coord_def& p) const
+{
+ if (!uptodate)
+ mprf(MSGCH_ERROR, "exclusion not up-to-date: e (%d,%d) p (%d,%d)",
+ pos.x, pos.y, p.x, p.y);
+ return (see_grid(show, pos, p));
+}
+
void init_exclusion_los()
{
for (unsigned int i = 0; i < curr_excludes.size(); i++)
curr_excludes[i].set_exclude_show();
}
-void update_exclusion_los(const coord_def &p)
+void _mark_excludes_non_updated(const coord_def &p)
{
for (unsigned int i = 0; i < curr_excludes.size(); i++)
- if (!curr_excludes[i].uptodate
- && (curr_excludes[i].pos - p).abs() <= LOS_RADIUS * LOS_RADIUS + 1)
- {
- curr_excludes[i].set_exclude_show();
- }
+ curr_excludes[i].uptodate = curr_excludes[i].uptodate &&
+ (curr_excludes[i].pos - p).abs() <= curr_excludes[i].radius_sq();
}
-void mark_all_excludes_non_updated()
+void _update_exclusion_los()
{
for (unsigned int i = 0; i < curr_excludes.size(); i++)
- curr_excludes[i].uptodate = false;
+ if (!curr_excludes[i].uptodate)
+ curr_excludes[i].set_exclude_show();
+}
+
+/*
+ * Update exclusions' LOS to reflect changes within their range.
+ * "changed" is a list of coordinates that have been changed.
+ * Only exclusions that might have one of the changed points
+ * in view are updated.
+ */
+void update_exclusion_los(std::vector<coord_def> changed)
+{
+ if (changed.empty())
+ return;
+
+ for (unsigned int i = 0; i < changed.size(); ++i)
+ _mark_excludes_non_updated(changed[i]);
+ _update_exclusion_los();
}
static bool _is_excluded(const coord_def &p,
const std::vector<travel_exclude> &exc)
{
- for (int i = 0, count = exc.size(); i < count; ++i)
- if ((exc[i].pos - p).abs() < exc[i].radius_sq()
- && see_grid(exc[i].show, exc[i].pos, p))
- {
+ for (unsigned int i = 0; i < exc.size(); ++i)
+ if (exc[i].affects(p))
return (true);
- }
-
return (false);
}
@@ -358,10 +392,9 @@ bool is_excluded(const coord_def &p)
static travel_exclude *_find_exclude_root(const coord_def &p)
{
- for (int i = 0, count = curr_excludes.size(); i < count; ++i)
+ for (unsigned int i = 0; i < curr_excludes.size(); ++i)
if (curr_excludes[i].pos == p)
return (&curr_excludes[i]);
-
return (NULL);
}
@@ -372,7 +405,7 @@ bool is_exclude_root(const coord_def &p)
#ifdef USE_TILE
// update Gmap for squares surrounding exclude centre
-static void _tile_exclude_gmap_update(const coord_def p)
+static void _tile_exclude_gmap_update(const coord_def &p)
{
for (int x = -8; x <= 8; x++)
for (int y = -8; y <= 8; y++)
@@ -386,6 +419,24 @@ static void _tile_exclude_gmap_update(const coord_def p)
}
#endif
+static void _exclude_update()
+{
+ if (can_travel_interlevel())
+ {
+ LevelInfo &li = travel_cache.get_level_info(level_id::current());
+ li.update();
+ }
+ set_level_exclusion_annotation(get_exclusion_desc());
+}
+
+static void _exclude_update(const coord_def &p)
+{
+#ifdef USE_TILE
+ _tile_exclude_gmap_update(p);
+#endif
+ _exclude_update();
+}
+
const char *run_mode_name(int runmode)
{
return (runmode == RMODE_TRAVEL ? "travel" :
@@ -420,55 +471,46 @@ void clear_excludes()
#ifdef USE_TILE
for (int i = curr_excludes.size()-1; i >= 0; i--)
- toggle_exclude(curr_excludes[i].pos);
+ _tile_exclude_gmap_update(curr_excludes[i].pos);
#endif
+
curr_excludes.clear();
clear_level_exclusion_annotation();
- if (can_travel_interlevel())
- {
- LevelInfo &li = travel_cache.get_level_info(level_id::current());
- li.update();
- }
+ _exclude_update();
}
+// Cycles the radius of an exclusion, including "off" state.
void cycle_exclude_radius(const coord_def &p)
{
+ // XXX: scanning through curr_excludes twice
if (travel_exclude *exc = _find_exclude_root(p))
{
- int &curr_radius = exc->radius;
-
- switch (curr_radius)
- {
- case LOS_RADIUS: curr_radius = 1; break;
- case 1 : set_exclude(p, 0); break;
- }
-
-#ifdef USE_TILE
- _tile_exclude_gmap_update(p);
-#endif
-
- if (can_travel_interlevel())
+ if (exc->radius == LOS_RADIUS)
+ set_exclude(p, 0);
+ else
{
- LevelInfo &li = travel_cache.get_level_info(level_id::current());
- li.update();
+ ASSERT(exc->radius == 0);
+ del_exclude(p);
}
}
+ else
+ set_exclude(p, LOS_RADIUS);
}
-void toggle_exclude(const coord_def &p, bool autoexcl)
+// Remove a possible exclude.
+void del_exclude(const coord_def &p)
{
- if (is_exclude_root(p))
- set_exclude(p, 0);
- else
- set_exclude(p, LOS_RADIUS, autoexcl);
-
-#ifdef USE_TILE
- _tile_exclude_gmap_update(p);
-#endif
- set_level_exclusion_annotation(get_exclusion_desc());
+ for (unsigned int i = 0; i < curr_excludes.size(); ++i)
+ if (curr_excludes[i].pos == p)
+ {
+ curr_excludes.erase(curr_excludes.begin() + i);
+ break;
+ }
+ _exclude_update(p);
}
+// Set or update an exclude.
void set_exclude(const coord_def &p, int radius, bool autoexcl)
{
// Sanity checks; excludes can be set in Pan and regular dungeon
@@ -479,24 +521,10 @@ void set_exclude(const coord_def &p, int radius, bool autoexcl)
if (!in_bounds(p))
return;
- if (is_exclude_root(p))
+ if (travel_exclude *exc = _find_exclude_root(p))
{
- for (int i = 0, count = curr_excludes.size(); i < count; ++i)
- {
- if (curr_excludes[i].pos == p)
- {
- if (!radius)
- {
- curr_excludes.erase( curr_excludes.begin() + i );
- break ;
- }
- else
- {
- curr_excludes[i].radius = radius;
- return;
- }
- }
- }
+ exc->radius = radius;
+ exc->set_exclude_show();
}
else
{
@@ -508,38 +536,22 @@ void set_exclude(const coord_def &p, int radius, bool autoexcl)
curr_excludes.push_back(travel_exclude(p, radius, autoexcl, montype));
}
- if (can_travel_interlevel())
- {
- LevelInfo &li = travel_cache.get_level_info(level_id::current());
- li.update();
- }
+ _exclude_update(p);
}
// If a grid that was placed automatically no longer contains the original
// monster (or it is invisible), remove the exclusion.
void maybe_remove_autoexclusion(const coord_def &p)
{
- ASSERT(in_bounds(p) && see_grid(p) && is_exclude_root(p));
-
- for (int i = 0, count = curr_excludes.size(); i < count; ++i)
+ if (travel_exclude *exc = _find_exclude_root(p))
{
- if (curr_excludes[i].pos == p)
- {
- if (curr_excludes[i].autoexclude)
- {
- const monsters *m = monster_at(p);
- if (!m || !you.can_see(m) || m->type != curr_excludes[i].mon)
- {
- set_exclude(p, 0);
- set_level_exclusion_annotation(get_exclusion_desc());
- }
- }
- break;
- }
+ const monsters *m = monster_at(p);
+ if (exc->autoexclude && (!m || !you.can_see(m) || m->type != exc->mon))
+ del_exclude(p);
}
}
-// Lists alls exclusions on the current level.
+// Lists all exclusions on the current level.
std::string get_exclusion_desc()
{
std::vector<std::string> monsters;
diff --git a/crawl-ref/source/travel.h b/crawl-ref/source/travel.h
index a035b29f74..7370d49d44 100644
--- a/crawl-ref/source/travel.h
+++ b/crawl-ref/source/travel.h
@@ -58,8 +58,8 @@ void init_travel_terrain_check(bool check_race_equip = true);
void stop_running(void);
void travel_init_new_level();
void cycle_exclude_radius(const coord_def &p);
-void toggle_exclude(const coord_def &p, bool autoexcl = false);
-void set_exclude(const coord_def &p, int radius2, bool autoexcl = false);
+void del_exclude(const coord_def &p);
+void set_exclude(const coord_def &p, int radius = LOS_RADIUS, bool autoexcl = false);
void maybe_remove_autoexclusion(const coord_def &p);
std::string get_exclusion_desc();
void clear_excludes();
@@ -347,8 +347,7 @@ public:
};
void init_exclusion_los();
-void update_exclusion_los(const coord_def &p);
-void mark_all_excludes_non_updated();
+void update_exclusion_los(std::vector<coord_def> changed);
struct travel_exclude
{
@@ -359,7 +358,9 @@ struct travel_exclude
env_show_grid show; // los from exclusion centre
bool uptodate; // Is show up to date?
+ int radius_sq() const;
void set_exclude_show();
+ bool affects(const coord_def& p) const;
travel_exclude(const coord_def &p, int r = LOS_RADIUS,
bool autoexcl = false, int mons = NON_MONSTER)
@@ -367,11 +368,6 @@ struct travel_exclude
{
set_exclude_show();
}
-
- int radius_sq() const
- {
- return (radius * radius + 1);
- }
};
// Information on a level that interlevel travel needs.
diff --git a/crawl-ref/source/view.cc b/crawl-ref/source/view.cc
index 2e8248644d..b3ddaad12c 100644
--- a/crawl-ref/source/view.cc
+++ b/crawl-ref/source/view.cc
@@ -2560,10 +2560,7 @@ void show_map( coord_def &spec_place, bool travel_mode )
case CMD_MAP_EXCLUDE_AREA:
{
const coord_def p(start_x + curs_x - 1, start_y + curs_y - 1);
- if (is_exclude_root(p))
- cycle_exclude_radius(p);
- else
- toggle_exclude(p);
+ cycle_exclude_radius(p);
_reset_travel_colours(features);
break;
@@ -4150,7 +4147,7 @@ void viewwindow(bool draw_it, bool do_updates)
const coord_def sep = ep - coord_def(1,1);
#endif
- if (in_bounds(gc) && see_grid(gc) && is_exclude_root(gc))
+ if (in_bounds(gc) && see_grid(gc))
maybe_remove_autoexclusion(gc);
// Print tutorial messages for features in LOS.
@@ -4367,13 +4364,7 @@ void viewwindow(bool draw_it, bool do_updates)
}
}
- if (!update_excludes.empty())
- {
- mark_all_excludes_non_updated();
-
- for (unsigned int k = 0; k < update_excludes.size(); k++)
- update_exclusion_los(update_excludes[k]);
- }
+ update_exclusion_los(update_excludes);
// Leaving it this way because short flashes can occur in long ones,
// and this simply works without requiring a stack.