summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crawl-ref/source/los.cc67
-rw-r--r--crawl-ref/source/los.h17
-rw-r--r--crawl-ref/source/losparam.h26
-rw-r--r--crawl-ref/source/monstuff.cc8
-rw-r--r--crawl-ref/source/travel.cc59
-rw-r--r--crawl-ref/source/travel.h30
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.