Source:NetHack 3.2.0/teleport.c
(Redirected from NetHack 3.2.0/teleport.c)
Jump to navigation
Jump to search
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
The NetHack General Public License applies to screenshots, source code and other content from NetHack.
This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.
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 <x,y> 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 <xx,yy> */ 707. if (!tele_jump_ok(xx, yy, x, y)) return FALSE; 708. } 709. /* <x,y> 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*/