/* 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; }
int tele_impl(boolean wizard_tele, boolean run_next_to_u) { coord cc; /* Disable teleportation in stronghold && Vlad's Tower */ if (level->flags.noteleport) { if (!wizard_tele) { pline("A mysterious force prevents you from teleporting!"); return 1; } } /* don't show trap if "Sorry..." */ if (!Blinded) make_blinded(0L, FALSE); /* when it happens at all, happens too often to be worth a custom RNG */ if ((Uhave_amulet || On_W_tower_level(&u.uz)) && !rn2(3)) { pline("You feel disoriented for a moment."); return 1; } if ((Teleport_control && !Stunned) || wizard_tele) { if (u_helpless(hm_unconscious)) { pline("Being unconscious, you cannot control your teleport."); } else { pline("To what position do you%s want to be teleported?", u.usteed ? msgcat(" and ", mon_nam(u.usteed)) : ""); cc.x = u.ux; cc.y = u.uy; if (getpos(&cc, FALSE, "the desired position", FALSE) == NHCR_CLIENT_CANCEL) return 0; /* abort */ if (run_next_to_u) { if (!next_to_u()) { pline("You shudder for a moment."); return 1; } } /* possible extensions: introduce a small error if magic power is low; allow transfer to solid rock */ if (u_teleok(cc.x, cc.y, FALSE, wizard_tele)) { teleds(cc.x, cc.y, FALSE); return 1; } pline("Sorry..."); } } safe_teleds(FALSE); return 1; }
/* 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 tele(void) { coord cc; /* Disable teleportation in stronghold && Vlad's Tower */ if (level->flags.noteleport) { if (!wizard) { pline("A mysterious force prevents you from teleporting!"); return; } } /* don't show trap if "Sorry..." */ if (!Blinded) make_blinded(0L, FALSE); if ((u.uhave.amulet || On_W_tower_level(&u.uz)) && !rn2(3)) { pline("You feel disoriented for a moment."); return; } if ((Teleport_control && !Stunned) || wizard) { if (unconscious()) { pline("Being unconscious, you cannot control your teleport."); } else { char buf[BUFSZ]; if (u.usteed) sprintf(buf, " and %s", mon_nam(u.usteed)); pline("To what position do you%s want to be teleported?", u.usteed ? buf : ""); cc.x = u.ux; cc.y = u.uy; if (getpos(&cc, TRUE, "the desired position") < 0) return; /* abort */ /* possible extensions: introduce a small error if magic power is low; allow transfer to solid rock */ if (teleok(cc.x, cc.y, FALSE)) { teleds(cc.x, cc.y, FALSE); return; } pline("Sorry..."); } } safe_teleds(FALSE); }