Fandom

Wikihack

Source:Teleport.c

2,034pages on
this wiki
Add New Page
Talk0

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.

Below is the full text to src/teleport.c from NetHack 3.4.3. To link to a particular line, write [[teleport.c#line123]], for example.

Top of file Edit

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.    
The NetHack General Public License applies to screenshots, source code and other content from NetHack.
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.   

goodpos Edit

13.   /*
14.    * Is (x,y) a good position of mtmp?  If mtmp is NULL, then is (x,y) good
15.    * for an object?
16.    *
17.    * This function will only look at mtmp->mdat, so makemon, mplayer, etc can
18.    * call it to generate new monster positions with fake monster structures.
19.    */
20.   boolean
21.   goodpos(x, y, mtmp, gpflags)
22.   int x,y;
23.   struct monst *mtmp;
24.   unsigned gpflags;
25.   {
26.   	struct permonst *mdat = NULL;
27.   	boolean ignorewater = ((gpflags & MM_IGNOREWATER) != 0);
28.   
29.   	if (!isok(x, y)) return FALSE;
30.   
31.   	/* in many cases, we're trying to create a new monster, which
32.   	 * can't go on top of the player or any existing monster.
33.   	 * however, occasionally we are relocating engravings or objects,
34.   	 * which could be co-located and thus get restricted a bit too much.
35.   	 * oh well.
36.   	 */
37.   	if (mtmp != &youmonst && x == u.ux && y == u.uy
38.   #ifdef STEED
39.   			&& (!u.usteed || mtmp != u.usteed)
40.   #endif
41.   			)
42.   		return FALSE;
43.   
44.   	if (mtmp) {
45.   	    struct monst *mtmp2 = m_at(x,y);
46.   
47.   	    /* Be careful with long worms.  A monster may be placed back in
48.   	     * its own location.  Normally, if m_at() returns the same monster
49.   	     * that we're trying to place, the monster is being placed in its
50.   	     * own location.  However, that is not correct for worm segments,
51.   	     * because all the segments of the worm return the same m_at().
52.   	     * Actually we overdo the check a little bit--a worm can't be placed
53.   	     * in its own location, period.  If we just checked for mtmp->mx
54.   	     * != x || mtmp->my != y, we'd miss the case where we're called
55.   	     * to place the worm segment and the worm's head is at x,y.
56.   	     */
57.   	    if (mtmp2 && (mtmp2 != mtmp || mtmp->wormno))
58.   		return FALSE;
59.   
60.   	    mdat = mtmp->data;
61.   	    if (is_pool(x,y) && !ignorewater) {
62.   		if (mtmp == &youmonst)
63.   			return !!(HLevitation || Flying || Wwalking ||
64.   					Swimming || Amphibious);
65.   		else	return (is_flyer(mdat) || is_swimmer(mdat) ||
66.   							is_clinger(mdat));
67.   	    } else if (mdat->mlet == S_EEL && rn2(13) && !ignorewater) {
68.   		return FALSE;
69.   	    } else if (is_lava(x,y)) {
70.   		if (mtmp == &youmonst)
71.   		    return !!HLevitation;
72.   		else
73.   		    return (is_flyer(mdat) || likes_lava(mdat));
74.   	    }
75.   	    if (passes_walls(mdat) && may_passwall(x,y)) return TRUE;
76.   	}
77.   	if (!ACCESSIBLE(levl[x][y].typ)) {
78.   		if (!(is_pool(x,y) && ignorewater)) return FALSE;
79.   	}
80.   
81.   	if (closed_door(x, y) && (!mdat || !amorphous(mdat)))
82.   		return FALSE;
83.   	if (sobj_at(BOULDER, x, y) && (!mdat || !throws_rocks(mdat)))
84.   		return FALSE;
85.   	return TRUE;
86.   }
87.   

enexto Edit

88.   /*
89.    * "entity next to"
90.    *
91.    * Attempt to find a good place for the given monster type in the closest
92.    * position to (xx,yy).  Do so in successive square rings around (xx,yy).
93.    * If there is more than one valid positon in the ring, choose one randomly.
94.    * Return TRUE and the position chosen when successful, FALSE otherwise.
95.    */
96.   boolean
97.   enexto(cc, xx, yy, mdat)
98.   coord *cc;
99.   register xchar xx, yy;
100.  struct permonst *mdat;
101.  {
102.  	return enexto_core(cc, xx, yy, mdat, 0);
103.  }
104.  

enexto_core Edit

105.  boolean
106.  enexto_core(cc, xx, yy, mdat, entflags)
107.  coord *cc;
108.  register xchar xx, yy;
109.  struct permonst *mdat;
110.  unsigned entflags;
111.  {
112.  #define MAX_GOOD 15
113.      coord good[MAX_GOOD], *good_ptr;
114.      int x, y, range, i;
115.      int xmin, xmax, ymin, ymax;
116.      struct monst fakemon;	/* dummy monster */
117.  
118.      if (!mdat) {
119.  #ifdef DEBUG
120.  	pline("enexto() called with mdat==0");
121.  #endif
122.  	/* default to player's original monster type */
123.  	mdat = &mons[u.umonster];
124.      }
125.      fakemon.data = mdat;	/* set up for goodpos */
126.      good_ptr = good;
127.      range = 1;
128.      /*
129.       * Walk around the border of the square with center (xx,yy) and
130.       * radius range.  Stop when we find at least one valid position.
131.       */
132.      do {
133.  	xmin = max(1, xx-range);
134.  	xmax = min(COLNO-1, xx+range);
135.  	ymin = max(0, yy-range);
136.  	ymax = min(ROWNO-1, yy+range);
137.  
138.  	for (x = xmin; x <= xmax; x++)
139.  	    if (goodpos(x, ymin, &fakemon, entflags)) {
140.  		good_ptr->x = x;
141.  		good_ptr->y = ymin ;
142.  		/* beware of accessing beyond segment boundaries.. */
143.  		if (good_ptr++ == &good[MAX_GOOD-1]) goto full;
144.  	    }
145.  	for (x = xmin; x <= xmax; x++)
146.  	    if (goodpos(x, ymax, &fakemon, entflags)) {
147.  		good_ptr->x = x;
148.  		good_ptr->y = ymax ;
149.  		/* beware of accessing beyond segment boundaries.. */
150.  		if (good_ptr++ == &good[MAX_GOOD-1]) goto full;
151.  	    }
152.  	for (y = ymin+1; y < ymax; y++)
153.  	    if (goodpos(xmin, y, &fakemon, entflags)) {
154.  		good_ptr->x = xmin;
155.  		good_ptr-> y = y ;
156.  		/* beware of accessing beyond segment boundaries.. */
157.  		if (good_ptr++ == &good[MAX_GOOD-1]) goto full;
158.  	    }
159.  	for (y = ymin+1; y < ymax; y++)
160.  	    if (goodpos(xmax, y, &fakemon, entflags)) {
161.  		good_ptr->x = xmax;
162.  		good_ptr->y = y ;
163.  		/* beware of accessing beyond segment boundaries.. */
164.  		if (good_ptr++ == &good[MAX_GOOD-1]) goto full;
165.  	    }
166.  	range++;
167.  
168.  	/* return if we've grown too big (nothing is valid) */
169.  	if (range > ROWNO && range > COLNO) return FALSE;
170.      } while (good_ptr == good);
171.  
172.  full:
173.      i = rn2((int)(good_ptr - good));
174.      cc->x = good[i].x;
175.      cc->y = good[i].y;
176.      return TRUE;
177.  }
178.  

tele_jump_ok Edit

179.  /*
180.   * Check for restricted areas present in some special levels.  (This might
181.   * need to be augmented to allow deliberate passage in wizard mode, but
182.   * only for explicitly chosen destinations.)
183.   */
184.  STATIC_OVL boolean
185.  tele_jump_ok(x1, y1, x2, y2)
186.  int x1, y1, x2, y2;
187.  {
188.  	if (dndest.nlx > 0) {
189.  	    /* if inside a restricted region, can't teleport outside */
190.  	    if (within_bounded_area(x1, y1, dndest.nlx, dndest.nly,
191.  						dndest.nhx, dndest.nhy) &&
192.  		!within_bounded_area(x2, y2, dndest.nlx, dndest.nly,
193.  						dndest.nhx, dndest.nhy))
194.  		return FALSE;
195.  	    /* and if outside, can't teleport inside */
196.  	    if (!within_bounded_area(x1, y1, dndest.nlx, dndest.nly,
197.  						dndest.nhx, dndest.nhy) &&
198.  		within_bounded_area(x2, y2, dndest.nlx, dndest.nly,
199.  						dndest.nhx, dndest.nhy))
200.  		return FALSE;
201.  	}
202.  	if (updest.nlx > 0) {		/* ditto */
203.  	    if (within_bounded_area(x1, y1, updest.nlx, updest.nly,
204.  						updest.nhx, updest.nhy) &&
205.  		!within_bounded_area(x2, y2, updest.nlx, updest.nly,
206.  						updest.nhx, updest.nhy))
207.  		return FALSE;
208.  	    if (!within_bounded_area(x1, y1, updest.nlx, updest.nly,
209.  						updest.nhx, updest.nhy) &&
210.  		within_bounded_area(x2, y2, updest.nlx, updest.nly,
211.  						updest.nhx, updest.nhy))
212.  		return FALSE;
213.  	}
214.  	return TRUE;
215.  }
216.  

teleok Edit

217.  STATIC_OVL boolean
218.  teleok(x, y, trapok)
219.  register int x, y;
220.  boolean trapok;
221.  {
222.  	if (!trapok && t_at(x, y)) return FALSE;
223.  	if (!goodpos(x, y, &youmonst, 0)) return FALSE;
224.  	if (!tele_jump_ok(u.ux, u.uy, x, y)) return FALSE;
225.  	if (!in_out_region(x, y)) return FALSE;
226.  	return TRUE;
227.  }
228.  

teleds Edit

229.  void
230.  teleds(nux, nuy, allow_drag)
231.  register int nux,nuy;
232.  boolean allow_drag;
233.  {
234.  	boolean ball_active = (Punished && uball->where != OBJ_FREE),
235.  		ball_still_in_range = FALSE;
236.  
237.  	/* If they have to move the ball, then drag if allow_drag is true;
238.  	 * otherwise they are teleporting, so unplacebc().  
239.  	 * If they don't have to move the ball, then always "drag" whether or
240.  	 * not allow_drag is true, because we are calling that function, not
241.  	 * to drag, but to move the chain.  *However* there are some dumb
242.  	 * special cases:
243.  	 *    0				 0
244.  	 *   _X  move east       ----->  X_
245.  	 *    @				  @
246.  	 * These are permissible if teleporting, but not if dragging.  As a
247.  	 * result, drag_ball() needs to know about allow_drag and might end
248.  	 * up dragging the ball anyway.  Also, drag_ball() might find that
249.  	 * dragging the ball is completely impossible (ball in range but there's
250.  	 * rock in the way), in which case it teleports the ball on its own.
251.  	 */
252.  	if (ball_active) {
253.  	    if (!carried(uball) && distmin(nux, nuy, uball->ox, uball->oy) <= 2)
254.  		ball_still_in_range = TRUE; /* don't have to move the ball */
255.  	    else {
256.  		/* have to move the ball */
257.  		if (!allow_drag || distmin(u.ux, u.uy, nux, nuy) > 1) {
258.  		    /* we should not have dist > 1 and allow_drag at the same
259.  		     * time, but just in case, we must then revert to teleport.
260.  		     */
261.  		    allow_drag = FALSE;
262.  		    unplacebc();
263.  		}
264.  	    }
265.  	}
266.  	u.utrap = 0;
267.  	u.ustuck = 0;
268.  	u.ux0 = u.ux;
269.  	u.uy0 = u.uy;
270.  
271.  	if (hides_under(youmonst.data))
272.  		u.uundetected = OBJ_AT(nux, nuy);
273.  	else if (youmonst.data->mlet == S_EEL)
274.  		u.uundetected = is_pool(nux, nuy);
275.  	else {
276.  		u.uundetected = 0;
277.  		/* mimics stop being unnoticed */
278.  		if (youmonst.data->mlet == S_MIMIC)
279.  		    youmonst.m_ap_type = M_AP_NOTHING;
280.  	}
281.  
282.  	if (u.uswallow) {
283.  		u.uswldtim = u.uswallow = 0;
284.  		if (Punished && !ball_active) {
285.  		    /* ensure ball placement, like unstuck */
286.  		    ball_active = TRUE;
287.  		    allow_drag = FALSE;
288.  		}
289.  		docrt();
290.  	}
291.  	if (ball_active) {
292.  	    if (ball_still_in_range || allow_drag) {
293.  		int bc_control;
294.  		xchar ballx, bally, chainx, chainy;
295.  		boolean cause_delay;
296.  
297.  		if (drag_ball(nux, nuy, &bc_control, &ballx, &bally,
298.  				    &chainx, &chainy, &cause_delay, allow_drag))
299.  		    move_bc(0, bc_control, ballx, bally, chainx, chainy);
300.  	    }
301.  	}
302.  	/* must set u.ux, u.uy after drag_ball(), which may need to know
303.  	   the old position if allow_drag is true... */
304.  	u.ux = nux;
305.  	u.uy = nuy;
306.  	fill_pit(u.ux0, u.uy0);
307.  	if (ball_active) {
308.  	    if (!ball_still_in_range && !allow_drag)
309.  		placebc();
310.  	}
311.  	initrack(); /* teleports mess up tracking monsters without this */
312.  	update_player_regions();
313.  #ifdef STEED
314.  	/* Move your steed, too */
315.  	if (u.usteed) {
316.  		u.usteed->mx = nux;
317.  		u.usteed->my = nuy;
318.  	}
319.  #endif
320.  	/*
321.  	 *  Make sure the hero disappears from the old location.  This will
322.  	 *  not happen if she is teleported within sight of her previous
323.  	 *  location.  Force a full vision recalculation because the hero
324.  	 *  is now in a new location.
325.  	 */
326.  	newsym(u.ux0,u.uy0);
327.  	see_monsters();
328.  	vision_full_recalc = 1;
329.  	nomul(0);
330.  	vision_recalc(0);	/* vision before effects */
331.  	spoteffects(TRUE);
332.  	invocation_message();
333.  }
334.  

safe_teleds Edit

335.  boolean
336.  safe_teleds(allow_drag)
337.  boolean allow_drag;
338.  {
339.  	register int nux, nuy, tcnt = 0;
340.  
341.  	do {
342.  		nux = rnd(COLNO-1);
343.  		nuy = rn2(ROWNO);
344.  	} while (!teleok(nux, nuy, (boolean)(tcnt > 200)) && ++tcnt <= 400);
345.  
346.  	if (tcnt <= 400) {
347.  		teleds(nux, nuy, allow_drag);
348.  		return TRUE;
349.  	} else
350.  		return FALSE;
351.  }
352.  

vault_tele Edit

353.  STATIC_OVL void
354.  vault_tele()
355.  {
356.  	register struct mkroom *croom = search_special(VAULT);
357.  	coord c;
358.  
359.  	if (croom && somexy(croom, &c) && teleok(c.x,c.y,FALSE)) {
360.  		teleds(c.x,c.y,FALSE);
361.  		return;
362.  	}
363.  	tele();
364.  }
365.  

teleport_pet Edit

366.  boolean
367.  teleport_pet(mtmp, force_it)
368.  register struct monst *mtmp;
369.  boolean force_it;
370.  {
371.  	register struct obj *otmp;
372.  
373.  #ifdef STEED
374.  	if (mtmp == u.usteed)
375.  		return (FALSE);
376.  #endif
377.  
378.  	if (mtmp->mleashed) {
379.  	    otmp = get_mleash(mtmp);
380.  	    if (!otmp) {
381.  		impossible("%s is leashed, without a leash.", Monnam(mtmp));
382.  		goto release_it;
383.  	    }
384.  	    if (otmp->cursed && !force_it) {
385.  		yelp(mtmp);
386.  		return FALSE;
387.  	    } else {
388.  		Your("leash goes slack.");
389.   release_it:
390.  		m_unleash(mtmp, FALSE);
391.  		return TRUE;
392.  	    }
393.  	}
394.  	return TRUE;
395.  }
396.  

tele Edit

397.  void
398.  tele()
399.  {
400.  	coord cc;
401.  
402.  	/* Disable teleportation in stronghold && Vlad's Tower */
403.  	if (level.flags.noteleport) {
404.  #ifdef WIZARD
405.  		if (!wizard) {
406.  #endif
407.  		    pline("A mysterious force prevents you from teleporting!");
408.  		    return;
409.  #ifdef WIZARD
410.  		}
411.  #endif
412.  	}
413.  
414.  	/* don't show trap if "Sorry..." */
415.  	if (!Blinded) make_blinded(0L,FALSE);
416.  
417.  	if ((u.uhave.amulet || On_W_tower_level(&u.uz)) && !rn2(3)) {
418.  	    You_feel("disoriented for a moment.");
419.  	    return;
420.  	}
421.  	if ((Teleport_control && !Stunned)
422.  #ifdef WIZARD
423.  			    || wizard
424.  #endif
425.  					) {
426.  	    if (unconscious()) {
427.  		pline("Being unconscious, you cannot control your teleport.");
428.  	    } else {
429.  #ifdef STEED
430.  		    char buf[BUFSZ];
431.  		    if (u.usteed) Sprintf(buf," and %s", mon_nam(u.usteed));
432.  #endif
433.  		    pline("To what position do you%s want to be teleported?",
434.  #ifdef STEED
435.  				u.usteed ? buf :
436.  #endif
437.  			   "");
438.  		    cc.x = u.ux;
439.  		    cc.y = u.uy;
440.  		    if (getpos(&cc, TRUE, "the desired position") < 0)
441.  			return;	/* abort */
442.  		    /* possible extensions: introduce a small error if
443.  		       magic power is low; allow transfer to solid rock */
444.  		    if (teleok(cc.x, cc.y, FALSE)) {
445.  			teleds(cc.x, cc.y, FALSE);
446.  			return;
447.  		    }
448.  		    pline("Sorry...");
449.  		}
450.  	}
451.  
452.  	(void) safe_teleds(FALSE);
453.  }
454.  

dotele Edit

455.  int
456.  dotele()
457.  {
458.  	struct trap *trap;
459.  
460.  	trap = t_at(u.ux, u.uy);
461.  	if (trap && (!trap->tseen || trap->ttyp != TELEP_TRAP))
462.  		trap = 0;
463.  
464.  	if (trap) {
465.  		if (trap->once) {
466.  			pline("This is a vault teleport, usable once only.");
467.  			if (yn("Jump in?") == 'n')
468.  				trap = 0;
469.  			else {
470.  				deltrap(trap);
471.  				newsym(u.ux, u.uy);
472.  			}
473.  		}
474.  		if (trap)
475.  			You("%s onto the teleportation trap.",
476.  			    locomotion(youmonst.data, "jump"));
477.  	}
478.  	if (!trap) {
479.  	    boolean castit = FALSE;
480.  	    register int sp_no = 0, energy = 0;
481.  
482.  	    if (!Teleportation || (u.ulevel < (Role_if(PM_WIZARD) ? 8 : 12)
483.  					&& !can_teleport(youmonst.data))) {
484.  		/* Try to use teleport away spell. */
485.  		if (objects[SPE_TELEPORT_AWAY].oc_name_known && !Confusion)
486.  		    for (sp_no = 0; sp_no < MAXSPELL; sp_no++)
487.  			if (spl_book[sp_no].sp_id == SPE_TELEPORT_AWAY) {
488.  				castit = TRUE;
489.  				break;
490.  			}
491.  #ifdef WIZARD
492.  		if (!wizard) {
493.  #endif
494.  		    if (!castit) {
495.  			if (!Teleportation)
496.  			    You("don't know that spell.");
497.  			else You("are not able to teleport at will.");
498.  			return(0);
499.  		    }
500.  #ifdef WIZARD
501.  		}
502.  #endif
503.  	    }
504.  
505.  	    if (u.uhunger <= 100 || ACURR(A_STR) < 6) {
506.  #ifdef WIZARD
507.  		if (!wizard) {
508.  #endif
509.  			You("lack the strength %s.",
510.  			    castit ? "for a teleport spell" : "to teleport");
511.  			return 1;
512.  #ifdef WIZARD
513.  		}
514.  #endif
515.  	    }
516.  
517.  	    energy = objects[SPE_TELEPORT_AWAY].oc_level * 7 / 2 - 2;
518.  	    if (u.uen <= energy) {
519.  #ifdef WIZARD
520.  		if (wizard)
521.  			energy = u.uen;
522.  		else
523.  #endif
524.  		{
525.  			You("lack the energy %s.",
526.  			    castit ? "for a teleport spell" : "to teleport");
527.  			return 1;
528.  		}
529.  	    }
530.  
531.  	    if (check_capacity(
532.  			"Your concentration falters from carrying so much."))
533.  		return 1;
534.  
535.  	    if (castit) {
536.  		exercise(A_WIS, TRUE);
537.  		if (spelleffects(sp_no, TRUE))
538.  			return(1);
539.  		else
540.  #ifdef WIZARD
541.  		    if (!wizard)
542.  #endif
543.  			return(0);
544.  	    } else {
545.  		u.uen -= energy;
546.  		flags.botl = 1;
547.  	    }
548.  	}
549.  
550.  	if (next_to_u()) {
551.  		if (trap && trap->once) vault_tele();
552.  		else tele();
553.  		(void) next_to_u();
554.  	} else {
555.  		You(shudder_for_moment);
556.  		return(0);
557.  	}
558.  	if (!trap) morehungry(100);
559.  	return(1);
560.  }
561.  
562.  

level_tele Edit

563.  void
564.  level_tele()
565.  {
566.  	register int newlev;
567.  	d_level newlevel;
568.  	const char *escape_by_flying = 0;	/* when surviving dest of -N */
569.  	char buf[BUFSZ];
570.  	boolean force_dest = FALSE;
571.  
572.  	if ((u.uhave.amulet || In_endgame(&u.uz) || In_sokoban(&u.uz))
573.  #ifdef WIZARD
574.  						&& !wizard
575.  #endif
576.  							) {
577.  	    You_feel("very disoriented for a moment.");
578.  	    return;
579.  	}
580.  	if ((Teleport_control && !Stunned)
581.  #ifdef WIZARD
582.  	   || wizard
583.  #endif
584.  		) {
585.  	    char qbuf[BUFSZ];
586.  	    int trycnt = 0;
587.  
588.  	    Strcpy(qbuf, "To what level do you want to teleport?");
589.  	    do {
590.  		if (++trycnt == 2) {
591.  #ifdef WIZARD
592.  			if (wizard) Strcat(qbuf, " [type a number or ? for a menu]");
593.  			else
594.  #endif
595.  			Strcat(qbuf, " [type a number]");
596.  		}
597.  		getlin(qbuf, buf);
598.  		if (!strcmp(buf,"\033")) {	/* cancelled */
599.  		    if (Confusion && rnl(5)) {
600.  			pline("Oops...");
601.  			goto random_levtport;
602.  		    }
603.  		    return;
604.  		} else if (!strcmp(buf,"*")) {
605.  		    goto random_levtport;
606.  		} else if (Confusion && rnl(5)) {
607.  		    pline("Oops...");
608.  		    goto random_levtport;
609.  		}
610.  #ifdef WIZARD
611.  		if (wizard && !strcmp(buf,"?")) {
612.  		    schar destlev = 0;
613.  		    xchar destdnum = 0;
614.  
615.  		    if ((newlev = (int)print_dungeon(TRUE, &destlev, &destdnum))) {
616.  			newlevel.dnum = destdnum;
617.  			newlevel.dlevel = destlev;
618.  			if (In_endgame(&newlevel) && !In_endgame(&u.uz)) {
619.  				Sprintf(buf,
620.  				    "Destination is earth level");
621.  				if (!u.uhave.amulet) {
622.  					struct obj *obj;
623.  					obj = mksobj(AMULET_OF_YENDOR,
624.  							TRUE, FALSE);
625.  					if (obj) {
626.  						obj = addinv(obj);
627.  						Strcat(buf, " with the amulet");
628.  					}
629.  				}
630.  				assign_level(&newlevel, &earth_level);
631.  				pline("%s.", buf);
632.  			}
633.  			force_dest = TRUE;
634.  		    } else return;
635.  		} else
636.  #endif
637.  		if ((newlev = lev_by_name(buf)) == 0) newlev = atoi(buf);
638.  	    } while (!newlev && !digit(buf[0]) &&
639.  		     (buf[0] != '-' || !digit(buf[1])) &&
640.  		     trycnt < 10);
641.  
642.  	    /* no dungeon escape via this route */
643.  	    if (newlev == 0) {
644.  		if (trycnt >= 10)
645.  		    goto random_levtport;
646.  		if (ynq("Go to Nowhere.  Are you sure?") != 'y') return;
647.  		You("%s in agony as your body begins to warp...",
648.  		    is_silent(youmonst.data) ? "writhe" : "scream");
649.  		display_nhwindow(WIN_MESSAGE, FALSE);
650.  		You("cease to exist.");
651.  		if (invent) Your("possessions land on the %s with a thud.",
652.  				surface(u.ux, u.uy));
653.  		killer_format = NO_KILLER_PREFIX;
654.  		killer = "committed suicide";
655.  		done(DIED);
656.  		pline("An energized cloud of dust begins to coalesce.");
657.  		Your("body rematerializes%s.", invent ?
658.  			", and you gather up all your possessions" : "");
659.  		return;
660.  	    }
661.  
662.  	    /* if in Knox and the requested level > 0, stay put.
663.  	     * we let negative values requests fall into the "heaven" loop.
664.  	     */
665.  	    if (Is_knox(&u.uz) && newlev > 0) {
666.  		You(shudder_for_moment);
667.  		return;
668.  	    }
669.  	    /* if in Quest, the player sees "Home 1", etc., on the status
670.  	     * line, instead of the logical depth of the level.  controlled
671.  	     * level teleport request is likely to be relativized to the
672.  	     * status line, and consequently it should be incremented to
673.  	     * the value of the logical depth of the target level.
674.  	     *
675.  	     * we let negative values requests fall into the "heaven" loop.
676.  	     */
677.  	    if (In_quest(&u.uz) && newlev > 0)
678.  		newlev = newlev + dungeons[u.uz.dnum].depth_start - 1;
679.  	} else { /* involuntary level tele */
680.   random_levtport:
681.  	    newlev = random_teleport_level();
682.  	    if (newlev == depth(&u.uz)) {
683.  		You(shudder_for_moment);
684.  		return;
685.  	    }
686.  	}
687.  
688.  	if (!next_to_u()) {
689.  		You(shudder_for_moment);
690.  		return;
691.  	}
692.  #ifdef WIZARD
693.  	if (In_endgame(&u.uz)) {	/* must already be wizard */
694.  	    int llimit = dunlevs_in_dungeon(&u.uz);
695.  
696.  	    if (newlev >= 0 || newlev <= -llimit) {
697.  		You_cant("get there from here.");
698.  		return;
699.  	    }
700.  	    newlevel.dnum = u.uz.dnum;
701.  	    newlevel.dlevel = llimit + newlev;
702.  	    schedule_goto(&newlevel, FALSE, FALSE, 0, (char *)0, (char *)0);
703.  	    return;
704.  	}
705.  #endif
706.  
707.  	killer = 0;		/* still alive, so far... */
708.  
709.  	if (newlev < 0 && !force_dest) {
710.  		if (*u.ushops0) {
711.  		    /* take unpaid inventory items off of shop bills */
712.  		    in_mklev = TRUE;	/* suppress map update */
713.  		    u_left_shop(u.ushops0, TRUE);
714.  		    /* you're now effectively out of the shop */
715.  		    *u.ushops0 = *u.ushops = '\0';
716.  		    in_mklev = FALSE;
717.  		}
718.  		if (newlev <= -10) {
719.  			You("arrive in heaven.");
720.  			verbalize("Thou art early, but we'll admit thee.");
721.  			killer_format = NO_KILLER_PREFIX;
722.  			killer = "went to heaven prematurely";
723.  		} else if (newlev == -9) {
724.  			You_feel("deliriously happy. ");
725.  			pline("(In fact, you're on Cloud 9!) ");
726.  			display_nhwindow(WIN_MESSAGE, FALSE);
727.  		} else
728.  			You("are now high above the clouds...");
729.  
730.  		if (killer) {
731.  		    ;		/* arrival in heaven is pending */
732.  		} else if (Levitation) {
733.  		    escape_by_flying = "float gently down to earth";
734.  		} else if (Flying) {
735.  		    escape_by_flying = "fly down to the ground";
736.  		} else {
737.  		    pline("Unfortunately, you don't know how to fly.");
738.  		    You("plummet a few thousand feet to your death.");
739.  		    Sprintf(buf,
740.  			  "teleported out of the dungeon and fell to %s death",
741.  			    uhis());
742.  		    killer = buf;
743.  		    killer_format = NO_KILLER_PREFIX;
744.  		}
745.  	}
746.  
747.  	if (killer) {	/* the chosen destination was not survivable */
748.  	    d_level lsav;
749.  
750.  	    /* set specific death location; this also suppresses bones */
751.  	    lsav = u.uz;	/* save current level, see below */
752.  	    u.uz.dnum = 0;	/* main dungeon */
753.  	    u.uz.dlevel = (newlev <= -10) ? -10 : 0;	/* heaven or surface */
754.  	    done(DIED);
755.  	    /* can only get here via life-saving (or declining to die in
756.  	       explore|debug mode); the hero has now left the dungeon... */
757.  	    escape_by_flying = "find yourself back on the surface";
758.  	    u.uz = lsav;	/* restore u.uz so escape code works */
759.  	}
760.  
761.  	/* calls done(ESCAPED) if newlevel==0 */
762.  	if (escape_by_flying) {
763.  	    You("%s.", escape_by_flying);
764.  	    newlevel.dnum = 0;		/* specify main dungeon */
765.  	    newlevel.dlevel = 0;	/* escape the dungeon */
766.  	    /* [dlevel used to be set to 1, but it doesn't make sense to
767.  		teleport out of the dungeon and float or fly down to the
768.  		surface but then actually arrive back inside the dungeon] */
769.  	} else if (u.uz.dnum == medusa_level.dnum &&
770.  	    newlev >= dungeons[u.uz.dnum].depth_start +
771.  						dunlevs_in_dungeon(&u.uz)) {
772.  #ifdef WIZARD
773.  	    if (!(wizard && force_dest))
774.  #endif
775.  	    find_hell(&newlevel);
776.  	} else {
777.  	    /* if invocation did not yet occur, teleporting into
778.  	     * the last level of Gehennom is forbidden.
779.  	     */
780.  #ifdef WIZARD
781.  		if (!wizard)
782.  #endif
783.  	    if (Inhell && !u.uevent.invoked &&
784.  			newlev >= (dungeons[u.uz.dnum].depth_start +
785.  					dunlevs_in_dungeon(&u.uz) - 1)) {
786.  		newlev = dungeons[u.uz.dnum].depth_start +
787.  					dunlevs_in_dungeon(&u.uz) - 2;
788.  		pline("Sorry...");
789.  	    }
790.  	    /* no teleporting out of quest dungeon */
791.  	    if (In_quest(&u.uz) && newlev < depth(&qstart_level))
792.  		newlev = depth(&qstart_level);
793.  	    /* the player thinks of levels purely in logical terms, so
794.  	     * we must translate newlev to a number relative to the
795.  	     * current dungeon.
796.  	     */
797.  #ifdef WIZARD
798.  	    if (!(wizard && force_dest))
799.  #endif
800.  	    get_level(&newlevel, newlev);
801.  	}
802.  	schedule_goto(&newlevel, FALSE, FALSE, 0, (char *)0, (char *)0);
803.  	/* in case player just read a scroll and is about to be asked to
804.  	   call it something, we can't defer until the end of the turn */
805.  	if (u.utotype && !flags.mon_moving) deferred_goto();
806.  }
807.  

domagicportal Edit

808.  void
809.  domagicportal(ttmp)
810.  register struct trap *ttmp;
811.  {
812.  	struct d_level target_level;
813.  
814.  	if (!next_to_u()) {
815.  		You(shudder_for_moment);
816.  		return;
817.  	}
818.  
819.  	/* if landed from another portal, do nothing */
820.  	/* problem: level teleport landing escapes the check */
821.  	if (!on_level(&u.uz, &u.uz0)) return;
822.  
823.  	You("activated a magic portal!");
824.  
825.  	/* prevent the poor shnook, whose amulet was stolen while in
826.  	 * the endgame, from accidently triggering the portal to the
827.  	 * next level, and thus losing the game
828.  	 */
829.  	if (In_endgame(&u.uz) && !u.uhave.amulet) {
830.  	    You_feel("dizzy for a moment, but nothing happens...");
831.  	    return;
832.  	}
833.  
834.  	target_level = ttmp->dst;
835.  	schedule_goto(&target_level, FALSE, FALSE, 1,
836.  		      "You feel dizzy for a moment, but the sensation passes.",
837.  		      (char *)0);
838.  }
839.  

tele_trap Edit

840.  void
841.  tele_trap(trap)
842.  struct trap *trap;
843.  {
844.  	if (In_endgame(&u.uz) || Antimagic) {
845.  		if (Antimagic)
846.  			shieldeff(u.ux, u.uy);
847.  		You_feel("a wrenching sensation.");
848.  	} else if (!next_to_u()) {
849.  		You(shudder_for_moment);
850.  	} else if (trap->once) {
851.  		deltrap(trap);
852.  		newsym(u.ux,u.uy);	/* get rid of trap symbol */
853.  		vault_tele();
854.  	} else
855.  		tele();
856.  }
857.  

level_tele_trap Edit

858.  void
859.  level_tele_trap(trap)
860.  struct trap *trap;
861.  {
862.  	You("%s onto a level teleport trap!",
863.  		      Levitation ? (const char *)"float" :
864.  				  locomotion(youmonst.data, "step"));
865.  	if (Antimagic) {
866.  	    shieldeff(u.ux, u.uy);
867.  	}
868.  	if (Antimagic || In_endgame(&u.uz)) {
869.  	    You_feel("a wrenching sensation.");
870.  	    return;
871.  	}
872.  	if (!Blind)
873.  	    You("are momentarily blinded by a flash of light.");
874.  	else
875.  	    You("are momentarily disoriented.");
876.  	deltrap(trap);
877.  	newsym(u.ux,u.uy);	/* get rid of trap symbol */
878.  	level_tele();
879.  }
880.  

rloc_pos_ok Edit

881.  /* check whether monster can arrive at location <x,y> via Tport (or fall) */
882.  STATIC_OVL boolean
883.  rloc_pos_ok(x, y, mtmp)
884.  register int x, y;		/* coordinates of candidate location */
885.  struct monst *mtmp;
886.  {
887.  	register int xx, yy;
888.  
889.  	if (!goodpos(x, y, mtmp, 0)) return FALSE;
890.  	/*
891.  	 * Check for restricted areas present in some special levels.
892.  	 *
893.  	 * `xx' is current column; if 0, then `yy' will contain flag bits
894.  	 * rather than row:  bit #0 set => moving upwards; bit #1 set =>
895.  	 * inside the Wizard's tower.
896.  	 */
897.  	xx = mtmp->mx;
898.  	yy = mtmp->my;
899.  	if (!xx) {
900.  	    /* no current location (migrating monster arrival) */
901.  	    if (dndest.nlx && On_W_tower_level(&u.uz))
902.  		return ((yy & 2) != 0) ^	/* inside xor not within */
903.  		       !within_bounded_area(x, y, dndest.nlx, dndest.nly,
904.  						  dndest.nhx, dndest.nhy);
905.  	    if (updest.lx && (yy & 1) != 0)	/* moving up */
906.  		return (within_bounded_area(x, y, updest.lx, updest.ly,
907.  						  updest.hx, updest.hy) &&
908.  		       (!updest.nlx ||
909.  			!within_bounded_area(x, y, updest.nlx, updest.nly,
910.  						   updest.nhx, updest.nhy)));
911.  	    if (dndest.lx && (yy & 1) == 0)	/* moving down */
912.  		return (within_bounded_area(x, y, dndest.lx, dndest.ly,
913.  						  dndest.hx, dndest.hy) &&
914.  		       (!dndest.nlx ||
915.  			!within_bounded_area(x, y, dndest.nlx, dndest.nly,
916.  						   dndest.nhx, dndest.nhy)));
917.  	} else {
918.  	    /* current location is <xx,yy> */
919.  	    if (!tele_jump_ok(xx, yy, x, y)) return FALSE;
920.  	}
921.  	/* <x,y> is ok */
922.  	return TRUE;
923.  }
924.  

rloc_to Edit

925.  /*
926.   * rloc_to()
927.   *
928.   * Pulls a monster from its current position and places a monster at
929.   * a new x and y.  If oldx is 0, then the monster was not in the levels.monsters
930.   * array.  However, if oldx is 0, oldy may still have a value because mtmp is a
931.   * migrating_mon.  Worm tails are always placed randomly around the head of
932.   * the worm.
933.   */
934.  void
935.  rloc_to(mtmp, x, y)
936.  struct monst *mtmp;
937.  register int x, y;
938.  {
939.  	register int oldx = mtmp->mx, oldy = mtmp->my;
940.  	boolean resident_shk = mtmp->isshk && inhishop(mtmp);
941.  
942.  	if (x == mtmp->mx && y == mtmp->my)	/* that was easy */
943.  		return;
944.  
945.  	if (oldx) {				/* "pick up" monster */
946.  	    if (mtmp->wormno)
947.  		remove_worm(mtmp);
948.  	    else {
949.  		remove_monster(oldx, oldy);
950.  		newsym(oldx, oldy);		/* update old location */
951.  	    }
952.  	}
953.  
954.  	place_monster(mtmp, x, y);		/* put monster down */
955.  	update_monster_region(mtmp);
956.  
957.  	if (mtmp->wormno)			/* now put down tail */
958.  		place_worm_tail_randomly(mtmp, x, y);
959.  
960.  	if (u.ustuck == mtmp) {
961.  		if (u.uswallow) {
962.  			u.ux = x;
963.  			u.uy = y;
964.  			docrt();
965.  		} else	u.ustuck = 0;
966.  	}
967.  
968.  	newsym(x, y);				/* update new location */
969.  	set_apparxy(mtmp);			/* orient monster */
970.  
971.  	/* shopkeepers will only teleport if you zap them with a wand of
972.  	   teleportation or if they've been transformed into a jumpy monster;
973.  	   the latter only happens if you've attacked them with polymorph */
974.  	if (resident_shk && !inhishop(mtmp)) make_angry_shk(mtmp, oldx, oldy);
975.  }
976.  

rloc Edit

977.  /* place a monster at a random location, typically due to teleport */
978.  /* return TRUE if successful, FALSE if not */
979.  boolean
980.  rloc(mtmp, suppress_impossible)
981.  struct monst *mtmp;	/* mx==0 implies migrating monster arrival */
982.  boolean suppress_impossible;
983.  {
984.  	register int x, y, trycount;
985.  
986.  #ifdef STEED
987.  	if (mtmp == u.usteed) {
988.  	    tele();
989.  	    return TRUE;
990.  	}
991.  #endif
992.  
993.  	if (mtmp->iswiz && mtmp->mx) {	/* Wizard, not just arriving */
994.  	    if (!In_W_tower(u.ux, u.uy, &u.uz))
995.  		x = xupstair,  y = yupstair;
996.  	    else if (!xdnladder)	/* bottom level of tower */
997.  		x = xupladder,  y = yupladder;
998.  	    else
999.  		x = xdnladder,  y = ydnladder;
1000. 	    /* if the wiz teleports away to heal, try the up staircase,
1001. 	       to block the player's escaping before he's healed
1002. 	       (deliberately use `goodpos' rather than `rloc_pos_ok' here) */
1003. 	    if (goodpos(x, y, mtmp, 0))
1004. 		goto found_xy;
1005. 	}
1006. 
1007. 	trycount = 0;
1008. 	do {
1009. 	    x = rn1(COLNO-3,2);
1010. 	    y = rn2(ROWNO);
1011. 	    if ((trycount < 500) ? rloc_pos_ok(x, y, mtmp)
1012. 				 : goodpos(x, y, mtmp, 0))
1013. 		goto found_xy;
1014. 	} while (++trycount < 1000);
1015. 
1016. 	/* last ditch attempt to find a good place */
1017. 	for (x = 2; x < COLNO - 1; x++)
1018. 	    for (y = 0; y < ROWNO; y++)
1019. 		if (goodpos(x, y, mtmp, 0))
1020. 		    goto found_xy;
1021. 
1022. 	/* level either full of monsters or somehow faulty */
1023. 	if (!suppress_impossible)
1024. 		impossible("rloc(): couldn't relocate monster");
1025. 	return FALSE;
1026. 
1027.  found_xy:
1028. 	rloc_to(mtmp, x, y);
1029. 	return TRUE;
1030. }
1031. 

mvault_tele Edit

1032. STATIC_OVL void
1033. mvault_tele(mtmp)
1034. struct monst *mtmp;
1035. {
1036. 	register struct mkroom *croom = search_special(VAULT);
1037. 	coord c;
1038. 
1039. 	if (croom && somexy(croom, &c) &&
1040. 				goodpos(c.x, c.y, mtmp, 0)) {
1041. 		rloc_to(mtmp, c.x, c.y);
1042. 		return;
1043. 	}
1044. 	(void) rloc(mtmp, FALSE);
1045. }
1046. 

tele_restrict Edit

1047. boolean
1048. tele_restrict(mon)
1049. struct monst *mon;
1050. {
1051. 	if (level.flags.noteleport) {
1052. 		if (canseemon(mon))
1053. 		    pline("A mysterious force prevents %s from teleporting!",
1054. 			mon_nam(mon));
1055. 		return TRUE;
1056. 	}
1057. 	return FALSE;
1058. }
1059. 

mtele_trap Edit

1060. void
1061. mtele_trap(mtmp, trap, in_sight)
1062. struct monst *mtmp;
1063. struct trap *trap;
1064. int in_sight;
1065. {
1066. 	char *monname;
1067. 
1068. 	if (tele_restrict(mtmp)) return;
1069. 	if (teleport_pet(mtmp, FALSE)) {
1070. 	    /* save name with pre-movement visibility */
1071. 	    monname = Monnam(mtmp);
1072. 
1073. 	    /* Note: don't remove the trap if a vault.  Other-
1074. 	     * wise the monster will be stuck there, since
1075. 	     * the guard isn't going to come for it...
1076. 	     */
1077. 	    if (trap->once) mvault_tele(mtmp);
1078. 	    else (void) rloc(mtmp, FALSE);
1079. 
1080. 	    if (in_sight) {
1081. 		if (canseemon(mtmp))
1082. 		    pline("%s seems disoriented.", monname);
1083. 		else
1084. 		    pline("%s suddenly disappears!", monname);
1085. 		seetrap(trap);
1086. 	    }
1087. 	}
1088. }
1089. 

mlevel_tele_trap Edit

1090. /* return 0 if still on level, 3 if not */
1091. int
1092. mlevel_tele_trap(mtmp, trap, force_it, in_sight)
1093. struct monst *mtmp;
1094. struct trap *trap;
1095. boolean force_it;
1096. int in_sight;
1097. {
1098. 	int tt = trap->ttyp;
1099. 	struct permonst *mptr = mtmp->data;
1100. 
1101. 	if (mtmp == u.ustuck)	/* probably a vortex */
1102. 	    return 0;		/* temporary? kludge */
1103. 	if (teleport_pet(mtmp, force_it)) {
1104. 	    d_level tolevel;
1105. 	    int migrate_typ = MIGR_RANDOM;
1106. 
1107. 	    if ((tt == HOLE || tt == TRAPDOOR)) {
1108. 		if (Is_stronghold(&u.uz)) {
1109. 		    assign_level(&tolevel, &valley_level);
1110. 		} else if (Is_botlevel(&u.uz)) {
1111. 		    if (in_sight && trap->tseen)
1112. 			pline("%s avoids the %s.", Monnam(mtmp),
1113. 			(tt == HOLE) ? "hole" : "trap");
1114. 		    return 0;
1115. 		} else {
1116. 		    get_level(&tolevel, depth(&u.uz) + 1);
1117. 		}
1118. 	    } else if (tt == MAGIC_PORTAL) {
1119. 		if (In_endgame(&u.uz) &&
1120. 		    (mon_has_amulet(mtmp) || is_home_elemental(mptr))) {
1121. 		    if (in_sight && mptr->mlet != S_ELEMENTAL) {
1122. 			pline("%s seems to shimmer for a moment.",
1123. 							Monnam(mtmp));
1124. 			seetrap(trap);
1125. 		    }
1126. 		    return 0;
1127. 		} else {
1128. 		    assign_level(&tolevel, &trap->dst);
1129. 		    migrate_typ = MIGR_PORTAL;
1130. 		}
1131. 	    } else { /* (tt == LEVEL_TELEP) */
1132. 		int nlev;
1133. 
1134. 		if (mon_has_amulet(mtmp) || In_endgame(&u.uz)) {
1135. 		    if (in_sight)
1136. 			pline("%s seems very disoriented for a moment.",
1137. 				Monnam(mtmp));
1138. 		    return 0;
1139. 		}
1140. 		nlev = random_teleport_level();
1141. 		if (nlev == depth(&u.uz)) {
1142. 		    if (in_sight)
1143. 			pline("%s shudders for a moment.", Monnam(mtmp));
1144. 		    return 0;
1145. 		}
1146. 		get_level(&tolevel, nlev);
1147. 	    }
1148. 
1149. 	    if (in_sight) {
1150. 		pline("Suddenly, %s disappears out of sight.", mon_nam(mtmp));
1151. 		seetrap(trap);
1152. 	    }
1153. 	    migrate_to_level(mtmp, ledger_no(&tolevel),
1154. 			     migrate_typ, (coord *)0);
1155. 	    return 3;	/* no longer on this level */
1156. 	}
1157. 	return 0;
1158. }
1159. 
1160. 

rloco Edit

1161. void
1162. rloco(obj)
1163. register struct obj *obj;
1164. {
1165. 	register xchar tx, ty, otx, oty;
1166. 	boolean restricted_fall;
1167. 	int try_limit = 4000;
1168. 
1169. 	if (obj->otyp == CORPSE && is_rider(&mons[obj->corpsenm])) {
1170. 	    if (revive_corpse(obj)) return;
1171. 	}
1172. 
1173. 	obj_extract_self(obj);
1174. 	otx = obj->ox;
1175. 	oty = obj->oy;
1176. 	restricted_fall = (otx == 0 && dndest.lx);
1177. 	do {
1178. 	    tx = rn1(COLNO-3,2);
1179. 	    ty = rn2(ROWNO);
1180. 	    if (!--try_limit) break;
1181. 	} while (!goodpos(tx, ty, (struct monst *)0, 0) ||
1182. 		/* bug: this lacks provision for handling the Wizard's tower */
1183. 		 (restricted_fall &&
1184. 		  (!within_bounded_area(tx, ty, dndest.lx, dndest.ly,
1185. 						dndest.hx, dndest.hy) ||
1186. 		   (dndest.nlx &&
1187. 		    within_bounded_area(tx, ty, dndest.nlx, dndest.nly,
1188. 						dndest.nhx, dndest.nhy)))));
1189. 
1190. 	if (flooreffects(obj, tx, ty, "fall")) {
1191. 	    return;
1192. 	} else if (otx == 0 && oty == 0) {
1193. 	    ;	/* fell through a trap door; no update of old loc needed */
1194. 	} else {
1195. 	    if (costly_spot(otx, oty)
1196. 	      && (!costly_spot(tx, ty) ||
1197. 		  !index(in_rooms(tx, ty, 0), *in_rooms(otx, oty, 0)))) {
1198. 		if (costly_spot(u.ux, u.uy) &&
1199. 			    index(u.urooms, *in_rooms(otx, oty, 0)))
1200. 		    addtobill(obj, FALSE, FALSE, FALSE);
1201. 		else (void)stolen_value(obj, otx, oty, FALSE, FALSE);
1202. 	    }
1203. 	    newsym(otx, oty);	/* update old location */
1204. 	}
1205. 	place_object(obj, tx, ty);
1206. 	newsym(tx, ty);
1207. }
1208. 

random_teleport_level Edit

1209. /* Returns an absolute depth */
1210. int
1211. random_teleport_level()
1212. {
1213. 	int nlev, max_depth, min_depth,
1214. 	    cur_depth = (int)depth(&u.uz);
1215. 
1216. 	if (!rn2(5) || Is_knox(&u.uz))
1217. 	    return cur_depth;
1218. 
1219. 	/* What I really want to do is as follows:
1220. 	 * -- If in a dungeon that goes down, the new level is to be restricted
1221. 	 *    to [top of parent, bottom of current dungeon]
1222. 	 * -- If in a dungeon that goes up, the new level is to be restricted
1223. 	 *    to [top of current dungeon, bottom of parent]
1224. 	 * -- If in a quest dungeon or similar dungeon entered by portals,
1225. 	 *    the new level is to be restricted to [top of current dungeon,
1226. 	 *    bottom of current dungeon]
1227. 	 * The current behavior is not as sophisticated as that ideal, but is
1228. 	 * still better what we used to do, which was like this for players
1229. 	 * but different for monsters for no obvious reason.  Currently, we
1230. 	 * must explicitly check for special dungeons.  We check for Knox
1231. 	 * above; endgame is handled in the caller due to its different
1232. 	 * message ("disoriented").
1233. 	 * --KAA
1234. 	 * 3.4.2: explicitly handle quest here too, to fix the problem of
1235. 	 * monsters sometimes level teleporting out of it into main dungeon.
1236. 	 * Also prevent monsters reaching the Sanctum prior to invocation.
1237. 	 */
1238. 	min_depth = In_quest(&u.uz) ? dungeons[u.uz.dnum].depth_start : 1;
1239. 	max_depth = dunlevs_in_dungeon(&u.uz) +
1240. 			(dungeons[u.uz.dnum].depth_start - 1);
1241. 	/* can't reach the Sanctum if the invocation hasn't been performed */
1242. 	if (Inhell && !u.uevent.invoked) max_depth -= 1;
1243. 
1244. 	/* Get a random value relative to the current dungeon */
1245. 	/* Range is 1 to current+3, current not counting */
1246. 	nlev = rn2(cur_depth + 3 - min_depth) + min_depth;
1247. 	if (nlev >= cur_depth) nlev++;
1248. 
1249. 	if (nlev > max_depth) {
1250. 	    nlev = max_depth;
1251. 	    /* teleport up if already on bottom */
1252. 	    if (Is_botlevel(&u.uz)) nlev -= rnd(3);
1253. 	}
1254. 	if (nlev < min_depth) {
1255. 	    nlev = min_depth;
1256. 	    if (nlev == cur_depth) {
1257. 	        nlev += rnd(3);
1258. 	        if (nlev > max_depth)
1259. 		    nlev = max_depth;
1260. 	    }
1261. 	}
1262. 	return nlev;
1263. }
1264. 

u_teleport_mon Edit

1265. /* you teleport a monster (via wand, spell, or poly'd q.mechanic attack);
1266.    return false iff the attempt fails */
1267. boolean
1268. u_teleport_mon(mtmp, give_feedback)
1269. struct monst *mtmp;
1270. boolean give_feedback;
1271. {
1272. 	coord cc;
1273. 
1274. 	if (mtmp->ispriest && *in_rooms(mtmp->mx, mtmp->my, TEMPLE)) {
1275. 	    if (give_feedback)
1276. 		pline("%s resists your magic!", Monnam(mtmp));
1277. 	    return FALSE;
1278. 	} else if (level.flags.noteleport && u.uswallow && mtmp == u.ustuck) {
1279. 	    if (give_feedback)
1280. 		You("are no longer inside %s!", mon_nam(mtmp));
1281. 	    unstuck(mtmp);
1282. 	    (void) rloc(mtmp, FALSE);
1283. 	} else if (is_rider(mtmp->data) && rn2(13) &&
1284. 		   enexto(&cc, u.ux, u.uy, mtmp->data))
1285. 	    rloc_to(mtmp, cc.x, cc.y);
1286. 	else
1287. 	    (void) rloc(mtmp, FALSE);
1288. 	return TRUE;
1289. }
1290. 
1291. /*teleport.c*/

Also on Fandom

Random Wiki