diff options
Diffstat (limited to 'crawl-ref')
m--------- | crawl-ref/source/contrib/lua | 0 | ||||
m--------- | crawl-ref/source/contrib/pcre | 0 | ||||
m--------- | crawl-ref/source/contrib/sqlite | 0 | ||||
-rw-r--r-- | crawl-ref/source/losparam.cc | 9 | ||||
-rw-r--r-- | crawl-ref/source/losparam.h | 27 | ||||
-rw-r--r-- | crawl-ref/source/makefile.obj | 1 | ||||
-rw-r--r-- | crawl-ref/source/mon-los.cc | 406 | ||||
-rw-r--r-- | crawl-ref/source/mon-los.h | 64 | ||||
-rw-r--r-- | crawl-ref/source/monstuff.cc | 34 |
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; |