targeting (see 1725723):
Comments and suggestions welcome.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@1511 c06c8d41-db1a-0410-9941-cceddc491573
GVCGKTH5IJ4VSQEIN4CRC7ZFVZW26JPIYNCPTO7GY66CSZZEW3ZQC VYGSRD6AGPW3JDTKAMFIUEERMWNCV35SPWXH75XCX2SCMMR72RQQC QKGDOYIYKE6B36ION5O2DRW65DWWPZMYNWJVH7LJJ7FPGGM2MYAQC RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC VD4KDTGHVKCN35AWREYB4TEOUMCTW7SAUPAMTMF5ABC7VBHVKP4AC K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC V4WGXVERZ34B7CEINV4D3ZYEKKT2TUIUYTOX5FSOX6B26U3DPVLQC BNTPYSO6ECZ76CHHLDP3ASSPDSEUH4Y3E3LETKNXVWAWJRFL3YEQC 77H4BWWPPGLM3PLZH4QTAJRXIZTSDVNCOKZE223I437FN2UJ34RQC 5ASC3STDYCNLZFEBN6UTMUCGDETHBR2OCBZCF5VIAZ5RRWLOTDYQC SDLKLUNFGVKDS55DDJZCBAVIB7NL3RRYPTACAY65SCUQKV6APFSAC MSQI3TH6T62JAXQGLL52QZCWAMC372TGB6ZNNRDGUGMJKBNNV2VAC RC6L3CIBLJEH4GWRFD7UQNGI6PZT74FRUVOYHSAN2XCC74NZUASQC AOAJ6D3OKSELEYKAT55XCVU5LYJ7SMCZKC6DIEGLLB3TF2LEENWQC FEGNPOJI2SALUA2PVIXIQ2CIXFLSXD7UB7CNUSAAKV4L3POXCRFQC YAAJ6PTN6QUSWE52URI5AENOGD366FIHOIFUOXFUJLVZYE4OG6HQC NQMXQ6OQVUSC7Y7F7IL252QW4A5JED224EECNHWAM4ZZYVNY745AC JQ2PG3ZI7ISKGQ2BZYNIM2PEG4Z2EJHA4ZNKXEBVFBB6KDSHF7NAC }double ray_def::reflect(double p, double c) const{return (c + c - p);}double ray_def::reflect(bool rx, double oldx, double newx) const{if (rx? abs(slope) > 1.0 : abs(slope) < 1.0)return (reflect(oldx, floor(oldx) + 0.5));const int flnew = newx;const int flold = oldx;return (reflect(oldx,flnew > flold? flnew :flold > flnew? flold :(newx + oldx) / 2));}void ray_def::set_reflect_point(const double oldx, const double oldy,double *newx, double *newy,bool blocked_x, bool blocked_y){if (blocked_x == blocked_y){// What to do?*newx = oldx;*newy = oldy;return;}if (blocked_x){ASSERT(int(oldy) != int(*newy));*newy = oldy;*newx = reflect(true, oldx, *newx);}else{ASSERT(int(oldx) != int(*newx));*newx = oldx;*newy = reflect(false, oldy, *newy);}
int ray_def::advance()
int ray_def::advance_through(const coord_def &target){return (advance(true, &target));}int ray_def::advance(bool shortest_possible, const coord_def *target){if (!shortest_possible)return (raw_advance());// If we want to minimize the number of moves on the ray, look one// step ahead and see if we can get a diagonal.const coord_def old(accx, accy);const int ret = raw_advance();if (ret == 2 || (target && pos() == *target))return (ret);const double maccx = accx, maccy = accy;if (raw_advance() != 2){const coord_def second(accx, accy);// If we can convert to a diagonal, do so.if ((second - old).abs() == 2)return (2);}// No diagonal, so roll back.accx = maccx;accy = maccy;return (ret);}int ray_def::raw_advance()
if (grid_is_solid(grd[sourcex+ signx * ray_coord_x[inray + cur_offset]][sourcey+ signy * ray_coord_y[inray + cur_offset]]))
const int xi = signx * ray_coord_x[inray + cur_offset];const int yi = signy * ray_coord_y[inray + cur_offset];if (grid_is_solid(grd[sourcex + xi][sourcey + yi]))
}if (find_shortest){c3 = coord_def(xi, yi);// We've moved at least two steps if inray > 0.if (inray){// Check for a perpendicular corner on the ray and// pretend that it's a diagonal.if ((c3 - c1).abs() != 2)++real_length;else{// c2 was a dud move, pop it offunaliased_ray.pop_back();}}else++real_length;unaliased_ray.push_back(c3);c1 = unaliased_ray[real_length - 1];
if ( !blocked )
int cimbalance = 0;// If this ray is a candidate for shortest, calculate// the imbalance. I'm defining 'imbalance' as the// number of consecutive diagonal or orthogonal moves// in the ray. This is a reasonable measure of deviation from// the Bresenham line between our selected source and// destination.if (!blocked && find_shortest && shortest >= real_length){int diags = 0, straights = 0;for (int i = 1, size = unaliased_ray.size(); i < size;++i){const int dist =(unaliased_ray[i] - unaliased_ray[i - 1]).abs();if (dist == 2){straights = 0;if (++diags > cimbalance)cimbalance = diags;}else{diags = 0;if (++straights > cimbalance)cimbalance = straights;}}}if ( !blocked&& (!find_shortest|| shortest > real_length|| (shortest == real_length&& imbalance > cimbalance)) )
int advance(); // returns the direction taken (0,1,2)
coord_def pos() const { return coord_def(accx, accy); }// returns the direction taken (0,1,2)int advance(bool shorten = false, const coord_def *p = NULL);int advance_through(const coord_def &point);
void regress();
void regress(const coord_def &point);private:int raw_advance();double reflect(bool x, double oldc, double newc) const;double reflect(double x, double c) const;void set_reflect_point(const double oldx, const double oldy,double *newx, double *newy,bool blocked_x, bool blocked_y);