summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source
diff options
context:
space:
mode:
Diffstat (limited to 'crawl-ref/source')
m---------crawl-ref/source/contrib/lua0
m---------crawl-ref/source/contrib/pcre0
m---------crawl-ref/source/contrib/sqlite0
-rw-r--r--crawl-ref/source/losparam.cc9
-rw-r--r--crawl-ref/source/losparam.h27
-rw-r--r--crawl-ref/source/makefile.obj1
-rw-r--r--crawl-ref/source/mon-los.cc406
-rw-r--r--crawl-ref/source/mon-los.h64
-rw-r--r--crawl-ref/source/monstuff.cc34
9 files changed, 46 insertions, 495 deletions
diff --git a/crawl-ref/source/contrib/lua b/crawl-ref/source/contrib/lua
-Subproject f641f8271c77ff5ad311d0f536accdc571d9b32
+Subproject bdb641df6b1d7c73e2df36b0fc7e5baeeba5712
diff --git a/crawl-ref/source/contrib/pcre b/crawl-ref/source/contrib/pcre
-Subproject 8e797e6e88e85e72bb9a030f3f46cd7aba544ff
+Subproject ea54053156083f38f70c0f0355027e150717b9c
diff --git a/crawl-ref/source/contrib/sqlite b/crawl-ref/source/contrib/sqlite
-Subproject 61cfa181cbe8f25a45d9d01e81032202614f9ad
+Subproject 206ea07a66e23fe3322862e4140a3adc383b052
diff --git a/crawl-ref/source/losparam.cc b/crawl-ref/source/losparam.cc
index 4f1f100244..da30165ed1 100644
--- a/crawl-ref/source/losparam.cc
+++ b/crawl-ref/source/losparam.cc
@@ -56,6 +56,15 @@ opacity_type opacity_solid::operator()(const coord_def& p) const
return OPC_CLEAR;
}
+opacity_type opacity_monmove::operator()(const coord_def& p) const
+{
+ dungeon_feature_type feat = env.grid(p);
+ if (feat < DNGN_MINMOVE || !mon.can_pass_through_feat(feat))
+ return (OPC_OPAQUE);
+ else
+ return (OPC_CLEAR);
+}
+
// LOS bounded by fixed presquared radius.
bool bounds_radius_sq::operator()(const coord_def& p) const
{
diff --git a/crawl-ref/source/losparam.h b/crawl-ref/source/losparam.h
index 8818f3a7d8..7a152a0225 100644
--- a/crawl-ref/source/losparam.h
+++ b/crawl-ref/source/losparam.h
@@ -52,6 +52,19 @@ struct opacity_solid : opacity_func
};
static opacity_solid opc_solid;
+// Opacity for monster movement, based on the late monster_los.
+struct opacity_monmove : opacity_func
+{
+ const monsters& mon;
+
+ opacity_monmove(const monsters& m)
+ : mon(m)
+ {
+ }
+
+ opacity_type operator()(const coord_def& p) const;
+};
+
// LOS bounded by fixed presquared radius.
struct bounds_radius_sq : bounds_func
{
@@ -60,8 +73,18 @@ struct bounds_radius_sq : bounds_func
: radius_sq(r_sq) {}
bool operator()(const coord_def& p) const;
};
-static bounds_radius_sq bds_deflos = bounds_radius_sq(LOS_RADIUS_SQ);
-static bounds_radius_sq bds_maxlos = bounds_radius_sq(LOS_MAX_RADIUS_SQ);
+
+// LOS bounded by fixed radius.
+struct bounds_radius : bounds_radius_sq
+{
+ bounds_radius(int r)
+ : bounds_radius_sq(r * r + 1)
+ {
+ }
+};
+
+static bounds_radius bds_deflos = bounds_radius(LOS_RADIUS);
+static bounds_radius bds_maxlos = bounds_radius(LOS_MAX_RADIUS);
// LOS bounded by current global LOS radius.
struct bounds_cur_los_radius : bounds_func
diff --git a/crawl-ref/source/makefile.obj b/crawl-ref/source/makefile.obj
index 5b214df070..58f9390345 100644
--- a/crawl-ref/source/makefile.obj
+++ b/crawl-ref/source/makefile.obj
@@ -50,7 +50,6 @@ menu.o \
message.o \
mgrow.o \
misc.o \
-mon-los.o \
monplace.o \
mon-pick.o \
monstuff.o \
diff --git a/crawl-ref/source/mon-los.cc b/crawl-ref/source/mon-los.cc
deleted file mode 100644
index c4161352cf..0000000000
--- a/crawl-ref/source/mon-los.cc
+++ /dev/null
@@ -1,406 +0,0 @@
-/*
- * File: mon-los.cc
- * Summary: Monster line-of-sight.
- */
-
-#include "AppHdr.h"
-REVISION("$Rev$");
-#include "mon-los.h"
-
-#include "los.h"
-#include "ray.h"
-#include "stuff.h"
-
-// Static class members must be initialised outside of the class
-// declaration, or gcc won't define them in view.o and we'll get a
-// linking error.
-const int monster_los::LSIZE = _monster_los_LSIZE;
-const int monster_los::L_VISIBLE = 1;
-const int monster_los::L_UNKNOWN = 0;
-const int monster_los::L_BLOCKED = -1;
-
-/////////////////////////////////////////////////////////////////////////////
-// monster_los
-
-monster_los::monster_los()
- : gridx(0), gridy(0), mons(), range(LOS_RADIUS), los_field()
-{
-}
-
-monster_los::~monster_los()
-{
-}
-
-void monster_los::set_monster(monsters *mon)
-{
- mons = mon;
- set_los_centre(mon->pos());
-}
-
-void monster_los::set_los_centre(int x, int y)
-{
- if (!in_bounds(x, y))
- return;
-
- gridx = x;
- gridy = y;
-}
-
-void monster_los::set_los_range(int r)
-{
- ASSERT (r >= 1 && r <= LOS_RADIUS);
- range = r;
-}
-
-coord_def monster_los::pos_to_index(coord_def &p)
-{
- int ix = LOS_RADIUS + p.x - gridx;
- int iy = LOS_RADIUS + p.y - gridy;
-
- ASSERT(ix >= 0 && ix < LSIZE);
- ASSERT(iy >= 0 && iy < LSIZE);
-
- return (coord_def(ix, iy));
-}
-
-coord_def monster_los::index_to_pos(coord_def &i)
-{
- int px = i.x + gridx - LOS_RADIUS;
- int py = i.y + gridy - LOS_RADIUS;
-
- ASSERT(in_bounds(px, py));
- return (coord_def(px, py));
-}
-
-void monster_los::set_los_value(int x, int y, bool blocked, bool override)
-{
- if (!override && !is_unknown(x,y))
- return;
-
- coord_def c(x,y);
- coord_def lpos = pos_to_index(c);
-
- int value = (blocked ? L_BLOCKED : L_VISIBLE);
-
- if (value != los_field[lpos.x][lpos.y])
- los_field[lpos.x][lpos.y] = value;
-}
-
-int monster_los::get_los_value(int x, int y)
-{
- // Too far away -> definitely out of sight!
- if (distance(x, y, gridx, gridy) > get_los_radius_sq())
- return (L_BLOCKED);
-
- coord_def c(x,y);
- coord_def lpos = pos_to_index(c);
- return (los_field[lpos.x][lpos.y]);
-}
-
-bool monster_los::in_sight(int x, int y)
-{
- // Is the path to (x,y) clear?
- return (get_los_value(x,y) == L_VISIBLE);
-}
-
-bool monster_los::is_blocked(int x, int y)
-{
- // Is the path to (x,y) blocked?
- return (get_los_value(x, y) == L_BLOCKED);
-}
-
-bool monster_los::is_unknown(int x, int y)
-{
- return (get_los_value(x, y) == L_UNKNOWN);
-}
-
-static bool _blocks_movement_sight(monsters *mon, dungeon_feature_type feat)
-{
- if (feat < DNGN_MINMOVE)
- return (true);
-
- if (!mon) // No monster defined?
- return (false);
-
- if (!mon->can_pass_through_feat(feat))
- return (true);
-
- return (false);
-}
-
-void monster_los::fill_los_field()
-{
- int pos_x, pos_y;
- for (int k = 1; k <= range; k++)
- for (int i = -1; i <= 1; i++)
- for (int j = -1; j <= 1; j++)
- {
- if (i == 0 && j == 0) // Ignore centre grid.
- continue;
-
- pos_x = gridx + k*i;
- pos_y = gridy + k*j;
-
- if (!in_bounds(pos_x, pos_y))
- continue;
-
- if (!_blocks_movement_sight(mons, grd[pos_x][pos_y]))
- set_los_value(pos_x, pos_y, false);
- else
- {
- set_los_value(pos_x, pos_y, true);
- // Check all beam potentially going through a blocked grid.
- check_los_beam(pos_x, pos_y);
- }
- }
-}
-
-// (cx, cy) is the centre point
-// (dx, dy) is the target we're aiming *through*
-// target1 and target2 are targets we'll be aiming *at* to fire through (dx,dy)
-static bool _set_beam_target(int cx, int cy, int dx, int dy,
- int &target1_x, int &target1_y,
- int &target2_x, int &target2_y,
- int range)
-{
- const int xdist = dx - cx;
- const int ydist = dy - cy;
-
- if (xdist == 0 && ydist == 0)
- return (false); // Nothing to be done.
-
- if (xdist <= -range || xdist >= range
- || ydist <= -range || ydist >= range)
- {
- // Grids on the edge of a monster's LOS don't block sight any further.
- return (false);
- }
-
-/*
- * The following code divides the field into eights of different directions.
- *
- * \ NW | NE /
- * \ | /
- * WN \ | / EN
- * ----------------
- * WS / | \ ES
- * / | \
- * / SW | SE \
- *
- * target1_x and target1_y mark the base line target, so the base beam ends
- * on the diagonal line closest to the target (or on one of the straight
- * lines if cx == dx or dx == dy).
- *
- * target2_x and target2_y then mark the second target our beam finder should
- * cycle through. It'll always be target2_x = dx or target2_y = dy, the other
- * being on the edge of LOS, which one depending on the quadrant.
- *
- * The beam finder can then cycle from the nearest corner (target1) to the
- * second edge target closest to (dx,dy).
- */
-
- if (xdist == 0)
- {
- target1_x = cx;
- target1_y = (ydist > 0 ? cy + range
- : cy - range);
-
- target2_x = target1_x;
- target2_y = target1_y;
- }
- else if (ydist == 0)
- {
- target1_x = (xdist > 0 ? cx + range
- : cx - range);
- target1_y = cy;
-
- target2_x = target1_x;
- target2_y = target1_y;
- }
- else if (xdist < 0 && ydist < 0 || xdist > 0 && ydist > 0)
- {
- if (xdist < 0)
- {
- target1_x = cx - range;
- target1_y = cy - range;
- }
- else
- {
- target1_x = cx + range;
- target1_y = cy + range;
- }
-
- if (xdist == ydist)
- {
- target2_x = target1_x;
- target2_y = target1_y;
- }
- else
- {
- if (xdist < 0) // both are negative (upper left corner)
- {
- if (dx > dy)
- {
- target2_x = dx;
- target2_y = cy - range;
- }
- else
- {
- target2_x = cx - range;
- target2_y = dy;
- }
- }
- else // both are positive (lower right corner)
- {
- if (dx > dy)
- {
- target2_x = cx + range;
- target2_y = dy;
- }
- else
- {
- target2_x = dx;
- target2_y = cy + range;
- }
- }
- }
- }
- else if (xdist < 0 && ydist > 0 || xdist > 0 && ydist < 0)
- {
- if (xdist < 0) // lower left corner
- {
- target1_x = cx - range;
- target1_y = cy + range;
- }
- else // upper right corner
- {
- target1_x = cx + range;
- target1_y = cy - range;
- }
-
- if (xdist == -ydist)
- {
- target2_x = target1_x;
- target2_y = target1_y;
- }
- else
- {
- if (xdist < 0) // ydist > 0
- {
- if (-xdist > ydist)
- {
- target2_x = cx - range;
- target2_y = dy;
- }
- else
- {
- target2_x = dx;
- target2_y = cy + range;
- }
- }
- else // xdist > 0, ydist < 0
- {
- if (-xdist > ydist)
- {
- target2_x = dx;
- target2_y = cy - range;
- }
- else
- {
- target2_x = cx + range;
- target2_y = dy;
- }
- }
- }
- }
- else
- {
- // Everything should have been handled above.
- ASSERT(false);
- }
-
- return (true);
-}
-
-void monster_los::check_los_beam(int dx, int dy)
-{
- ray_def ray;
-
- int target1_x = 0, target1_y = 0, target2_x = 0, target2_y = 0;
- if (!_set_beam_target(gridx, gridy, dx, dy, target1_x, target1_y,
- target2_x, target2_y, range))
- {
- // Nothing to be done.
- return;
- }
-
- if (target1_x > target2_x || target1_y > target2_y)
- {
- // Swap the two targets so our loop will work correctly.
- int help = target1_x;
- target1_x = target2_x;
- target2_x = help;
-
- help = target1_y;
- target1_y = target2_y;
- target2_y = help;
- }
-
- const int max_dist = range;
- int dist;
- bool blocked = false;
- for (int tx = target1_x; tx <= target2_x; tx++)
- for (int ty = target1_y; ty <= target2_y; ty++)
- {
- // If (tx, ty) lies outside the level boundaries, there's nothing
- // that shooting a ray into that direction could bring us, esp.
- // as earlier grids in the ray will already have been handled, and
- // out of bounds grids are simply skipped in any LoS check.
- if (!map_bounds(tx, ty))
- continue;
-
- // Already calculated a beam to (tx, ty), don't do so again.
- if (!is_unknown(tx, ty))
- continue;
-
- dist = 0;
- if (!find_ray(coord_def(gridx, gridy), coord_def(tx, ty), ray))
- fallback_ray(coord_def(gridx, gridy), coord_def(tx, ty), ray);
-
- if (ray.x() == gridx && ray.y() == gridy)
- ray.advance(true);
-
- while (dist++ <= max_dist)
- {
- // The ray brings us out of bounds of the level map.
- // Since we're always shooting outwards there's nothing more
- // to look at in that direction, and we can break the loop.
- if (!map_bounds(ray.x(), ray.y()))
- break;
-
- if (blocked)
- {
- // Earlier grid blocks this beam, set to blocked if
- // unknown, but don't overwrite visible grids.
- set_los_value(ray.x(), ray.y(), true);
- }
- else if (_blocks_movement_sight(mons, grd[ray.x()][ray.y()]))
- {
- set_los_value(ray.x(), ray.y(), true);
- // The rest of the beam will now be blocked.
- blocked = true;
- }
- else
- {
- // Allow overriding in case another beam has marked this
- // field as blocked, because we've found a solution where
- // that isn't the case.
- set_los_value(ray.x(), ray.y(), false, true);
- }
- if (ray.x() == tx && ray.y() == ty)
- break;
-
- ray.advance(true);
- }
- }
-}
diff --git a/crawl-ref/source/mon-los.h b/crawl-ref/source/mon-los.h
deleted file mode 100644
index 1d2921aecc..0000000000
--- a/crawl-ref/source/mon-los.h
+++ /dev/null
@@ -1,64 +0,0 @@
-#ifndef MON_LOS_H
-/*
- * File: mon-los.cc
- * Summary: Monster line-of-sight.
- */
-
-#define MON_LOS_H
-
-#define _monster_los_LSIZE (2 * LOS_RADIUS + 1)
-
-// This class can be used to fill the entire surroundings (los_range)
-// of a monster or other position with seen/unseen values, so as to be able
-// to compare several positions within this range.
-class monster_los
-{
-public:
- monster_los();
- virtual ~monster_los();
-
- // public methods
- void set_monster(monsters *mon);
- void set_los_centre(int x, int y);
- void set_los_centre(const coord_def& p) { this->set_los_centre(p.x, p.y); }
- void set_los_range(int r);
- void fill_los_field(void);
- bool in_sight(int x, int y);
- bool in_sight(const coord_def& p) { return this->in_sight(p.x, p.y); }
-
-protected:
- // protected methods
- coord_def pos_to_index(coord_def &p);
- coord_def index_to_pos(coord_def &i);
-
- void set_los_value(int x, int y, bool blocked, bool override = false);
- int get_los_value(int x, int y);
- bool is_blocked(int x, int y);
- bool is_unknown(int x, int y);
-
- void check_los_beam(int dx, int dy);
-
- // The (fixed) size of the array.
- static const int LSIZE;
-
- static const int L_VISIBLE;
- static const int L_UNKNOWN;
- static const int L_BLOCKED;
-
- // The centre of our los field.
- int gridx, gridy;
-
- // Habitat checks etc. should be done for this monster.
- // Usually the monster whose LOS we're trying to calculate
- // (if mon->x == gridx, mon->y == gridy).
- // Else, any monster trying to move around within this los field.
- monsters *mons;
-
- // Range may never be greater than LOS_RADIUS!
- int range;
-
- // The array to store the LOS values.
- int los_field[_monster_los_LSIZE][_monster_los_LSIZE];
-};
-
-#endif
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc
index dd4ca7822a..4a90029b39 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -44,7 +44,6 @@ REVISION("$Rev$");
#include "misc.h"
#include "monplace.h"
#include "monspeak.h"
-#include "mon-los.h"
#include "mon-util.h"
#include "mutation.h"
#include "mstuff2.h"
@@ -3256,19 +3255,14 @@ 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);
- monster_los patrol;
- // Set monster to make monster_los respect habitat restrictions.
- patrol.set_monster(mon);
- patrol.set_los_centre(mon->patrol_point);
- patrol.set_los_range(rad);
- patrol.fill_los_field();
+ env_show_grid patrol;
+ losight(patrol, mon->patrol_point, opacity_monmove(*mon), bounds_radius(rad));
- monster_los lm;
+ env_show_grid lm;
if (is_smart || !patrol_seen)
{
// For stupid monsters, don't bother if the patrol point is in sight.
- lm.set_monster(mon);
- lm.fill_los_field();
+ losight(lm, mon->pos(), opacity_monmove(*mon));
}
int count_grids = 0;
@@ -3304,8 +3298,11 @@ static bool _choose_random_patrol_target_grid(monsters *mon)
// and the patrol point is out of sight, too. Such a case
// will be handled below, though it might take a while until
// a monster gets out of a deadlock. (5% chance per turn.)
- if (!patrol.in_sight(*ri) && (!is_smart || !lm.in_sight(*ri)))
+ if (!see_cell(patrol, mon->patrol_point, *ri) &&
+ (!is_smart || !see_cell(lm, mon->pos(), *ri)))
+ {
continue;
+ }
}
else
{
@@ -3313,8 +3310,11 @@ static bool _choose_random_patrol_target_grid(monsters *mon)
// make sure the new target brings us into reach of it.
// This means that the target must be reachable BOTH from
// the patrol point AND the current position.
- if (!patrol.in_sight(*ri) || !lm.in_sight(*ri))
+ if (!see_cell(patrol, mon->patrol_point, *ri) ||
+ !see_cell(lm, mon->pos(), *ri))
+ {
continue;
+ }
// If this fails for all surrounding squares (probably because
// we're too far away), we fall back to heading directly for
@@ -3789,11 +3789,6 @@ static bool _find_siren_water_target(monsters *mon)
return (true);
}
- monster_los lm;
- lm.set_monster(mon);
- lm.set_los_range(LOS_RADIUS);
- lm.fill_los_field();
-
int best_water_count = 0;
coord_def best_target;
bool first = true;
@@ -3911,11 +3906,6 @@ static bool _find_wall_target(monsters *mon)
mon->travel_target = MTRAV_NONE;
}
- monster_los lm;
- lm.set_monster(mon);
- lm.set_los_range(LOS_RADIUS);
- lm.fill_los_field();
-
int best_dist = INT_MAX;
bool best_closer_to_player = false;
coord_def best_target;