1 /*	SCCS Id: @(#)teleport.c	3.4	2003/08/11	*/
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed.  See license for details. */
4 
5 #include "hack.h"
6 
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 *));
12 
13 /*
14  * Is (x, y) a bad position of mtmp?  If mtmp is NULL, then is (x, y) bad
15  * for an object?
16  *
17  * Caller is responsible for checking (x, y) with isok() if required.
18  *
19  * Returns: -1: Inaccessible, 0: Good pos, 1: Temporally inacessible
20  */
21 static int
badpos(x,y,mtmp,gpflags)22 badpos(x, y, mtmp, gpflags)
23 int x, y;
24 struct monst *mtmp;
25 unsigned gpflags;
26 {
27 	int is_badpos = 0, pool;
28 	struct permonst *mdat = NULL;
29 	boolean ignorewater = ((gpflags & MM_IGNOREWATER) != 0);
30 	struct monst *mtmp2;
31 
32 	/* in many cases, we're trying to create a new monster, which
33 	 * can't go on top of the player or any existing monster.
34 	 * however, occasionally we are relocating engravings or objects,
35 	 * which could be co-located and thus get restricted a bit too much.
36 	 * oh well.
37 	 */
38 	if (mtmp != &youmonst && x == u.ux && y == u.uy
39 #ifdef STEED
40 			&& (!u.usteed || mtmp != u.usteed)
41 #endif
42 			)
43 	    is_badpos = 1;
44 
45 	if (mtmp) {
46 	    mtmp2 = m_at(x,y);
47 
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.
57 	     */
58 	    if (mtmp2 && (mtmp2 != mtmp || mtmp->wormno))
59 		is_badpos = 1;
60 
61 	    mdat = mtmp->data;
62 	    pool = is_pool(x,y);
63 	    if (mdat->mlet == S_EEL && !pool && rn2(13) && !ignorewater)
64 		is_badpos = 1;
65 
66 	    if (pool && !ignorewater) {
67 		if (mtmp == &youmonst)
68 			return (HLevitation || Flying || Wwalking ||
69 				    Swimming || Amphibious) ? is_badpos : -1;
70 		else	return (is_flyer(mdat) || is_swimmer(mdat) ||
71 				    is_clinger(mdat)) ? is_badpos : -1;
72 	    } else if (is_lava(x,y)) {
73 		if (mtmp == &youmonst)
74 		    return HLevitation ? is_badpos : -1;
75 		else
76 		    return (is_flyer(mdat) || likes_lava(mdat)) ?
77 			    is_badpos : -1;
78 	    }
79 	    if (passes_walls(mdat) && may_passwall(x,y)) return is_badpos;
80 	}
81 	if (!ACCESSIBLE(levl[x][y].typ)) {
82 		if (!(is_pool(x,y) && ignorewater)) return -1;
83 	}
84 
85 	if (closed_door(x, y) && (!mdat || !amorphous(mdat)))
86 	    return mdat && (nohands(mdat) || verysmall(mdat)) ? -1 : 1;
87 	if (sobj_at(BOULDER, x, y) && (!mdat || !throws_rocks(mdat)))
88 	    return mdat ? -1 : 1;
89 	return is_badpos;
90 }
91 
92 /*
93  * Is (x,y) a good position of mtmp?  If mtmp is NULL, then is (x,y) good
94  * for an object?
95  *
96  * This function will only look at mtmp->mdat, so makemon, mplayer, etc can
97  * call it to generate new monster positions with fake monster structures.
98  */
99 boolean
goodpos(x,y,mtmp,gpflags)100 goodpos(x, y, mtmp, gpflags)
101 int x,y;
102 struct monst *mtmp;
103 unsigned gpflags;
104 {
105     if (!isok(x, y)) return FALSE;
106 
107     return !badpos(x, y, mtmp, gpflags);
108 }
109 
110 /*
111  * "entity next to"
112  *
113  * Attempt to find a good place for the given monster type in the closest
114  * position to (xx,yy).  Do so in successive square rings around (xx,yy).
115  * If there is more than one valid positon in the ring, choose one randomly.
116  * Return TRUE and the position chosen when successful, FALSE otherwise.
117  */
118 boolean
enexto(cc,xx,yy,mdat)119 enexto(cc, xx, yy, mdat)
120 coord *cc;
121 register xchar xx, yy;
122 struct permonst *mdat;
123 {
124 	return enexto_core(cc, xx, yy, mdat, 0);
125 }
126 
127 boolean
enexto_core(cc,xx,yy,mdat,entflags)128 enexto_core(cc, xx, yy, mdat, entflags)
129 coord *cc;
130 register xchar xx, yy;
131 struct permonst *mdat;
132 unsigned entflags;
133 {
134 #define MAX_GOOD 15
135     coord good[MAX_GOOD], *good_ptr;
136     int x, y, range, i;
137     int xmin, xmax, ymin, ymax;
138     struct monst fakemon;	/* dummy monster */
139 
140     if (!mdat) {
141 #ifdef DEBUG
142 	pline("enexto() called with mdat==0");
143 #endif
144 	/* default to player's original monster type */
145 	mdat = &mons[u.umonster];
146     }
147     fakemon.data = mdat;	/* set up for goodpos */
148     good_ptr = good;
149     range = 1;
150     /*
151      * Walk around the border of the square with center (xx,yy) and
152      * radius range.  Stop when we find at least one valid position.
153      */
154     do {
155 	xmin = max(1, xx-range);
156 	xmax = min(COLNO-1, xx+range);
157 	ymin = max(0, yy-range);
158 	ymax = min(ROWNO-1, yy+range);
159 
160 	for (x = xmin; x <= xmax; x++)
161 	    if (goodpos(x, ymin, &fakemon, entflags)) {
162 		good_ptr->x = x;
163 		good_ptr->y = ymin ;
164 		/* beware of accessing beyond segment boundaries.. */
165 		if (good_ptr++ == &good[MAX_GOOD-1]) goto full;
166 	    }
167 	for (x = xmin; x <= xmax; x++)
168 	    if (goodpos(x, ymax, &fakemon, entflags)) {
169 		good_ptr->x = x;
170 		good_ptr->y = ymax ;
171 		/* beware of accessing beyond segment boundaries.. */
172 		if (good_ptr++ == &good[MAX_GOOD-1]) goto full;
173 	    }
174 	for (y = ymin+1; y < ymax; y++)
175 	    if (goodpos(xmin, y, &fakemon, entflags)) {
176 		good_ptr->x = xmin;
177 		good_ptr-> y = y ;
178 		/* beware of accessing beyond segment boundaries.. */
179 		if (good_ptr++ == &good[MAX_GOOD-1]) goto full;
180 	    }
181 	for (y = ymin+1; y < ymax; y++)
182 	    if (goodpos(xmax, y, &fakemon, entflags)) {
183 		good_ptr->x = xmax;
184 		good_ptr->y = y ;
185 		/* beware of accessing beyond segment boundaries.. */
186 		if (good_ptr++ == &good[MAX_GOOD-1]) goto full;
187 	    }
188 	range++;
189 
190 	/* return if we've grown too big (nothing is valid) */
191 	if (range > ROWNO && range > COLNO) return FALSE;
192     } while (good_ptr == good);
193 
194 full:
195     i = rn2((int)(good_ptr - good));
196     cc->x = good[i].x;
197     cc->y = good[i].y;
198     return TRUE;
199 }
200 
201 /*
202  * "entity path to"
203  *
204  * Attempt to find nc good places for the given monster type with the shortest
205  * path to (xx,yy).  Where there is more than one valid set of positions, one
206  * will be chosen at random.  Return the number of positions found.
207  * Warning:  This routine is much slower than enexto and should be used
208  * with caution.
209  */
210 
211 #define EPATHTO_UNSEEN		0x0
212 #define EPATHTO_INACCESSIBLE	0x1
213 #define EPATHTO_DONE		0x2
214 #define EPATHTO_TAIL(n)		(0x3 + ((n) & 1))
215 
216 #define EPATHTO_XY(x,y)		(((y) + 1) * COLNO + (x))
217 #define EPATHTO_Y(xy)		((xy) / COLNO - 1)
218 #define EPATHTO_X(xy)		((xy) % COLNO)
219 
220 #ifdef DEBUG
221 coord epathto_debug_cc[100];
222 #endif
223 
224 int
epathto(cc,nc,xx,yy,mdat)225 epathto(cc, nc, xx, yy, mdat)
226 coord *cc;
227 int nc;
228 register xchar xx, yy;
229 struct permonst *mdat;
230 {
231     int i, j, dir, ndirs, xy, x, y, r;
232     int path_len, postype;
233     int first_col, last_col;
234     int nd, n;
235     unsigned char *map;
236     static const int dirs[8] =
237       /* N, S, E, W, NW, NE, SE, SW */
238       { -COLNO, COLNO, 1, -1, -COLNO-1, -COLNO+1, COLNO+1, COLNO-1};
239     struct monst fakemon;	/* dummy monster */
240     fakemon.data = mdat;	/* set up for badpos */
241     map = (unsigned char *)alloc(COLNO * (ROWNO + 2));
242     (void) memset((genericptr_t)map, EPATHTO_INACCESSIBLE, COLNO * (ROWNO + 2));
243     for(i = 1; i < COLNO; i++)
244 	for(j = 0; j < ROWNO; j++)
245 	    map[EPATHTO_XY(i, j)] = EPATHTO_UNSEEN;
246     map[EPATHTO_XY(xx, yy)] = EPATHTO_TAIL(0);
247     if (badpos(xx, yy, &fakemon, 0) == 0) {
248 	cc[0].x = xx;
249 	cc[0].y = yy;
250 	nd = n = 1;
251     }
252     else
253 	nd = n = 0;
254     for(path_len = 0; nd < nc; path_len++)
255     {
256 	first_col = max(1, xx - path_len);
257 	last_col = min(COLNO - 1, xx + path_len);
258 	for(j = max(0, yy - path_len); j <= min(ROWNO - 1, yy + path_len); j++)
259 	    for(i = first_col; i <= last_col; i++)
260 		if (map[EPATHTO_XY(i, j)] == EPATHTO_TAIL(path_len)) {
261 		    map[EPATHTO_XY(i, j)] = EPATHTO_DONE;
262 		    ndirs = mdat == &mons[PM_GRID_BUG] ? 4 : 8;
263 		    for(dir = 0; dir < ndirs; dir++) {
264 			xy = EPATHTO_XY(i, j) + dirs[dir];
265 			if (map[xy] == EPATHTO_UNSEEN) {
266 			    x = EPATHTO_X(xy);
267 			    y = EPATHTO_Y(xy);
268 			    postype = badpos(x, y, &fakemon, 0);
269 			    map[xy] = postype < 0 ? EPATHTO_INACCESSIBLE :
270 				    EPATHTO_TAIL(path_len + 1);
271 			    if (postype == 0) {
272 				if (n < nc)
273 				{
274 				    cc[n].x = x;
275 				    cc[n].y = y;
276 				}
277 				else if (rn2(n - nd + 1) < nc - nd)
278 				{
279 				    r = rn2(nc - nd) + nd;
280 				    cc[r].x = x;
281 				    cc[r].y = y;
282 				}
283 				++n;
284 			    }
285 			}
286 		    }
287 		}
288 	if (nd == n)
289 	    break;	/* No more positions */
290 	else
291 	    nd = n;
292     }
293     if (nd > nc)
294 	nd = nc;
295 #ifdef DEBUG
296     if (cc == epathto_debug_cc)
297     {
298 	winid win;
299 	int glyph;
300 	char row[COLNO+1];
301 
302 	win = create_nhwindow(NHW_TEXT);
303 	putstr(win, 0, "");
304 	for (y = 0; y < ROWNO; y++) {
305 	    for (x = 1; x < COLNO; x++) {
306 		xy = EPATHTO_XY(x, y);
307 		if (map[xy] == EPATHTO_INACCESSIBLE) {
308 		    glyph = back_to_glyph(x, y);
309 		    row[x] = showsyms[glyph_to_cmap(glyph)];
310 		}
311 		else
312 		    row[x] = ' ';
313 	    }
314 	    for (i = 0; i < nd; i++)
315 		if (cc[i].y == y)
316 		    row[cc[i].x] = i < 10 ? '0' + i :
317 			i < 36 ? 'a' + i - 10 :
318 			i < 62 ? 'A' + i - 36 :
319 			'?';
320 	    /* remove trailing spaces */
321 	    for (x = COLNO-1; x >= 1; x--)
322 		if (row[x] != ' ') break;
323 	    row[x+1] = '\0';
324 
325 	    putstr(win, 0, &row[1]);
326 	}
327 	display_nhwindow(win, TRUE);
328 	destroy_nhwindow(win);
329     }
330 #endif
331 
332     free((genericptr_t)map);
333     return nd;
334 }
335 
336 /*
337  * func should return 1 if the location should be counted as inaccessible
338  * (path won't continue through this point) or 0 if it is accessible.
339  */
340 
341 void
xpathto(r,xx,yy,func,data)342 xpathto(r, xx, yy, func, data)
343 int r;
344 register xchar xx, yy;
345 int (*func)(genericptr_t, int, int);
346 genericptr_t data;
347 {
348     int i, j, dir, xy, x, y;
349     int path_len, postype;
350     int first_col, last_col;
351     int nd, n;
352     unsigned char *map;
353     static const int dirs[8] =
354       /* N, S, E, W, NW, NE, SE, SW */
355       { -COLNO, COLNO, 1, -1, -COLNO-1, -COLNO+1, COLNO+1, COLNO-1};
356     map = (unsigned char *)alloc(COLNO * (ROWNO + 2));
357     (void) memset((genericptr_t)map, EPATHTO_INACCESSIBLE, COLNO * (ROWNO + 2));
358     for(i = 1; i < COLNO; i++)
359 	for(j = 0; j < ROWNO; j++)
360 	    map[EPATHTO_XY(i, j)] = EPATHTO_UNSEEN;
361     map[EPATHTO_XY(xx, yy)] = EPATHTO_TAIL(0);
362     if (func(data, xx, yy) == 0)
363 	nd = n = 1;
364     else
365 	nd = n = 0;
366     for(path_len = 0; path_len < r; path_len++)
367     {
368 	first_col = max(1, xx - path_len);
369 	last_col = min(COLNO - 1, xx + path_len);
370 	for(j = max(0, yy - path_len); j <= min(ROWNO - 1, yy + path_len); j++)
371 	    for(i = first_col; i <= last_col; i++)
372 		if (map[EPATHTO_XY(i, j)] == EPATHTO_TAIL(path_len)) {
373 		    map[EPATHTO_XY(i, j)] = EPATHTO_DONE;
374 		    for(dir = 0; dir < 8; dir++) {
375 			xy = EPATHTO_XY(i, j) + dirs[dir];
376 			if (map[xy] == EPATHTO_UNSEEN) {
377 			    x = EPATHTO_X(xy);
378 			    y = EPATHTO_Y(xy);
379 			    postype = func(data, x, y);
380 			    map[xy] = postype ? EPATHTO_INACCESSIBLE :
381 				    EPATHTO_TAIL(path_len + 1);
382 			    if (postype == 0)
383 				++n;
384 			}
385 		    }
386 		}
387 	if (nd == n)
388 	    break;	/* No more positions */
389 	else
390 	    nd = n;
391     }
392     free((genericptr_t)map);
393 }
394 
395 #ifdef DEBUG
396 void
wiz_debug_cmd()397 wiz_debug_cmd() /* in this case, run epathto on arbitary monster & goal */
398 {
399     struct permonst *ptr;
400     int mndx, i;
401     coord cc;
402     char buf[BUFSIZ];
403     for(i = 0; ; i++) {
404 	if(i >= 5) {
405 	    pline(thats_enough_tries);
406 	    return;
407 	}
408 	getlin("What monster do you want to test? [type the name]", buf);
409 
410 	mndx = name_to_mon(buf);
411 	if (mndx == NON_PM) {
412 	    pline("Such creatures do not exist in this world.");
413 	    continue;
414 	}
415 	ptr = &mons[mndx];
416 	pline("Which position do you want to aim for?");
417 	cc.x = u.ux;
418 	cc.y = u.uy;
419 	if (getpos(&cc, TRUE, "the goal position") < 0)
420 	    return;	/* abort */
421 	epathto(epathto_debug_cc, SIZE(epathto_debug_cc), cc.x, cc.y, ptr);
422 	break;
423     }
424 }
425 #endif	/* DEBUG */
426 
427 /*
428  * Check for restricted areas present in some special levels.  (This might
429  * need to be augmented to allow deliberate passage in wizard mode, but
430  * only for explicitly chosen destinations.)
431  */
432 STATIC_OVL boolean
tele_jump_ok(x1,y1,x2,y2)433 tele_jump_ok(x1, y1, x2, y2)
434 int x1, y1, x2, y2;
435 {
436 	if (dndest.nlx > 0) {
437 	    /* if inside a restricted region, can't teleport outside */
438 	    if (within_bounded_area(x1, y1, dndest.nlx, dndest.nly,
439 						dndest.nhx, dndest.nhy) &&
440 		!within_bounded_area(x2, y2, dndest.nlx, dndest.nly,
441 						dndest.nhx, dndest.nhy))
442 # ifdef WIZARD
443                 if (!wizard)
444 # endif /* WIZARD */
445 		return FALSE;
446 	    /* and if outside, can't teleport inside */
447 	    if (!within_bounded_area(x1, y1, dndest.nlx, dndest.nly,
448 						dndest.nhx, dndest.nhy) &&
449 		within_bounded_area(x2, y2, dndest.nlx, dndest.nly,
450 						dndest.nhx, dndest.nhy))
451 # ifdef WIZARD
452                 if (!wizard)
453 # endif /* WIZARD */
454 		return FALSE;
455 	}
456 	if (updest.nlx > 0) {		/* ditto */
457 	    if (within_bounded_area(x1, y1, updest.nlx, updest.nly,
458 						updest.nhx, updest.nhy) &&
459 		!within_bounded_area(x2, y2, updest.nlx, updest.nly,
460 						updest.nhx, updest.nhy))
461 # ifdef WIZARD
462                 if (!wizard)
463 # endif /* WIZARD */
464 		return FALSE;
465 	    if (!within_bounded_area(x1, y1, updest.nlx, updest.nly,
466 						updest.nhx, updest.nhy) &&
467 		within_bounded_area(x2, y2, updest.nlx, updest.nly,
468 						updest.nhx, updest.nhy))
469 # ifdef WIZARD
470                 if (!wizard)
471 # endif /* WIZARD */
472 		return FALSE;
473 	}
474 	return TRUE;
475 }
476 
477 STATIC_OVL boolean
teleok(x,y,trapok)478 teleok(x, y, trapok)
479 register int x, y;
480 boolean trapok;
481 {
482 	if (!trapok && t_at(x, y)) return FALSE;
483 	if (!goodpos(x, y, &youmonst, 0)) return FALSE;
484 	if (!tele_jump_ok(u.ux, u.uy, x, y)) return FALSE;
485 	if (!in_out_region(x, y)) return FALSE;
486 	return TRUE;
487 }
488 
489 void
teleds(nux,nuy,allow_drag)490 teleds(nux, nuy, allow_drag)
491 register int nux,nuy;
492 boolean allow_drag;
493 {
494 	boolean ball_active = (Punished && uball->where != OBJ_FREE),
495 		ball_still_in_range = FALSE;
496 
497 	/* If they have to move the ball, then drag if allow_drag is true;
498 	 * otherwise they are teleporting, so unplacebc().
499 	 * If they don't have to move the ball, then always "drag" whether or
500 	 * not allow_drag is true, because we are calling that function, not
501 	 * to drag, but to move the chain.  *However* there are some dumb
502 	 * special cases:
503 	 *    0                          0
504 	 *   _X  move east       ----->  X_
505 	 *    @                           @
506 	 * These are permissible if teleporting, but not if dragging.  As a
507 	 * result, drag_ball() needs to know about allow_drag and might end
508 	 * up dragging the ball anyway.  Also, drag_ball() might find that
509 	 * dragging the ball is completely impossible (ball in range but there's
510 	 * rock in the way), in which case it teleports the ball on its own.
511 	 */
512 	if (ball_active) {
513 	    if (!carried(uball) && distmin(nux, nuy, uball->ox, uball->oy) <= 2)
514 		ball_still_in_range = TRUE; /* don't have to move the ball */
515 	    else {
516 		/* have to move the ball */
517 		if (!allow_drag || distmin(u.ux, u.uy, nux, nuy) > 1) {
518 		    /* we should not have dist > 1 and allow_drag at the same
519 		     * time, but just in case, we must then revert to teleport.
520 		     */
521 		    allow_drag = FALSE;
522 		    unplacebc();
523 		}
524 	    }
525 	}
526 	u.utrap = 0;
527 	setustuck(0);
528 	u.ux0 = u.ux;
529 	u.uy0 = u.uy;
530 
531 	if (hides_under(youmonst.data))
532 		u.uundetected = OBJ_AT(nux, nuy);
533 	else if (youmonst.data->mlet == S_EEL)
534 		u.uundetected = is_pool(nux, nuy);
535 	else {
536 		u.uundetected = 0;
537 		/* mimics stop being unnoticed */
538 		if (youmonst.data->mlet == S_MIMIC)
539 		    youmonst.m_ap_type = M_AP_NOTHING;
540 	}
541 
542 	if (u.uswallow) {
543 		u.uswldtim = u.uswallow = 0;
544 		if (Punished && !ball_active) {
545 		    /* ensure ball placement, like unstuck */
546 		    ball_active = TRUE;
547 		    allow_drag = FALSE;
548 		}
549 		docrt();
550 	}
551 	if (ball_active) {
552 	    if (ball_still_in_range || allow_drag) {
553 		int bc_control;
554 		xchar ballx, bally, chainx, chainy;
555 		boolean cause_delay;
556 
557 		if (drag_ball(nux, nuy, &bc_control, &ballx, &bally,
558 				    &chainx, &chainy, &cause_delay, allow_drag))
559 		    move_bc(0, bc_control, ballx, bally, chainx, chainy);
560 	    }
561 	}
562 	/* must set u.ux, u.uy after drag_ball(), which may need to know
563 	   the old position if allow_drag is true... */
564 	u.ux = nux;
565 	u.uy = nuy;
566 	fill_pit(u.ux0, u.uy0);
567 	if (ball_active) {
568 	    if (!ball_still_in_range && !allow_drag)
569 		placebc();
570 	}
571 	initrack(); /* teleports mess up tracking monsters without this */
572 	update_player_regions();
573 #ifdef STEED
574 	/* Move your steed, too */
575 	if (u.usteed) {
576 		u.usteed->mx = nux;
577 		u.usteed->my = nuy;
578 	}
579 #endif
580 
581 	/*
582 	 *  Make sure the hero disappears from the old location.  This will
583 	 *  not happen if she is teleported within sight of her previous
584 	 *  location.  Force a full vision recalculation because the hero
585 	 *  is now in a new location.
586 	 */
587 	newsym(u.ux0,u.uy0);
588 	see_monsters();
589 	vision_full_recalc = 1;
590 	nomul(0);
591 	vision_recalc(0);	/* vision before effects */
592 	spoteffects(TRUE);
593 	invocation_message();
594 }
595 
596 boolean
safe_teleds(allow_drag)597 safe_teleds(allow_drag)
598 boolean allow_drag;
599 {
600 	register int nux, nuy, tcnt = 0;
601 
602 	do {
603 		nux = rnd(COLNO-1);
604 		nuy = rn2(ROWNO);
605 	} while (!teleok(nux, nuy, (boolean)(tcnt > 200)) && ++tcnt <= 400);
606 
607 	if (tcnt <= 400) {
608 		teleds(nux, nuy, allow_drag);
609 		return TRUE;
610 	} else
611 		return FALSE;
612 }
613 
614 STATIC_OVL void
vault_tele()615 vault_tele()
616 {
617 	register struct mkroom *croom = search_special(VAULT);
618 	coord c;
619 
620 	if (croom && somexy(croom, &c) && teleok(c.x,c.y,FALSE)) {
621 		teleds(c.x,c.y,FALSE);
622 		return;
623 	}
624 	tele();
625 }
626 
627 boolean
teleport_pet(mtmp,force_it)628 teleport_pet(mtmp, force_it)
629 register struct monst *mtmp;
630 boolean force_it;
631 {
632 	register struct obj *otmp;
633 
634 #ifdef STEED
635 	if (mtmp == u.usteed)
636 		return (FALSE);
637 #endif
638 
639 	if (mtmp->mleashed) {
640 	    otmp = get_mleash(mtmp);
641 	    if (!otmp) {
642 		impossible("%s is leashed, without a leash.", Monnam(mtmp));
643 		goto release_it;
644 	    }
645 	    if (otmp->cursed && !force_it) {
646 		yelp(mtmp);
647 		return FALSE;
648 	    } else {
649 		Your("leash goes slack.");
650  release_it:
651 		m_unleash(mtmp, FALSE);
652 		return TRUE;
653 	    }
654 	}
655 	return TRUE;
656 }
657 
658 void
tele()659 tele()
660 {
661 	coord cc;
662 
663 	/* Disable teleportation in stronghold && Vlad's Tower */
664 	if (level.flags.noteleport) {
665 #ifdef WIZARD
666 		if (!wizard) {
667 #endif
668 		    pline("A mysterious force prevents you from teleporting!");
669 		    return;
670 #ifdef WIZARD
671 		}
672 #endif
673 	}
674 
675 	/* don't show trap if "Sorry..." */
676 	if (!Blinded) make_blinded(0L,FALSE);
677 
678 	if
679 #ifdef WIZARD
680         (
681 #endif
682         (u.uhave.amulet || On_W_tower_level(&u.uz)
683 #ifdef STEED
684 	|| (u.usteed && mon_has_amulet(u.usteed))
685 #endif
686 	)
687 #ifdef WIZARD
688         && (!wizard) )
689 #endif
690 	{
691 	    You_feel("disoriented for a moment.");
692 	    return;
693 	}
694 	if ((Teleport_control && !Stunned)
695 #ifdef WIZARD
696 			    || wizard
697 #endif
698 					) {
699 	    if (unconscious()) {
700 		pline("Being unconscious, you cannot control your teleport.");
701 	    } else {
702 #ifdef STEED
703 		    char buf[BUFSZ];
704 		    if (u.usteed) Sprintf(buf," and %s", mon_nam(u.usteed));
705 #endif
706 		    pline("To what position do you%s want to be teleported?",
707 #ifdef STEED
708 				u.usteed ? buf :
709 #endif
710 			   "");
711 		    cc.x = u.ux;
712 		    cc.y = u.uy;
713 		    if (getpos(&cc, TRUE, "the desired position") < 0)
714 			return;	/* abort */
715 		    /* possible extensions: introduce a small error if
716 		       magic power is low; allow transfer to solid rock */
717 		    if (teleok(cc.x, cc.y, FALSE)) {
718 			teleds(cc.x, cc.y, FALSE);
719 			return;
720 		    }
721 		    pline("Sorry...");
722 		}
723 	}
724 
725 	(void) safe_teleds(FALSE);
726 }
727 
728 int
dotele()729 dotele()
730 {
731 	struct trap *trap;
732 
733 	trap = t_at(u.ux, u.uy);
734 	if (trap && (!trap->tseen || trap->ttyp != TELEP_TRAP))
735 		trap = 0;
736 
737 	if (trap) {
738 		if (trap->once) {
739 			pline("This is a vault teleport, usable once only.");
740 			if (yn("Jump in?") == 'n')
741 				trap = 0;
742 			else {
743 				deltrap(trap);
744 				newsym(u.ux, u.uy);
745 			}
746 		}
747 		if (trap)
748 			You("%s onto the teleportation trap.",
749 			    locomotion(youmonst.data, "jump"));
750 	}
751 	if (!trap) {
752 	    boolean castit = FALSE;
753 	    register int sp_no = 0, energy = 0;
754 
755 	    if (!Teleportation || (u.ulevel < (Role_if(PM_WIZARD) ? 8 : 12)
756 					&& !can_teleport(youmonst.data))) {
757 		/* Try to use teleport away spell. */
758 		if (objects[SPE_TELEPORT_AWAY].oc_name_known && !Confusion)
759 		    for (sp_no = 0; sp_no < MAXSPELL; sp_no++)
760 			if (spl_book[sp_no].sp_id == SPE_TELEPORT_AWAY) {
761 				castit = TRUE;
762 				break;
763 			}
764 #ifdef WIZARD
765 		if (!wizard) {
766 #endif
767 		    if (!castit) {
768 			if (!Teleportation)
769 			    You("don't know that spell.");
770 			else You("are not able to teleport at will.");
771 			return(0);
772 		    }
773 #ifdef WIZARD
774 		}
775 #endif
776 	    }
777 
778 	    if (u.uhunger <= 10 || ACURR(A_STR) < 6) {
779 #ifdef WIZARD
780 		if (!wizard) {
781 #endif
782 			You("lack the strength %s.",
783 			    castit ? "for a teleport spell" : "to teleport");
784 			return 1;
785 #ifdef WIZARD
786 		}
787 #endif
788 	    }
789 
790 	    energy = objects[SPE_TELEPORT_AWAY].oc_level * 5;
791 	    if (u.uen <= energy) {
792 #ifdef WIZARD
793 		if (wizard)
794 			energy = u.uen;
795 		else
796 #endif
797 		{
798 			You("lack the energy %s.",
799 			    castit ? "for a teleport spell" : "to teleport");
800 			return 1;
801 		}
802 	    }
803 
804 	    if (check_capacity(
805 			"Your concentration falters from carrying so much."))
806 		return 1;
807 
808 	    if (castit) {
809 		exercise(A_WIS, TRUE);
810 		if (spelleffects(sp_no, TRUE))
811 			return(1);
812 		else
813 #ifdef WIZARD
814 		    if (!wizard)
815 #endif
816 			return(0);
817 	    } else {
818 		u.uen -= energy;
819 		flags.botl = 1;
820 	    }
821 	}
822 
823 	if (next_to_u()) {
824 		if (trap && trap->once) vault_tele();
825 		else tele();
826 		(void) next_to_u();
827 	} else {
828 		You(shudder_for_moment);
829 		return(0);
830 	}
831 	if (!trap) morehungry(10);
832 	return(1);
833 }
834 
835 void
level_tele()836 level_tele()
837 {
838 	register int newlev;
839 	d_level newlevel;
840 	const char *escape_by_flying = 0;	/* when surviving dest of -N */
841 	char buf[BUFSZ];
842 	boolean force_dest = FALSE;
843 
844 	if ((u.uhave.amulet || In_endgame(&u.uz) || In_sokoban(&u.uz)
845 #ifdef STEED
846 			|| (u.usteed && mon_has_amulet(u.usteed))
847 #endif
848 	   )
849 #ifdef WIZARD
850 						&& !wizard
851 #endif
852 							) {
853 	    You_feel("very disoriented for a moment.");
854 	    return;
855 	}
856 	if ((Teleport_control && !Stunned)
857 #ifdef WIZARD
858 	   || wizard
859 #endif
860 		) {
861 	    char qbuf[BUFSZ];
862 	    int trycnt = 0;
863 
864 	    Strcpy(qbuf, "To what level do you want to teleport?");
865 	    do {
866 		if (++trycnt == 2) {
867 #ifdef WIZARD
868 			if (wizard) Strcat(qbuf, " [type a number or ? for a menu]");
869 			else
870 #endif
871 			Strcat(qbuf, " [type a number]");
872 		}
873 		getlin(qbuf, buf);
874 		if (!strcmp(buf,"\033")) {	/* cancelled */
875 		    if (Confusion && rnl(5)) {
876 			pline("Oops...");
877 			goto random_levtport;
878 		    }
879 		    return;
880 		} else if (!strcmp(buf,"*")) {
881 		    goto random_levtport;
882 		} else if (Confusion && rnl(5)) {
883 		    pline("Oops...");
884 		    goto random_levtport;
885 		}
886 #ifdef WIZARD
887 		if (wizard && !strcmp(buf,"?")) {
888 		    schar destlev = 0;
889 		    xchar destdnum = 0;
890 
891 		    if ((newlev = (int)print_dungeon(TRUE, &destlev, &destdnum))) {
892 			newlevel.dnum = destdnum;
893 			newlevel.dlevel = destlev;
894 			if (In_endgame(&newlevel) && !In_endgame(&u.uz)) {
895 				Sprintf(buf,
896 				    "Destination is earth level");
897 				if (!u.uhave.amulet) {
898 					struct obj *obj;
899 					obj = mksobj(AMULET_OF_YENDOR,
900 							TRUE, FALSE);
901 					if (obj) {
902 						obj = addinv(obj);
903 						Strcat(buf, " with the amulet");
904 					}
905 				}
906 				assign_level(&newlevel, &earth_level);
907 				pline("%s.", buf);
908 			}
909 			force_dest = TRUE;
910 		    } else return;
911 		} else
912 #endif
913 		if ((newlev = lev_by_name(buf)) == 0) {
914 #ifdef WIZARD
915 		    s_level *slev;
916 
917 		    /* if you're using wizard mode, you shouldn't really need
918 		     * the game to interpret things like `mine town level' */
919 		    if (wizard && (slev = find_level(buf))) {
920 			schedule_goto(&slev->dlevel, FALSE, FALSE, 0,
921 				      (char *)0, (char *)0);
922 			return;
923 		    }
924 #endif
925 		    newlev = atoi(buf);
926                 }
927 	    } while (!newlev && !digit(buf[0]) &&
928 		     (buf[0] != '-' || !digit(buf[1])) &&
929 		     trycnt < 10);
930 
931 	    /* no dungeon escape via this route */
932 	    if (newlev == 0) {
933 		if (trycnt >= 10)
934 		    goto random_levtport;
935 		if (ynq("Go to Nowhere.  Are you sure?") != 'y') return;
936 		You("%s in agony as your body begins to warp...",
937 		    is_silent(youmonst.data) ? "writhe" : "scream");
938 		display_nhwindow(WIN_MESSAGE, FALSE);
939 		You("cease to exist.");
940 		if (invent) Your("possessions land on the %s with a thud.",
941 				surface(u.ux, u.uy));
942 		killer_format = NO_KILLER_PREFIX;
943 		killer = "committed suicide";
944 		done(DIED);
945 		pline("An energized cloud of dust begins to coalesce.");
946 		Your("body rematerializes%s.", invent ?
947 			", and you gather up all your possessions" : "");
948 		return;
949 	    }
950 
951 	    /* if in Knox and the requested level > 0, stay put.
952 	     * we let negative values requests fall into the "heaven" loop.
953 	     * [ALI] Add other single level dungeons entered via portal.
954 	     */
955 	    if ((Is_knox(&u.uz) ||
956 #ifdef BLACKMARKET
957 		    Is_blackmarket(&u.uz) ||
958 #endif
959 		    Is_aligned_quest(&u.uz)) && newlev > 0) {
960 		You(shudder_for_moment);
961 		return;
962 	    }
963 	    /* if in Quest, the player sees "Home 1", etc., on the status
964 	     * line, instead of the logical depth of the level.  controlled
965 	     * level teleport request is likely to be relativized to the
966 	     * status line, and consequently it should be incremented to
967 	     * the value of the logical depth of the target level.
968 	     *
969 	     * we let negative values requests fall into the "heaven" loop.
970 	     */
971 	    if (In_quest(&u.uz) && newlev > 0)
972 		newlev = newlev + dungeons[u.uz.dnum].depth_start - 1;
973 	} else { /* involuntary level tele */
974  random_levtport:
975 	    newlev = random_teleport_level();
976 	    if (newlev == depth(&u.uz)) {
977 		You(shudder_for_moment);
978 		return;
979 	    }
980 	}
981 
982 	if (!next_to_u()) {
983 		You(shudder_for_moment);
984 		return;
985 	}
986 #ifdef WIZARD
987 	if (In_endgame(&u.uz)) {	/* must already be wizard */
988 	    int llimit = dunlevs_in_dungeon(&u.uz);
989 
990 	    if (newlev >= 0 || newlev <= -llimit) {
991 		You_cant("get there from here.");
992 		return;
993 	    }
994 	    newlevel.dnum = u.uz.dnum;
995 	    newlevel.dlevel = llimit + newlev;
996 	    schedule_goto(&newlevel, FALSE, FALSE, 0, (char *)0, (char *)0);
997 	    return;
998 	}
999 #endif
1000 	killer = 0;		/* still alive, so far... */
1001 
1002 	if (newlev < 0 && !force_dest) {
1003 		if (*u.ushops0) {
1004 		    /* take unpaid inventory items off of shop bills */
1005 		    in_mklev = TRUE;	/* suppress map update */
1006 		    u_left_shop(u.ushops0, TRUE);
1007 		    /* you're now effectively out of the shop */
1008 		    *u.ushops0 = *u.ushops = '\0';
1009 		    in_mklev = FALSE;
1010 		}
1011 		if (newlev <= -10) {
1012 			You("arrive in heaven.");
1013 			verbalize("Thou art early, but we'll admit thee.");
1014 			killer_format = NO_KILLER_PREFIX;
1015 			killer = "went to heaven prematurely";
1016 		} else if (newlev == -9) {
1017 			You_feel("deliriously happy. ");
1018 			pline("(In fact, you're on Cloud 9!) ");
1019 			display_nhwindow(WIN_MESSAGE, FALSE);
1020 		} else
1021 			You("are now high above the clouds...");
1022 
1023 		if (killer) {
1024 		    ;		/* arrival in heaven is pending */
1025 		} else if (Levitation) {
1026 		    escape_by_flying = "float gently down to earth";
1027 		} else if (Flying) {
1028 		    escape_by_flying = "fly down to the ground";
1029 		} else {
1030 		    pline("Unfortunately, you don't know how to fly.");
1031 		    You("plummet a few thousand feet to your death.");
1032 		    Sprintf(buf,
1033 			  "teleported out of the dungeon and fell to %s death",
1034 			    uhis());
1035 		    killer = buf;
1036 		    killer_format = NO_KILLER_PREFIX;
1037 		}
1038 	}
1039 
1040 	if (killer) {	/* the chosen destination was not survivable */
1041 	    d_level lsav;
1042 
1043 	    /* set specific death location; this also suppresses bones */
1044 	    lsav = u.uz;	/* save current level, see below */
1045 	    u.uz.dnum = 0;	/* main dungeon */
1046 	    u.uz.dlevel = (newlev <= -10) ? -10 : 0;	/* heaven or surface */
1047 	    done(DIED);
1048 	    /* can only get here via life-saving (or declining to die in
1049 	       explore|debug mode); the hero has now left the dungeon... */
1050 	    escape_by_flying = "find yourself back on the surface";
1051 	    u.uz = lsav;	/* restore u.uz so escape code works */
1052 	}
1053 
1054 	/* calls done(ESCAPED) if newlevel==0 */
1055 	if (escape_by_flying) {
1056 	    You("%s.", escape_by_flying);
1057 	    newlevel.dnum = 0;		/* specify main dungeon */
1058 	    newlevel.dlevel = 0;	/* escape the dungeon */
1059 	    /* [dlevel used to be set to 1, but it doesn't make sense to
1060 		teleport out of the dungeon and float or fly down to the
1061 		surface but then actually arrive back inside the dungeon] */
1062 	} else if (u.uz.dnum == medusa_level.dnum &&
1063 	    newlev >= dungeons[u.uz.dnum].depth_start +
1064 						dunlevs_in_dungeon(&u.uz)) {
1065 #ifdef WIZARD
1066 	    if (!(wizard && force_dest))
1067 #endif
1068 	    find_hell(&newlevel);
1069 	} else {
1070 	    /* if invocation did not yet occur, teleporting into
1071 	     * the last level of Gehennom is forbidden.
1072 	     */
1073 #ifdef WIZARD
1074 		if (!wizard)
1075 #endif
1076 	    if (Inhell && !u.uevent.invoked &&
1077 			newlev >= (dungeons[u.uz.dnum].depth_start +
1078 					dunlevs_in_dungeon(&u.uz) - 1)) {
1079 # ifdef WIZARD
1080                 if (!wizard)
1081                 {
1082 # endif /* WIZARD */
1083 		newlev = dungeons[u.uz.dnum].depth_start +
1084 					dunlevs_in_dungeon(&u.uz) - 2;
1085 		pline("Sorry...");
1086 # ifdef WIZARD
1087                 }
1088 # endif /* WIZARD */
1089 
1090 	    }
1091 	    /* no teleporting out of quest dungeon */
1092             if
1093 # ifdef WIZARD
1094                 ((!wizard) &&
1095 # endif /* WIZARD */
1096                 (In_quest(&u.uz) && newlev < depth(&qstart_level))
1097 # ifdef WIZARD
1098                 )
1099 # endif /* WIZARD */
1100 		newlev = depth(&qstart_level);
1101 	    /* the player thinks of levels purely in logical terms, so
1102 	     * we must translate newlev to a number relative to the
1103 	     * current dungeon.
1104 	     */
1105 #ifdef WIZARD
1106 	    if (!(wizard && force_dest))
1107 #endif
1108 	    get_level(&newlevel, newlev);
1109 	}
1110 	schedule_goto(&newlevel, FALSE, FALSE, 0, (char *)0, (char *)0);
1111 	/* in case player just read a scroll and is about to be asked to
1112 	   call it something, we can't defer until the end of the turn */
1113 	if (u.utotype && !flags.mon_moving) deferred_goto();
1114 }
1115 
1116 void
domagicportal(ttmp)1117 domagicportal(ttmp)
1118 register struct trap *ttmp;
1119 {
1120 	struct d_level target_level;
1121 
1122 	if (!next_to_u()) {
1123 		You(shudder_for_moment);
1124 		return;
1125 	}
1126 
1127 	/* if landed from another portal, do nothing */
1128 	/* problem: level teleport landing escapes the check */
1129 	if (!on_level(&u.uz, &u.uz0)) return;
1130 
1131 	You("activated a magic portal!");
1132 
1133 	/* prevent the poor shnook, whose amulet was stolen while in
1134 	 * the endgame, from accidently triggering the portal to the
1135 	 * next level, and thus losing the game
1136 	 */
1137 	if (In_endgame(&u.uz) && !u.uhave.amulet) {
1138 	    You_feel("dizzy for a moment, but nothing happens...");
1139 	    return;
1140 	}
1141 
1142 	target_level = ttmp->dst;
1143 	schedule_goto(&target_level, FALSE, FALSE, 1,
1144 		      "You feel dizzy for a moment, but the sensation passes.",
1145 		      (char *)0);
1146 }
1147 
1148 void
tele_trap(trap)1149 tele_trap(trap)
1150 struct trap *trap;
1151 {
1152 	if (In_endgame(&u.uz) || Antimagic) {
1153 		if (Antimagic)
1154 			shieldeff(u.ux, u.uy);
1155 		You_feel("a wrenching sensation.");
1156 	} else if (!next_to_u()) {
1157 		You(shudder_for_moment);
1158 	} else if (trap->once) {
1159 		deltrap(trap);
1160 		newsym(u.ux,u.uy);	/* get rid of trap symbol */
1161 		vault_tele();
1162 	} else
1163 		tele();
1164 }
1165 
1166 void
level_tele_trap(trap)1167 level_tele_trap(trap)
1168 struct trap *trap;
1169 {
1170 	You("%s onto a level teleport trap!",
1171 		      Levitation ? (const char *)"float" :
1172 				  locomotion(youmonst.data, "step"));
1173 	if (Antimagic) {
1174 	    shieldeff(u.ux, u.uy);
1175 	}
1176 	if (Antimagic || In_endgame(&u.uz)) {
1177 	    You_feel("a wrenching sensation.");
1178 	    return;
1179 	}
1180 	if (!Blind)
1181 	    You("are momentarily blinded by a flash of light.");
1182 	else
1183 	    You("are momentarily disoriented.");
1184 	deltrap(trap);
1185 	newsym(u.ux,u.uy);	/* get rid of trap symbol */
1186 	level_tele();
1187 }
1188 
1189 /* check whether monster can arrive at location <x,y> via Tport (or fall) */
1190 STATIC_OVL boolean
rloc_pos_ok(x,y,mtmp)1191 rloc_pos_ok(x, y, mtmp)
1192 register int x, y;		/* coordinates of candidate location */
1193 struct monst *mtmp;
1194 {
1195 	register int xx, yy;
1196 
1197 	if (!goodpos(x, y, mtmp, 0)) return FALSE;
1198 	/*
1199 	 * Check for restricted areas present in some special levels.
1200 	 *
1201 	 * `xx' is current column; if 0, then `yy' will contain flag bits
1202 	 * rather than row:  bit #0 set => moving upwards; bit #1 set =>
1203 	 * inside the Wizard's tower.
1204 	 */
1205 	xx = mtmp->mx;
1206 	yy = mtmp->my;
1207 	if (!xx) {
1208 	    /* no current location (migrating monster arrival) */
1209 	    if (dndest.nlx && On_W_tower_level(&u.uz))
1210 		return ((yy & 2) != 0) ^	/* inside xor not within */
1211 		       !within_bounded_area(x, y, dndest.nlx, dndest.nly,
1212 						  dndest.nhx, dndest.nhy);
1213 	    if (updest.lx && (yy & 1) != 0)	/* moving up */
1214 		return (within_bounded_area(x, y, updest.lx, updest.ly,
1215 						  updest.hx, updest.hy) &&
1216 		       (!updest.nlx ||
1217 			!within_bounded_area(x, y, updest.nlx, updest.nly,
1218 						   updest.nhx, updest.nhy)));
1219 	    if (dndest.lx && (yy & 1) == 0)	/* moving down */
1220 		return (within_bounded_area(x, y, dndest.lx, dndest.ly,
1221 						  dndest.hx, dndest.hy) &&
1222 		       (!dndest.nlx ||
1223 			!within_bounded_area(x, y, dndest.nlx, dndest.nly,
1224 						   dndest.nhx, dndest.nhy)));
1225 	} else {
1226 	    /* current location is <xx,yy> */
1227 	    if (!tele_jump_ok(xx, yy, x, y)) return FALSE;
1228 	}
1229 	/* <x,y> is ok */
1230 	return TRUE;
1231 }
1232 
1233 /*
1234  * rloc_to()
1235  *
1236  * Pulls a monster from its current position and places a monster at
1237  * a new x and y.  If oldx is 0, then the monster was not in the levels.monsters
1238  * array.  However, if oldx is 0, oldy may still have a value because mtmp is a
1239  * migrating_mon.  Worm tails are always placed randomly around the head of
1240  * the worm.
1241  */
1242 void
rloc_to(mtmp,x,y)1243 rloc_to(mtmp, x, y)
1244 struct monst *mtmp;
1245 register int x, y;
1246 {
1247 	register int oldx = mtmp->mx, oldy = mtmp->my;
1248 	boolean resident_shk = mtmp->isshk && inhishop(mtmp);
1249 
1250 	if (x == mtmp->mx && y == mtmp->my)	/* that was easy */
1251 		return;
1252 
1253 	if (oldx) {				/* "pick up" monster */
1254 	    if (mtmp->wormno)
1255 		remove_worm(mtmp);
1256 	    else {
1257 		remove_monster(oldx, oldy);
1258 		newsym(oldx, oldy);		/* update old location */
1259 	    }
1260 	}
1261 
1262 	place_monster(mtmp, x, y);		/* put monster down */
1263 	update_monster_region(mtmp);
1264 
1265 	if (mtmp->wormno)			/* now put down tail */
1266 		place_worm_tail_randomly(mtmp, x, y);
1267 
1268 	if (u.ustuck == mtmp) {
1269 		if (u.uswallow) {
1270 			u.ux = x;
1271 			u.uy = y;
1272 			docrt();
1273 		} else	setustuck(0);
1274 	}
1275 
1276 	newsym(x, y);				/* update new location */
1277 	set_apparxy(mtmp);			/* orient monster */
1278 
1279 	/* shopkeepers will only teleport if you zap them with a wand of
1280 	   teleportation or if they've been transformed into a jumpy monster;
1281 	   the latter only happens if you've attacked them with polymorph */
1282 	if (resident_shk && !inhishop(mtmp)) make_angry_shk(mtmp, oldx, oldy);
1283 }
1284 
1285 /* place a monster at a random location, typically due to teleport */
1286 /* return TRUE if successful, FALSE if not */
1287 boolean
rloc(mtmp,suppress_impossible)1288 rloc(mtmp, suppress_impossible)
1289 struct monst *mtmp;	/* mx==0 implies migrating monster arrival */
1290 boolean suppress_impossible;
1291 {
1292 	register int x, y, trycount;
1293 
1294 #ifdef STEED
1295 	if (mtmp == u.usteed) {
1296 	    tele();
1297 	    return TRUE;
1298 	}
1299 #endif
1300 
1301 	if (mtmp->iswiz && mtmp->mx) {	/* Wizard, not just arriving */
1302 	    if (!In_W_tower(u.ux, u.uy, &u.uz))
1303 		x = xupstair,  y = yupstair;
1304 	    else if (!xdnladder)	/* bottom level of tower */
1305 		x = xupladder,  y = yupladder;
1306 	    else
1307 		x = xdnladder,  y = ydnladder;
1308 	    /* if the wiz teleports away to heal, try the up staircase,
1309 	       to block the player's escaping before he's healed
1310 	       (deliberately use `goodpos' rather than `rloc_pos_ok' here) */
1311 	    if (goodpos(x, y, mtmp, 0))
1312 		goto found_xy;
1313 	}
1314 
1315 	trycount = 0;
1316 	do {
1317 	    x = rn1(COLNO-3,2);
1318 	    y = rn2(ROWNO);
1319 	    if ((trycount < 500) ? rloc_pos_ok(x, y, mtmp)
1320 				 : goodpos(x, y, mtmp, 0))
1321 		goto found_xy;
1322 	} while (++trycount < 1000);
1323 
1324 	/* last ditch attempt to find a good place */
1325 	for (x = 2; x < COLNO - 1; x++)
1326 	    for (y = 0; y < ROWNO; y++)
1327 		if (goodpos(x, y, mtmp, 0))
1328 		    goto found_xy;
1329 
1330 	/* level either full of monsters or somehow faulty */
1331 	if (!suppress_impossible)
1332 		impossible("rloc(): couldn't relocate monster");
1333 	return FALSE;
1334 
1335  found_xy:
1336 	rloc_to(mtmp, x, y);
1337 	return TRUE;
1338 }
1339 
1340 STATIC_OVL void
mvault_tele(mtmp)1341 mvault_tele(mtmp)
1342 struct monst *mtmp;
1343 {
1344 	register struct mkroom *croom = search_special(VAULT);
1345 	coord c;
1346 
1347 	if (croom && somexy(croom, &c) &&
1348 				goodpos(c.x, c.y, mtmp, 0)) {
1349 		rloc_to(mtmp, c.x, c.y);
1350 		return;
1351 	}
1352 	(void) rloc(mtmp, FALSE);
1353 }
1354 
1355 boolean
tele_restrict(mon)1356 tele_restrict(mon)
1357 struct monst *mon;
1358 {
1359 	if (level.flags.noteleport) {
1360 		if (canseemon(mon))
1361 		    pline("A mysterious force prevents %s from teleporting!",
1362 			mon_nam(mon));
1363 		return TRUE;
1364 	}
1365 	return FALSE;
1366 }
1367 
1368 void
mtele_trap(mtmp,trap,in_sight)1369 mtele_trap(mtmp, trap, in_sight)
1370 struct monst *mtmp;
1371 struct trap *trap;
1372 int in_sight;
1373 {
1374 	char *monname;
1375 
1376 	if (tele_restrict(mtmp)) return;
1377 	if (teleport_pet(mtmp, FALSE)) {
1378 	    /* save name with pre-movement visibility */
1379 	    monname = Monnam(mtmp);
1380 
1381 	    /* Note: don't remove the trap if a vault.  Other-
1382 	     * wise the monster will be stuck there, since
1383 	     * the guard isn't going to come for it...
1384 	     */
1385 	    if (trap->once) mvault_tele(mtmp);
1386 	    else (void) rloc(mtmp, FALSE);
1387 
1388 	    if (in_sight) {
1389 		if (canseemon(mtmp))
1390 		    pline("%s seems disoriented.", monname);
1391 		else
1392 		    pline("%s suddenly disappears!", monname);
1393 		seetrap(trap);
1394 	    }
1395 	}
1396 }
1397 
1398 /* return 0 if still on level, 3 if not */
1399 int
mlevel_tele_trap(mtmp,trap,force_it,in_sight)1400 mlevel_tele_trap(mtmp, trap, force_it, in_sight)
1401 struct monst *mtmp;
1402 struct trap *trap;
1403 boolean force_it;
1404 int in_sight;
1405 {
1406 	int tt = trap->ttyp;
1407 	struct permonst *mptr = mtmp->data;
1408 
1409 	if (mtmp == u.ustuck)	/* probably a vortex */
1410 	    return 0;		/* temporary? kludge */
1411 	if (teleport_pet(mtmp, force_it)) {
1412 	    d_level tolevel;
1413 	    int migrate_typ = MIGR_RANDOM;
1414 
1415 	    if ((tt == HOLE || tt == TRAPDOOR)) {
1416 		if (Is_stronghold(&u.uz)) {
1417 		    assign_level(&tolevel, &valley_level);
1418 		} else if (Is_botlevel(&u.uz)) {
1419 		    if (in_sight && trap->tseen)
1420 			pline("%s avoids the %s.", Monnam(mtmp),
1421 			(tt == HOLE) ? "hole" : "trap");
1422 		    return 0;
1423 		} else {
1424 		    get_level(&tolevel, depth(&u.uz) + 1);
1425 		}
1426 	    } else if (tt == MAGIC_PORTAL) {
1427 		if (In_endgame(&u.uz) &&
1428 		    (mon_has_amulet(mtmp) || is_home_elemental(mptr))) {
1429 		    if (in_sight && mptr->mlet != S_ELEMENTAL) {
1430 			pline("%s seems to shimmer for a moment.",
1431 							Monnam(mtmp));
1432 			seetrap(trap);
1433 		    }
1434 		    return 0;
1435 		}
1436 #ifdef BLACKMARKET
1437 	      	else if (mtmp->mtame &&
1438 			(Is_blackmarket(&trap->dst) || Is_blackmarket(&u.uz))) {
1439 	          if (in_sight) {
1440 		     pline("%s seems to shimmer for a moment.",
1441 		     Monnam(mtmp));
1442 		     seetrap(trap);
1443 	          }
1444 	          return 0;
1445 	        }
1446 #endif /* BLACKMARKET */
1447 		  else {
1448 		    assign_level(&tolevel, &trap->dst);
1449 		    migrate_typ = MIGR_PORTAL;
1450 		}
1451 	    } else { /* (tt == LEVEL_TELEP) */
1452 		int nlev;
1453 
1454 		if (mon_has_amulet(mtmp) || In_endgame(&u.uz)) {
1455 		    if (in_sight)
1456 			pline("%s seems very disoriented for a moment.",
1457 				Monnam(mtmp));
1458 		    return 0;
1459 		}
1460 		nlev = random_teleport_level();
1461 		if (nlev == depth(&u.uz)) {
1462 		    if (in_sight)
1463 			pline("%s shudders for a moment.", Monnam(mtmp));
1464 		    return 0;
1465 		}
1466 		get_level(&tolevel, nlev);
1467 	    }
1468 
1469 	    if (in_sight) {
1470 		pline("Suddenly, %s disappears out of sight.", mon_nam(mtmp));
1471 		seetrap(trap);
1472 	    }
1473 	    migrate_to_level(mtmp, ledger_no(&tolevel),
1474 			     migrate_typ, (coord *)0);
1475 	    return 3;	/* no longer on this level */
1476 	}
1477 	return 0;
1478 }
1479 
1480 
1481 void
rloco(obj)1482 rloco(obj)
1483 register struct obj *obj;
1484 {
1485 	register xchar tx, ty, otx, oty;
1486 	boolean restricted_fall;
1487 	int try_limit = 4000;
1488 
1489 	if (obj->otyp == CORPSE && is_rider(&mons[obj->corpsenm])) {
1490 	    if (revive_corpse(obj, FALSE)) return;
1491 	}
1492 
1493 	obj_extract_self(obj);
1494 	otx = obj->ox;
1495 	oty = obj->oy;
1496 	restricted_fall = (otx == 0 && dndest.lx);
1497 	do {
1498 	    tx = rn1(COLNO-3,2);
1499 	    ty = rn2(ROWNO);
1500 	    if (!--try_limit) break;
1501 	} while (!goodpos(tx, ty, (struct monst *)0, 0) ||
1502 		/* bug: this lacks provision for handling the Wizard's tower */
1503 		 (restricted_fall &&
1504 		  (!within_bounded_area(tx, ty, dndest.lx, dndest.ly,
1505 						dndest.hx, dndest.hy) ||
1506 		   (dndest.nlx &&
1507 		    within_bounded_area(tx, ty, dndest.nlx, dndest.nly,
1508 						dndest.nhx, dndest.nhy)))));
1509 
1510 	if (flooreffects(obj, tx, ty, "fall")) {
1511 	    return;
1512 	} else if (otx == 0 && oty == 0) {
1513 	    ;	/* fell through a trap door; no update of old loc needed */
1514 	} else {
1515 	    if (costly_spot(otx, oty)
1516 	      && (!costly_spot(tx, ty) ||
1517 		  !index(in_rooms(tx, ty, 0), *in_rooms(otx, oty, 0)))) {
1518 		if (costly_spot(u.ux, u.uy) &&
1519 			    index(u.urooms, *in_rooms(otx, oty, 0)))
1520 		    addtobill(obj, FALSE, FALSE, FALSE);
1521 		else (void)stolen_value(obj, otx, oty, FALSE, FALSE, FALSE);
1522 	    }
1523 	    newsym(otx, oty);	/* update old location */
1524 	}
1525 	place_object(obj, tx, ty);
1526 	newsym(tx, ty);
1527 }
1528 
1529 /* Returns an absolute depth */
1530 int
random_teleport_level()1531 random_teleport_level()
1532 {
1533 	int nlev, max_depth, min_depth,
1534 	    cur_depth = (int)depth(&u.uz);
1535 
1536 	if (!rn2(5) || Is_knox(&u.uz) ||
1537 #ifdef BLACKMARKET
1538 		Is_blackmarket(&u.uz) ||
1539 #endif
1540 		Is_aligned_quest(&u.uz))
1541 	    return cur_depth;
1542 
1543 	/* What I really want to do is as follows:
1544 	 * -- If in a dungeon that goes down, the new level is to be restricted
1545 	 *    to [top of parent, bottom of current dungeon]
1546 	 * -- If in a dungeon that goes up, the new level is to be restricted
1547 	 *    to [top of current dungeon, bottom of parent]
1548 	 * -- If in a quest dungeon or similar dungeon entered by portals,
1549 	 *    the new level is to be restricted to [top of current dungeon,
1550 	 *    bottom of current dungeon]
1551 	 * The current behavior is not as sophisticated as that ideal, but is
1552 	 * still better what we used to do, which was like this for players
1553 	 * but different for monsters for no obvious reason.  Currently, we
1554 	 * must explicitly check for special dungeons.  We check for Knox
1555 	 * above; endgame is handled in the caller due to its different
1556 	 * message ("disoriented").
1557 	 * --KAA
1558 	 * [ALI] Also check for Sam's blackmarket and the three aligned quests
1559 	 * above.
1560 	 * 3.4.2: explicitly handle quest here too, to fix the problem of
1561 	 * monsters sometimes level teleporting out of it into main dungeon.
1562 	 * Also prevent monsters reaching the Sanctum prior to invocation.
1563 	 */
1564 	min_depth = In_quest(&u.uz) ? dungeons[u.uz.dnum].depth_start : 1;
1565 	max_depth = dunlevs_in_dungeon(&u.uz) +
1566 		(dungeons[u.uz.dnum].depth_start - 1);
1567 	/* can't reach the Sanctum if the invocation hasn't been performed */
1568 	if (Inhell && !u.uevent.invoked) max_depth -= 1;
1569 
1570 	/* Get a random value relative to the current dungeon */
1571 	/* Range is 1 to current+3, current not counting */
1572 	nlev = rn2(cur_depth + 3 - min_depth) + min_depth;
1573 	if (nlev >= cur_depth) nlev++;
1574 
1575 	if (nlev > max_depth) {
1576 	    nlev = max_depth;
1577 	    /* teleport up if already on bottom */
1578 	    if (Is_botlevel(&u.uz)) nlev -= rnd(3);
1579 	}
1580 	if (nlev < min_depth) {
1581 	    nlev = min_depth;
1582 	    if (nlev == cur_depth) {
1583 		nlev += rnd(3);
1584 		if (nlev > max_depth)
1585 		    nlev = max_depth;
1586 	    }
1587 	}
1588 	return nlev;
1589 }
1590 
1591 /* you teleport a monster (via wand, spell, or poly'd q.mechanic attack);
1592    return false iff the attempt fails */
1593 boolean
u_teleport_mon(mtmp,give_feedback)1594 u_teleport_mon(mtmp, give_feedback)
1595 struct monst *mtmp;
1596 boolean give_feedback;
1597 {
1598 	coord cc;
1599 
1600 	if (mtmp->ispriest && *in_rooms(mtmp->mx, mtmp->my, TEMPLE)) {
1601 	    if (give_feedback)
1602 		pline("%s resists your magic!", Monnam(mtmp));
1603 	    return FALSE;
1604 	} else if (level.flags.noteleport && u.uswallow && mtmp == u.ustuck) {
1605 	    if (give_feedback)
1606 		You("are no longer inside %s!", mon_nam(mtmp));
1607 	    unstuck(mtmp);
1608 	    rloc(mtmp, FALSE);
1609 	} else if (is_rider(mtmp->data) && rn2(13) &&
1610 		   enexto(&cc, u.ux, u.uy, mtmp->data))
1611 	    rloc_to(mtmp, cc.x, cc.y);
1612 	else {
1613 #ifdef WIZARD
1614 	    if (wizard && Teleport_control)
1615 	    {
1616 		/*
1617 		 * [ALI] This code will only allow monsters to be
1618 		 * teleported to positions acceptable to rloc_pos_ok().
1619 		 * We could use goodpos() which would allow more
1620 		 * locations but, in my view, is less informative.
1621 		 */
1622 		xchar omx, omy;
1623 		pline("To what position do you want %s to be teleported?",
1624 		       mon_nam(mtmp));
1625 		cc.x = omx = mtmp->mx;
1626 		cc.y = omy = mtmp->my;
1627 		if (getpos(&cc, TRUE, "the desired position") < 0)
1628 		    rloc(mtmp, FALSE);	/* abort */
1629 		else if (rloc_pos_ok(cc.x, cc.y, mtmp)) {
1630 		    rloc_to(mtmp, cc.x, cc.y);
1631 		    /* As rloc() ... */
1632 		    if (mtmp->isshk && !inhishop(mtmp))
1633 			make_angry_shk(mtmp, omx, omy);
1634 		} else {
1635 		    pline("Sorry...");
1636 		    rloc(mtmp, FALSE);
1637 		}
1638 	    } else
1639 #endif /* WIZARD */
1640 	    rloc(mtmp, FALSE);
1641 	}
1642 	return TRUE;
1643 }
1644 /*teleport.c*/
1645