Move getpos return values to header
[aNetHack.git] / src / teleport.c
blobf45abfb5ed54db3b2f86fc9fd74597115dc0691a
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 or ? for a menu]");
613 else
614 Strcat(qbuf, " [type a number]");
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)
876 struct trap *trap;
878 You("%s onto a level teleport trap!",
879 Levitation ? (const char *) "float"
880 : locomotion(youmonst.data, "step"));
881 if (Antimagic) {
882 shieldeff(u.ux, u.uy);
884 if (Antimagic || In_endgame(&u.uz)) {
885 You_feel("a wrenching sensation.");
886 return;
888 if (!Blind)
889 You("are momentarily blinded by a flash of light.");
890 else
891 You("are momentarily disoriented.");
892 deltrap(trap);
893 newsym(u.ux, u.uy); /* get rid of trap symbol */
894 level_tele();
897 /* check whether monster can arrive at location <x,y> via Tport (or fall) */
898 STATIC_OVL boolean
899 rloc_pos_ok(x, y, mtmp)
900 register int x, y; /* coordinates of candidate location */
901 struct monst *mtmp;
903 register int xx, yy;
905 if (!goodpos(x, y, mtmp, 0))
906 return FALSE;
908 * Check for restricted areas present in some special levels.
910 * `xx' is current column; if 0, then `yy' will contain flag bits
911 * rather than row: bit #0 set => moving upwards; bit #1 set =>
912 * inside the Wizard's tower.
914 xx = mtmp->mx;
915 yy = mtmp->my;
916 if (!xx) {
917 /* no current location (migrating monster arrival) */
918 if (dndest.nlx && On_W_tower_level(&u.uz))
919 return (((yy & 2) != 0)
920 /* inside xor not within */
921 ^ !within_bounded_area(x, y, dndest.nlx, dndest.nly,
922 dndest.nhx, dndest.nhy));
923 if (updest.lx && (yy & 1) != 0) /* moving up */
924 return (within_bounded_area(x, y, updest.lx, updest.ly,
925 updest.hx, updest.hy)
926 && (!updest.nlx
927 || !within_bounded_area(x, y, updest.nlx, updest.nly,
928 updest.nhx, updest.nhy)));
929 if (dndest.lx && (yy & 1) == 0) /* moving down */
930 return (within_bounded_area(x, y, dndest.lx, dndest.ly,
931 dndest.hx, dndest.hy)
932 && (!dndest.nlx
933 || !within_bounded_area(x, y, dndest.nlx, dndest.nly,
934 dndest.nhx, dndest.nhy)));
935 } else {
936 /* [try to] prevent a shopkeeper or temple priest from being
937 sent out of his room (caller might resort to goodpos() if
938 we report failure here, so this isn't full prevention) */
939 if (mtmp->isshk && inhishop(mtmp)) {
940 if (levl[x][y].roomno != ESHK(mtmp)->shoproom)
941 return FALSE;
942 } else if (mtmp->ispriest && inhistemple(mtmp)) {
943 if (levl[x][y].roomno != EPRI(mtmp)->shroom)
944 return FALSE;
946 /* current location is <xx,yy> */
947 if (!tele_jump_ok(xx, yy, x, y))
948 return FALSE;
950 /* <x,y> is ok */
951 return TRUE;
955 * rloc_to()
957 * Pulls a monster from its current position and places a monster at
958 * a new x and y. If oldx is 0, then the monster was not in the
959 * levels.monsters array. However, if oldx is 0, oldy may still have
960 * a value because mtmp is a migrating_mon. Worm tails are always
961 * placed randomly around the head of the worm.
963 void
964 rloc_to(mtmp, x, y)
965 struct monst *mtmp;
966 register int x, y;
968 register int oldx = mtmp->mx, oldy = mtmp->my;
969 boolean resident_shk = mtmp->isshk && inhishop(mtmp);
971 if (x == mtmp->mx && y == mtmp->my) /* that was easy */
972 return;
974 if (oldx) { /* "pick up" monster */
975 if (mtmp->wormno) {
976 remove_worm(mtmp);
977 } else {
978 remove_monster(oldx, oldy);
979 newsym(oldx, oldy); /* update old location */
983 memset(mtmp->mtrack, 0, sizeof mtmp->mtrack);
984 place_monster(mtmp, x, y); /* put monster down */
985 update_monster_region(mtmp);
987 if (mtmp->wormno) /* now put down tail */
988 place_worm_tail_randomly(mtmp, x, y);
990 if (u.ustuck == mtmp) {
991 if (u.uswallow) {
992 u.ux = x;
993 u.uy = y;
994 docrt();
995 } else
996 u.ustuck = 0;
999 newsym(x, y); /* update new location */
1000 set_apparxy(mtmp); /* orient monster */
1002 /* shopkeepers will only teleport if you zap them with a wand of
1003 teleportation or if they've been transformed into a jumpy monster;
1004 the latter only happens if you've attacked them with polymorph */
1005 if (resident_shk && !inhishop(mtmp))
1006 make_angry_shk(mtmp, oldx, oldy);
1009 /* place a monster at a random location, typically due to teleport */
1010 /* return TRUE if successful, FALSE if not */
1011 boolean
1012 rloc(mtmp, suppress_impossible)
1013 struct monst *mtmp; /* mx==0 implies migrating monster arrival */
1014 boolean suppress_impossible;
1016 register int x, y, trycount;
1018 if (mtmp == u.usteed) {
1019 tele();
1020 return TRUE;
1023 if (mtmp->iswiz && mtmp->mx) { /* Wizard, not just arriving */
1024 if (!In_W_tower(u.ux, u.uy, &u.uz))
1025 x = xupstair, y = yupstair;
1026 else if (!xdnladder) /* bottom level of tower */
1027 x = xupladder, y = yupladder;
1028 else
1029 x = xdnladder, y = ydnladder;
1030 /* if the wiz teleports away to heal, try the up staircase,
1031 to block the player's escaping before he's healed
1032 (deliberately use `goodpos' rather than `rloc_pos_ok' here) */
1033 if (goodpos(x, y, mtmp, 0))
1034 goto found_xy;
1037 trycount = 0;
1038 do {
1039 x = rn1(COLNO - 3, 2);
1040 y = rn2(ROWNO);
1041 if ((trycount < 500) ? rloc_pos_ok(x, y, mtmp)
1042 : goodpos(x, y, mtmp, 0))
1043 goto found_xy;
1044 } while (++trycount < 1000);
1046 /* last ditch attempt to find a good place */
1047 for (x = 2; x < COLNO - 1; x++)
1048 for (y = 0; y < ROWNO; y++)
1049 if (goodpos(x, y, mtmp, 0))
1050 goto found_xy;
1052 /* level either full of monsters or somehow faulty */
1053 if (!suppress_impossible)
1054 impossible("rloc(): couldn't relocate monster");
1055 return FALSE;
1057 found_xy:
1058 rloc_to(mtmp, x, y);
1059 return TRUE;
1062 STATIC_OVL void
1063 mvault_tele(mtmp)
1064 struct monst *mtmp;
1066 register struct mkroom *croom = search_special(VAULT);
1067 coord c;
1069 if (croom && somexy(croom, &c) && goodpos(c.x, c.y, mtmp, 0)) {
1070 rloc_to(mtmp, c.x, c.y);
1071 return;
1073 (void) rloc(mtmp, TRUE);
1076 boolean
1077 tele_restrict(mon)
1078 struct monst *mon;
1080 if (level.flags.noteleport) {
1081 if (canseemon(mon))
1082 pline("A mysterious force prevents %s from teleporting!",
1083 mon_nam(mon));
1084 return TRUE;
1086 return FALSE;
1089 void
1090 mtele_trap(mtmp, trap, in_sight)
1091 struct monst *mtmp;
1092 struct trap *trap;
1093 int in_sight;
1095 char *monname;
1097 if (tele_restrict(mtmp))
1098 return;
1099 if (teleport_pet(mtmp, FALSE)) {
1100 /* save name with pre-movement visibility */
1101 monname = Monnam(mtmp);
1103 /* Note: don't remove the trap if a vault. Other-
1104 * wise the monster will be stuck there, since
1105 * the guard isn't going to come for it...
1107 if (trap->once)
1108 mvault_tele(mtmp);
1109 else
1110 (void) rloc(mtmp, TRUE);
1112 if (in_sight) {
1113 if (canseemon(mtmp))
1114 pline("%s seems disoriented.", monname);
1115 else
1116 pline("%s suddenly disappears!", monname);
1117 seetrap(trap);
1122 /* return 0 if still on level, 3 if not */
1124 mlevel_tele_trap(mtmp, trap, force_it, in_sight)
1125 struct monst *mtmp;
1126 struct trap *trap;
1127 boolean force_it;
1128 int in_sight;
1130 int tt = trap->ttyp;
1131 struct permonst *mptr = mtmp->data;
1133 if (mtmp == u.ustuck) /* probably a vortex */
1134 return 0; /* temporary? kludge */
1135 if (teleport_pet(mtmp, force_it)) {
1136 d_level tolevel;
1137 int migrate_typ = MIGR_RANDOM;
1139 if ((tt == HOLE || tt == TRAPDOOR)) {
1140 if (Is_stronghold(&u.uz)) {
1141 assign_level(&tolevel, &valley_level);
1142 } else if (Is_botlevel(&u.uz)) {
1143 if (in_sight && trap->tseen)
1144 pline("%s avoids the %s.", Monnam(mtmp),
1145 (tt == HOLE) ? "hole" : "trap");
1146 return 0;
1147 } else {
1148 get_level(&tolevel, depth(&u.uz) + 1);
1150 } else if (tt == MAGIC_PORTAL) {
1151 if (In_endgame(&u.uz)
1152 && (mon_has_amulet(mtmp) || is_home_elemental(mptr))) {
1153 if (in_sight && mptr->mlet != S_ELEMENTAL) {
1154 pline("%s seems to shimmer for a moment.", Monnam(mtmp));
1155 seetrap(trap);
1157 return 0;
1158 } else {
1159 assign_level(&tolevel, &trap->dst);
1160 migrate_typ = MIGR_PORTAL;
1162 } else { /* (tt == LEVEL_TELEP) */
1163 int nlev;
1165 if (mon_has_amulet(mtmp) || In_endgame(&u.uz)) {
1166 if (in_sight)
1167 pline("%s seems very disoriented for a moment.",
1168 Monnam(mtmp));
1169 return 0;
1171 nlev = random_teleport_level();
1172 if (nlev == depth(&u.uz)) {
1173 if (in_sight)
1174 pline("%s shudders for a moment.", Monnam(mtmp));
1175 return 0;
1177 get_level(&tolevel, nlev);
1180 if (in_sight) {
1181 pline("Suddenly, %s disappears out of sight.", mon_nam(mtmp));
1182 seetrap(trap);
1184 migrate_to_level(mtmp, ledger_no(&tolevel), migrate_typ, (coord *) 0);
1185 return 3; /* no longer on this level */
1187 return 0;
1190 /* place object randomly, returns False if it's gone (eg broken) */
1191 boolean
1192 rloco(obj)
1193 register struct obj *obj;
1195 register xchar tx, ty, otx, oty;
1196 boolean restricted_fall;
1197 int try_limit = 4000;
1199 if (obj->otyp == CORPSE && is_rider(&mons[obj->corpsenm])) {
1200 if (revive_corpse(obj))
1201 return FALSE;
1204 obj_extract_self(obj);
1205 otx = obj->ox;
1206 oty = obj->oy;
1207 restricted_fall = (otx == 0 && dndest.lx);
1208 do {
1209 tx = rn1(COLNO - 3, 2);
1210 ty = rn2(ROWNO);
1211 if (!--try_limit)
1212 break;
1213 } while (!goodpos(tx, ty, (struct monst *) 0, 0)
1214 || (restricted_fall
1215 && (!within_bounded_area(tx, ty, dndest.lx, dndest.ly,
1216 dndest.hx, dndest.hy)
1217 || (dndest.nlx
1218 && within_bounded_area(tx, ty,
1219 dndest.nlx, dndest.nly,
1220 dndest.nhx, dndest.nhy))))
1221 /* on the Wizard Tower levels, objects inside should
1222 stay inside and objects outside should stay outside */
1223 || (dndest.nlx && On_W_tower_level(&u.uz)
1224 && within_bounded_area(tx, ty, dndest.nlx, dndest.nly,
1225 dndest.nhx, dndest.nhy)
1226 != within_bounded_area(otx, oty, dndest.nlx, dndest.nly,
1227 dndest.nhx, dndest.nhy)));
1229 if (flooreffects(obj, tx, ty, "fall")) {
1230 return FALSE;
1231 } else if (otx == 0 && oty == 0) {
1232 ; /* fell through a trap door; no update of old loc needed */
1233 } else {
1234 if (costly_spot(otx, oty)
1235 && (!costly_spot(tx, ty)
1236 || !index(in_rooms(tx, ty, 0), *in_rooms(otx, oty, 0)))) {
1237 if (costly_spot(u.ux, u.uy)
1238 && index(u.urooms, *in_rooms(otx, oty, 0)))
1239 addtobill(obj, FALSE, FALSE, FALSE);
1240 else
1241 (void) stolen_value(obj, otx, oty, FALSE, FALSE);
1243 newsym(otx, oty); /* update old location */
1245 place_object(obj, tx, ty);
1246 newsym(tx, ty);
1247 return TRUE;
1250 /* Returns an absolute depth */
1252 random_teleport_level()
1254 int nlev, max_depth, min_depth, cur_depth = (int) depth(&u.uz);
1256 /* [the endgame case can only occur in wizard mode] */
1257 if (!rn2(5) || Is_knox(&u.uz) || In_endgame(&u.uz))
1258 return cur_depth;
1260 /* What I really want to do is as follows:
1261 * -- If in a dungeon that goes down, the new level is to be restricted
1262 * to [top of parent, bottom of current dungeon]
1263 * -- If in a dungeon that goes up, the new level is to be restricted
1264 * to [top of current dungeon, bottom of parent]
1265 * -- If in a quest dungeon or similar dungeon entered by portals,
1266 * the new level is to be restricted to [top of current dungeon,
1267 * bottom of current dungeon]
1268 * The current behavior is not as sophisticated as that ideal, but is
1269 * still better what we used to do, which was like this for players
1270 * but different for monsters for no obvious reason. Currently, we
1271 * must explicitly check for special dungeons. We check for Knox
1272 * above; endgame is handled in the caller due to its different
1273 * message ("disoriented").
1274 * --KAA
1275 * 3.4.2: explicitly handle quest here too, to fix the problem of
1276 * monsters sometimes level teleporting out of it into main dungeon.
1277 * Also prevent monsters reaching the Sanctum prior to invocation.
1279 if (In_quest(&u.uz)) {
1280 int bottom = dunlevs_in_dungeon(&u.uz),
1281 qlocate_depth = qlocate_level.dlevel;
1283 /* if hero hasn't reached the middle locate level yet,
1284 no one can randomly teleport past it */
1285 if (dunlev_reached(&u.uz) < qlocate_depth)
1286 bottom = qlocate_depth;
1287 min_depth = dungeons[u.uz.dnum].depth_start;
1288 max_depth = bottom + (dungeons[u.uz.dnum].depth_start - 1);
1289 } else {
1290 min_depth = 1;
1291 max_depth =
1292 dunlevs_in_dungeon(&u.uz) + (dungeons[u.uz.dnum].depth_start - 1);
1293 /* can't reach Sanctum if the invocation hasn't been performed */
1294 if (Inhell && !u.uevent.invoked)
1295 max_depth -= 1;
1298 /* Get a random value relative to the current dungeon */
1299 /* Range is 1 to current+3, current not counting */
1300 nlev = rn2(cur_depth + 3 - min_depth) + min_depth;
1301 if (nlev >= cur_depth)
1302 nlev++;
1304 if (nlev > max_depth) {
1305 nlev = max_depth;
1306 /* teleport up if already on bottom */
1307 if (Is_botlevel(&u.uz))
1308 nlev -= rnd(3);
1310 if (nlev < min_depth) {
1311 nlev = min_depth;
1312 if (nlev == cur_depth) {
1313 nlev += rnd(3);
1314 if (nlev > max_depth)
1315 nlev = max_depth;
1318 return nlev;
1321 /* you teleport a monster (via wand, spell, or poly'd q.mechanic attack);
1322 return false iff the attempt fails */
1323 boolean
1324 u_teleport_mon(mtmp, give_feedback)
1325 struct monst *mtmp;
1326 boolean give_feedback;
1328 coord cc;
1330 if (mtmp->ispriest && *in_rooms(mtmp->mx, mtmp->my, TEMPLE)) {
1331 if (give_feedback)
1332 pline("%s resists your magic!", Monnam(mtmp));
1333 return FALSE;
1334 } else if (level.flags.noteleport && u.uswallow && mtmp == u.ustuck) {
1335 if (give_feedback)
1336 You("are no longer inside %s!", mon_nam(mtmp));
1337 unstuck(mtmp);
1338 (void) rloc(mtmp, TRUE);
1339 } else if (is_rider(mtmp->data) && rn2(13)
1340 && enexto(&cc, u.ux, u.uy, mtmp->data))
1341 rloc_to(mtmp, cc.x, cc.y);
1342 else
1343 (void) rloc(mtmp, TRUE);
1344 return TRUE;
1347 /*teleport.c*/