// "dual" edge-drop problems // cylinder: zero diam edge/ellipse, r-radius cylinder, find r-offset == cl (ITO surface XY-slice is a circle) // sphere: zero diam cylinder. ellipse around edge, find offset == cl (ITO surface slice is ellipse) (?) // toroid: radius2 diam edge, radius1 cylinder, find radius1-offset-ellipse=cl (ITO surf slice is offset ellipse) (this is the offset-ellipse problem) // cone: ??? (how is this an ellipse??) bool MillingCutter::singleEdgeDrop(CLPoint& cl, const Point& p1, const Point& p2, double d) const { Point v = p2 - p1; // vector along edge, from p1 -> p2 Point vxy( v.x, v.y, 0.0); vxy.xyNormalize(); // normalized XY edge vector // figure out u-coordinates of p1 and p2 (i.e. x-coord in the rotated system) Point sc = cl.xyClosestPoint( p1, p2 ); assert( ( (cl-sc).xyNorm() - d ) < 1E-6 ); // edge endpoints in the new coordinate system, in these coordinates, CL is at origo Point up1( (p1-sc).dot(vxy) , d, p1.z); // d, distance to line, is the y-coord in the rotated system Point up2( (p2-sc).dot(vxy) , d, p2.z); CC_CLZ_Pair contact = this->singleEdgeDropCanonical( up1, up2 ); // the subclass handles this CCPoint cc_tmp( sc + contact.first * vxy, EDGE); // translate back into original coord-system cc_tmp.z_projectOntoEdge(p1,p2); return cl.liftZ_if_InsidePoints( contact.second , cc_tmp , p1, p2); }
/* For smart monster movement, build a proximity ripple from the player's position, out to a 'distance' of 20. For example: W 5 4 4 W W X Player is at position marked 1 W 5 W 3 3 W W W is a wall. Monsters will attempt W 6 W 2 W 4 W to move to a location with a smaller W 7 W 1 W 5 W value than their current position. W 8 W W W 6 W Note that a monster at location X W 9 9 8 7 7 7 will not move at all. W W W 8 W W W */ static void build_proximity_ripple(void) { int xl, yl, xh, yh ; int k, m, z, tmpx, tmpy; int curx, cury, curdist; xl=tmp3-2; yl=tmp1-2; xh=tmp4+2; yh=tmp2+2; vxy(&xl,&yl); vxy(&xh,&yh); for (k=yl; k<=yh; k++) for (m=xl; m<=xh; m++) { switch(item[m][k]) { case OWALL: case OPIT: case OTRAPARROW: case ODARTRAP: case OCLOSEDDOOR: case OTRAPDOOR: case OTELEPORTER: screen[m][k]=127; break; case OENTRANCE: if (level==1) screen[m][k] = 127; else screen[m][k] = 0; break; default: screen[m][k] = 0; break; }; } screen[playerx][playery]=1; /* now perform proximity ripple from playerx,playery to monster */ xl=tmp3-1; yl=tmp1-1; xh=tmp4+1; yh=tmp2+1; vxy(&xl,&yl); vxy(&xh,&yh); PUTQUEUE( playerx, playery, 1 ); do { GETQUEUE( curx, cury, curdist ); /* test all spots around the current one being looked at. */ if ( ( curx >= xl && curx <= xh ) && ( cury >= yl && cury <= yh ) ) { for (z=1; z<9; z++) { tmpx = curx + diroffx[z] ; tmpy = cury + diroffy[z] ; vxy( &tmpx, &tmpy ); if (screen[tmpx][tmpy] == 0 ) { screen[tmpx][tmpy] = curdist + 1; PUTQUEUE( tmpx, tmpy, curdist + 1 ); } } } } while (!QUEUEEMPTY()); }