Source:NetHack 3.2.0/teleport.c

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

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

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