summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/los.cc
diff options
context:
space:
mode:
authorRobert Vollmert <rvollmert@gmx.net>2009-10-08 16:47:06 +0200
committerRobert Vollmert <rvollmert@gmx.net>2009-10-08 18:31:55 +0200
commitefbe1be543f6781d73b056d0acab3143dfde704f (patch)
tree5b9d5186a99f920fa6be0f8c15c43744ea85f3fc /crawl-ref/source/los.cc
parented5f5311c213fb847bc37293e4330aa268a406ed (diff)
downloadcrawl-ref-efbe1be543f6781d73b056d0acab3143dfde704f.tar.gz
crawl-ref-efbe1be543f6781d73b056d0acab3143dfde704f.zip
A rewrite of losight() to allow future generalization.
Parameters relevant to the LOS calculation are now passed as an object los_param that takes care of coordinate translation, bounds checking, opacity of cells and what is written to the output array. A check for in_bounds was changed to map_bounds for simlicity; this should not have any effect. Special casing for arena was removed from losight; instead calc_show_los now calls the new losight_permissive.
Diffstat (limited to 'crawl-ref/source/los.cc')
-rw-r--r--crawl-ref/source/los.cc179
1 files changed, 87 insertions, 92 deletions
diff --git a/crawl-ref/source/los.cc b/crawl-ref/source/los.cc
index 4a63c04b25..400ea200a2 100644
--- a/crawl-ref/source/los.cc
+++ b/crawl-ref/source/los.cc
@@ -15,6 +15,7 @@ REVISION("$Rev$");
#include "debug.h"
#include "directn.h"
#include "externs.h"
+#include "losparam.h"
#include "ray.h"
#include "state.h"
#include "stuff.h"
@@ -35,6 +36,7 @@ REVISION("$Rev$");
const int sh_xo = 9; // X and Y origins for the sh array
const int sh_yo = 9;
+const coord_def sh_o = coord_def(sh_xo, sh_yo);
unsigned long* los_blockrays = NULL;
unsigned long* dead_rays = NULL;
@@ -738,118 +740,111 @@ bool grid_see_grid(const coord_def& p1, const coord_def& p2,
// IMPROVEMENTS:
// Smoke will now only block LOS after two cells of smoke. This is
// done by updating with a second array.
-void losight(env_show_grid &sh,
- feature_grid &gr, const coord_def& center,
- bool clear_walls_block, bool ignore_clouds)
-{
- raycast();
- const int x_p = center.x;
- const int y_p = center.y;
- // go quadrant by quadrant
- const int quadrant_x[4] = { 1, -1, -1, 1 };
- const int quadrant_y[4] = { 1, 1, -1, -1 };
-
- // clear out sh
- sh.init(0);
-
- if (crawl_state.arena || crawl_state.arena_suspended)
- {
- for (int y = -ENV_SHOW_OFFSET; y <= ENV_SHOW_OFFSET; ++y)
- for (int x = -ENV_SHOW_OFFSET; x <= ENV_SHOW_OFFSET; ++x)
- {
- const coord_def pos = center + coord_def(x, y);
- if (map_bounds(pos))
- sh[x + sh_xo][y + sh_yo] = gr(pos);
- }
- return;
- }
+void _losight_quadrant(env_show_grid& sh, const los_param& dat, int sx, int sy)
+{
const unsigned int num_cellrays = compressed_ray_x.size();
const unsigned int num_words = (num_cellrays + LONGSIZE - 1) / LONGSIZE;
- for (int quadrant = 0; quadrant < 4; ++quadrant)
- {
- const int xmult = quadrant_x[quadrant];
- const int ymult = quadrant_y[quadrant];
+ // clear out the dead rays array
+ memset( (void*)dead_rays, 0, sizeof(unsigned long) * num_words);
+ memset( (void*)smoke_rays, 0, sizeof(unsigned long) * num_words);
- // clear out the dead rays array
- memset( (void*)dead_rays, 0, sizeof(unsigned long) * num_words);
- memset( (void*)smoke_rays, 0, sizeof(unsigned long) * num_words);
+ // kill all blocked rays
+ const unsigned long* inptr = los_blockrays;
- // kill all blocked rays
- const unsigned long* inptr = los_blockrays;
+ for (int x = 0; x <= LOS_MAX_RANGE_X; ++x)
+ for (int y = 0; y <= LOS_MAX_RANGE_Y; ++y, inptr += num_words)
+ {
+ coord_def p = coord_def(sx*x, sy*y);
+ if (!dat.map_bounds(p))
+ continue;
- for (int xdiff = 0; xdiff <= LOS_MAX_RANGE_X; ++xdiff)
- for (int ydiff = 0; ydiff <= LOS_MAX_RANGE_Y;
- ++ydiff, inptr += num_words)
+ // if this cell is opaque...
+ switch (dat.opacity(p))
{
-
- const int realx = x_p + xdiff * xmult;
- const int realy = y_p + ydiff * ymult;
-
- if (!map_bounds(realx, realy))
- continue;
-
- coord_def real(realx, realy);
- dungeon_feature_type dfeat = grid_appearance(gr, real);
-
- // if this cell is opaque...
- // ... or something you can see but not walk through ...
- if (grid_is_opaque(dfeat)
- || clear_walls_block && dfeat < DNGN_MINMOVE)
- {
- // then block the appropriate rays
- for (unsigned int i = 0; i < num_words; ++i)
- dead_rays[i] |= inptr[i];
- }
- else if (!ignore_clouds
- && is_opaque_cloud(env.cgrid[realx][realy]))
+ case OPC_OPAQUE:
+ // then block the appropriate rays
+ for (unsigned int i = 0; i < num_words; ++i)
+ dead_rays[i] |= inptr[i];
+ break;
+ case OPC_HALF:
+ // block rays which have already seen a cloud
+ for (unsigned int i = 0; i < num_words; ++i)
{
- // block rays which have already seen a cloud
- for (unsigned int i = 0; i < num_words; ++i)
- {
- dead_rays[i] |= (smoke_rays[i] & inptr[i]);
- smoke_rays[i] |= inptr[i];
- }
+ dead_rays[i] |= (smoke_rays[i] & inptr[i]);
+ smoke_rays[i] |= inptr[i];
}
+ break;
+ default:
+ break;
}
+ }
- // ray calculation done, now work out which cells in this
- // quadrant are visible
- unsigned int rayidx = 0;
- for (unsigned int wordloc = 0; wordloc < num_words; ++wordloc)
+ // ray calculation done, now work out which cells in this
+ // quadrant are visible
+ unsigned int rayidx = 0;
+ for (unsigned int wordloc = 0; wordloc < num_words; ++wordloc)
+ {
+ const unsigned long curword = dead_rays[wordloc];
+ // Note: the last word may be incomplete
+ for (unsigned int bitloc = 0; bitloc < LONGSIZE; ++bitloc)
{
- const unsigned long curword = dead_rays[wordloc];
- // Note: the last word may be incomplete
- for (unsigned int bitloc = 0; bitloc < LONGSIZE; ++bitloc)
+ // make the cells seen by this ray at this point visible
+ if ( ((curword >> bitloc) & 1UL) == 0 )
{
- // make the cells seen by this ray at this point visible
- if ( ((curword >> bitloc) & 1UL) == 0 )
+ // this ray is alive!
+ const coord_def p = coord_def(sx * compressed_ray_x[rayidx],
+ sy * compressed_ray_y[rayidx]);
+ // update shadow map
+ if (dat.map_bounds(p) && p.abs() <= _los_radius_squared)
{
- // this ray is alive!
- const int realx = xmult * compressed_ray_x[rayidx];
- const int realy = ymult * compressed_ray_y[rayidx];
- // update shadow map
- if (x_p + realx >= 0 && x_p + realx < GXM
- && y_p + realy >= 0 && y_p + realy < GYM
- && realx * realx + realy * realy <= _los_radius_squared)
- {
- sh[sh_xo+realx][sh_yo+realy] = gr[x_p+realx][y_p+realy];
- }
+ sh(p+sh_o) = dat.appearance(p);
}
- ++rayidx;
- if (rayidx == num_cellrays)
- break;
}
+ ++rayidx;
+ if (rayidx == num_cellrays)
+ break;
}
}
+}
+
+void losight(env_show_grid& sh, const los_param& dat)
+{
+ sh.init(0);
+
+ // ensure precomputations are done
+ raycast();
+
+ const int quadrant_x[4] = { 1, -1, -1, 1 };
+ const int quadrant_y[4] = { 1, 1, -1, -1 };
+
+ for (int q = 0; q < 4; ++q)
+ {
+ _losight_quadrant(sh, dat, quadrant_x[q], quadrant_y[q]);
+ }
- // [dshaligram] The player's current position is always visible.
- sh[sh_xo][sh_yo] = gr[x_p][y_p];
+ // center is always visible
+ const coord_def o = coord_def(0,0);
+ sh(o+sh_o) = dat.appearance(o);
+}
- *dead_rays = NULL;
- *smoke_rays = NULL;
- *los_blockrays = NULL;
+void losight(env_show_grid &sh, feature_grid &gr,
+ const coord_def& center, bool clear_walls_block,
+ bool ignore_clouds)
+{
+ losight(sh, los_param_compat(gr, center, clear_walls_block, ignore_clouds));
+}
+
+void losight_permissive(env_show_grid &sh, const coord_def& center)
+{
+ for (int x = -ENV_SHOW_OFFSET; x <= ENV_SHOW_OFFSET; ++x)
+ for (int y = -ENV_SHOW_OFFSET; y <= ENV_SHOW_OFFSET; ++y)
+ {
+ const coord_def pos = center + coord_def(x, y);
+ if (map_bounds(pos))
+ sh[x + sh_xo][y + sh_yo] = env.grid(pos);
+ }
}
void calc_show_los()
@@ -865,7 +860,7 @@ void calc_show_los()
}
else
{
- losight(env.show, grd, crawl_view.glosc());
+ losight_permissive(env.show, crawl_view.glosc());
}
}