From 85cb24e611061807818fbb6be250f9f770d3433b Mon Sep 17 00:00:00 2001 From: Robert Vollmert Date: Thu, 15 Oct 2009 18:00:27 +0200 Subject: Rewrite part of the exclusion code. * Exclusion radius 0 no longer encodes "no exclusion". * toggle_exclusion split into set_exclusion and del_exclusion: It was never used as a toggle. * Exclusion updates for changed cells unified in void update_exclusion_los(std::vector coord_def changed). Now doesn't leave invalidly non-uptodate exclusions laying around. Still need to find out why off-level exclusions aren't updated after restore. --- crawl-ref/source/acr.cc | 16 +--- crawl-ref/source/misc.cc | 6 +- crawl-ref/source/travel.cc | 190 ++++++++++++++++++++++++--------------------- crawl-ref/source/travel.h | 14 ++-- crawl-ref/source/view.cc | 15 +--- 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 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 &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 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 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. -- cgit v1.2.3-54-g00ecf