miscellaneous formatting
[aNetHack.git] / src / teleport.c
blob8fb3f8c842733d3f31dc61cdd8d1a6424c4bf732
1 /* NetHack 3.6 teleport.c $NHDT-Date: 1455140444 2016/02/10 21:40:44 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.66 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
5 #include "hack.h"
7 STATIC_DCL boolean FDECL(tele_jump_ok, (int, int, int, int));
8 STATIC_DCL boolean FDECL(teleok, (int, int, BOOLEAN_P));
9 STATIC_DCL void NDECL(vault_tele);
10 STATIC_DCL boolean FDECL(rloc_pos_ok, (int, int, struct monst *));
11 STATIC_DCL void FDECL(mvault_tele, (struct monst *));
13 /* non-null when teleporting via having read this scroll */
14 STATIC_VAR struct obj *telescroll = 0;
17 * Is (x,y) a good position of mtmp? If mtmp is NULL, then is (x,y) good
18 * for an object?
20 * This function will only look at mtmp->mdat, so makemon, mplayer, etc can
21 * call it to generate new monster positions with fake monster structures.
23 boolean
24 goodpos(x, y, mtmp, gpflags)
25 int x, y;
26 struct monst *mtmp;
27 unsigned gpflags;
29 struct permonst *mdat = (struct permonst *) 0;
30 boolean ignorewater = ((gpflags & MM_IGNOREWATER) != 0);
32 if (!isok(x, y))
33 return FALSE;
35 /* in many cases, we're trying to create a new monster, which
36 * can't go on top of the player or any existing monster.
37 * however, occasionally we are relocating engravings or objects,
38 * which could be co-located and thus get restricted a bit too much.
39 * oh well.
41 if (mtmp != &youmonst && x == u.ux && y == u.uy
42 && (!u.usteed || mtmp != u.usteed))
43 return FALSE;
45 if (mtmp) {
46 struct monst *mtmp2 = m_at(x, y);
48 /* Be careful with long worms. A monster may be placed back in
49 * its own location. Normally, if m_at() returns the same monster
50 * that we're trying to place, the monster is being placed in its
51 * own location. However, that is not correct for worm segments,
52 * because all the segments of the worm return the same m_at().
53 * Actually we overdo the check a little bit--a worm can't be placed
54 * in its own location, period. If we just checked for mtmp->mx
55 * != x || mtmp->my != y, we'd miss the case where we're called
56 * to place the worm segment and the worm's head is at x,y.
58 if (mtmp2 && (mtmp2 != mtmp || mtmp->wormno))
59 return FALSE;
61 mdat = mtmp->data;
62 if (is_pool(x, y) && !ignorewater) {
63 if (mtmp == &youmonst)
64 return (Levitation || Flying || Wwalking || Swimming
65 || Amphibious);
66 else
67 return (is_floater(mdat) || is_flyer(mdat) || is_swimmer(mdat)
68 || is_clinger(mdat));
69 } else if (mdat->mlet == S_EEL && rn2(13) && !ignorewater) {
70 return FALSE;
71 } else if (is_lava(x, y)) {
72 if (mtmp == &youmonst)
73 return (Levitation || Flying
74 || (Fire_resistance && Wwalking && uarmf
75 && uarmf->oerodeproof)
76 || (Upolyd && likes_lava(youmonst.data)));
77 else
78 return (is_floater(mdat) || is_flyer(mdat)
79 || likes_lava(mdat));
81 if (passes_walls(mdat) && may_passwall(x, y))
82 return TRUE;
83 if (amorphous(mdat) && closed_door(x, y))
84 return TRUE;
86 if (!accessible(x, y)) {
87 if (!(is_pool(x, y) && ignorewater))
88 return FALSE;
91 if (sobj_at(BOULDER, x, y) && (!mdat || !throws_rocks(mdat)))
92 return FALSE;
93 return TRUE;
97 * "entity next to"
99 * Attempt to find a good place for the given monster type in the closest
100 * position to (xx,yy). Do so in successive square rings around (xx,yy).
101 * If there is more than one valid position in the ring, choose one randomly.
102 * Return TRUE and the position chosen when successful, FALSE otherwise.
104 boolean
105 enexto(cc, xx, yy, mdat)
106 coord *cc;
107 register xchar xx, yy;
108 struct permonst *mdat;
110 return enexto_core(cc, xx, yy, mdat, 0);
113 boolean
114 enexto_core(cc, xx, yy, mdat, entflags)
115 coord *cc;
116 register xchar xx, yy;
117 struct permonst *mdat;
118 unsigned entflags;
120 #define MAX_GOOD 15
121 coord good[MAX_GOOD], *good_ptr;
122 int x, y, range, i;
123 int xmin, xmax, ymin, ymax;
124 struct monst fakemon; /* dummy monster */
126 if (!mdat) {
127 debugpline0("enexto() called with null mdat");
128 /* default to player's original monster type */
129 mdat = &mons[u.umonster];
131 fakemon = zeromonst;
132 set_mon_data(&fakemon, mdat, -1); /* set up for goodpos */
134 good_ptr = good;
135 range = 1;
137 * Walk around the border of the square with center (xx,yy) and
138 * radius range. Stop when we find at least one valid position.
140 do {
141 xmin = max(1, xx - range);
142 xmax = min(COLNO - 1, xx + range);
143 ymin = max(0, yy - range);
144 ymax = min(ROWNO - 1, yy + range);
146 for (x = xmin; x <= xmax; x++)
147 if (goodpos(x, ymin, &fakemon, entflags)) {
148 good_ptr->x = x;
149 good_ptr->y = ymin;
150 /* beware of accessing beyond segment boundaries.. */
151 if (good_ptr++ == &good[MAX_GOOD - 1])
152 goto full;
154 for (x = xmin; x <= xmax; x++)
155 if (goodpos(x, ymax, &fakemon, entflags)) {
156 good_ptr->x = x;
157 good_ptr->y = ymax;
158 /* beware of accessing beyond segment boundaries.. */
159 if (good_ptr++ == &good[MAX_GOOD - 1])
160 goto full;
162 for (y = ymin + 1; y < ymax; y++)
163 if (goodpos(xmin, y, &fakemon, entflags)) {
164 good_ptr->x = xmin;
165 good_ptr->y = y;
166 /* beware of accessing beyond segment boundaries.. */
167 if (good_ptr++ == &good[MAX_GOOD - 1])
168 goto full;
170 for (y = ymin + 1; y < ymax; y++)
171 if (goodpos(xmax, y, &fakemon, entflags)) {
172 good_ptr->x = xmax;
173 good_ptr->y = y;
174 /* beware of accessing beyond segment boundaries.. */
175 if (good_ptr++ == &good[MAX_GOOD - 1])
176 goto full;
178 range++;
180 /* return if we've grown too big (nothing is valid) */
181 if (range > ROWNO && range > COLNO)
182 return FALSE;
183 } while (good_ptr == good);
185 full:
186 i = rn2((int) (good_ptr - good));
187 cc->x = good[i].x;
188 cc->y = good[i].y;
189 return TRUE;
193 * Check for restricted areas present in some special levels. (This might
194 * need to be augmented to allow deliberate passage in wizard mode, but
195 * only for explicitly chosen destinations.)
197 STATIC_OVL boolean
198 tele_jump_ok(x1, y1, x2, y2)
199 int x1, y1, x2, y2;
201 if (dndest.nlx > 0) {
202 /* if inside a restricted region, can't teleport outside */
203 if (within_bounded_area(x1, y1, dndest.nlx, dndest.nly, dndest.nhx,
204 dndest.nhy)
205 && !within_bounded_area(x2, y2, dndest.nlx, dndest.nly,
206 dndest.nhx, dndest.nhy))
207 return FALSE;
208 /* and if outside, can't teleport inside */
209 if (!within_bounded_area(x1, y1, dndest.nlx, dndest.nly, dndest.nhx,
210 dndest.nhy)
211 && within_bounded_area(x2, y2, dndest.nlx, dndest.nly, dndest.nhx,
212 dndest.nhy))
213 return FALSE;
215 if (updest.nlx > 0) { /* ditto */
216 if (within_bounded_area(x1, y1, updest.nlx, updest.nly, updest.nhx,
217 updest.nhy)
218 && !within_bounded_area(x2, y2, updest.nlx, updest.nly,
219 updest.nhx, updest.nhy))
220 return FALSE;
221 if (!within_bounded_area(x1, y1, updest.nlx, updest.nly, updest.nhx,
222 updest.nhy)
223 && within_bounded_area(x2, y2, updest.nlx, updest.nly, updest.nhx,
224 updest.nhy))
225 return FALSE;
227 return TRUE;
230 STATIC_OVL boolean
231 teleok(x, y, trapok)
232 register int x, y;
233 boolean trapok;
235 if (!trapok && t_at(x, y))
236 return FALSE;
237 if (!goodpos(x, y, &youmonst, 0))
238 return FALSE;
239 if (!tele_jump_ok(u.ux, u.uy, x, y))
240 return FALSE;
241 if (!in_out_region(x, y))
242 return FALSE;
243 return TRUE;
246 void
247 teleds(nux, nuy, allow_drag)
248 register int nux, nuy;
249 boolean allow_drag;
251 boolean ball_active, ball_still_in_range;
253 if (u.utraptype == TT_BURIEDBALL) {
254 /* unearth it */
255 buried_ball_to_punishment();
257 ball_active = (Punished && uball->where != OBJ_FREE);
258 ball_still_in_range = FALSE;
260 /* If they have to move the ball, then drag if allow_drag is true;
261 * otherwise they are teleporting, so unplacebc().
262 * If they don't have to move the ball, then always "drag" whether or
263 * not allow_drag is true, because we are calling that function, not
264 * to drag, but to move the chain. *However* there are some dumb
265 * special cases:
266 * 0 0
267 * _X move east -----> X_
268 * @ @
269 * These are permissible if teleporting, but not if dragging. As a
270 * result, drag_ball() needs to know about allow_drag and might end
271 * up dragging the ball anyway. Also, drag_ball() might find that
272 * dragging the ball is completely impossible (ball in range but there's
273 * rock in the way), in which case it teleports the ball on its own.
275 if (ball_active) {
276 if (!carried(uball) && distmin(nux, nuy, uball->ox, uball->oy) <= 2)
277 ball_still_in_range = TRUE; /* don't have to move the ball */
278 else {
279 /* have to move the ball */
280 if (!allow_drag || distmin(u.ux, u.uy, nux, nuy) > 1) {
281 /* we should not have dist > 1 and allow_drag at the same
282 * time, but just in case, we must then revert to teleport.
284 allow_drag = FALSE;
285 unplacebc();
289 u.utrap = 0;
290 u.ustuck = 0;
291 u.ux0 = u.ux;
292 u.uy0 = u.uy;
294 if (!hideunder(&youmonst) && youmonst.data->mlet == S_MIMIC) {
295 /* mimics stop being unnoticed */
296 youmonst.m_ap_type = M_AP_NOTHING;
299 if (u.uswallow) {
300 u.uswldtim = u.uswallow = 0;
301 if (Punished && !ball_active) {
302 /* ensure ball placement, like unstuck */
303 ball_active = TRUE;
304 allow_drag = FALSE;
306 docrt();
308 if (ball_active) {
309 if (ball_still_in_range || allow_drag) {
310 int bc_control;
311 xchar ballx, bally, chainx, chainy;
312 boolean cause_delay;
314 if (drag_ball(nux, nuy, &bc_control, &ballx, &bally, &chainx,
315 &chainy, &cause_delay, allow_drag))
316 move_bc(0, bc_control, ballx, bally, chainx, chainy);
319 /* must set u.ux, u.uy after drag_ball(), which may need to know
320 the old position if allow_drag is true... */
321 u_on_newpos(nux, nuy); /* set u.<x,y>, usteed-><mx,my>; cliparound() */
322 fill_pit(u.ux0, u.uy0);
323 if (ball_active) {
324 if (!ball_still_in_range && !allow_drag)
325 placebc();
327 initrack(); /* teleports mess up tracking monsters without this */
328 update_player_regions();
330 * Make sure the hero disappears from the old location. This will
331 * not happen if she is teleported within sight of her previous
332 * location. Force a full vision recalculation because the hero
333 * is now in a new location.
335 newsym(u.ux0, u.uy0);
336 see_monsters();
337 vision_full_recalc = 1;
338 nomul(0);
339 vision_recalc(0); /* vision before effects */
340 if (telescroll) {
341 /* when teleporting by scroll, we need to handle discovery
342 now before getting feedback about any objects at our
343 destination since we might land on another such scroll */
344 if (distu(u.ux0, u.uy0) >= 16 || !couldsee(u.ux0, u.uy0))
345 learnscroll(telescroll);
346 else
347 telescroll = 0; /* no discovery by scrolltele()'s caller */
349 spoteffects(TRUE);
350 invocation_message();
353 boolean
354 safe_teleds(allow_drag)
355 boolean allow_drag;
357 register int nux, nuy, tcnt = 0;
359 do {
360 nux = rnd(COLNO - 1);
361 nuy = rn2(ROWNO);
362 } while (!teleok(nux, nuy, (boolean) (tcnt > 200)) && ++tcnt <= 400);
364 if (tcnt <= 400) {
365 teleds(nux, nuy, allow_drag);
366 return TRUE;
367 } else
368 return FALSE;
371 STATIC_OVL void
372 vault_tele()
374 register struct mkroom *croom = search_special(VAULT);
375 coord c;
377 if (croom && somexy(croom, &c) && teleok(c.x, c.y, FALSE)) {
378 teleds(c.x, c.y, FALSE);
379 return;
381 tele();
384 boolean
385 teleport_pet(mtmp, force_it)
386 register struct monst *mtmp;
387 boolean force_it;
389 register struct obj *otmp;
391 if (mtmp == u.usteed)
392 return FALSE;
394 if (mtmp->mleashed) {
395 otmp = get_mleash(mtmp);
396 if (!otmp) {
397 impossible("%s is leashed, without a leash.", Monnam(mtmp));
398 goto release_it;
400 if (otmp->cursed && !force_it) {
401 yelp(mtmp);
402 return FALSE;
403 } else {
404 Your("leash goes slack.");
405 release_it:
406 m_unleash(mtmp, FALSE);
407 return TRUE;
410 return TRUE;
413 /* teleport the hero via some method other than scroll of teleport */
414 void
415 tele()
417 (void) scrolltele((struct obj *) 0);
420 /* teleport the hero; return true if scroll of teleportation should become
421 discovered; teleds() will usually do the actual discovery, since the
422 outcome sometimes depends upon destination and discovery needs to be
423 performed before arrival, in case we land on another teleport scroll */
424 boolean
425 scrolltele(scroll)
426 struct obj *scroll;
428 coord cc;
429 boolean result = FALSE; /* don't learn scroll */
431 /* Disable teleportation in stronghold && Vlad's Tower */
432 if (level.flags.noteleport) {
433 if (!wizard) {
434 pline("A mysterious force prevents you from teleporting!");
435 return TRUE;
439 /* don't show trap if "Sorry..." */
440 if (!Blinded)
441 make_blinded(0L, FALSE);
443 if ((u.uhave.amulet || On_W_tower_level(&u.uz)) && !rn2(3)) {
444 You_feel("disoriented for a moment.");
445 if (!wizard || yn("Override?") != 'y')
446 return FALSE;
448 if ((Teleport_control && !Stunned) || wizard) {
449 if (unconscious()) {
450 pline("Being unconscious, you cannot control your teleport.");
451 } else {
452 char whobuf[BUFSZ];
454 Strcpy(whobuf, "you");
455 if (u.usteed)
456 Sprintf(eos(whobuf), " and %s", mon_nam(u.usteed));
457 pline("To what position do %s want to be teleported?", whobuf);
458 cc.x = u.ux;
459 cc.y = u.uy;
460 if (getpos(&cc, TRUE, "the desired position") < 0)
461 return TRUE; /* abort */
462 /* possible extensions: introduce a small error if
463 magic power is low; allow transfer to solid rock */
464 if (teleok(cc.x, cc.y, FALSE)) {
465 /* for scroll, discover it regardless of destination */
466 if (scroll)
467 learnscroll(scroll);
468 teleds(cc.x, cc.y, FALSE);
469 return TRUE;
471 pline("Sorry...");
472 result = TRUE;
474 } else if (scroll && scroll->blessed) {
475 /* (this used to be handled in seffects()) */
476 if (yn("Do you wish to teleport?") == 'n')
477 return TRUE;
478 result = TRUE;
481 telescroll = scroll;
482 (void) safe_teleds(FALSE);
483 /* teleds() will leave telescroll intact iff random destination
484 is far enough away for scroll discovery to be warranted */
485 if (telescroll)
486 result = TRUE;
487 telescroll = 0; /* reset */
488 return result;
492 dotele()
494 struct trap *trap;
495 boolean trap_once = FALSE;
497 trap = t_at(u.ux, u.uy);
498 if (trap && (!trap->tseen || trap->ttyp != TELEP_TRAP))
499 trap = 0;
501 if (trap) {
502 trap_once = trap->once; /* trap may get deleted, save this */
503 if (trap->once) {
504 pline("This is a vault teleport, usable once only.");
505 if (yn("Jump in?") == 'n')
506 trap = 0;
507 else {
508 deltrap(trap);
509 newsym(u.ux, u.uy);
512 if (trap)
513 You("%s onto the teleportation trap.",
514 locomotion(youmonst.data, "jump"));
516 if (!trap) {
517 boolean castit = FALSE;
518 register int sp_no = 0, energy = 0;
520 if (!Teleportation || (u.ulevel < (Role_if(PM_WIZARD) ? 8 : 12)
521 && !can_teleport(youmonst.data))) {
522 /* Try to use teleport away spell. */
523 if (objects[SPE_TELEPORT_AWAY].oc_name_known && !Confusion)
524 for (sp_no = 0; sp_no < MAXSPELL; sp_no++)
525 if (spl_book[sp_no].sp_id == SPE_TELEPORT_AWAY) {
526 castit = TRUE;
527 break;
529 if (!wizard) {
530 if (!castit) {
531 if (!Teleportation)
532 You("don't know that spell.");
533 else
534 You("are not able to teleport at will.");
535 return 0;
540 if (u.uhunger <= 100 || ACURR(A_STR) < 6) {
541 if (!wizard) {
542 You("lack the strength %s.",
543 castit ? "for a teleport spell" : "to teleport");
544 return 1;
548 energy = objects[SPE_TELEPORT_AWAY].oc_level * 7 / 2 - 2;
549 if (u.uen <= energy) {
550 if (wizard)
551 energy = u.uen;
552 else {
553 You("lack the energy %s.",
554 castit ? "for a teleport spell" : "to teleport");
555 return 1;
559 if (check_capacity(
560 "Your concentration falters from carrying so much."))
561 return 1;
563 if (castit) {
564 exercise(A_WIS, TRUE);
565 if (spelleffects(sp_no, TRUE))
566 return 1;
567 else if (!wizard)
568 return 0;
569 } else {
570 u.uen -= energy;
571 context.botl = 1;
575 if (next_to_u()) {
576 if (trap && trap_once)
577 vault_tele();
578 else
579 tele();
580 (void) next_to_u();
581 } else {
582 You1(shudder_for_moment);
583 return 0;
585 if (!trap)
586 morehungry(100);
587 return 1;
590 void
591 level_tele()
593 register int newlev;
594 d_level newlevel;
595 const char *escape_by_flying = 0; /* when surviving dest of -N */
596 char buf[BUFSZ];
597 boolean force_dest = FALSE;
599 if ((u.uhave.amulet || In_endgame(&u.uz) || In_sokoban(&u.uz))
600 && !wizard) {
601 You_feel("very disoriented for a moment.");
602 return;
604 if ((Teleport_control && !Stunned) || wizard) {
605 char qbuf[BUFSZ];
606 int trycnt = 0;
608 Strcpy(qbuf, "To what level do you want to teleport?");
609 do {
610 if (++trycnt == 2) {
611 if (wizard)
612 Strcat(qbuf, " [type a number, name, or ? for a menu]");
613 else
614 Strcat(qbuf, " [type a number or name]");
616 getlin(qbuf, buf);
617 if (!strcmp(buf, "\033")) { /* cancelled */
618 if (Confusion && rnl(5)) {
619 pline("Oops...");
620 goto random_levtport;
622 return;
623 } else if (!strcmp(buf, "*")) {
624 goto random_levtport;
625 } else if (Confusion && rnl(5)) {
626 pline("Oops...");
627 goto random_levtport;
629 if (wizard && !strcmp(buf, "?")) {
630 schar destlev = 0;
631 xchar destdnum = 0;
633 newlev = (int) print_dungeon(TRUE, &destlev, &destdnum);
634 if (!newlev)
635 return;
637 newlevel.dnum = destdnum;
638 newlevel.dlevel = destlev;
639 if (In_endgame(&newlevel) && !In_endgame(&u.uz)) {
640 struct obj *amu;
642 if (!u.uhave.amulet
643 && (amu = mksobj(AMULET_OF_YENDOR, TRUE, FALSE))
644 != 0) {
645 /* ordinarily we'd use hold_another_object()
646 for something like this, but we don't want
647 fumbling or already full pack to interfere */
648 amu = addinv(amu);
649 prinv("Endgame prerequisite:", amu, 0L);
652 force_dest = TRUE;
653 } else if ((newlev = lev_by_name(buf)) == 0)
654 newlev = atoi(buf);
655 } while (!newlev && !digit(buf[0])
656 && (buf[0] != '-' || !digit(buf[1])) && trycnt < 10);
658 /* no dungeon escape via this route */
659 if (newlev == 0) {
660 if (trycnt >= 10)
661 goto random_levtport;
662 if (ynq("Go to Nowhere. Are you sure?") != 'y')
663 return;
664 You("%s in agony as your body begins to warp...",
665 is_silent(youmonst.data) ? "writhe" : "scream");
666 display_nhwindow(WIN_MESSAGE, FALSE);
667 You("cease to exist.");
668 if (invent)
669 Your("possessions land on the %s with a thud.",
670 surface(u.ux, u.uy));
671 killer.format = NO_KILLER_PREFIX;
672 Strcpy(killer.name, "committed suicide");
673 done(DIED);
674 pline("An energized cloud of dust begins to coalesce.");
675 Your("body rematerializes%s.",
676 invent ? ", and you gather up all your possessions" : "");
677 return;
680 /* if in Knox and the requested level > 0, stay put.
681 * we let negative values requests fall into the "heaven" loop.
683 if (Is_knox(&u.uz) && newlev > 0 && !force_dest) {
684 You1(shudder_for_moment);
685 return;
687 /* if in Quest, the player sees "Home 1", etc., on the status
688 * line, instead of the logical depth of the level. controlled
689 * level teleport request is likely to be relativized to the
690 * status line, and consequently it should be incremented to
691 * the value of the logical depth of the target level.
693 * we let negative values requests fall into the "heaven" loop.
695 if (In_quest(&u.uz) && newlev > 0)
696 newlev = newlev + dungeons[u.uz.dnum].depth_start - 1;
697 } else { /* involuntary level tele */
698 random_levtport:
699 newlev = random_teleport_level();
700 if (newlev == depth(&u.uz)) {
701 You1(shudder_for_moment);
702 return;
706 if (u.utrap && u.utraptype == TT_BURIEDBALL)
707 buried_ball_to_punishment();
709 if (!next_to_u() && !force_dest) {
710 You1(shudder_for_moment);
711 return;
713 if (In_endgame(&u.uz)) { /* must already be wizard */
714 int llimit = dunlevs_in_dungeon(&u.uz);
716 if (newlev >= 0 || newlev <= -llimit) {
717 You_cant("get there from here.");
718 return;
720 newlevel.dnum = u.uz.dnum;
721 newlevel.dlevel = llimit + newlev;
722 schedule_goto(&newlevel, FALSE, FALSE, 0, (char *) 0, (char *) 0);
723 return;
726 killer.name[0] = 0; /* still alive, so far... */
728 if (newlev < 0 && !force_dest) {
729 if (*u.ushops0) {
730 /* take unpaid inventory items off of shop bills */
731 in_mklev = TRUE; /* suppress map update */
732 u_left_shop(u.ushops0, TRUE);
733 /* you're now effectively out of the shop */
734 *u.ushops0 = *u.ushops = '\0';
735 in_mklev = FALSE;
737 if (newlev <= -10) {
738 You("arrive in heaven.");
739 verbalize("Thou art early, but we'll admit thee.");
740 killer.format = NO_KILLER_PREFIX;
741 Strcpy(killer.name, "went to heaven prematurely");
742 } else if (newlev == -9) {
743 You_feel("deliriously happy. ");
744 pline("(In fact, you're on Cloud 9!) ");
745 display_nhwindow(WIN_MESSAGE, FALSE);
746 } else
747 You("are now high above the clouds...");
749 if (killer.name[0]) {
750 ; /* arrival in heaven is pending */
751 } else if (Levitation) {
752 escape_by_flying = "float gently down to earth";
753 } else if (Flying) {
754 escape_by_flying = "fly down to the ground";
755 } else {
756 pline("Unfortunately, you don't know how to fly.");
757 You("plummet a few thousand feet to your death.");
758 Sprintf(killer.name,
759 "teleported out of the dungeon and fell to %s death",
760 uhis());
761 killer.format = NO_KILLER_PREFIX;
765 if (killer.name[0]) { /* the chosen destination was not survivable */
766 d_level lsav;
768 /* set specific death location; this also suppresses bones */
769 lsav = u.uz; /* save current level, see below */
770 u.uz.dnum = 0; /* main dungeon */
771 u.uz.dlevel = (newlev <= -10) ? -10 : 0; /* heaven or surface */
772 done(DIED);
773 /* can only get here via life-saving (or declining to die in
774 explore|debug mode); the hero has now left the dungeon... */
775 escape_by_flying = "find yourself back on the surface";
776 u.uz = lsav; /* restore u.uz so escape code works */
779 /* calls done(ESCAPED) if newlevel==0 */
780 if (escape_by_flying) {
781 You("%s.", escape_by_flying);
782 newlevel.dnum = 0; /* specify main dungeon */
783 newlevel.dlevel = 0; /* escape the dungeon */
784 /* [dlevel used to be set to 1, but it doesn't make sense to
785 teleport out of the dungeon and float or fly down to the
786 surface but then actually arrive back inside the dungeon] */
787 } else if (u.uz.dnum == medusa_level.dnum
788 && newlev >= dungeons[u.uz.dnum].depth_start
789 + dunlevs_in_dungeon(&u.uz)) {
790 if (!(wizard && force_dest))
791 find_hell(&newlevel);
792 } else {
793 /* if invocation did not yet occur, teleporting into
794 * the last level of Gehennom is forbidden.
796 if (!wizard && Inhell && !u.uevent.invoked
797 && newlev >= (dungeons[u.uz.dnum].depth_start
798 + dunlevs_in_dungeon(&u.uz) - 1)) {
799 newlev = dungeons[u.uz.dnum].depth_start
800 + dunlevs_in_dungeon(&u.uz) - 2;
801 pline("Sorry...");
803 /* no teleporting out of quest dungeon */
804 if (In_quest(&u.uz) && newlev < depth(&qstart_level))
805 newlev = depth(&qstart_level);
806 /* the player thinks of levels purely in logical terms, so
807 * we must translate newlev to a number relative to the
808 * current dungeon.
810 if (!(wizard && force_dest))
811 get_level(&newlevel, newlev);
813 schedule_goto(&newlevel, FALSE, FALSE, 0, (char *) 0, (char *) 0);
814 /* in case player just read a scroll and is about to be asked to
815 call it something, we can't defer until the end of the turn */
816 if (u.utotype && !context.mon_moving)
817 deferred_goto();
820 void
821 domagicportal(ttmp)
822 register struct trap *ttmp;
824 struct d_level target_level;
826 if (u.utrap && u.utraptype == TT_BURIEDBALL)
827 buried_ball_to_punishment();
829 if (!next_to_u()) {
830 You1(shudder_for_moment);
831 return;
834 /* if landed from another portal, do nothing */
835 /* problem: level teleport landing escapes the check */
836 if (!on_level(&u.uz, &u.uz0))
837 return;
839 You("activated a magic portal!");
841 /* prevent the poor shnook, whose amulet was stolen while in
842 * the endgame, from accidently triggering the portal to the
843 * next level, and thus losing the game
845 if (In_endgame(&u.uz) && !u.uhave.amulet) {
846 You_feel("dizzy for a moment, but nothing happens...");
847 return;
850 target_level = ttmp->dst;
851 schedule_goto(&target_level, FALSE, FALSE, 1,
852 "You feel dizzy for a moment, but the sensation passes.",
853 (char *) 0);
856 void
857 tele_trap(trap)
858 struct trap *trap;
860 if (In_endgame(&u.uz) || Antimagic) {
861 if (Antimagic)
862 shieldeff(u.ux, u.uy);
863 You_feel("a wrenching sensation.");
864 } else if (!next_to_u()) {
865 You1(shudder_for_moment);
866 } else if (trap->once) {
867 deltrap(trap);
868 newsym(u.ux, u.uy); /* get rid of trap symbol */
869 vault_tele();
870 } else
871 tele();
874 void
875 level_tele_trap(trap, trflags)
876 struct trap *trap;
877 unsigned trflags;
879 char verbbuf[BUFSZ];
881 if ((trflags & VIASITTING) != 0)
882 Strcpy(verbbuf, "trigger"); /* follows "You sit down." */
883 else
884 Sprintf(verbbuf, "%s onto",
885 Levitation ? (const char *) "float"
886 : locomotion(youmonst.data, "step"));
887 You("%s a level teleport trap!", verbbuf);
889 if (Antimagic) {
890 shieldeff(u.ux, u.uy);
892 if (Antimagic || In_endgame(&u.uz)) {
893 You_feel("a wrenching sensation.");
894 return;
896 if (!Blind)
897 You("are momentarily blinded by a flash of light.");
898 else
899 You("are momentarily disoriented.");
900 deltrap(trap);
901 newsym(u.ux, u.uy); /* get rid of trap symbol */
902 level_tele();
905 /* check whether monster can arrive at location <x,y> via Tport (or fall) */
906 STATIC_OVL boolean
907 rloc_pos_ok(x, y, mtmp)
908 register int x, y; /* coordinates of candidate location */
909 struct monst *mtmp;
911 register int xx, yy;
913 if (!goodpos(x, y, mtmp, 0))
914 return FALSE;
916 * Check for restricted areas present in some special levels.
918 * `xx' is current column; if 0, then `yy' will contain flag bits
919 * rather than row: bit #0 set => moving upwards; bit #1 set =>
920 * inside the Wizard's tower.
922 xx = mtmp->mx;
923 yy = mtmp->my;
924 if (!xx) {
925 /* no current location (migrating monster arrival) */
926 if (dndest.nlx && On_W_tower_level(&u.uz))
927 return (((yy & 2) != 0)
928 /* inside xor not within */
929 ^ !within_bounded_area(x, y, dndest.nlx, dndest.nly,
930 dndest.nhx, dndest.nhy));
931 if (updest.lx && (yy & 1) != 0) /* moving up */
932 return (within_bounded_area(x, y, updest.lx, updest.ly,
933 updest.hx, updest.hy)
934 && (!updest.nlx
935 || !within_bounded_area(x, y, updest.nlx, updest.nly,
936 updest.nhx, updest.nhy)));
937 if (dndest.lx && (yy & 1) == 0) /* moving down */
938 return (within_bounded_area(x, y, dndest.lx, dndest.ly,
939 dndest.hx, dndest.hy)
940 && (!dndest.nlx
941 || !within_bounded_area(x, y, dndest.nlx, dndest.nly,
942 dndest.nhx, dndest.nhy)));
943 } else {
944 /* [try to] prevent a shopkeeper or temple priest from being
945 sent out of his room (caller might resort to goodpos() if
946 we report failure here, so this isn't full prevention) */
947 if (mtmp->isshk && inhishop(mtmp)) {
948 if (levl[x][y].roomno != ESHK(mtmp)->shoproom)
949 return FALSE;
950 } else if (mtmp->ispriest && inhistemple(mtmp)) {
951 if (levl[x][y].roomno != EPRI(mtmp)->shroom)
952 return FALSE;
954 /* current location is <xx,yy> */
955 if (!tele_jump_ok(xx, yy, x, y))
956 return FALSE;
958 /* <x,y> is ok */
959 return TRUE;
963 * rloc_to()
965 * Pulls a monster from its current position and places a monster at
966 * a new x and y. If oldx is 0, then the monster was not in the
967 * levels.monsters array. However, if oldx is 0, oldy may still have
968 * a value because mtmp is a migrating_mon. Worm tails are always
969 * placed randomly around the head of the worm.
971 void
972 rloc_to(mtmp, x, y)
973 struct monst *mtmp;
974 register int x, y;
976 register int oldx = mtmp->mx, oldy = mtmp->my;
977 boolean resident_shk = mtmp->isshk && inhishop(mtmp);
979 if (x == mtmp->mx && y == mtmp->my) /* that was easy */
980 return;
982 if (oldx) { /* "pick up" monster */
983 if (mtmp->wormno) {
984 remove_worm(mtmp);
985 } else {
986 remove_monster(oldx, oldy);
987 newsym(oldx, oldy); /* update old location */
991 memset(mtmp->mtrack, 0, sizeof mtmp->mtrack);
992 place_monster(mtmp, x, y); /* put monster down */
993 update_monster_region(mtmp);
995 if (mtmp->wormno) /* now put down tail */
996 place_worm_tail_randomly(mtmp, x, y);
998 if (u.ustuck == mtmp) {
999 if (u.uswallow) {
1000 u.ux = x;
1001 u.uy = y;
1002 docrt();
1003 } else
1004 u.ustuck = 0;
1007 newsym(x, y); /* update new location */
1008 set_apparxy(mtmp); /* orient monster */
1010 /* shopkeepers will only teleport if you zap them with a wand of
1011 teleportation or if they've been transformed into a jumpy monster;
1012 the latter only happens if you've attacked them with polymorph */
1013 if (resident_shk && !inhishop(mtmp))
1014 make_angry_shk(mtmp, oldx, oldy);
1017 /* place a monster at a random location, typically due to teleport */
1018 /* return TRUE if successful, FALSE if not */
1019 boolean
1020 rloc(mtmp, suppress_impossible)
1021 struct monst *mtmp; /* mx==0 implies migrating monster arrival */
1022 boolean suppress_impossible;
1024 register int x, y, trycount;
1026 if (mtmp == u.usteed) {
1027 tele();
1028 return TRUE;
1031 if (mtmp->iswiz && mtmp->mx) { /* Wizard, not just arriving */
1032 if (!In_W_tower(u.ux, u.uy, &u.uz))
1033 x = xupstair, y = yupstair;
1034 else if (!xdnladder) /* bottom level of tower */
1035 x = xupladder, y = yupladder;
1036 else
1037 x = xdnladder, y = ydnladder;
1038 /* if the wiz teleports away to heal, try the up staircase,
1039 to block the player's escaping before he's healed
1040 (deliberately use `goodpos' rather than `rloc_pos_ok' here) */
1041 if (goodpos(x, y, mtmp, 0))
1042 goto found_xy;
1045 trycount = 0;
1046 do {
1047 x = rn1(COLNO - 3, 2);
1048 y = rn2(ROWNO);
1049 if ((trycount < 500) ? rloc_pos_ok(x, y, mtmp)
1050 : goodpos(x, y, mtmp, 0))
1051 goto found_xy;
1052 } while (++trycount < 1000);
1054 /* last ditch attempt to find a good place */
1055 for (x = 2; x < COLNO - 1; x++)
1056 for (y = 0; y < ROWNO; y++)
1057 if (goodpos(x, y, mtmp, 0))
1058 goto found_xy;
1060 /* level either full of monsters or somehow faulty */
1061 if (!suppress_impossible)
1062 impossible("rloc(): couldn't relocate monster");
1063 return FALSE;
1065 found_xy:
1066 rloc_to(mtmp, x, y);
1067 return TRUE;
1070 STATIC_OVL void
1071 mvault_tele(mtmp)
1072 struct monst *mtmp;
1074 register struct mkroom *croom = search_special(VAULT);
1075 coord c;
1077 if (croom && somexy(croom, &c) && goodpos(c.x, c.y, mtmp, 0)) {
1078 rloc_to(mtmp, c.x, c.y);
1079 return;
1081 (void) rloc(mtmp, TRUE);
1084 boolean
1085 tele_restrict(mon)
1086 struct monst *mon;
1088 if (level.flags.noteleport) {
1089 if (canseemon(mon))
1090 pline("A mysterious force prevents %s from teleporting!",
1091 mon_nam(mon));
1092 return TRUE;
1094 return FALSE;
1097 void
1098 mtele_trap(mtmp, trap, in_sight)
1099 struct monst *mtmp;
1100 struct trap *trap;
1101 int in_sight;
1103 char *monname;
1105 if (tele_restrict(mtmp))
1106 return;
1107 if (teleport_pet(mtmp, FALSE)) {
1108 /* save name with pre-movement visibility */
1109 monname = Monnam(mtmp);
1111 /* Note: don't remove the trap if a vault. Other-
1112 * wise the monster will be stuck there, since
1113 * the guard isn't going to come for it...
1115 if (trap->once)
1116 mvault_tele(mtmp);
1117 else
1118 (void) rloc(mtmp, TRUE);
1120 if (in_sight) {
1121 if (canseemon(mtmp))
1122 pline("%s seems disoriented.", monname);
1123 else
1124 pline("%s suddenly disappears!", monname);
1125 seetrap(trap);
1130 /* return 0 if still on level, 3 if not */
1132 mlevel_tele_trap(mtmp, trap, force_it, in_sight)
1133 struct monst *mtmp;
1134 struct trap *trap;
1135 boolean force_it;
1136 int in_sight;
1138 int tt = trap->ttyp;
1139 struct permonst *mptr = mtmp->data;
1141 if (mtmp == u.ustuck) /* probably a vortex */
1142 return 0; /* temporary? kludge */
1143 if (teleport_pet(mtmp, force_it)) {
1144 d_level tolevel;
1145 int migrate_typ = MIGR_RANDOM;
1147 if ((tt == HOLE || tt == TRAPDOOR)) {
1148 if (Is_stronghold(&u.uz)) {
1149 assign_level(&tolevel, &valley_level);
1150 } else if (Is_botlevel(&u.uz)) {
1151 if (in_sight && trap->tseen)
1152 pline("%s avoids the %s.", Monnam(mtmp),
1153 (tt == HOLE) ? "hole" : "trap");
1154 return 0;
1155 } else {
1156 get_level(&tolevel, depth(&u.uz) + 1);
1158 } else if (tt == MAGIC_PORTAL) {
1159 if (In_endgame(&u.uz)
1160 && (mon_has_amulet(mtmp) || is_home_elemental(mptr))) {
1161 if (in_sight && mptr->mlet != S_ELEMENTAL) {
1162 pline("%s seems to shimmer for a moment.", Monnam(mtmp));
1163 seetrap(trap);
1165 return 0;
1166 } else {
1167 assign_level(&tolevel, &trap->dst);
1168 migrate_typ = MIGR_PORTAL;
1170 } else { /* (tt == LEVEL_TELEP) */
1171 int nlev;
1173 if (mon_has_amulet(mtmp) || In_endgame(&u.uz)) {
1174 if (in_sight)
1175 pline("%s seems very disoriented for a moment.",
1176 Monnam(mtmp));
1177 return 0;
1179 nlev = random_teleport_level();
1180 if (nlev == depth(&u.uz)) {
1181 if (in_sight)
1182 pline("%s shudders for a moment.", Monnam(mtmp));
1183 return 0;
1185 get_level(&tolevel, nlev);
1188 if (in_sight) {
1189 pline("Suddenly, %s disappears out of sight.", mon_nam(mtmp));
1190 seetrap(trap);
1192 migrate_to_level(mtmp, ledger_no(&tolevel), migrate_typ, (coord *) 0);
1193 return 3; /* no longer on this level */
1195 return 0;
1198 /* place object randomly, returns False if it's gone (eg broken) */
1199 boolean
1200 rloco(obj)
1201 register struct obj *obj;
1203 register xchar tx, ty, otx, oty;
1204 boolean restricted_fall;
1205 int try_limit = 4000;
1207 if (obj->otyp == CORPSE && is_rider(&mons[obj->corpsenm])) {
1208 if (revive_corpse(obj))
1209 return FALSE;
1212 obj_extract_self(obj);
1213 otx = obj->ox;
1214 oty = obj->oy;
1215 restricted_fall = (otx == 0 && dndest.lx);
1216 do {
1217 tx = rn1(COLNO - 3, 2);
1218 ty = rn2(ROWNO);
1219 if (!--try_limit)
1220 break;
1221 } while (!goodpos(tx, ty, (struct monst *) 0, 0)
1222 || (restricted_fall
1223 && (!within_bounded_area(tx, ty, dndest.lx, dndest.ly,
1224 dndest.hx, dndest.hy)
1225 || (dndest.nlx
1226 && within_bounded_area(tx, ty,
1227 dndest.nlx, dndest.nly,
1228 dndest.nhx, dndest.nhy))))
1229 /* on the Wizard Tower levels, objects inside should
1230 stay inside and objects outside should stay outside */
1231 || (dndest.nlx && On_W_tower_level(&u.uz)
1232 && within_bounded_area(tx, ty, dndest.nlx, dndest.nly,
1233 dndest.nhx, dndest.nhy)
1234 != within_bounded_area(otx, oty, dndest.nlx, dndest.nly,
1235 dndest.nhx, dndest.nhy)));
1237 if (flooreffects(obj, tx, ty, "fall")) {
1238 return FALSE;
1239 } else if (otx == 0 && oty == 0) {
1240 ; /* fell through a trap door; no update of old loc needed */
1241 } else {
1242 if (costly_spot(otx, oty)
1243 && (!costly_spot(tx, ty)
1244 || !index(in_rooms(tx, ty, 0), *in_rooms(otx, oty, 0)))) {
1245 if (costly_spot(u.ux, u.uy)
1246 && index(u.urooms, *in_rooms(otx, oty, 0)))
1247 addtobill(obj, FALSE, FALSE, FALSE);
1248 else
1249 (void) stolen_value(obj, otx, oty, FALSE, FALSE);
1251 newsym(otx, oty); /* update old location */
1253 place_object(obj, tx, ty);
1254 newsym(tx, ty);
1255 return TRUE;
1258 /* Returns an absolute depth */
1260 random_teleport_level()
1262 int nlev, max_depth, min_depth, cur_depth = (int) depth(&u.uz);
1264 /* [the endgame case can only occur in wizard mode] */
1265 if (!rn2(5) || Is_knox(&u.uz) || In_endgame(&u.uz))
1266 return cur_depth;
1268 /* What I really want to do is as follows:
1269 * -- If in a dungeon that goes down, the new level is to be restricted
1270 * to [top of parent, bottom of current dungeon]
1271 * -- If in a dungeon that goes up, the new level is to be restricted
1272 * to [top of current dungeon, bottom of parent]
1273 * -- If in a quest dungeon or similar dungeon entered by portals,
1274 * the new level is to be restricted to [top of current dungeon,
1275 * bottom of current dungeon]
1276 * The current behavior is not as sophisticated as that ideal, but is
1277 * still better what we used to do, which was like this for players
1278 * but different for monsters for no obvious reason. Currently, we
1279 * must explicitly check for special dungeons. We check for Knox
1280 * above; endgame is handled in the caller due to its different
1281 * message ("disoriented").
1282 * --KAA
1283 * 3.4.2: explicitly handle quest here too, to fix the problem of
1284 * monsters sometimes level teleporting out of it into main dungeon.
1285 * Also prevent monsters reaching the Sanctum prior to invocation.
1287 if (In_quest(&u.uz)) {
1288 int bottom = dunlevs_in_dungeon(&u.uz),
1289 qlocate_depth = qlocate_level.dlevel;
1291 /* if hero hasn't reached the middle locate level yet,
1292 no one can randomly teleport past it */
1293 if (dunlev_reached(&u.uz) < qlocate_depth)
1294 bottom = qlocate_depth;
1295 min_depth = dungeons[u.uz.dnum].depth_start;
1296 max_depth = bottom + (dungeons[u.uz.dnum].depth_start - 1);
1297 } else {
1298 min_depth = 1;
1299 max_depth =
1300 dunlevs_in_dungeon(&u.uz) + (dungeons[u.uz.dnum].depth_start - 1);
1301 /* can't reach Sanctum if the invocation hasn't been performed */
1302 if (Inhell && !u.uevent.invoked)
1303 max_depth -= 1;
1306 /* Get a random value relative to the current dungeon */
1307 /* Range is 1 to current+3, current not counting */
1308 nlev = rn2(cur_depth + 3 - min_depth) + min_depth;
1309 if (nlev >= cur_depth)
1310 nlev++;
1312 if (nlev > max_depth) {
1313 nlev = max_depth;
1314 /* teleport up if already on bottom */
1315 if (Is_botlevel(&u.uz))
1316 nlev -= rnd(3);
1318 if (nlev < min_depth) {
1319 nlev = min_depth;
1320 if (nlev == cur_depth) {
1321 nlev += rnd(3);
1322 if (nlev > max_depth)
1323 nlev = max_depth;
1326 return nlev;
1329 /* you teleport a monster (via wand, spell, or poly'd q.mechanic attack);
1330 return false iff the attempt fails */
1331 boolean
1332 u_teleport_mon(mtmp, give_feedback)
1333 struct monst *mtmp;
1334 boolean give_feedback;
1336 coord cc;
1338 if (mtmp->ispriest && *in_rooms(mtmp->mx, mtmp->my, TEMPLE)) {
1339 if (give_feedback)
1340 pline("%s resists your magic!", Monnam(mtmp));
1341 return FALSE;
1342 } else if (level.flags.noteleport && u.uswallow && mtmp == u.ustuck) {
1343 if (give_feedback)
1344 You("are no longer inside %s!", mon_nam(mtmp));
1345 unstuck(mtmp);
1346 (void) rloc(mtmp, TRUE);
1347 } else if (is_rider(mtmp->data) && rn2(13)
1348 && enexto(&cc, u.ux, u.uy, mtmp->data))
1349 rloc_to(mtmp, cc.x, cc.y);
1350 else
1351 (void) rloc(mtmp, TRUE);
1352 return TRUE;
1355 /*teleport.c*/