예제 #1
0
파일: teleport.c 프로젝트: FredrIQ/nhfourk
/* return TRUE if successful, FALSE if not */
boolean
rloc(struct monst *mtmp,        /* mx==COLNO implies migrating monster arrival */
     boolean suppress_impossible)
{
    int x, y, trycount;
    int relaxed_goodpos;

    if (mtmp == u.usteed) {
        tele();
        return TRUE;
    }

    if (mtmp->iswiz && mtmp->mx != COLNO) {      /* Wizard, not just arriving */
        if (!In_W_tower(u.ux, u.uy, &u.uz))
            x = level->upstair.sx, y = level->upstair.sy;
        else if (!isok(level->dnladder.sx, level->dnladder.sy))
            x = level->upladder.sx, y = level->upladder.sy;/* bottom of tower */
        else
            x = level->dnladder.sx, y = level->dnladder.sy;
        /* if the wiz teleports away to heal, try the up staircase, to block
           the player's escaping before he's healed (deliberately use `goodpos'
           rather than `rloc_pos_ok' here) */
        if (goodpos(level, x, y, mtmp, 0))
            goto found_xy;
    }

    for (relaxed_goodpos = -1; relaxed_goodpos < 2; relaxed_goodpos++) {

        /* If this is a monster that blinks, try to do that first. */
        if (relaxed_goodpos < 0) {
            if ((isok(mtmp->mx, mtmp->my)) &&
                mtmp->data->mflags3 & M3_BLINKAWAY) {
                /* We're going to do a polar-to-rectangular conversion here,
                   because it's a convenient way to select positions at the
                   correct distance from where we're starting.  We'll try
                   with the maximum radius then back it off. */
                int maxradius = 2 * mtmp->data->mlevel;
                int minradius = 2;
                int theta[24] = {   0,  15,  30,  45,  60,  75,
                                    90, 105, 120, 135, 150, 165,
                                    180, 195, 210, 225, 240, 255,
                                    270, 285, 300, 315, 330, 345 };
                int angle, fineangle, swi, sw;
                coord rectcoord;
                if (maxradius < minradius + 3)
                    maxradius = minradius + 3;
                /* Shuffle the order of the angles so we don't always get the same
                   one tried first. */
                for (angle = 0; angle < 24; angle++) {
                    swi          = rn2(24);
                    sw           = theta[swi];
                    theta[swi]   = theta[angle];
                    theta[angle] = sw;
                }
                for (trycount = maxradius; trycount >= minradius; trycount--) {
                    for (angle = 0; angle < 24; angle++)
                        for (fineangle = 0; fineangle < 15; fineangle += 3) {
                            /* theta is shuffled so that the angle isn't the
                               same all the time, but it isn't necessary to
                               shuffle over a hundred different angles; we use
                               fineangle to allow positions that don't line up
                               to the 15-degree increments, but the randomness
                               of the blink direction doesn't need that much
                               precision. */
                            rectcoord = polartorect(trycount, theta[angle] +
                                                    fineangle);
                            x = mtmp->mx + rectcoord.x;
                            y = mtmp->my + rectcoord.y;
                            if (isok(x,y) && !m_at(level,x,y) &&
                                /* TODO: evaluate whether goodpos() should be
                                 * used here */
                                (level->locations[x][y].typ >= CORR) &&
                                /* Blinking only works with line-of-sight, but
                                   for now I am not requiring the monster to
                                   actually _see_ the tile, so e.g. blinking
                                   into the dark works ok. */
                                clear_path(mtmp->mx, mtmp->my, x, y, viz_array)
                                ) {
                                goto found_xy;
                            }
                        }
                }
            }
            continue;
        }

        /* first try sensible terrain; if none exists, ignore water,
           doors and boulders */
        int gpflags = relaxed_goodpos ? MM_IGNOREWATER | MM_IGNOREDOORS : 0;

        /* try several pairs of positions; try the more restrictive rloc_pos_ok
           before we use the less restrictive goodpos */
        trycount = 0;
        do {
            x = rn2(COLNO);
            y = rn2(ROWNO);
            if ((trycount < 500) ? rloc_pos_ok(x, y, mtmp)
                : goodpos(level, x, y, mtmp, gpflags))
                goto found_xy;
        } while (++trycount < 1000);

        /* try every square on the level as a fallback */
        for (x = 0; x < COLNO; x++)
            for (y = 0; y < ROWNO; y++)
                if (goodpos(level, x, y, mtmp, gpflags))
                    goto found_xy;
    }

    /* level either full of monsters or somehow faulty */
    if (!suppress_impossible)
        impossible("rloc(): couldn't relocate monster");
    return FALSE;

found_xy:
    rloc_to(mtmp, x, y);
    return TRUE;
}
예제 #2
0
파일: upweik.c 프로젝트: gwowen/seismicunix
/* functions defined and used internally */
void eiktam (float xs, float zs, 
	int nz, float dz, float fz, int nx, float dx, float fx, float **vel,
	float **time, float **angle, float **sig, float **bet)
/*****************************************************************************
eiktam - Compute traveltimes t(x,z) and  propagation angle a(x,z) via 
         eikonal equation, and ray_theoretic_sigma sig(x,z), incident angle bet(x,z) 
         via Crank-Nicolson Method
******************************************************************************
Input:
xs		x coordinate of source (must be within x samples)
zs		z coordinate of source (must be within z samples)
nz		number of z samples
dz		z sampling interval
fz		first z sample
nx		number of x samples
dx		x sampling interval
fx		first x sample
vel		array[nx][nz] containing velocities

Output:
time		array[nx][nz] containing first-arrival times
angle		array[nx][nz] containing propagation angles
sig  		array[nx][nz] containing ray_theoretic_sigmas
bet		array[nx][nz] containing ray_theoretic_betas
******************************************************************************
Notes:
The actual computation of times and ray_theoretic_sigmas is done in polar coordinates,
with bilinear interpolation used to map to/from rectangular coordinates.
******************************************************************************
Revisor:  Zhenyue Liu, Colorado School of Mines, 7/8/92
******************************************************************************/
{
	int ix,iz,ia,ir,na,nr;
	float ss,a,r,da,dr,fa,fr,ex,ez,ea,rmax,rmaxs,
		**s,**sp,**tp,**up,**wp,**ap;

	/* shift coordinates so source is at (x=0,z=0) */
	fx -= xs;
	fz -= zs;
	ex = fx+(nx-1)*dx;
	ez = fz+(nz-1)*dz;
	
	/* determine polar coordinate sampling */
	rmaxs = fx*fx+fz*fz;
	rmaxs = MAX(rmaxs,fx*fx+ez*ez);
	rmaxs = MAX(rmaxs,ex*ex+ez*ez);
	rmaxs = MAX(rmaxs,ex*ex+fz*fz);
	rmax = sqrt(rmaxs);
	dr = MIN(ABS(dx),ABS(dz));
	nr = 1+NINT(rmax/dr);
	dr = rmax/(nr-1);
	fr = 0.0;
	if (fx==0.0 && fz==0.0) {
		fa = 0.0;  ea = PI/2.0;
	} else if (fx<0.0 && fz==0.0) {
		fa = -PI/2.0;  ea = PI/2.0;
	} else if (fx==0.0 && fz<0.0) {
		fa = 0.0;  ea = PI;
	} else {
		fa = -PI;  ea = PI;
	}
	da = dr/rmax;
	na = 1+NINT((ea-fa)/da);
	da = (ea-fa)/(na-1);
	if (fa==-PI && ea==PI)
		na = na-1;
	
	/* allocate space */
	s = alloc2float(nz,nx);
	sp = alloc2float(na,nr);
	tp = alloc2float(na,nr);
	up = alloc2float(na,nr);
	wp = alloc2float(na,nr);
	ap = alloc2float(na,nr);
	
	/* compute slownesses */
	for (ix=0; ix<nx; ++ix)
		for (iz=0; iz<nz; ++iz)
			s[ix][iz] = 1.0/vel[ix][iz];
	
	/* convert from rectangular to polar coordinates */
	recttopolar(nz,dz,fz,nx,dx,fx,s,na,da,fa,nr,dr,fr,sp);
	
	/* average the slownesses in source region */
	for (ir=0,ss=0.0; ir<2; ++ir)
		for (ia=0; ia<na; ++ia)
			ss += sp[ir][ia];
	ss /= 2*na;

	/* compute traveltimes and derivatives in source region */
	for (ir=0,r=0; ir<2; ++ir,r+=dr) {
		for (ia=0; ia<na; ++ia) {
			up[ir][ia] = ss;
			wp[ir][ia] = 0.0;
			tp[ir][ia] = r*ss;
		}
	}

/* 	tt=cpusec();   */
	/* solve eikonal equation for remaining times and derivatives */
	for (ir=1,r=dr; ir<nr-1; ++ir,r+=dr) {
		eikpex(na,da,r,dr,
			sp[ir],up[ir],wp[ir],tp[ir],
			sp[ir+1],up[ir+1],wp[ir+1],tp[ir+1]);
	}
	
	/* convert times from polar to rectangular coordinates */
	polartorect(na,da,fa,nr,dr,fr,tp,nz,dz,fz,nx,dx,fx,time);

/*  	fprintf(stderr,"\t CPU time for traveltimes= %f \n",cpusec()-tt); 
 	tt=cpusec();   */
	
	/* compute propagation angles in polar and convert */
	for (ia=0,a=fa; ia<na; ++ia,a+=da)
		ap[0][ia] = a;
	for (ir=1,r=fr+dr; ir<nr; ++ir,r+=dr)
		for (ia=0,a=fa; ia<na; ++ia,a+=da){
		    ap[ir][ia] = a+asin(wp[ir][ia]/(sp[ir][ia]*r));
		}
	polartorect(na,da,fa,nr,dr,fr,ap,nz,dz,fz,nx,dx,fx,angle);
/*  	fprintf(stderr,"\t CPU time for propagation angles= %f\n", 	
		cpusec()-tt); 
	tt=cpusec();   */
	
	/* compute ray_theoretic_sigmas  for initial values */
	for (ir=0,r=0; ir<2; ++ir,r+=dr) 
		for (ia=0; ia<na; ++ia) tp[ir][ia] = r/ss;

	/* solve diffrence equation for remaining ray_theoretic_sigmas */
	for (ir=1,r=dr; ir<nr-1; ++ir,r+=dr) 
 		ray_theoretic_sigma(na,da,r,dr,up[ir],wp[ir],tp[ir],
			up[ir+1],wp[ir+1],tp[ir+1]);  
	polartorect(na,da,fa,nr,dr,fr,tp,nz,dz,fz,nx,dx,fx,sig);

/* 	fprintf(stderr,"\t CPU time for sigmas= %f \n",cpusec()-tt); 
	tt=cpusec(); */
	
	/* compute ray_theoretic_betas for initial values */
	for (ir=0; ir<2; ++ir) 
		for (ia=0,a=fa; ia<na; ++ia,a+=da) tp[ir][ia] = a;

	/* solve diffrence equation for remaining ray_theoretic_betas */
	for (ir=1,r=dr; ir<nr-1; ++ir,r+=dr) 
 		ray_theoretic_beta(na,da,r,dr,up[ir],wp[ir],tp[ir],
			up[ir+1],wp[ir+1],tp[ir+1]);  
	polartorect(na,da,fa,nr,dr,fr,tp,nz,dz,fz,nx,dx,fx,bet);
	
/* 	fprintf(stderr,"\t CPU time for incident angles= %f \n",
		cpusec()-tt); */
	
	/* free space */
	free2float(s);
	free2float(sp);
	free2float(tp);
	free2float(up);
	free2float(wp);
	free2float(ap);
}