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.
2EBEWIV4YHXXAFR4GG2GMZJ2K77NK762HNQ77CZLHI3LDVGX7RJAC ACZYEIX7WMPIIODKCATBCUE626AJ4ZGGBOMVC6BGXM27EQU2RECAC PEZFWKRHDHV4UJTPK5XJZ3CGTZ3LPTDYSPTYBENLQ7VRSP7YFSIQC ZNMT5CZHP2FC4HTLNA7KYEDGFBXSCUE5QHJOALVPE6RDPHSEDXRQC SVY2PTCLXR3KNPQAWXVXTTGCC5DR334HOAKHYO3VDDRWM2BWMALAC W52PCSHX72WAMWKG6L4BPUBVMO6E72KYYBNKAA7554KNOTY6V7WQC MQ62OAMLGJVRW2QIL4PAZRAU6PC52ZVGY2FCOBIY6IWGQIHMU5CAC UL7XFKMUX3WIU4O2LZANK4ECJ654UZPDBFGNXUEYZYOLKBYBCG6AC /** File: losparam.h* Summary: Parameters for the LOS algorithm*/#ifndef LOSPARAM_H#define LOSPARAM_Henum opacity_type{OPC_CLEAR,OPC_HALF, // for opaque clouds; two or more blockOPC_OPAQUE,NUM_OPACITIES};// Subclasses of this are passed to losight() to modify the// LOS calculation. Implementations will have to translate between// relative coordinates (-8,-8)..(8,8) and real coordinates,// specify how opaque the cells are and determine what values// are written to the visible cells.struct los_param{virtual ~los_param() {}// Whether the translated coordinate lies in the map (including boundary)virtual bool map_bounds(const coord_def& p) const = 0;// appearance(p) will be copied to show(p) for visible p.virtual unsigned appearance(const coord_def& p) const = 0;virtual opacity_type opacity(const coord_def& p) const = 0;};// Provides translation to given center and bounds checking.struct los_param_trans : los_param{coord_def center;los_param_trans(const coord_def& c);coord_def trans(const coord_def& p) const;bool map_bounds(const coord_def& p) const;};// A complete base implementation that does standard visibility// based on env.grid.struct los_param_base : los_param_trans{los_param_base(const coord_def& c);dungeon_feature_type feature(const coord_def& p) const;unsigned appearance(const coord_def& p) const;unsigned short cloud_idx(const coord_def& p) const;opacity_type opacity(const coord_def& p) const;};// Provides a compatible set of parameters for use with the// legacy losight() function.struct los_param_compat : los_param_base{feature_grid grid;bool solid_blocks;bool ignore_clouds;los_param_compat(const feature_grid& gr, const coord_def& c,bool sb, bool ic);dungeon_feature_type feature(const coord_def& p) const;unsigned appearance(const coord_def& p) const;opacity_type opacity(const coord_def& p) const;};#endif
/** File: losparam.h* Summary: Parameters for the LOS algorithm*/#include "AppHdr.h"REVISION("$Rev$");#include "losparam.h"#include "cloud.h"#include "externs.h"#include "stuff.h"#include "terrain.h"los_param_trans::los_param_trans(const coord_def& c): center(c){}coord_def los_param_trans::trans(const coord_def& p) const{return p + center;}bool los_param_trans::map_bounds(const coord_def& p) const{return ::map_bounds(trans(p));}los_param_base::los_param_base(const coord_def& c): los_param_trans(c){}dungeon_feature_type los_param_base::feature(const coord_def& p) const{return env.grid(trans(p));}unsigned los_param_base::appearance(const coord_def& p) const{return grid_appearance(trans(p));}unsigned short los_param_base::cloud_idx(const coord_def& p) const{return env.cgrid(trans(p));}opacity_type los_param_base::opacity(const coord_def& p) const{dungeon_feature_type f = feature(p);if (grid_is_opaque(f))return OPC_OPAQUE;else if (is_opaque_cloud(cloud_idx(p)))return OPC_HALF;elsereturn OPC_CLEAR;}los_param_compat::los_param_compat(const feature_grid& gr, const coord_def& c,bool sb, bool ic): los_param_base(c), grid(gr), solid_blocks(sb), ignore_clouds(ic){}dungeon_feature_type los_param_compat::feature(const coord_def& p) const{return grid(trans(p));}unsigned los_param_compat::appearance(const coord_def& p) const{return grid_appearance(grid, trans(p));}opacity_type los_param_compat::opacity(const coord_def& p) const{dungeon_feature_type f = feature(p);if (grid_is_opaque(f) || solid_blocks && grid_is_solid(f))return OPC_OPAQUE;else if (!ignore_clouds && is_opaque_cloud(cloud_idx(p)))return OPC_HALF;elsereturn OPC_CLEAR;}
raycast();const int x_p = center.x;const int y_p = center.y;// go quadrant by quadrantconst int quadrant_x[4] = { 1, -1, -1, 1 };const int quadrant_y[4] = { 1, 1, -1, -1 };// clear out shsh.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;}
for (int quadrant = 0; quadrant < 4; ++quadrant){const int xmult = quadrant_x[quadrant];const int ymult = quadrant_y[quadrant];
// clear out the dead rays arraymemset( (void*)dead_rays, 0, sizeof(unsigned long) * num_words);memset( (void*)smoke_rays, 0, sizeof(unsigned long) * num_words);
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)
case OPC_OPAQUE:// then block the appropriate raysfor (unsigned int i = 0; i < num_words; ++i)dead_rays[i] |= inptr[i];break;case OPC_HALF:// block rays which have already seen a cloudfor (unsigned int i = 0; i < num_words; ++i)
else if (!ignore_clouds&& is_opaque_cloud(env.cgrid[realx][realy])){// block rays which have already seen a cloudfor (unsigned int i = 0; i < num_words; ++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 visibleunsigned int rayidx = 0;for (unsigned int wordloc = 0; wordloc < num_words; ++wordloc)
// ray calculation done, now work out which cells in this// quadrant are visibleunsigned 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 incompletefor (unsigned int bitloc = 0; bitloc < LONGSIZE; ++bitloc)
// make the cells seen by this ray at this point visibleif ( ((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 mapif (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 mapif (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);
*dead_rays = NULL;*smoke_rays = NULL;*los_blockrays = NULL;
// ensure precomputations are doneraycast();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]);}// center is always visibleconst coord_def o = coord_def(0,0);sh(o+sh_o) = dat.appearance(o);}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);}