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. */
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
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.
24 goodpos(x
, y
, mtmp
, gpflags
)
29 struct permonst
*mdat
= (struct permonst
*) 0;
30 boolean ignorewater
= ((gpflags
& MM_IGNOREWATER
) != 0);
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.
41 if (mtmp
!= &youmonst
&& x
== u
.ux
&& y
== u
.uy
42 && (!u
.usteed
|| mtmp
!= u
.usteed
))
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
))
62 if (is_pool(x
, y
) && !ignorewater
) {
63 if (mtmp
== &youmonst
)
64 return (Levitation
|| Flying
|| Wwalking
|| Swimming
67 return (is_floater(mdat
) || is_flyer(mdat
) || is_swimmer(mdat
)
69 } else if (mdat
->mlet
== S_EEL
&& rn2(13) && !ignorewater
) {
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
)));
78 return (is_floater(mdat
) || is_flyer(mdat
)
81 if (passes_walls(mdat
) && may_passwall(x
, y
))
83 if (amorphous(mdat
) && closed_door(x
, y
))
86 if (!accessible(x
, y
)) {
87 if (!(is_pool(x
, y
) && ignorewater
))
91 if (sobj_at(BOULDER
, x
, y
) && (!mdat
|| !throws_rocks(mdat
)))
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.
105 enexto(cc
, xx
, yy
, mdat
)
107 register xchar xx
, yy
;
108 struct permonst
*mdat
;
110 return enexto_core(cc
, xx
, yy
, mdat
, 0);
114 enexto_core(cc
, xx
, yy
, mdat
, entflags
)
116 register xchar xx
, yy
;
117 struct permonst
*mdat
;
121 coord good
[MAX_GOOD
], *good_ptr
;
123 int xmin
, xmax
, ymin
, ymax
;
124 struct monst fakemon
; /* dummy monster */
127 debugpline0("enexto() called with null mdat");
128 /* default to player's original monster type */
129 mdat
= &mons
[u
.umonster
];
132 set_mon_data(&fakemon
, mdat
, -1); /* set up for goodpos */
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.
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
)) {
150 /* beware of accessing beyond segment boundaries.. */
151 if (good_ptr
++ == &good
[MAX_GOOD
- 1])
154 for (x
= xmin
; x
<= xmax
; x
++)
155 if (goodpos(x
, ymax
, &fakemon
, entflags
)) {
158 /* beware of accessing beyond segment boundaries.. */
159 if (good_ptr
++ == &good
[MAX_GOOD
- 1])
162 for (y
= ymin
+ 1; y
< ymax
; y
++)
163 if (goodpos(xmin
, y
, &fakemon
, entflags
)) {
166 /* beware of accessing beyond segment boundaries.. */
167 if (good_ptr
++ == &good
[MAX_GOOD
- 1])
170 for (y
= ymin
+ 1; y
< ymax
; y
++)
171 if (goodpos(xmax
, y
, &fakemon
, entflags
)) {
174 /* beware of accessing beyond segment boundaries.. */
175 if (good_ptr
++ == &good
[MAX_GOOD
- 1])
180 /* return if we've grown too big (nothing is valid) */
181 if (range
> ROWNO
&& range
> COLNO
)
183 } while (good_ptr
== good
);
186 i
= rn2((int) (good_ptr
- good
));
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.)
198 tele_jump_ok(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
,
205 && !within_bounded_area(x2
, y2
, dndest
.nlx
, dndest
.nly
,
206 dndest
.nhx
, dndest
.nhy
))
208 /* and if outside, can't teleport inside */
209 if (!within_bounded_area(x1
, y1
, dndest
.nlx
, dndest
.nly
, dndest
.nhx
,
211 && within_bounded_area(x2
, y2
, dndest
.nlx
, dndest
.nly
, dndest
.nhx
,
215 if (updest
.nlx
> 0) { /* ditto */
216 if (within_bounded_area(x1
, y1
, updest
.nlx
, updest
.nly
, updest
.nhx
,
218 && !within_bounded_area(x2
, y2
, updest
.nlx
, updest
.nly
,
219 updest
.nhx
, updest
.nhy
))
221 if (!within_bounded_area(x1
, y1
, updest
.nlx
, updest
.nly
, updest
.nhx
,
223 && within_bounded_area(x2
, y2
, updest
.nlx
, updest
.nly
, updest
.nhx
,
235 if (!trapok
&& t_at(x
, y
))
237 if (!goodpos(x
, y
, &youmonst
, 0))
239 if (!tele_jump_ok(u
.ux
, u
.uy
, x
, y
))
241 if (!in_out_region(x
, y
))
247 teleds(nux
, nuy
, allow_drag
)
248 register int nux
, nuy
;
251 boolean ball_active
, ball_still_in_range
;
253 if (u
.utraptype
== TT_BURIEDBALL
) {
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
267 * _X move east -----> X_
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.
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 */
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.
294 if (!hideunder(&youmonst
) && youmonst
.data
->mlet
== S_MIMIC
) {
295 /* mimics stop being unnoticed */
296 youmonst
.m_ap_type
= M_AP_NOTHING
;
300 u
.uswldtim
= u
.uswallow
= 0;
301 if (Punished
&& !ball_active
) {
302 /* ensure ball placement, like unstuck */
309 if (ball_still_in_range
|| allow_drag
) {
311 xchar ballx
, bally
, chainx
, chainy
;
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
);
324 if (!ball_still_in_range
&& !allow_drag
)
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
);
337 vision_full_recalc
= 1;
339 vision_recalc(0); /* vision before effects */
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
);
347 telescroll
= 0; /* no discovery by scrolltele()'s caller */
350 invocation_message();
354 safe_teleds(allow_drag
)
357 register int nux
, nuy
, tcnt
= 0;
360 nux
= rnd(COLNO
- 1);
362 } while (!teleok(nux
, nuy
, (boolean
) (tcnt
> 200)) && ++tcnt
<= 400);
365 teleds(nux
, nuy
, allow_drag
);
374 register struct mkroom
*croom
= search_special(VAULT
);
377 if (croom
&& somexy(croom
, &c
) && teleok(c
.x
, c
.y
, FALSE
)) {
378 teleds(c
.x
, c
.y
, FALSE
);
385 teleport_pet(mtmp
, force_it
)
386 register struct monst
*mtmp
;
389 register struct obj
*otmp
;
391 if (mtmp
== u
.usteed
)
394 if (mtmp
->mleashed
) {
395 otmp
= get_mleash(mtmp
);
397 impossible("%s is leashed, without a leash.", Monnam(mtmp
));
400 if (otmp
->cursed
&& !force_it
) {
404 Your("leash goes slack.");
406 m_unleash(mtmp
, FALSE
);
413 /* teleport the hero via some method other than scroll of teleport */
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 */
429 boolean result
= FALSE
; /* don't learn scroll */
431 /* Disable teleportation in stronghold && Vlad's Tower */
432 if (level
.flags
.noteleport
) {
434 pline("A mysterious force prevents you from teleporting!");
439 /* don't show trap if "Sorry..." */
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')
448 if ((Teleport_control
&& !Stunned
) || wizard
) {
450 pline("Being unconscious, you cannot control your teleport.");
454 Strcpy(whobuf
, "you");
456 Sprintf(eos(whobuf
), " and %s", mon_nam(u
.usteed
));
457 pline("To what position do %s want to be teleported?", whobuf
);
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 */
468 teleds(cc
.x
, cc
.y
, FALSE
);
474 } else if (scroll
&& scroll
->blessed
) {
475 /* (this used to be handled in seffects()) */
476 if (yn("Do you wish to teleport?") == 'n')
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 */
487 telescroll
= 0; /* reset */
495 boolean trap_once
= FALSE
;
497 trap
= t_at(u
.ux
, u
.uy
);
498 if (trap
&& (!trap
->tseen
|| trap
->ttyp
!= TELEP_TRAP
))
502 trap_once
= trap
->once
; /* trap may get deleted, save this */
504 pline("This is a vault teleport, usable once only.");
505 if (yn("Jump in?") == 'n')
513 You("%s onto the teleportation trap.",
514 locomotion(youmonst
.data
, "jump"));
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
) {
532 You("don't know that spell.");
534 You("are not able to teleport at will.");
540 if (u
.uhunger
<= 100 || ACURR(A_STR
) < 6) {
542 You("lack the strength %s.",
543 castit
? "for a teleport spell" : "to teleport");
548 energy
= objects
[SPE_TELEPORT_AWAY
].oc_level
* 7 / 2 - 2;
549 if (u
.uen
<= energy
) {
553 You("lack the energy %s.",
554 castit
? "for a teleport spell" : "to teleport");
560 "Your concentration falters from carrying so much."))
564 exercise(A_WIS
, TRUE
);
565 if (spelleffects(sp_no
, TRUE
))
576 if (trap
&& trap_once
)
582 You1(shudder_for_moment
);
595 const char *escape_by_flying
= 0; /* when surviving dest of -N */
597 boolean force_dest
= FALSE
;
599 if ((u
.uhave
.amulet
|| In_endgame(&u
.uz
) || In_sokoban(&u
.uz
))
601 You_feel("very disoriented for a moment.");
604 if ((Teleport_control
&& !Stunned
) || wizard
) {
608 Strcpy(qbuf
, "To what level do you want to teleport?");
612 Strcat(qbuf
, " [type a number or ? for a menu]");
614 Strcat(qbuf
, " [type a number]");
617 if (!strcmp(buf
, "\033")) { /* cancelled */
618 if (Confusion
&& rnl(5)) {
620 goto random_levtport
;
623 } else if (!strcmp(buf
, "*")) {
624 goto random_levtport
;
625 } else if (Confusion
&& rnl(5)) {
627 goto random_levtport
;
629 if (wizard
&& !strcmp(buf
, "?")) {
633 newlev
= (int) print_dungeon(TRUE
, &destlev
, &destdnum
);
637 newlevel
.dnum
= destdnum
;
638 newlevel
.dlevel
= destlev
;
639 if (In_endgame(&newlevel
) && !In_endgame(&u
.uz
)) {
643 && (amu
= mksobj(AMULET_OF_YENDOR
, TRUE
, FALSE
))
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 */
649 prinv("Endgame prerequisite:", amu
, 0L);
653 } else if ((newlev
= lev_by_name(buf
)) == 0)
655 } while (!newlev
&& !digit(buf
[0])
656 && (buf
[0] != '-' || !digit(buf
[1])) && trycnt
< 10);
658 /* no dungeon escape via this route */
661 goto random_levtport
;
662 if (ynq("Go to Nowhere. Are you sure?") != 'y')
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.");
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");
674 pline("An energized cloud of dust begins to coalesce.");
675 Your("body rematerializes%s.",
676 invent
? ", and you gather up all your possessions" : "");
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
);
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 */
699 newlev
= random_teleport_level();
700 if (newlev
== depth(&u
.uz
)) {
701 You1(shudder_for_moment
);
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
);
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.");
720 newlevel
.dnum
= u
.uz
.dnum
;
721 newlevel
.dlevel
= llimit
+ newlev
;
722 schedule_goto(&newlevel
, FALSE
, FALSE
, 0, (char *) 0, (char *) 0);
726 killer
.name
[0] = 0; /* still alive, so far... */
728 if (newlev
< 0 && !force_dest
) {
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';
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
);
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";
754 escape_by_flying
= "fly down to the ground";
756 pline("Unfortunately, you don't know how to fly.");
757 You("plummet a few thousand feet to your death.");
759 "teleported out of the dungeon and fell to %s death",
761 killer
.format
= NO_KILLER_PREFIX
;
765 if (killer
.name
[0]) { /* the chosen destination was not survivable */
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 */
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
);
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;
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
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
)
822 register struct trap
*ttmp
;
824 struct d_level target_level
;
826 if (u
.utrap
&& u
.utraptype
== TT_BURIEDBALL
)
827 buried_ball_to_punishment();
830 You1(shudder_for_moment
);
834 /* if landed from another portal, do nothing */
835 /* problem: level teleport landing escapes the check */
836 if (!on_level(&u
.uz
, &u
.uz0
))
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...");
850 target_level
= ttmp
->dst
;
851 schedule_goto(&target_level
, FALSE
, FALSE
, 1,
852 "You feel dizzy for a moment, but the sensation passes.",
860 if (In_endgame(&u
.uz
) || 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
) {
868 newsym(u
.ux
, u
.uy
); /* get rid of trap symbol */
875 level_tele_trap(trap
)
878 You("%s onto a level teleport trap!",
879 Levitation
? (const char *) "float"
880 : locomotion(youmonst
.data
, "step"));
882 shieldeff(u
.ux
, u
.uy
);
884 if (Antimagic
|| In_endgame(&u
.uz
)) {
885 You_feel("a wrenching sensation.");
889 You("are momentarily blinded by a flash of light.");
891 You("are momentarily disoriented.");
893 newsym(u
.ux
, u
.uy
); /* get rid of trap symbol */
897 /* check whether monster can arrive at location <x,y> via Tport (or fall) */
899 rloc_pos_ok(x
, y
, mtmp
)
900 register int x
, y
; /* coordinates of candidate location */
905 if (!goodpos(x
, y
, mtmp
, 0))
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.
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
)
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
)
933 || !within_bounded_area(x
, y
, dndest
.nlx
, dndest
.nly
,
934 dndest
.nhx
, dndest
.nhy
)));
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
)
942 } else if (mtmp
->ispriest
&& inhistemple(mtmp
)) {
943 if (levl
[x
][y
].roomno
!= EPRI(mtmp
)->shroom
)
946 /* current location is <xx,yy> */
947 if (!tele_jump_ok(xx
, yy
, x
, y
))
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.
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 */
974 if (oldx
) { /* "pick up" monster */
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
) {
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 */
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
) {
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
;
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))
1039 x
= rn1(COLNO
- 3, 2);
1041 if ((trycount
< 500) ? rloc_pos_ok(x
, y
, mtmp
)
1042 : goodpos(x
, y
, mtmp
, 0))
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))
1052 /* level either full of monsters or somehow faulty */
1053 if (!suppress_impossible
)
1054 impossible("rloc(): couldn't relocate monster");
1058 rloc_to(mtmp
, x
, y
);
1066 register struct mkroom
*croom
= search_special(VAULT
);
1069 if (croom
&& somexy(croom
, &c
) && goodpos(c
.x
, c
.y
, mtmp
, 0)) {
1070 rloc_to(mtmp
, c
.x
, c
.y
);
1073 (void) rloc(mtmp
, TRUE
);
1080 if (level
.flags
.noteleport
) {
1082 pline("A mysterious force prevents %s from teleporting!",
1090 mtele_trap(mtmp
, trap
, in_sight
)
1097 if (tele_restrict(mtmp
))
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...
1110 (void) rloc(mtmp
, TRUE
);
1113 if (canseemon(mtmp
))
1114 pline("%s seems disoriented.", monname
);
1116 pline("%s suddenly disappears!", monname
);
1122 /* return 0 if still on level, 3 if not */
1124 mlevel_tele_trap(mtmp
, trap
, force_it
, 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
)) {
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");
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
));
1159 assign_level(&tolevel
, &trap
->dst
);
1160 migrate_typ
= MIGR_PORTAL
;
1162 } else { /* (tt == LEVEL_TELEP) */
1165 if (mon_has_amulet(mtmp
) || In_endgame(&u
.uz
)) {
1167 pline("%s seems very disoriented for a moment.",
1171 nlev
= random_teleport_level();
1172 if (nlev
== depth(&u
.uz
)) {
1174 pline("%s shudders for a moment.", Monnam(mtmp
));
1177 get_level(&tolevel
, nlev
);
1181 pline("Suddenly, %s disappears out of sight.", mon_nam(mtmp
));
1184 migrate_to_level(mtmp
, ledger_no(&tolevel
), migrate_typ
, (coord
*) 0);
1185 return 3; /* no longer on this level */
1190 /* place object randomly, returns False if it's gone (eg broken) */
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
))
1204 obj_extract_self(obj
);
1207 restricted_fall
= (otx
== 0 && dndest
.lx
);
1209 tx
= rn1(COLNO
- 3, 2);
1213 } while (!goodpos(tx
, ty
, (struct monst
*) 0, 0)
1215 && (!within_bounded_area(tx
, ty
, dndest
.lx
, dndest
.ly
,
1216 dndest
.hx
, dndest
.hy
)
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")) {
1231 } else if (otx
== 0 && oty
== 0) {
1232 ; /* fell through a trap door; no update of old loc needed */
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
);
1241 (void) stolen_value(obj
, otx
, oty
, FALSE
, FALSE
);
1243 newsym(otx
, oty
); /* update old location */
1245 place_object(obj
, tx
, ty
);
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
))
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").
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);
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
)
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
)
1304 if (nlev
> max_depth
) {
1306 /* teleport up if already on bottom */
1307 if (Is_botlevel(&u
.uz
))
1310 if (nlev
< min_depth
) {
1312 if (nlev
== cur_depth
) {
1314 if (nlev
> max_depth
)
1321 /* you teleport a monster (via wand, spell, or poly'd q.mechanic attack);
1322 return false iff the attempt fails */
1324 u_teleport_mon(mtmp
, give_feedback
)
1326 boolean give_feedback
;
1330 if (mtmp
->ispriest
&& *in_rooms(mtmp
->mx
, mtmp
->my
, TEMPLE
)) {
1332 pline("%s resists your magic!", Monnam(mtmp
));
1334 } else if (level
.flags
.noteleport
&& u
.uswallow
&& mtmp
== u
.ustuck
) {
1336 You("are no longer inside %s!", mon_nam(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
);
1343 (void) rloc(mtmp
, TRUE
);