Wikia

Wikihack

Source:NetHack 3.4.0/teleport.c

2,032pages on
this wiki
Talk0

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

Warning! This is the source code from an old release. For the latest release, see Source code

The NetHack General Public License applies to screenshots, source code and other content from NetHack.
1.    /*	SCCS Id: @(#)teleport.c	3.4	2002/03/09	*/
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 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)
22.   int x,y;
23.   struct monst *mtmp;
24.   {
25.   	struct permonst *mdat = NULL;
26.   
27.   	if (!isok(x, y)) return FALSE;
28.   
29.   	/* in many cases, we're trying to create a new monster, which
30.   	 * can't go on top of the player or any existing monster.
31.   	 * however, occasionally we are relocating engravings or objects,
32.   	 * which could be co-located and thus get restricted a bit too much.
33.   	 * oh well.
34.   	 */
35.   	if (mtmp != &youmonst && x == u.ux && y == u.uy
36.   #ifdef STEED
37.   			&& (!u.usteed || mtmp != u.usteed)
38.   #endif
39.   			)
40.   		return FALSE;
41.   
42.   	if (mtmp) {
43.   	    struct monst *mtmp2 = m_at(x,y);
44.   
45.   	    if (mtmp2 && mtmp2 != mtmp)
46.   		return FALSE;
47.   
48.   	    mdat = mtmp->data;
49.   	    if (is_pool(x,y)) {
50.   		if (mtmp == &youmonst)
51.   			return !!(HLevitation || Flying || Wwalking ||
52.   					Swimming || Amphibious);
53.   		else	return (is_flyer(mdat) || is_swimmer(mdat) ||
54.   							is_clinger(mdat));
55.   	    } else if (mdat->mlet == S_EEL && rn2(13)) {
56.   		return FALSE;
57.   	    } else if (is_lava(x,y)) {
58.   		if (mtmp == &youmonst)
59.   		    return !!HLevitation;
60.   		else
61.   		    return (is_flyer(mdat) || likes_lava(mdat));
62.   	    }
63.   	    if (passes_walls(mdat) && may_passwall(x,y)) return TRUE;
64.   	}
65.   	if (!ACCESSIBLE(levl[x][y].typ)) return FALSE;
66.   	if (closed_door(x, y) && (!mdat || !amorphous(mdat)))
67.   		return FALSE;
68.   	if (sobj_at(BOULDER, x, y) && (!mdat || !throws_rocks(mdat)))
69.   		return FALSE;
70.   	return TRUE;
71.   }
72.   
73.   /*
74.    * "entity next to"
75.    *
76.    * Attempt to find a good place for the given monster type in the closest
77.    * position to (xx,yy).  Do so in successive square rings around (xx,yy).
78.    * If there is more than one valid positon in the ring, choose one randomly.
79.    * Return TRUE and the position chosen when successful, FALSE otherwise.
80.    */
81.   boolean
82.   enexto(cc, xx, yy, mdat)
83.   coord *cc;
84.   register xchar xx, yy;
85.   struct permonst *mdat;
86.   {
87.   #define MAX_GOOD 15
88.       coord good[MAX_GOOD], *good_ptr;
89.       int x, y, range, i;
90.       int xmin, xmax, ymin, ymax;
91.       struct monst fakemon;	/* dummy monster */
92.   
93.       if (!mdat) {
94.   #ifdef DEBUG
95.   	pline("enexto() called with mdat==0");
96.   #endif
97.   	/* default to player's original monster type */
98.   	mdat = &mons[u.umonster];
99.       }
100.      fakemon.data = mdat;	/* set up for goodpos */
101.      good_ptr = good;
102.      range = 1;
103.      /*
104.       * Walk around the border of the square with center (xx,yy) and
105.       * radius range.  Stop when we find at least one valid position.
106.       */
107.      do {
108.  	xmin = max(1, xx-range);
109.  	xmax = min(COLNO-1, xx+range);
110.  	ymin = max(0, yy-range);
111.  	ymax = min(ROWNO-1, yy+range);
112.  
113.  	for (x = xmin; x <= xmax; x++)
114.  	    if (goodpos(x, ymin, &fakemon)) {
115.  		good_ptr->x = x;
116.  		good_ptr->y = ymin ;
117.  		/* beware of accessing beyond segment boundaries.. */
118.  		if (good_ptr++ == &good[MAX_GOOD-1]) goto full;
119.  	    }
120.  	for (x = xmin; x <= xmax; x++)
121.  	    if (goodpos(x, ymax, &fakemon)) {
122.  		good_ptr->x = x;
123.  		good_ptr->y = ymax ;
124.  		/* beware of accessing beyond segment boundaries.. */
125.  		if (good_ptr++ == &good[MAX_GOOD-1]) goto full;
126.  	    }
127.  	for (y = ymin+1; y < ymax; y++)
128.  	    if (goodpos(xmin, y, &fakemon)) {
129.  		good_ptr->x = xmin;
130.  		good_ptr-> y = y ;
131.  		/* beware of accessing beyond segment boundaries.. */
132.  		if (good_ptr++ == &good[MAX_GOOD-1]) goto full;
133.  	    }
134.  	for (y = ymin+1; y < ymax; y++)
135.  	    if (goodpos(xmax, y, &fakemon)) {
136.  		good_ptr->x = xmax;
137.  		good_ptr->y = y ;
138.  		/* beware of accessing beyond segment boundaries.. */
139.  		if (good_ptr++ == &good[MAX_GOOD-1]) goto full;
140.  	    }
141.  	range++;
142.  
143.  	/* return if we've grown too big (nothing is valid) */
144.  	if (range > ROWNO && range > COLNO) return FALSE;
145.      } while (good_ptr == good);
146.  
147.  full:
148.      i = rn2((int)(good_ptr - good));
149.      cc->x = good[i].x;
150.      cc->y = good[i].y;
151.      return TRUE;
152.  }
153.  
154.  /*
155.   * Check for restricted areas present in some special levels.  (This might
156.   * need to be augmented to allow deliberate passage in wizard mode, but
157.   * only for explicitly chosen destinations.)
158.   */
159.  STATIC_OVL boolean
160.  tele_jump_ok(x1, y1, x2, y2)
161.  int x1, y1, x2, y2;
162.  {
163.  	if (dndest.nlx > 0) {
164.  	    /* if inside a restricted region, can't teleport outside */
165.  	    if (within_bounded_area(x1, y1, dndest.nlx, dndest.nly,
166.  						dndest.nhx, dndest.nhy) &&
167.  		!within_bounded_area(x2, y2, dndest.nlx, dndest.nly,
168.  						dndest.nhx, dndest.nhy))
169.  		return FALSE;
170.  	    /* and if outside, can't teleport inside */
171.  	    if (!within_bounded_area(x1, y1, dndest.nlx, dndest.nly,
172.  						dndest.nhx, dndest.nhy) &&
173.  		within_bounded_area(x2, y2, dndest.nlx, dndest.nly,
174.  						dndest.nhx, dndest.nhy))
175.  		return FALSE;
176.  	}
177.  	if (updest.nlx > 0) {		/* ditto */
178.  	    if (within_bounded_area(x1, y1, updest.nlx, updest.nly,
179.  						updest.nhx, updest.nhy) &&
180.  		!within_bounded_area(x2, y2, updest.nlx, updest.nly,
181.  						updest.nhx, updest.nhy))
182.  		return FALSE;
183.  	    if (!within_bounded_area(x1, y1, updest.nlx, updest.nly,
184.  						updest.nhx, updest.nhy) &&
185.  		within_bounded_area(x2, y2, updest.nlx, updest.nly,
186.  						updest.nhx, updest.nhy))
187.  		return FALSE;
188.  	}
189.  	return TRUE;
190.  }
191.  
192.  STATIC_OVL boolean
193.  teleok(x, y, trapok)
194.  register int x, y;
195.  boolean trapok;
196.  {
197.  	if (!trapok && t_at(x, y)) return FALSE;
198.  	if (!goodpos(x, y, &youmonst)) return FALSE;
199.  	if (!tele_jump_ok(u.ux, u.uy, x, y)) return FALSE;
200.  	return TRUE;
201.  }
202.  
203.  void
204.  teleds(nux, nuy)
205.  register int nux,nuy;
206.  {
207.  	boolean dont_teleport_ball = FALSE;
208.  
209.  	if (Punished) {
210.  	    /* If they're teleporting to a position where the ball doesn't need
211.  	     * to be moved, don't place the ball.  Especially useful when this
212.  	     * function is being called for crawling out of water instead of
213.  	     * real teleportation.
214.  	     */
215.  	    if (!carried(uball) && distmin(nux, nuy, uball->ox, uball->oy) <= 2)
216.  		dont_teleport_ball = TRUE;
217.  	    else
218.  		unplacebc();
219.  	}
220.  	u.utrap = 0;
221.  	u.ustuck = 0;
222.  	u.ux0 = u.ux;
223.  	u.uy0 = u.uy;
224.  	u.ux = nux;
225.  	u.uy = nuy;
226.  	fill_pit(u.ux0, u.uy0); /* do this now so that cansee() is correct */
227.  
228.  	if (hides_under(youmonst.data))
229.  		u.uundetected = OBJ_AT(nux, nuy);
230.  	else if (youmonst.data->mlet == S_EEL)
231.  		u.uundetected = is_pool(u.ux, u.uy);
232.  	else {
233.  		u.uundetected = 0;
234.  		/* mimics stop being unnoticed */
235.  		if (youmonst.data->mlet == S_MIMIC)
236.  		    youmonst.m_ap_type = M_AP_NOTHING;
237.  	}
238.  
239.  	if (u.uswallow) {
240.  		u.uswldtim = u.uswallow = 0;
241.  		docrt();
242.  	}
243.  	if (Punished) {
244.  	    if (dont_teleport_ball) {
245.  		int bc_control;
246.  		xchar ballx, bally, chainx, chainy;
247.  		boolean cause_delay;
248.  
249.  		/* this should only drag the chain (and never give a near-
250.  		   capacity message) since we already checked ball distance */
251.  		(void) drag_ball(u.ux, u.uy, &bc_control, &ballx, &bally,
252.  					&chainx, &chainy, &cause_delay);
253.  		move_bc(0, bc_control, ballx, bally, chainx, chainy);
254.  	    } else
255.  		 placebc();
256.  	}
257.  	initrack(); /* teleports mess up tracking monsters without this */
258.  	update_player_regions();
259.  #ifdef STEED
260.  	/* Move your steed, too */
261.  	if (u.usteed) {
262.  		u.usteed->mx = nux;
263.  		u.usteed->my = nuy;
264.  	}
265.  #endif
266.  	/*
267.  	 *  Make sure the hero disappears from the old location.  This will
268.  	 *  not happen if she is teleported within sight of her previous
269.  	 *  location.  Force a full vision recalculation because the hero
270.  	 *  is now in a new location.
271.  	 */
272.  	newsym(u.ux0,u.uy0);
273.  	see_monsters();
274.  	vision_full_recalc = 1;
275.  	nomul(0);
276.  	vision_recalc(0);	/* vision before effects */
277.  	spoteffects(TRUE);
278.  	invocation_message();
279.  }
280.  
281.  boolean
282.  safe_teleds()
283.  {
284.  	register int nux, nuy, tcnt = 0;
285.  
286.  	do {
287.  		nux = rnd(COLNO-1);
288.  		nuy = rn2(ROWNO);
289.  	} while (!teleok(nux, nuy, (boolean)(tcnt > 200)) && ++tcnt <= 400);
290.  
291.  	if (tcnt <= 400) {
292.  		teleds(nux, nuy);
293.  		return TRUE;
294.  	} else
295.  		return FALSE;
296.  }
297.  
298.  STATIC_OVL void
299.  vault_tele()
300.  {
301.  	register struct mkroom *croom = search_special(VAULT);
302.  	coord c;
303.  
304.  	if (croom && somexy(croom, &c) && teleok(c.x,c.y,FALSE)) {
305.  		teleds(c.x,c.y);
306.  		return;
307.  	}
308.  	tele();
309.  }
310.  
311.  boolean
312.  teleport_pet(mtmp, force_it)
313.  register struct monst *mtmp;
314.  boolean force_it;
315.  {
316.  	register struct obj *otmp;
317.  
318.  #ifdef STEED
319.  	if (mtmp == u.usteed)
320.  		return (FALSE);
321.  #endif
322.  
323.  	if (mtmp->mleashed) {
324.  	    otmp = get_mleash(mtmp);
325.  	    if (!otmp) {
326.  		impossible("%s is leashed, without a leash.", Monnam(mtmp));
327.  		goto release_it;
328.  	    }
329.  	    if (otmp->cursed && !force_it) {
330.  		yelp(mtmp);
331.  		return FALSE;
332.  	    } else {
333.  		Your("leash goes slack.");
334.   release_it:
335.  		m_unleash(mtmp, FALSE);
336.  		return TRUE;
337.  	    }
338.  	}
339.  	return TRUE;
340.  }
341.  
342.  void
343.  tele()
344.  {
345.  	coord cc;
346.  
347.  	/* Disable teleportation in stronghold && Vlad's Tower */
348.  	if (level.flags.noteleport) {
349.  #ifdef WIZARD
350.  		if (!wizard) {
351.  #endif
352.  		    pline("A mysterious force prevents you from teleporting!");
353.  		    return;
354.  #ifdef WIZARD
355.  		}
356.  #endif
357.  	}
358.  
359.  	/* don't show trap if "Sorry..." */
360.  	if (!Blinded) make_blinded(0L,FALSE);
361.  
362.  	if ((u.uhave.amulet || On_W_tower_level(&u.uz)) && !rn2(3)) {
363.  	    You_feel("disoriented for a moment.");
364.  	    return;
365.  	}
366.  	if (Teleport_control
367.  #ifdef WIZARD
368.  			    || wizard
369.  #endif
370.  					) {
371.  	    if (unconscious()) {
372.  		pline("Being unconscious, you cannot control your teleport.");
373.  	    } else {
374.  #ifdef STEED
375.  		    char buf[BUFSZ];
376.  		    if (u.usteed) Sprintf(buf," and %s", mon_nam(u.usteed));
377.  #endif
378.  		    pline("To what position do you%s want to be teleported?",
379.  #ifdef STEED
380.  				u.usteed ? buf :
381.  #endif
382.  			   "");
383.  		    cc.x = u.ux;
384.  		    cc.y = u.uy;
385.  		    if (getpos(&cc, TRUE, "the desired position") < 0)
386.  			return;	/* abort */
387.  		    /* possible extensions: introduce a small error if
388.  		       magic power is low; allow transfer to solid rock */
389.  		    if (teleok(cc.x, cc.y, FALSE)) {
390.  			teleds(cc.x, cc.y);
391.  			return;
392.  		    }
393.  		    pline("Sorry...");
394.  		}
395.  	}
396.  
397.  	(void) safe_teleds();
398.  }
399.  
400.  int
401.  dotele()
402.  {
403.  	struct trap *trap;
404.  
405.  	trap = t_at(u.ux, u.uy);
406.  	if (trap && (!trap->tseen || trap->ttyp != TELEP_TRAP))
407.  		trap = 0;
408.  
409.  	if (trap) {
410.  		if (trap->once) {
411.  			pline("This is a vault teleport, usable once only.");
412.  			if (yn("Jump in?") == 'n')
413.  				trap = 0;
414.  			else {
415.  				deltrap(trap);
416.  				newsym(u.ux, u.uy);
417.  			}
418.  		}
419.  		if (trap)
420.  			You("%s onto the teleportation trap.",
421.  			    locomotion(youmonst.data, "jump"));
422.  	}
423.  	if (!trap) {
424.  	    boolean castit = FALSE;
425.  	    register int sp_no = 0, energy = 0;
426.  
427.  	    if (!Teleportation || (u.ulevel < (Role_if(PM_WIZARD) ? 8 : 12)
428.  					&& !can_teleport(youmonst.data))) {
429.  		/* Try to use teleport away spell. */
430.  		if (objects[SPE_TELEPORT_AWAY].oc_name_known && !Confusion)
431.  		    for (sp_no = 0; sp_no < MAXSPELL; sp_no++)
432.  			if (spl_book[sp_no].sp_id == SPE_TELEPORT_AWAY) {
433.  				castit = TRUE;
434.  				break;
435.  			}
436.  #ifdef WIZARD
437.  		if (!wizard) {
438.  #endif
439.  		    if (!castit) {
440.  			if (!Teleportation)
441.  			    You("don't know that spell.");
442.  			else You("are not able to teleport at will.");
443.  			return(0);
444.  		    }
445.  #ifdef WIZARD
446.  		}
447.  #endif
448.  	    }
449.  
450.  	    if (u.uhunger <= 100 || ACURR(A_STR) < 6) {
451.  #ifdef WIZARD
452.  		if (!wizard) {
453.  #endif
454.  			You("lack the strength %s.",
455.  			    castit ? "for a teleport spell" : "to teleport");
456.  			return 1;
457.  #ifdef WIZARD
458.  		}
459.  #endif
460.  	    }
461.  
462.  	    energy = objects[SPE_TELEPORT_AWAY].oc_level * 7 / 2 - 2;
463.  	    if (u.uen <= energy) {
464.  #ifdef WIZARD
465.  		if (wizard)
466.  			energy = u.uen;
467.  		else
468.  #endif
469.  		{
470.  			You("lack the energy %s.",
471.  			    castit ? "for a teleport spell" : "to teleport");
472.  			return 1;
473.  		}
474.  	    }
475.  
476.  	    if (check_capacity(
477.  			"Your concentration falters from carrying so much."))
478.  		return 1;
479.  
480.  	    if (castit) {
481.  		exercise(A_WIS, TRUE);
482.  		if (spelleffects(sp_no, TRUE))
483.  			return(1);
484.  		else
485.  #ifdef WIZARD
486.  		    if (!wizard)
487.  #endif
488.  			return(0);
489.  	    } else {
490.  		u.uen -= energy;
491.  		flags.botl = 1;
492.  	    }
493.  	}
494.  
495.  	if (next_to_u()) {
496.  		if (trap && trap->once) vault_tele();
497.  		else tele();
498.  		(void) next_to_u();
499.  	} else {
500.  		You(shudder_for_moment);
501.  		return(0);
502.  	}
503.  	if (!trap) morehungry(100);
504.  	return(1);
505.  }
506.  
507.  
508.  void
509.  level_tele()
510.  {
511.  	register int newlev;
512.  	d_level newlevel;
513.  	const char *escape_by_flying = 0;	/* when surviving dest of -N */
514.  	char buf[BUFSZ];
515.  
516.  	if ((u.uhave.amulet || In_endgame(&u.uz) || In_sokoban(&u.uz))
517.  #ifdef WIZARD
518.  						&& !wizard
519.  #endif
520.  							) {
521.  	    You_feel("very disoriented for a moment.");
522.  	    return;
523.  	}
524.  	if (Teleport_control
525.  #ifdef WIZARD
526.  	   || wizard
527.  #endif
528.  		) {
529.  	    char qbuf[BUFSZ];
530.  	    int trycnt = 0;
531.  
532.  	    Strcpy(qbuf, "To what level do you want to teleport?");
533.  	    do {
534.  		if (++trycnt == 2) Strcat(qbuf, " [type a number]");
535.  		getlin(qbuf, buf);
536.  		if (!strcmp(buf,"\033"))	/* cancelled */
537.  		    return;
538.  		else if (!strcmp(buf,"*"))
539.  		    goto random_levtport;
540.  		if ((newlev = lev_by_name(buf)) == 0) newlev = atoi(buf);
541.  	    } while (!newlev && !digit(buf[0]) &&
542.  		     (buf[0] != '-' || !digit(buf[1])) &&
543.  		     trycnt < 10);
544.  
545.  	    /* no dungeon escape via this route */
546.  	    if (newlev == 0) {
547.  		if (trycnt >= 10)
548.  		    goto random_levtport;
549.  		if (ynq("Go to Nowhere.  Are you sure?") != 'y') return;
550.  		You("%s in agony as your body begins to warp...",
551.  		    is_silent(youmonst.data) ? "writhe" : "scream");
552.  		display_nhwindow(WIN_MESSAGE, FALSE);
553.  		You("cease to exist.");
554.  		killer_format = NO_KILLER_PREFIX;
555.  		killer = "committed suicide";
556.  		done(DIED);
557.  		return;
558.  	    }
559.  
560.  	    /* if in Knox and the requested level > 0, stay put.
561.  	     * we let negative values requests fall into the "heaven" loop.
562.  	     */
563.  	    if (Is_knox(&u.uz) && newlev > 0) {
564.  		You(shudder_for_moment);
565.  		return;
566.  	    }
567.  	    /* if in Quest, the player sees "Home 1", etc., on the status
568.  	     * line, instead of the logical depth of the level.  controlled
569.  	     * level teleport request is likely to be relativized to the
570.  	     * status line, and consequently it should be incremented to
571.  	     * the value of the logical depth of the target level.
572.  	     *
573.  	     * we let negative values requests fall into the "heaven" loop.
574.  	     */
575.  	    if (In_quest(&u.uz) && newlev > 0)
576.  		newlev = newlev + dungeons[u.uz.dnum].depth_start - 1;
577.  	} else { /* involuntary level tele */
578.   random_levtport:
579.  	    newlev = random_teleport_level();
580.  	    if (newlev == depth(&u.uz)) {
581.  		You(shudder_for_moment);
582.  		return;
583.  	    }
584.  	}
585.  
586.  	if (!next_to_u()) {
587.  		You(shudder_for_moment);
588.  		return;
589.  	}
590.  #ifdef WIZARD
591.  	if (In_endgame(&u.uz)) {	/* must already be wizard */
592.  	    int llimit = dunlevs_in_dungeon(&u.uz);
593.  
594.  	    if (newlev >= 0 || newlev <= -llimit) {
595.  		You_cant("get there from here.");
596.  		return;
597.  	    }
598.  	    newlevel.dnum = u.uz.dnum;
599.  	    newlevel.dlevel = llimit + newlev;
600.  	    schedule_goto(&newlevel, FALSE, FALSE, 0, (char *)0, (char *)0);
601.  	    return;
602.  	}
603.  #endif
604.  
605.  	killer = 0;		/* still alive, so far... */
606.  
607.  	if (newlev < 0) {
608.  		if (newlev <= -10) {
609.  			You("arrive in heaven.");
610.  			verbalize("Thou art early, but we'll admit thee.");
611.  			killer_format = NO_KILLER_PREFIX;
612.  			killer = "went to heaven prematurely";
613.  		} else if (newlev == -9) {
614.  			You_feel("deliriously happy. ");
615.  			pline("(In fact, you're on Cloud 9!) ");
616.  			display_nhwindow(WIN_MESSAGE, FALSE);
617.  		} else
618.  			You("are now high above the clouds...");
619.  
620.  		if (killer) {
621.  		    ;		/* arrival in heaven is pending */
622.  		} else if (Levitation) {
623.  		    escape_by_flying = "float gently down to earth";
624.  		} else if (Flying) {
625.  		    escape_by_flying = "fly down to the ground";
626.  		} else {
627.  		    pline("Unfortunately, you don't know how to fly.");
628.  		    You("plummet a few thousand feet to your death.");
629.  		    Sprintf(buf,
630.  				"teleported out of the dungeon and fell to %s death",
631.  				uhis());
632.  		    killer = buf;
633.  		    killer_format = NO_KILLER_PREFIX;
634.  		}
635.  	}
636.  
637.  	if (killer) {	/* the chosen destination was not survivable */
638.  	    d_level lsav;
639.  
640.  	    /* set specific death location; this also suppresses bones */
641.  	    lsav = u.uz;	/* save current level, see below */
642.  	    u.uz.dnum = 0;	/* main dungeon */
643.  	    u.uz.dlevel = (newlev <= -10) ? -10 : 0;	/* heaven or surface */
644.  	    done(DIED);
645.  	    /* can only get here via life-saving (or declining to die in
646.  	       explore|debug mode); the hero has now left the dungeon... */
647.  	    escape_by_flying = "find yourself back on the surface";
648.  	    u.uz = lsav;	/* restore u.uz so escape code works */
649.  	}
650.  
651.  	/* calls done(ESCAPED) if newlevel==0 */
652.  	if (escape_by_flying) {
653.  	    You("%s.", escape_by_flying);
654.  	    newlevel.dnum = 0;		/* specify main dungeon */
655.  	    newlevel.dlevel = 0;	/* escape the dungeon */
656.  	    /* [dlevel used to be set to 1, but it doesn't make sense to
657.  		teleport out of the dungeon and float or fly down to the
658.  		surface but then actually arrive back inside the dungeon] */
659.  	} else if (u.uz.dnum == medusa_level.dnum &&
660.  	    newlev >= dungeons[u.uz.dnum].depth_start +
661.  						dunlevs_in_dungeon(&u.uz)) {
662.  	    find_hell(&newlevel);
663.  	} else {
664.  	    /* if invocation did not yet occur, teleporting into
665.  	     * the last level of Gehennom is forbidden.
666.  	     */
667.  #ifdef WIZARD
668.  		if (!wizard)
669.  #endif
670.  	    if (Inhell && !u.uevent.invoked &&
671.  			newlev >= (dungeons[u.uz.dnum].depth_start +
672.  					dunlevs_in_dungeon(&u.uz) - 1)) {
673.  		newlev = dungeons[u.uz.dnum].depth_start +
674.  					dunlevs_in_dungeon(&u.uz) - 2;
675.  		pline("Sorry...");
676.  	    }
677.  	    /* no teleporting out of quest dungeon */
678.  	    if (In_quest(&u.uz) && newlev < depth(&qstart_level))
679.  		newlev = depth(&qstart_level);
680.  	    /* the player thinks of levels purely in logical terms, so
681.  	     * we must translate newlev to a number relative to the
682.  	     * current dungeon.
683.  	     */
684.  	    get_level(&newlevel, newlev);
685.  	}
686.  	schedule_goto(&newlevel, FALSE, FALSE, 0, (char *)0, (char *)0);
687.  	/* in case player just read a scroll and is about to be asked to
688.  	   call it something, we can't defer until the end of the turn */
689.  	if (u.utotype && !flags.mon_moving) deferred_goto();
690.  }
691.  
692.  void
693.  domagicportal(ttmp)
694.  register struct trap *ttmp;
695.  {
696.  	struct d_level target_level;
697.  
698.  	if (!next_to_u()) {
699.  		You(shudder_for_moment);
700.  		return;
701.  	}
702.  
703.  	/* if landed from another portal, do nothing */
704.  	/* problem: level teleport landing escapes the check */
705.  	if (!on_level(&u.uz, &u.uz0)) return;
706.  
707.  	You("activated a magic portal!");
708.  
709.  	/* prevent the poor shnook, whose amulet was stolen while in
710.  	 * the endgame, from accidently triggering the portal to the
711.  	 * next level, and thus losing the game
712.  	 */
713.  	if (In_endgame(&u.uz) && !u.uhave.amulet) {
714.  	    You_feel("dizzy for a moment, but nothing happens...");
715.  	    return;
716.  	}
717.  
718.  	target_level = ttmp->dst;
719.  	schedule_goto(&target_level, FALSE, FALSE, 1,
720.  		      "You feel dizzy for a moment, but the sensation passes.",
721.  		      (char *)0);
722.  }
723.  
724.  void
725.  tele_trap(trap)
726.  struct trap *trap;
727.  {
728.  	if (In_endgame(&u.uz) || Antimagic) {
729.  		if (Antimagic)
730.  			shieldeff(u.ux, u.uy);
731.  		You_feel("a wrenching sensation.");
732.  	} else if (!next_to_u()) {
733.  		You(shudder_for_moment);
734.  	} else if (trap->once) {
735.  		deltrap(trap);
736.  		newsym(u.ux,u.uy);	/* get rid of trap symbol */
737.  		vault_tele();
738.  	} else
739.  		tele();
740.  }
741.  
742.  void
743.  level_tele_trap(trap)
744.  struct trap *trap;
745.  {
746.  	You("%s onto a level teleport trap!",
747.  		      Levitation ? (const char *)"float" :
748.  				  locomotion(youmonst.data, "step"));
749.  	if (Antimagic) {
750.  	    shieldeff(u.ux, u.uy);
751.  	}
752.  	if (Antimagic || In_endgame(&u.uz)) {
753.  	    You_feel("a wrenching sensation.");
754.  	    return;
755.  	}
756.  	if (!Blind)
757.  	    You("are momentarily blinded by a flash of light.");
758.  	else
759.  	    You("are momentarily disoriented.");
760.  	deltrap(trap);
761.  	newsym(u.ux,u.uy);	/* get rid of trap symbol */
762.  	level_tele();
763.  }
764.  
765.  /* check whether monster can arrive at location <x,y> via Tport (or fall) */
766.  STATIC_OVL boolean
767.  rloc_pos_ok(x, y, mtmp)
768.  register int x, y;		/* coordinates of candidate location */
769.  struct monst *mtmp;
770.  {
771.  	register int xx, yy;
772.  
773.  	if (!goodpos(x, y, mtmp)) return FALSE;
774.  	/*
775.  	 * Check for restricted areas present in some special levels.
776.  	 *
777.  	 * `xx' is current column; if 0, then `yy' will contain flag bits
778.  	 * rather than row:  bit #0 set => moving upwards; bit #1 set =>
779.  	 * inside the Wizard's tower.
780.  	 */
781.  	xx = mtmp->mx;
782.  	yy = mtmp->my;
783.  	if (!xx) {
784.  	    /* no current location (migrating monster arrival) */
785.  	    if (dndest.nlx && On_W_tower_level(&u.uz))
786.  		return ((yy & 2) != 0) ^	/* inside xor not within */
787.  		       !within_bounded_area(x, y, dndest.nlx, dndest.nly,
788.  						  dndest.nhx, dndest.nhy);
789.  	    if (updest.lx && (yy & 1) != 0)	/* moving up */
790.  		return (within_bounded_area(x, y, updest.lx, updest.ly,
791.  						  updest.hx, updest.hy) &&
792.  		       (!updest.nlx ||
793.  			!within_bounded_area(x, y, updest.nlx, updest.nly,
794.  						   updest.nhx, updest.nhy)));
795.  	    if (dndest.lx && (yy & 1) == 0)	/* moving down */
796.  		return (within_bounded_area(x, y, dndest.lx, dndest.ly,
797.  						  dndest.hx, dndest.hy) &&
798.  		       (!dndest.nlx ||
799.  			!within_bounded_area(x, y, dndest.nlx, dndest.nly,
800.  						   dndest.nhx, dndest.nhy)));
801.  	} else {
802.  	    /* current location is <xx,yy> */
803.  	    if (!tele_jump_ok(xx, yy, x, y)) return FALSE;
804.  	}
805.  	/* <x,y> is ok */
806.  	return TRUE;
807.  }
808.  
809.  /*
810.   * rloc_to()
811.   *
812.   * Pulls a monster from its current position and places a monster at
813.   * a new x and y.  If oldx is 0, then the monster was not in the levels.monsters
814.   * array.  However, if oldx is 0, oldy may still have a value because mtmp is a
815.   * migrating_mon.  Worm tails are always placed randomly around the head of
816.   * the worm.
817.   */
818.  void
819.  rloc_to(mtmp, x, y)
820.  struct monst *mtmp;
821.  register int x, y;
822.  {
823.  	register int oldx = mtmp->mx, oldy = mtmp->my;
824.  	boolean resident_shk = mtmp->isshk && inhishop(mtmp);
825.  
826.  	if (x == mtmp->mx && y == mtmp->my)	/* that was easy */
827.  		return;
828.  
829.  	if (oldx) {				/* "pick up" monster */
830.  	    if (mtmp->wormno)
831.  		remove_worm(mtmp);
832.  	    else {
833.  		remove_monster(oldx, oldy);
834.  		newsym(oldx, oldy);		/* update old location */
835.  	    }
836.  	}
837.  
838.  	place_monster(mtmp, x, y);		/* put monster down */
839.  	update_monster_region(mtmp);
840.  
841.  	if (mtmp->wormno)			/* now put down tail */
842.  		place_worm_tail_randomly(mtmp, x, y);
843.  
844.  	if (u.ustuck == mtmp) {
845.  		if (u.uswallow) {
846.  			u.ux = x;
847.  			u.uy = y;
848.  			docrt();
849.  		} else	u.ustuck = 0;
850.  	}
851.  
852.  	newsym(x, y);				/* update new location */
853.  	set_apparxy(mtmp);			/* orient monster */
854.  
855.  	/* shopkeepers will only teleport if you zap them with a wand of
856.  	   teleportation or if they've been transformed into a jumpy monster;
857.  	   the latter only happens if you've attacked them with polymorph */
858.  	if (resident_shk && !inhishop(mtmp)) make_angry_shk(mtmp, oldx, oldy);
859.  }
860.  
861.  /* place a monster at a random location, typically due to teleport */
862.  void
863.  rloc(mtmp)
864.  struct monst *mtmp;	/* mx==0 implies migrating monster arrival */
865.  {
866.  	register int x, y, trycount;
867.  
868.  #ifdef STEED
869.  	if (mtmp == u.usteed) {
870.  	    tele();
871.  	    return;
872.  	}
873.  #endif
874.  
875.  	if (mtmp->iswiz && mtmp->mx) {	/* Wizard, not just arriving */
876.  	    if (!In_W_tower(u.ux, u.uy, &u.uz))
877.  		x = xupstair,  y = yupstair;
878.  	    else if (!xdnladder)	/* bottom level of tower */
879.  		x = xupladder,  y = yupladder;
880.  	    else
881.  		x = xdnladder,  y = ydnladder;
882.  	    /* if the wiz teleports away to heal, try the up staircase,
883.  	       to block the player's escaping before he's healed
884.  	       (deliberately use `goodpos' rather than `rloc_pos_ok' here) */
885.  	    if (goodpos(x, y, mtmp))
886.  		goto found_xy;
887.  	}
888.  
889.  	trycount = 0;
890.  	do {
891.  	    x = rn1(COLNO-3,2);
892.  	    y = rn2(ROWNO);
893.  	    if ((trycount < 500) ? rloc_pos_ok(x, y, mtmp)
894.  				 : goodpos(x, y, mtmp))
895.  		goto found_xy;
896.  	} while (++trycount < 1000);
897.  
898.  	/* last ditch attempt to find a good place */
899.  	for (x = 2; x < COLNO - 1; x++)
900.  	    for (y = 0; y < ROWNO; y++)
901.  		if (goodpos(x, y, mtmp))
902.  		    goto found_xy;
903.  
904.  	/* level either full of monsters or somehow faulty */
905.  	impossible("rloc(): couldn't relocate monster");
906.  	return;
907.  
908.   found_xy:
909.  	rloc_to(mtmp, x, y);
910.  }
911.  
912.  STATIC_OVL void
913.  mvault_tele(mtmp)
914.  struct monst *mtmp;
915.  {
916.  	register struct mkroom *croom = search_special(VAULT);
917.  	coord c;
918.  
919.  	if (croom && somexy(croom, &c) &&
920.  				goodpos(c.x, c.y, mtmp)) {
921.  		rloc_to(mtmp, c.x, c.y);
922.  		return;
923.  	}
924.  	rloc(mtmp);
925.  }
926.  
927.  boolean
928.  tele_restrict(mon)
929.  struct monst *mon;
930.  {
931.  	if (level.flags.noteleport) {
932.  		if (canseemon(mon))
933.  		    pline("A mysterious force prevents %s from teleporting!",
934.  			mon_nam(mon));
935.  		return TRUE;
936.  	}
937.  	return FALSE;
938.  }
939.  
940.  void
941.  mtele_trap(mtmp, trap, in_sight)
942.  struct monst *mtmp;
943.  struct trap *trap;
944.  int in_sight;
945.  {
946.  	char *monname;
947.  
948.  	if (tele_restrict(mtmp)) return;
949.  	if (teleport_pet(mtmp, FALSE)) {
950.  	    /* save name with pre-movement visibility */
951.  	    monname = Monnam(mtmp);
952.  
953.  	    /* Note: don't remove the trap if a vault.  Other-
954.  	     * wise the monster will be stuck there, since
955.  	     * the guard isn't going to come for it...
956.  	     */
957.  	    if (trap->once) mvault_tele(mtmp);
958.  	    else rloc(mtmp);
959.  
960.  	    if (in_sight) {
961.  		if (canseemon(mtmp))
962.  		    pline("%s seems disoriented.", monname);
963.  		else
964.  		    pline("%s suddenly disappears!", monname);
965.  		seetrap(trap);
966.  	    }
967.  	}
968.  }
969.  
970.  /* return 0 if still on level, 3 if not */
971.  int
972.  mlevel_tele_trap(mtmp, trap, force_it, in_sight)
973.  struct monst *mtmp;
974.  struct trap *trap;
975.  boolean force_it;
976.  int in_sight;
977.  {
978.  	int tt = trap->ttyp;
979.  	struct permonst *mptr = mtmp->data;
980.  
981.  	if (mtmp == u.ustuck)	/* probably a vortex */
982.  	    return 0;		/* temporary? kludge */
983.  	if (teleport_pet(mtmp, force_it)) {
984.  	    d_level tolevel;
985.  	    int migrate_typ = MIGR_RANDOM;
986.  
987.  	    if ((tt == HOLE || tt == TRAPDOOR)) {
988.  		if (Is_stronghold(&u.uz)) {
989.  		    assign_level(&tolevel, &valley_level);
990.  		} else if (Is_botlevel(&u.uz)) {
991.  		    if (in_sight && trap->tseen)
992.  			pline("%s avoids the %s.", Monnam(mtmp),
993.  			(tt == HOLE) ? "hole" : "trap");
994.  		    return 0;
995.  		} else {
996.  		    get_level(&tolevel, depth(&u.uz) + 1);
997.  		}
998.  	    } else if (tt == MAGIC_PORTAL) {
999.  		if (In_endgame(&u.uz) &&
1000. 		    (mon_has_amulet(mtmp) || is_home_elemental(mptr))) {
1001. 		    if (in_sight && mptr->mlet != S_ELEMENTAL) {
1002. 			pline("%s seems to shimmer for a moment.",
1003. 							Monnam(mtmp));
1004. 			seetrap(trap);
1005. 		    }
1006. 		    return 0;
1007. 		} else {
1008. 		    assign_level(&tolevel, &trap->dst);
1009. 		    migrate_typ = MIGR_PORTAL;
1010. 		}
1011. 	    } else { /* (tt == LEVEL_TELEP) */
1012. 		int nlev;
1013. 
1014. 		if (mon_has_amulet(mtmp) || In_endgame(&u.uz)) {
1015. 		    if (in_sight)
1016. 			pline("%s seems very disoriented for a moment.",
1017. 				Monnam(mtmp));
1018. 		    return 0;
1019. 		}
1020. 		nlev = random_teleport_level();
1021. 		if (nlev == depth(&u.uz)) {
1022. 		    if (in_sight)
1023. 			pline("%s shudders for a moment.", Monnam(mtmp));
1024. 		    return 0;
1025. 		}
1026. 		get_level(&tolevel, nlev);
1027. 	    }
1028. 
1029. 	    if (in_sight) {
1030. 		pline("Suddenly, %s disappears out of sight.", mon_nam(mtmp));
1031. 		seetrap(trap);
1032. 	    }
1033. 	    migrate_to_level(mtmp, ledger_no(&tolevel),
1034. 			     migrate_typ, (coord *)0);
1035. 	    return 3;	/* no longer on this level */
1036. 	}
1037. 	return 0;
1038. }
1039. 
1040. 
1041. void
1042. rloco(obj)
1043. register struct obj *obj;
1044. {
1045. 	register xchar tx, ty, otx, oty;
1046. 	boolean restricted_fall;
1047. 	int try_limit = 4000;
1048. 
1049. 	if (obj->otyp == CORPSE && is_rider(&mons[obj->corpsenm])) {
1050. 	    if (revive_corpse(obj)) return;
1051. 	}
1052. 
1053. 	obj_extract_self(obj);
1054. 	otx = obj->ox;
1055. 	oty = obj->oy;
1056. 	restricted_fall = (otx == 0 && dndest.lx);
1057. 	do {
1058. 	    tx = rn1(COLNO-3,2);
1059. 	    ty = rn2(ROWNO);
1060. 	    if (!--try_limit) break;
1061. 	} while (!goodpos(tx, ty, (struct monst *)0) ||
1062. 		/* bug: this lacks provision for handling the Wizard's tower */
1063. 		 (restricted_fall &&
1064. 		  (!within_bounded_area(tx, ty, dndest.lx, dndest.ly,
1065. 						dndest.hx, dndest.hy) ||
1066. 		   (dndest.nlx &&
1067. 		    within_bounded_area(tx, ty, dndest.nlx, dndest.nly,
1068. 						dndest.nhx, dndest.nhy)))));
1069. 
1070. 	if (flooreffects(obj, tx, ty, "fall")) {
1071. 	    return;
1072. 	} else if (otx == 0 && oty == 0) {
1073. 	    ;	/* fell through a trap door; no update of old loc needed */
1074. 	} else {
1075. 	    if (costly_spot(otx, oty)
1076. 	      && (!costly_spot(tx, ty) ||
1077. 		  !index(in_rooms(tx, ty, 0), *in_rooms(otx, oty, 0)))) {
1078. 		if (costly_spot(u.ux, u.uy) &&
1079. 			    index(u.urooms, *in_rooms(otx, oty, 0)))
1080. 		    addtobill(obj, FALSE, FALSE, FALSE);
1081. 		else (void)stolen_value(obj, otx, oty, FALSE, FALSE);
1082. 	    }
1083. 	    newsym(otx, oty);	/* update old location */
1084. 	}
1085. 	place_object(obj, tx, ty);
1086. 	newsym(tx, ty);
1087. }
1088. 
1089. /* Returns an absolute depth */
1090. int
1091. random_teleport_level()
1092. {
1093. 	int nlev, max_depth, min_depth;
1094. 
1095. 	if (!rn2(5) || Is_knox(&u.uz))
1096. 		return (int)depth(&u.uz);
1097. 
1098. 	/* Get a random value relative to the current dungeon */
1099. 	/* Range is 1 to current+3, current not counting */
1100. 	nlev = rnd((int)depth(&u.uz) + 2);
1101. 	if (nlev >= (int)depth(&u.uz)) nlev++;
1102. 
1103. 	/* What I really want to do is as follows:
1104. 	 * -- If in a dungeon that goes down, the new level is to be restricted
1105. 	 *    to [top of parent, bottom of current dungeon]
1106. 	 * -- If in a dungeon that goes up, the new level is to be restricted
1107. 	 *    to [top of current dungeon, bottom of parent]
1108. 	 * -- If in a quest dungeon or similar dungeon entered by portals,
1109. 	 *    the new level is to be restricted to [top of current dungeon,
1110. 	 *    bottom of current dungeon]
1111. 	 * The current behavior is not as sophisticated as that ideal, but is
1112. 	 * still better what we used to do, which was like this for players
1113. 	 * but different for monsters for no obvious reason.  Currently, we
1114. 	 * must explicitly check for special dungeons.  We check for Knox
1115. 	 * above; endgame is handled in the caller due to its different
1116. 	 * message ("disoriented").
1117. 	 * --KAA
1118. 	 */
1119. 	min_depth = 1;
1120. 	max_depth = dunlevs_in_dungeon(&u.uz) +
1121. 			(dungeons[u.uz.dnum].depth_start - 1);
1122. 
1123. 	if (nlev > max_depth) {
1124. 	    nlev = max_depth;
1125. 	    /* teleport up if already on bottom */
1126. 	    if (Is_botlevel(&u.uz)) nlev -= rnd(3);
1127. 	}
1128. 	if (nlev < min_depth) {
1129. 	    nlev = min_depth;
1130. 	    if ((int)depth(&u.uz) == min_depth) {
1131. 		nlev += rnd(3);
1132. 		if (nlev > max_depth)
1133. 		    nlev = max_depth;
1134. 	    }
1135. 	}
1136. 	return nlev;
1137. }
1138. 
1139. /* you teleport a monster (via wand, spell, or poly'd q.mechanic attack);
1140.    return false iff the attempt fails */
1141. boolean
1142. u_teleport_mon(mtmp, give_feedback)
1143. struct monst *mtmp;
1144. boolean give_feedback;
1145. {
1146. 	coord cc;
1147. 
1148. 	if (mtmp->ispriest && *in_rooms(mtmp->mx, mtmp->my, TEMPLE)) {
1149. 	    if (give_feedback)
1150. 		pline("%s resists your magic!", Monnam(mtmp));
1151. 	    return FALSE;
1152. 	} else if (level.flags.noteleport && u.uswallow && mtmp == u.ustuck) {
1153. 	    if (give_feedback)
1154. 		You("are no longer inside %s!", mon_nam(mtmp));
1155. 	    unstuck(mtmp);
1156. 	    rloc(mtmp);
1157. 	} else if (is_rider(mtmp->data) && rn2(13) &&
1158. 		   enexto(&cc, u.ux, u.uy, mtmp->data))
1159. 	    rloc_to(mtmp, cc.x, cc.y);
1160. 	else
1161. 	    rloc(mtmp);
1162. 	return TRUE;
1163. }
1164. 
1165. /*teleport.c*/

Around Wikia's network

Random Wiki