diff options
author | Robert Vollmert <rvollmert@gmx.net> | 2009-10-25 17:54:10 +0100 |
---|---|---|
committer | Robert Vollmert <rvollmert@gmx.net> | 2009-10-26 16:43:04 +0100 |
commit | 4cead2d3ab94322f080e143e9786b76f953ac85e (patch) | |
tree | 07c287e82e323b8373bccbdf1fdf57664f2eeefb /crawl-ref | |
parent | cc1219315e2533f36b5e1f131fffa77041b919e6 (diff) | |
download | crawl-ref-4cead2d3ab94322f080e143e9786b76f953ac85e.tar.gz crawl-ref-4cead2d3ab94322f080e143e9786b76f953ac85e.zip |
Rewrite los_def to handle function parameters sensibly.
Previously, it was holding on to pointers to objects it
didn't own, causing various bugs.
los_def now copies the opacity_func and bounds_func
parameters. Making them copyable required introducing
opacity_func::clone(). Also implement los_def
copy constructor and copy assignment operator.
Finally, update travel exclusions and monster
patrolling to these changes.
Diffstat (limited to 'crawl-ref')
-rw-r--r-- | crawl-ref/source/los.cc | 67 | ||||
-rw-r--r-- | crawl-ref/source/los.h | 17 | ||||
-rw-r--r-- | crawl-ref/source/losparam.h | 26 | ||||
-rw-r--r-- | crawl-ref/source/monstuff.cc | 8 | ||||
-rw-r--r-- | crawl-ref/source/travel.cc | 59 | ||||
-rw-r--r-- | crawl-ref/source/travel.h | 30 |
6 files changed, 150 insertions, 57 deletions
diff --git a/crawl-ref/source/los.cc b/crawl-ref/source/los.cc index f42f55afbf..e4a1d6429e 100644 --- a/crawl-ref/source/los.cc +++ b/crawl-ref/source/los.cc @@ -643,6 +643,8 @@ struct opacity_trans : opacity_func { } + CLONE(opacity_trans) + opacity_type operator()(const coord_def &l) const { return orig(transform(l)); @@ -921,42 +923,75 @@ void losight(env_show_grid& sh, const coord_def& center, } -// class los -// TODO: lazy update? - -los_def::los_def() {} +// class los_def los_def::los_def(const coord_def& c, const opacity_func &o, - const bounds_func &b) + const bounds_func &b) + : center(c), opc(o.clone()), bds(b.clone()) +{ +} + +los_def::los_def(const los_def& los) + : show(los.show), center(los.center), + opc(los.opc->clone()), bds(los.bds->clone()) +{ +} + +los_def& los_def::operator=(const los_def& los) +{ + init(los.center, *los.opc, *los.bds); + show = los.show; + return (*this); +} + +void los_def::init(const coord_def &c, const opacity_func &o, + const bounds_func &b) { - init(c, o, b); + set_center(c); + set_opacity(o); + set_bounds(b); } -void los_def::init(const coord_def& c, const opacity_func &o, - const bounds_func &b) +los_def::~los_def() { - center = &c; - opc = &o; - bds = &b; - update(); + delete opc; + delete bds; } void los_def::update() { - losight(show, *center, *opc, *bds); + losight(show, center, *opc, *bds); } void los_def::set_center(const coord_def& c) { - center = &c; - update(); + center = c; +} + +void los_def::set_opacity(const opacity_func &o) +{ + delete opc; + opc = o.clone(); +} + +void los_def::set_bounds(const bounds_func &b) +{ + delete bds; + bds = b.clone(); +} + +bool los_def::in_bounds(const coord_def& p) const +{ + return ((*bds)(p)); } bool los_def::see_cell(const coord_def& p) const { - return (::see_cell(show, *center, p)); + return (::see_cell(show, center, p)); } +// end los_def + void losight_permissive(env_show_grid &sh, const coord_def& center) { diff --git a/crawl-ref/source/los.h b/crawl-ref/source/los.h index 943a5674d6..eec4d13909 100644 --- a/crawl-ref/source/los.h +++ b/crawl-ref/source/los.h @@ -44,18 +44,25 @@ void losight(env_show_grid& sh, const los_param& param); class los_def { env_show_grid show; - coord_def const * center; + coord_def center; opacity_func const * opc; - const bounds_func * bds; + bounds_func const * bds; public: los_def(); los_def(const coord_def& c, const opacity_func &o = opc_default, const bounds_func &b = bds_default); - void init(const coord_def& c, const opacity_func &o = opc_default, - const bounds_func &b = bds_default); - void update(); + los_def(const los_def& l); + ~los_def(); + los_def& operator=(const los_def& l); + void init(const coord_def& center, const opacity_func& o, + const bounds_func& b); void set_center(const coord_def& center); + void set_opacity(const opacity_func& o); + void set_bounds(const bounds_func& b); + + void update(); + bool in_bounds(const coord_def& p) const; bool see_cell(const coord_def& p) const; }; diff --git a/crawl-ref/source/losparam.h b/crawl-ref/source/losparam.h index b2d378192b..d6bc6a6b55 100644 --- a/crawl-ref/source/losparam.h +++ b/crawl-ref/source/losparam.h @@ -19,8 +19,9 @@ enum opacity_type struct opacity_func { - virtual ~opacity_func() {} virtual opacity_type operator()(const coord_def& p) const = 0; + virtual ~opacity_func() {} + virtual opacity_func* clone() const = 0; // XXX: to be able to call from gdb. virtual opacity_type call(const coord_def& p) const @@ -33,6 +34,7 @@ struct bounds_func { virtual ~bounds_func() {} virtual bool operator()(const coord_def& p) const = 0; + virtual bounds_func* clone() const = 0; // XXX: to be able to call from gdb. virtual bool call(const coord_def& p) const @@ -41,9 +43,18 @@ struct bounds_func } }; +#define CLONE(typename) \ + typename* clone() const \ + { \ + return (new typename(*this)); \ + } + + // Default LOS rules. struct opacity_default : opacity_func { + CLONE(opacity_default) + opacity_type operator()(const coord_def& p) const; }; static opacity_default opc_default; @@ -52,6 +63,8 @@ static opacity_default opc_default; // In particular, clouds don't affect the result. struct opacity_fullyopaque : opacity_func { + CLONE(opacity_fullyopaque) + opacity_type operator()(const coord_def& p) const; }; static opacity_fullyopaque opc_fullyopaque; @@ -60,6 +73,8 @@ static opacity_fullyopaque opc_fullyopaque; // XXX: Are trees, bushes solid? struct opacity_solid : opacity_func { + CLONE(opacity_solid) + opacity_type operator()(const coord_def& p) const; }; static opacity_solid opc_solid; @@ -74,6 +89,8 @@ struct opacity_monmove : opacity_func { } + CLONE(opacity_monmove) + opacity_type operator()(const coord_def& p) const; }; @@ -83,6 +100,9 @@ struct bounds_radius_sq : bounds_func int radius_sq; bounds_radius_sq(int r_sq) : radius_sq(r_sq) {} + + CLONE(bounds_radius_sq) + bool operator()(const coord_def& p) const; }; @@ -93,6 +113,8 @@ struct bounds_radius : bounds_radius_sq : bounds_radius_sq(r * r + 1) { } + + CLONE(bounds_radius) }; static bounds_radius bds_deflos = bounds_radius(LOS_RADIUS); @@ -101,6 +123,8 @@ static bounds_radius bds_maxlos = bounds_radius(LOS_MAX_RADIUS); // LOS bounded by current global LOS radius. struct bounds_cur_los_radius : bounds_func { + CLONE(bounds_cur_los_radius) + bool operator()(const coord_def& p) const; }; static bounds_cur_los_radius bds_default; diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc index 8ed4f0b259..74bc150b01 100644 --- a/crawl-ref/source/monstuff.cc +++ b/crawl-ref/source/monstuff.cc @@ -3263,13 +3263,13 @@ static bool _choose_random_patrol_target_grid(monsters *mon) const int rad = (intel >= I_ANIMAL || !patrol_seen) ? LOS_RADIUS : 5; const bool is_smart = (intel >= I_NORMAL); - los_def patrol = los_def(mon->patrol_point, opacity_monmove(*mon), - bounds_radius(rad)); - los_def lm; + los_def patrol(mon->patrol_point, opacity_monmove(*mon), bounds_radius(rad)); + patrol.update(); + los_def lm(mon->pos(), opacity_monmove(*mon)); if (is_smart || !patrol_seen) { // For stupid monsters, don't bother if the patrol point is in sight. - lm.init(mon->pos(), opacity_monmove(*mon)); + lm.update(); } int count_grids = 0; diff --git a/crawl-ref/source/travel.cc b/crawl-ref/source/travel.cc index c42131916b..704f9437e0 100644 --- a/crawl-ref/source/travel.cc +++ b/crawl-ref/source/travel.cc @@ -84,7 +84,8 @@ TravelCache travel_cache; static std::vector<stair_info> curr_stairs; // Squares that are not safe to travel to on the current level. -static std::vector<travel_exclude> curr_excludes; +typedef std::vector<travel_exclude> exclvec; +static exclvec curr_excludes; // This is where we last tried to take a stair during interlevel travel. // Note that last_stair.depth should be set to -1 before initiating interlevel @@ -278,6 +279,8 @@ opacity_type _feat_opacity(dungeon_feature_type feat) // opaque. struct opacity_excl : opacity_func { + CLONE(opacity_excl) + opacity_type operator()(const coord_def& p) const { if (!is_terrain_seen(p)) @@ -294,18 +297,31 @@ struct opacity_excl : opacity_func } } }; -opacity_excl opc_excl; +static opacity_excl opc_excl; + +// Note: bounds_radius gives a circle with square radius r*r+1; +// this doesn't work well for radius 0, but then we want to +// skip LOS calculation in that case anyway since it doesn't +// currently short-cut for small bounds. So radius 0 is special-cased. -int travel_exclude::radius_sq() const +travel_exclude::travel_exclude(const coord_def &p, int r, + bool autoex, int mons, bool vault) + : pos(p), radius(r), + los(los_def(p, opc_excl, bounds_radius(r))), + uptodate(false), autoexclude(autoex), vaultexclude(vault) { - return (radius > 0 ? radius*radius + 1 : 0); + set_los(); } -void travel_exclude::set_exclude_show() +void travel_exclude::set_los() { uptodate = true; if (radius > 0) - losight(show, pos, opc_excl, bounds_radius_sq(radius_sq())); + { + // Radius might have been changed, and this is cheap. + los.set_bounds(bounds_radius(radius)); + los.update(); + } } bool travel_exclude::affects(const coord_def& p) const @@ -315,27 +331,38 @@ bool travel_exclude::affects(const coord_def& p) const pos.x, pos.y, p.x, p.y); if (radius == 0) return (p == pos); - return (see_cell(show, pos, p)); + return (los.see_cell(p)); +} + +bool travel_exclude::in_bounds(const coord_def &p) const +{ + return (radius == 0 && p == pos + || los.in_bounds(p)); } void init_exclusion_los() { for (unsigned int i = 0; i < curr_excludes.size(); i++) - curr_excludes[i].set_exclude_show(); + curr_excludes[i].set_los(); } void _mark_excludes_non_updated(const coord_def &p) { - for (unsigned int i = 0; i < curr_excludes.size(); i++) - curr_excludes[i].uptodate = curr_excludes[i].uptodate && - (curr_excludes[i].pos - p).abs() <= curr_excludes[i].radius_sq(); + for (exclvec::iterator it = curr_excludes.begin(); + it != curr_excludes.end(); ++it) + { + it->uptodate = it->uptodate && it->in_bounds(p); + } } void _update_exclusion_los(bool all=false) { - for (unsigned int i = 0; i < curr_excludes.size(); i++) - if (all || !curr_excludes[i].uptodate) - curr_excludes[i].set_exclude_show(); + for (exclvec::iterator it = curr_excludes.begin(); + it != curr_excludes.end(); ++it) + { + if (all || !it->uptodate) + it->set_los(); + } } /* @@ -355,7 +382,7 @@ void update_exclusion_los(std::vector<coord_def> changed) } static bool _is_excluded(const coord_def &p, - const std::vector<travel_exclude> &exc) + const exclvec &exc) { for (unsigned int i = 0; i < exc.size(); ++i) if (exc[i].affects(p)) @@ -502,7 +529,7 @@ void set_exclude(const coord_def &p, int radius, bool autoexcl, bool vaultexcl) if (travel_exclude *exc = _find_exclude_root(p)) { exc->radius = radius; - exc->set_exclude_show(); + exc->set_los(); } else { diff --git a/crawl-ref/source/travel.h b/crawl-ref/source/travel.h index 78b21b23b6..5a4fa07135 100644 --- a/crawl-ref/source/travel.h +++ b/crawl-ref/source/travel.h @@ -7,6 +7,9 @@ #define TRAVEL_H #include "externs.h" + +#include "los.h" + #include <stdio.h> #include <string> #include <vector> @@ -352,25 +355,22 @@ void update_exclusion_los(std::vector<coord_def> changed); struct travel_exclude { - coord_def pos; // exclusion centre - int radius; // exclusion radius - bool autoexclude; // Was set automatically. - int mon; // Monster around which exclusion is centered. - env_show_grid show; // los from exclusion centre - bool uptodate; // Is show up to date? + coord_def pos; // exclusion centre + int radius; // exclusion radius + los_def los; // los from exclusion centre + bool uptodate; // Is los up to date? + bool autoexclude; // Was set automatically. + int mon; // Monster around which exclusion is centered. bool vaultexclude; // Is this exclusion set by a vault? - 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, - bool vaultexcl = false) - : pos(p), radius(r), autoexclude(autoexcl), mon(mons), vaultexclude(vaultexcl) - { - set_exclude_show(); - } + bool vaultexcl = false); + + int radius_sq() const; + void set_los(); + bool in_bounds(const coord_def& p) const; + bool affects(const coord_def& p) const; }; // Information on a level that interlevel travel needs. |