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;
}
Exemple #2
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;
}
/*
 * Check for restricted areas present in some special levels.  (This might
 * need to be augmented to allow deliberate passage in wizard mode, but
 * only for explicitly chosen destinations.)
 */
static boolean
tele_jump_ok(struct level *mdl, int x1, int y1, int x2, int y2)
{
    if (mdl->dndest.nlx != COLNO) {
        /* if inside a restricted region, can't teleport outside */
        if (within_bounded_area
            (x1, y1, mdl->dndest.nlx, mdl->dndest.nly, mdl->dndest.nhx,
             mdl->dndest.nhy) &&
            !within_bounded_area(x2, y2, mdl->dndest.nlx, mdl->dndest.nly,
                                 mdl->dndest.nhx, mdl->dndest.nhy))
            return FALSE;
        /* and if outside, can't teleport inside */
        if (!within_bounded_area
            (x1, y1, mdl->dndest.nlx, mdl->dndest.nly, mdl->dndest.nhx,
             mdl->dndest.nhy) &&
            within_bounded_area(x2, y2, mdl->dndest.nlx, mdl->dndest.nly,
                                mdl->dndest.nhx, mdl->dndest.nhy))
            return FALSE;
    }
    if (mdl->updest.nlx != COLNO) {        /* ditto */
        if (within_bounded_area
            (x1, y1, mdl->updest.nlx, mdl->updest.nly, mdl->updest.nhx,
             mdl->updest.nhy) &&
            !within_bounded_area(x2, y2, mdl->updest.nlx, mdl->updest.nly,
                                 mdl->updest.nhx, mdl->updest.nhy))
            return FALSE;
        if (!within_bounded_area
            (x1, y1, mdl->updest.nlx, mdl->updest.nly, mdl->updest.nhx,
             mdl->updest.nhy) &&
            within_bounded_area(x2, y2, mdl->updest.nlx, mdl->updest.nly,
                                mdl->updest.nhx, mdl->updest.nhy))
            return FALSE;
    }
    return TRUE;
}
/* 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;
}
Exemple #5
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);
}