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; }
/* 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; }
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); }