Exemplo n.º 1
0
/* return TRUE if successful, FALSE if not */
boolean
rloc(struct monst *mtmp,        /* mx==0 implies migrating monster arrival */
     boolean suppress_impossible)
{
    int x, y, trycount;

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

    if (mtmp->iswiz && mtmp->mx) {      /* Wizard, not just arriving */
        if (!In_W_tower(u.ux, u.uy, &u.uz))
            x = level->upstair.sx, y = level->upstair.sy;
        else if (!level->dnladder.sx)   /* bottom level of tower */
            x = level->upladder.sx, y = level->upladder.sy;
        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;
    }

    trycount = 0;
    do {
        x = rn1(COLNO - 3, 2);
        y = rn2(ROWNO);
        if ((trycount < 500) ? rloc_pos_ok(x, y, mtmp)
            : goodpos(level, x, y, mtmp, 0))
            goto found_xy;
    } while (++trycount < 1000);

    /* last ditch attempt to find a good place */
    for (x = 2; x < COLNO - 1; x++)
        for (y = 0; y < ROWNO; y++)
            if (goodpos(level, x, y, mtmp, 0))
                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;
}
Exemplo n.º 2
0
void
rloco_pos(struct level *lev, struct obj *obj, int *nx, int *ny)
{
    xchar tx, ty, otx;
    boolean restricted_fall;
    int try_limit = 4000;

    otx = obj->ox;
    restricted_fall = (otx == -1 && lev->dndest.lx);
    do {
        tx = rn2(COLNO);
        ty = rn2(ROWNO);
        if (!--try_limit)
            break;
    } while (!goodpos(lev, tx, ty, NULL, 0) ||
             /* bug: this lacks provision for handling the Wizard's tower */
             (restricted_fall &&
              (!within_bounded_area
               (tx, ty, lev->dndest.lx, lev->dndest.ly, lev->dndest.hx,
                lev->dndest.hy) ||
               (level->dndest.nlx &&
                within_bounded_area(tx, ty,
                                    lev->dndest.nlx, lev->dndest.nly,
                                    lev->dndest.nhx, lev->dndest.nhy)))));

    *nx = tx;
    *ny = ty;
}
Exemplo n.º 3
0
void
rloc(struct monst *mtmp)
{
	int tx, ty;
	char ch = mtmp->data->mlet;

#ifndef NOWORM
	if (ch == 'w' && mtmp->mx)	/* do not relocate worms */
		return;
#endif /* NOWORM */
	do {
		tx = rn1(COLNO - 3, 2);
		ty = rn2(ROWNO);
	} while (!goodpos(tx, ty));
	mtmp->mx = tx;
	mtmp->my = ty;
	if (u.ustuck == mtmp) {
		if (u.uswallow) {
			u.ux = tx;
			u.uy = ty;
			docrt();
		} else
			u.ustuck = 0;
	}
	pmon(mtmp);
}
Exemplo n.º 4
0
static boolean teleok(int x, int y, boolean trapok)
{
	if (!trapok && t_at(level, x, y)) return FALSE;
	if (!goodpos(level, x, y, &youmonst, 0)) return FALSE;
	if (!tele_jump_ok(u.ux, u.uy, x, y)) return FALSE;
	if (!in_out_region(level, x, y)) return FALSE;
	return TRUE;
}
Exemplo n.º 5
0
/* check whether monster can arrive at location <x,y> via Tport (or fall) */
static boolean
rloc_pos_ok(int x, int y,       /* coordinates of candidate location */
            struct monst *mtmp)
{
    int xx, yy;

    if (!goodpos(level, x, y, mtmp, 0))
        return FALSE;
    /*
     * Check for restricted areas present in some special levels.
     *
     * `xx' is current column; if 0, then `yy' will contain flag bits
     * rather than row:  bit #0 set => moving upwards; bit #1 set =>
     * inside the Wizard's tower.
     */
    xx = mtmp->mx;
    yy = mtmp->my;
    if (!xx) {
        /* no current location (migrating monster arrival) */
        if (level->dndest.nlx && On_W_tower_level(&u.uz))
            return ((yy & 2) != 0) ^    /* inside xor not within */
                !within_bounded_area(x, y, level->dndest.nlx, level->dndest.nly,
                                     level->dndest.nhx, level->dndest.nhy);
        if (level->updest.lx && (yy & 1) != COLNO)  /* moving up */
            return (within_bounded_area
                    (x, y, level->updest.lx, level->updest.ly,
                     level->updest.hx, level->updest.hy) &&
                    (!level->updest.nlx ||
                     !within_bounded_area(
                       x, y, level->updest.nlx, level->updest.nly,
                       level->updest.nhx, level->updest.nhy)));
        if (level->dndest.lx && (yy & 1) == COLNO)  /* moving down */
            return (within_bounded_area
                    (x, y, level->dndest.lx, level->dndest.ly,
                     level->dndest.hx, level->dndest.hy) &&
                    (!level->dndest.nlx ||
                     !within_bounded_area(
                         x, y, level->dndest.nlx, level->dndest.nly,
                         level->dndest.nhx, level->dndest.nhy)));
    } else { /* [try to] prevent a shopkeeper or temple priest from being
                sent out of his room (caller might resort to goodpos() if
                we report failure here, so this isn't full prevention) */
        if (mtmp->isshk && inhishop(mtmp)) {
            if (level->locations[x][y].roomno != ESHK(mtmp)->shoproom)
                return FALSE;
        } else if (mtmp->ispriest && inhistemple(mtmp)) {
            if (level->locations[x][y].roomno != EPRI(mtmp)->shroom)
                return FALSE;
        }
        /* current location is <xx,yy> */
        if (!tele_jump_ok(xx, yy, x, y))
            return FALSE;
    }
    /* <x,y> is ok */
    return TRUE;
}
Exemplo n.º 6
0
coord
enexto(xchar xx, xchar yy)
{
	xchar x, y;
	coord foo[15], *tfoo;
	int range;

	tfoo = foo;
	range = 1;
	do {	/* full kludge action. */
		for (x = xx - range; x <= xx + range; x++)
			if (goodpos(x, yy - range)) {
				tfoo->x = x;
				tfoo++->y = yy - range;
				if (tfoo == &foo[15])
					goto foofull;
			}
		for (x = xx - range; x <= xx + range; x++)
			if (goodpos(x, yy + range)) {
				tfoo->x = x;
				tfoo++->y = yy + range;
				if (tfoo == &foo[15])
					goto foofull;
			}
		for (y = yy + 1 - range; y < yy + range; y++)
			if (goodpos(xx - range, y)) {
				tfoo->x = xx - range;
				tfoo++->y = y;
				if (tfoo == &foo[15])
					goto foofull;
			}
		for (y = yy + 1 - range; y < yy + range; y++)
			if (goodpos(xx + range, y)) {
				tfoo->x = xx + range;
				tfoo++->y = y;
				if (tfoo == &foo[15])
					goto foofull;
			}
		range++;
	} while (tfoo == foo);
foofull:
	return (foo[rn2(tfoo - foo)]);
}
Exemplo n.º 7
0
struct coord enexto(int xx, int yy)
{
    int8_t x, y;
    struct coord foo[15], *tfoo;
    int range;

    tfoo = foo;
    range = 1;
    do {		       // full kludge action.
	for (x = xx - range; x <= xx + range; ++x)
	    if (goodpos(x, yy - range)) {
		tfoo->x = x;
		tfoo++->y = yy - range;
		if (tfoo == &foo[15])
		    goto foofull;
	    }
	for (x = xx - range; x <= xx + range; ++x)
	    if (goodpos(x, yy + range)) {
		tfoo->x = x;
		tfoo++->y = yy + range;
		if (tfoo == &foo[15])
		    goto foofull;
	    }
	for (y = yy + 1 - range; y < yy + range; ++y)
	    if (goodpos(xx - range, y)) {
		tfoo->x = xx - range;
		tfoo++->y = y;
		if (tfoo == &foo[15])
		    goto foofull;
	    }
	for (y = yy + 1 - range; y < yy + range; ++y)
	    if (goodpos(xx + range, y)) {
		tfoo->x = xx + range;
		tfoo++->y = y;
		if (tfoo == &foo[15])
		    goto foofull;
	    }
	++range;
    } while (tfoo == foo);
  foofull:
    return foo[rn2(tfoo - foo)];
}
Exemplo n.º 8
0
void rloc(struct monst *mtmp)
{
    int tx, ty;
    do {
	tx = rn1(COLNO - 3, 2);
	ty = rn2(ROWNO);
    } while (!goodpos(tx, ty));
    mtmp->mx = tx;
    mtmp->my = ty;
    pmon(mtmp);
}
Exemplo n.º 9
0
static void
mvault_tele(struct monst *mtmp)
{
    struct mkroom *croom = search_special(level, VAULT);
    coord c;

    if (croom && somexy(level, croom, &c) && goodpos(level, c.x, c.y, mtmp, 0)) {
        rloc_to(mtmp, c.x, c.y);
        return;
    }
    rloc(mtmp, FALSE);
}
Exemplo n.º 10
0
/*
 *  place_worm_tail_randomly()
 *
 *  Place a worm tail somewhere on a level behind the head.
 *  This routine essentially reverses the order of the wsegs from head
 *  to tail while placing them.
 *  x, and y are most likely the worm->mx, and worm->my, but don't *need* to
 *  be, if somehow the head is disjoint from the tail.
 */
void
place_worm_tail_randomly(struct monst *worm, xchar x, xchar y, enum rng rng)
{
    int wnum = worm->wormno;
    struct level *lev = worm->dlevel;
    struct wseg *curr = lev->wtails[wnum];
    struct wseg *new_tail;
    xchar ox = x, oy = y;

/*  if (!wnum) return;  bullet proofing */

    if (wnum && (!lev->wtails[wnum] || !lev->wheads[wnum])) {
        impossible("place_worm_tail_randomly: wormno is set without a tail!");
        return;
    }

    lev->wheads[wnum] = new_tail = curr;
    curr = curr->nseg;
    new_tail->nseg = NULL;
    new_tail->wx = x;
    new_tail->wy = y;

    while (curr) {
        xchar nx, ny;
        char tryct = 0;

        /* pick a random direction from x, y and search for goodpos() */

        do {
            random_dir(ox, oy, &nx, &ny, rng);
        } while (!goodpos(lev, nx, ny, worm, 0) && (tryct++ < 50));

        if (tryct < 50) {
            place_worm_seg(worm, nx, ny);
            curr->wx = ox = nx;
            curr->wy = oy = ny;
            lev->wtails[wnum] = curr;
            curr = curr->nseg;
            lev->wtails[wnum]->nseg = new_tail;
            new_tail = lev->wtails[wnum];
            if (lev == level)
                newsym(nx, ny);
        } else {        /* Oops.  Truncate because there was */
            toss_wsegs(lev, curr, FALSE);      /* no place for the rest of it */
            curr = NULL;
        }
    }
}
Exemplo n.º 11
0
/* check whether monster can arrive at location <x,y> via Tport (or fall) */
static boolean
rloc_pos_ok(int x, int y,       /* coordinates of candidate location */
            struct monst *mtmp)
{
    int xx, yy;
    struct level *mdl = mtmp->dlevel;

    if (!goodpos(mdl, x, y, mtmp, 0))
        return FALSE;
    /*
     * Check for restricted areas present in some special levels.
     *
     * `xx' is current column; if 0, then `yy' will contain flag bits
     * rather than row:  bit #0 set => moving upwards; bit #1 set =>
     * inside the Wizard's tower.
     */
    xx = mtmp->mx;
    yy = mtmp->my;
    if (!xx) {
        /* no current location (migrating monster arrival) */
        if (mdl->dndest.nlx && On_W_tower_level(m_mz(mtmp)))
            return ((yy & 2) != 0) ^    /* inside xor not within */
                !within_bounded_area(x, y, mdl->dndest.nlx, mdl->dndest.nly,
                                     mdl->dndest.nhx, mdl->dndest.nhy);
        if (mdl->updest.lx && (yy & 1) != COLNO)  /* moving up */
            return (within_bounded_area
                    (x, y, mdl->updest.lx, mdl->updest.ly,
                     mdl->updest.hx, mdl->updest.hy) &&
                    (!mdl->updest.nlx ||
                     !within_bounded_area(
                       x, y, mdl->updest.nlx, mdl->updest.nly,
                       mdl->updest.nhx, mdl->updest.nhy)));
        if (mdl->dndest.lx && (yy & 1) == COLNO)  /* moving down */
            return (within_bounded_area
                    (x, y, mdl->dndest.lx, mdl->dndest.ly,
                     mdl->dndest.hx, mdl->dndest.hy) &&
                    (!mdl->dndest.nlx ||
                     !within_bounded_area(
                         x, y, mdl->dndest.nlx, mdl->dndest.nly,
                         mdl->dndest.nhx, mdl->dndest.nhy)));
    } else {
        /* current location is <xx,yy> */
        if (!tele_jump_ok(mdl, xx, yy, x, y))
            return FALSE;
    }
    /* <x,y> is ok */
    return TRUE;
}
Exemplo n.º 12
0
static void
rloco(struct obj *obj)
{
	int tx,ty,otx,oty;

	otx = obj->ox;
	oty = obj->oy;
	do {
		tx = rn1(COLNO-3,2);
		ty = rn2(ROWNO);
	} while(!goodpos(tx,ty));
	obj->ox = tx;
	obj->oy = ty;
	if(cansee(otx,oty))
		newsym(otx,oty);
}
Exemplo n.º 13
0
void rloco(struct obj *obj)
{
	xchar tx, ty, otx, oty;
	boolean restricted_fall;
	int try_limit = 4000;

	if (obj->otyp == CORPSE && is_rider(&mons[obj->corpsenm])) {
	    if (revive_corpse(obj)) return;
	}

	obj_extract_self(obj);
	otx = obj->ox;
	oty = obj->oy;
	restricted_fall = (otx == 0 && level->dndest.lx);
	do {
	    tx = rn1(COLNO-3,2);
	    ty = rn2(ROWNO);
	    if (!--try_limit) break;
	} while (!goodpos(level, tx, ty, NULL, 0) ||
		/* bug: this lacks provision for handling the Wizard's tower */
		 (restricted_fall &&
		  (!within_bounded_area(tx, ty, level->dndest.lx, level->dndest.ly,
						level->dndest.hx, level->dndest.hy) ||
		   (level->dndest.nlx &&
		    within_bounded_area(tx, ty, level->dndest.nlx, level->dndest.nly,
						level->dndest.nhx, level->dndest.nhy)))));

	if (flooreffects(obj, tx, ty, "fall")) {
	    return;
	} else if (otx == 0 && oty == 0) {
	    ;	/* fell through a trap door; no update of old loc needed */
	} else {
	    if (costly_spot(otx, oty)
	      && (!costly_spot(tx, ty) ||
		  !strchr(in_rooms(level, tx, ty, 0), *in_rooms(level, otx, oty, 0)))) {
		if (costly_spot(u.ux, u.uy) &&
			    strchr(u.urooms, *in_rooms(level, otx, oty, 0)))
		    addtobill(obj, FALSE, FALSE, FALSE);
		else stolen_value(obj, otx, oty, FALSE, FALSE);
	    }
	    newsym(otx, oty);	/* update old location */
	}
	place_object(obj, level, tx, ty);
	newsym(tx, ty);
}
Exemplo n.º 14
0
void rloc(struct monst *mtmp)
{
    int tx;
    int ty;
    char ch = mtmp->data->mlet;

#ifndef NOWORM
    if((ch == 'w') && (mtmp->mx)) {
        /* Do not relocate worms */
        return;
    }
#endif

    tx = rn1(COLNO - 3, 2);
    ty = rn2(ROWNO);

    while(goodpos(tx, ty) == 0) {
        tx = rn1(COLNO - 3, 2);
        ty = rn2(ROWNO);
    }

    mtmp->mx = tx;
    mtmp->my = ty;

    if(u.ustuck == mtmp) {
        if(u.uswallow != 0) {
            u.ux = tx;
            u.uy = ty;
            docrt();
        }
        else {
            u.ustuck = 0;
        }
    }

    pmon(mtmp);
}
Exemplo n.º 15
0
/* 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->dlevel))
        panic("trying to teleport monster onto which level?");

    struct level *mdl = mtmp->dlevel;

    if (mtmp->iswiz && mtmp->mx != COLNO &&
        mdl == level) {      /* Wizard, not just arriving */
        if (!In_W_tower(u.ux, u.uy, &u.uz))
            x = mdl->upstair.sx, y = mdl->upstair.sy;
        else if (!isok(mdl->dnladder.sx, mdl->dnladder.sy))
            x = mdl->upladder.sx, y = mdl->upladder.sy;/* bottom of tower */
        else
            x = mdl->dnladder.sx, y = mdl->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(mdl, x, y, mtmp, 0))
            goto found_xy;
    }

    for (relaxed_goodpos = 0; relaxed_goodpos < 2; relaxed_goodpos++) {

        /* 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(mdl, x, y, mtmp, gpflags))
                goto found_xy;
        } while (++trycount < 1000);

        /* try every square on the mdl as a fallback */
        for (x = 0; x < COLNO; x++)
            for (y = 0; y < ROWNO; y++)
                if (goodpos(mdl, 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;
}
Exemplo n.º 16
0
boolean
enexto_core(coord * cc, struct level *lev, xchar xx, xchar yy,
            const struct permonst *mdat, unsigned entflags)
{
#define MAX_GOOD 15
    coord good[MAX_GOOD], *good_ptr;
    int x, y, range, i;
    int xmin, xmax, ymin, ymax;
    struct monst fakemon = zeromonst;   /* dummy monster */

    if (!mdat) {
        /* default to player's original monster type */
        mdat = &mons[u.umonster];
    }

    fakemon.data = mdat;        /* set up for goodpos */
    good_ptr = good;
    range = 1;
    /*
     * Walk around the border of the square with center (xx,yy) and
     * radius range.  Stop when we find at least one valid position.
     */
    do {
        xmin = max(0, xx - range);
        xmax = min(COLNO - 1, xx + range);
        ymin = max(0, yy - range);
        ymax = min(ROWNO - 1, yy + range);

        for (x = xmin; x <= xmax; x++)
            if (goodpos(lev, x, ymin, &fakemon, entflags)) {
                good_ptr->x = x;
                good_ptr->y = ymin;
                /* beware of accessing beyond segment boundaries.. */
                if (good_ptr++ == &good[MAX_GOOD - 1])
                    goto full;
            }
        for (x = xmin; x <= xmax; x++)
            if (goodpos(lev, x, ymax, &fakemon, entflags)) {
                good_ptr->x = x;
                good_ptr->y = ymax;
                /* beware of accessing beyond segment boundaries.. */
                if (good_ptr++ == &good[MAX_GOOD - 1])
                    goto full;
            }
        for (y = ymin + 1; y < ymax; y++)
            if (goodpos(lev, xmin, y, &fakemon, entflags)) {
                good_ptr->x = xmin;
                good_ptr->y = y;
                /* beware of accessing beyond segment boundaries.. */
                if (good_ptr++ == &good[MAX_GOOD - 1])
                    goto full;
            }
        for (y = ymin + 1; y < ymax; y++)
            if (goodpos(lev, xmax, y, &fakemon, entflags)) {
                good_ptr->x = xmax;
                good_ptr->y = y;
                /* beware of accessing beyond segment boundaries.. */
                if (good_ptr++ == &good[MAX_GOOD - 1])
                    goto full;
            }
        range++;

        /* return if we've grown too big (nothing is valid) */
        if (range > ROWNO && range > COLNO)
            return FALSE;
    } while (good_ptr == good);

full:
    i = rn2((int)(good_ptr - good));
    cc->x = good[i].x;
    cc->y = good[i].y;
    return TRUE;
}
Exemplo n.º 17
0
/* 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;
}
Exemplo n.º 18
0
/* exclusively for mktemple(); uses level creation RNG */
void
priestini(struct level *lev, struct mkroom *sroom, int sx, int sy,
          boolean sanctum)
{       /* is it the seat of the high priest? */
    struct monst *priest = NULL;
    struct obj *otmp;
    int cnt;

    coord *priest_pos, pos_array[] = {
        { sx + 1, sy },
        { sx - 1, sy },
        { sx, sy + 1 },
        { sx, sy - 1 },
        { sx, sy },
        { COLNO, ROWNO },
    };

    /* Search for a good position for the priest. The -1 in the array bound is
     * to ensure that we stop on the { COLNO, ROWNO } entry which is not ok. Do
     * not pass a monster to goodpos(), because we will move any monster later.
     */
    for (priest_pos = pos_array;
         !goodpos(lev, priest_pos->x, priest_pos->y, NULL, 0) &&
         (priest_pos < pos_array + ARRAY_SIZE(pos_array) - 1);
         ++priest_pos)
         {}
    
    if (!isok(priest_pos->x, priest_pos->y)) {
        impossible("Unable to find location for priest in shrine");
    } else {
        if (MON_AT(lev, priest_pos->x, priest_pos->y))
            rloc(m_at(lev, priest_pos->x, priest_pos->y), FALSE);

        priest = makemon(&mons[sanctum ? PM_HIGH_PRIEST : PM_ALIGNED_PRIEST],
                         lev, priest_pos->x, priest_pos->y, MM_ALLLEVRNG);
    }

    if (priest) {
        EPRI(priest)->shroom = (sroom - lev->rooms) + ROOMOFFSET;
        EPRI(priest)->shralign = Amask2align(lev->locations[sx][sy].altarmask);
        EPRI(priest)->shrpos.x = sx;
        EPRI(priest)->shrpos.y = sy;
        assign_level(&(EPRI(priest)->shrlevel), &lev->z);
        priest->mtrapseen = ~0; /* traps are known */
        priest->mpeaceful = 1;
        priest->ispriest = 1;
        priest->msleeping = 0;
        set_malign(priest);     /* mpeaceful may have changed */

        /* now his/her goodies... */
        if (sanctum && CONST_EPRI(priest)->shralign == A_NONE &&
            on_level(&sanctum_level, &lev->z)) {
            mongets(priest, AMULET_OF_YENDOR, rng_for_level(&lev->z));
        }
        /* 2 to 4 spellbooks */
        for (cnt = rn1(3, 2); cnt > 0; --cnt) {
            mpickobj(priest, mkobj(level, SPBOOK_CLASS, FALSE,
                                   rng_for_level(&lev->z)));
        }
        /* robe [via makemon()] */
        if (mklev_rn2(2, lev) && (otmp = which_armor(priest, os_armc)) != 0) {
            if (p_coaligned(priest))
                uncurse(otmp);
            else
                curse(otmp);
        }
    }
}