PropertyValue
rdfs:label
  • Source:NetHack 3.3.0/trap.c
rdfs:comment
  • Below is the full text to trap.c from the source code of NetHack 3.3.0. To link to a particular line, write [[NetHack 3.3.0/trap.c#line123]], for example. Warning! This is the source code from an old release. For the latest release, see Source code
dcterms:subject
dbkwik:nethack/property/wikiPageUsesTemplate
abstract
  • Below is the full text to trap.c from the source code of NetHack 3.3.0. To link to a particular line, write [[NetHack 3.3.0/trap.c#line123]], for example. Warning! This is the source code from an old release. For the latest release, see Source code 1. /* SCCS Id: @(#)trap.c 3.3 1999/12/05 */ 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 void FDECL(dofiretrap, (struct obj *)); 8. STATIC_DCL void NDECL(domagictrap); 9. STATIC_DCL boolean FDECL(emergency_disrobe,(boolean *)); 10. STATIC_DCL int FDECL(untrap_prob, (struct trap *ttmp)); 11. STATIC_DCL void FDECL(cnv_trap_obj, (int, int, struct trap *)); 12. STATIC_DCL void FDECL(move_into_trap, (struct trap *)); 13. STATIC_DCL int FDECL(try_disarm, (struct trap *,BOOLEAN_P)); 14. STATIC_DCL void FDECL(reward_untrap, (struct trap *, struct monst *)); 15. STATIC_DCL int FDECL(disarm_beartrap, (struct trap *)); 16. STATIC_DCL int FDECL(disarm_landmine, (struct trap *)); 17. STATIC_DCL int FDECL(disarm_squeaky_board, (struct trap *)); 18. STATIC_DCL int FDECL(disarm_shooting_trap, (struct trap *, int)); 19. STATIC_DCL int FDECL(try_lift, (struct monst *, struct trap *, int, BOOLEAN_P)); 20. STATIC_DCL int FDECL(help_monster_out, (struct monst *, struct trap *)); 21. STATIC_DCL boolean FDECL(thitm, (int, struct monst *, struct obj *, int)); 22. STATIC_DCL int FDECL(mkroll_launch, 23. (struct trap *,XCHAR_P,XCHAR_P,SHORT_P,long)); 24. STATIC_DCL boolean FDECL(isclearpath,(coord *, int, SCHAR_P, SCHAR_P)); 25. STATIC_DCL void FDECL(blow_up_landmine, (struct trap *)); 26. 27. #ifndef OVLB 28. STATIC_VAR const char *a_your[2]; 29. STATIC_VAR const char *A_Your[2]; 30. STATIC_VAR const char *the_your[2]; 31. STATIC_VAR const char tower_of_flame[]; 32. STATIC_VAR const char *A_gush_of_water_hits; 33. 34. #else 35. 36. STATIC_VAR const char *a_your[2] = { "a", "your" }; 37. STATIC_VAR const char *A_Your[2] = { "A", "Your" }; 38. STATIC_VAR const char *the_your[2] = { "the", "your" }; 39. STATIC_VAR const char tower_of_flame[] = "tower of flame"; 40. STATIC_VAR const char *A_gush_of_water_hits = "A gush of water hits"; 41. 42. #endif /* OVLB */ 43. 44. #ifdef OVLB 45. 46. /* called when you're hit by fire (dofiretrap,buzz,zapyourself,explode) */ 47. boolean /* returns TRUE if hit on torso */ 48. burnarmor(victim) 49. struct monst *victim; 50. { 51. struct obj *item; 52. 53. if (!victim) return 0; 54. #define burn_dmg(obj,descr) rust_dmg(obj, descr, 0, FALSE, victim) 55. while (1) { 56. switch (rn2(5)) { 57. case 0: 58. item = (victim == &youmonst) ? uarmh : which_armor(victim, W_ARMH); 59. if (!burn_dmg(item, "leather helmet")) continue; 60. break; 61. case 1: 62. item = (victim == &youmonst) ? uarmc : which_armor(victim, W_ARMC); 63. if (item) { 64. (void) burn_dmg(item, "cloak"); 65. return TRUE; 66. } 67. item = (victim == &youmonst) ? uarm : which_armor(victim, W_ARM); 68. if (item) { 69. (void) burn_dmg(item, xname(item)); 70. return TRUE; 71. } 72. #ifdef TOURIST 73. item = (victim == &youmonst) ? uarmu : which_armor(victim, W_ARMU); 74. if (item) 75. (void) burn_dmg(item, "shirt"); 76. #endif 77. return TRUE; 78. case 2: 79. item = (victim == &youmonst) ? uarms : which_armor(victim, W_ARMS); 80. if (!burn_dmg(item, "wooden shield")) continue; 81. break; 82. case 3: 83. item = (victim == &youmonst) ? uarmg : which_armor(victim, W_ARMG); 84. if (!burn_dmg(item, "gloves")) continue; 85. break; 86. case 4: 87. item = (victim == &youmonst) ? uarmf : which_armor(victim, W_ARMF); 88. if (!burn_dmg(item, "boots")) continue; 89. break; 90. } 91. break; /* Out of while loop */ 92. } 93. return FALSE; 94. #undef burn_dmg 95. } 96. 97. /* Generic rust-armor function. Returns TRUE if a message was printed; 98. * "print", if set, means to print a message (and thus to return TRUE) even 99. * if the item could not be rusted; otherwise a message is printed and TRUE is 100. * returned only for rustable items. 101. */ 102. boolean 103. rust_dmg(otmp, ostr, type, print, victim) 104. register struct obj *otmp; 105. register const char *ostr; 106. int type; 107. boolean print; 108. struct monst *victim; 109. { 110. static NEARDATA const char *action[] = { "smoulder", "rust", "rot", "corrode" }; 111. static NEARDATA const char *msg[] = { "burnt", "rusted", "rotten", "corroded" }; 112. boolean vulnerable = FALSE; 113. boolean plural; 114. boolean grprot = FALSE; 115. boolean is_primary = TRUE; 116. boolean vismon = (victim != &youmonst) && canseemon(victim); 117. int erosion; 118. 119. if (!otmp) return(FALSE); 120. switch(type) { 121. case 0: vulnerable = is_flammable(otmp); 122. break; 123. case 1: vulnerable = is_rustprone(otmp); 124. grprot = TRUE; 125. break; 126. case 2: vulnerable = is_rottable(otmp); 127. is_primary = FALSE; 128. break; 129. case 3: vulnerable = is_corrodeable(otmp); 130. grprot = TRUE; 131. is_primary = FALSE; 132. break; 133. } 134. erosion = is_primary ? otmp->oeroded : otmp->oeroded2; 135. 136. if (!print && (!vulnerable || otmp->oerodeproof || erosion == MAX_ERODE)) 137. return FALSE; 138. 139. plural = is_gloves(otmp) || is_boots(otmp); 140. 141. if (!vulnerable) { 142. if (flags.verbose) { 143. if (victim == &youmonst) 144. Your("%s %s not affected.", ostr, plural ? "are" : "is"); 145. else if (vismon) 146. pline("%s's %s %s not affected.", Monnam(victim), ostr, 147. plural ? "are" : "is"); 148. } 149. } else if (erosion < MAX_ERODE) { 150. if (grprot && otmp->greased) { 151. grease_protect(otmp,ostr,plural,victim); 152. } else if (otmp->oerodeproof || (otmp->blessed && !rnl(4))) { 153. if (flags.verbose) { 154. if (victim == &youmonst) 155. pline("Somehow, your %s %s not affected.", 156. ostr, plural ? "are" : "is"); 157. else if (vismon) 158. pline("Somehow, %s's %s %s not affected.", 159. mon_nam(victim), ostr, plural ? "are" : "is"); 160. } 161. } else { 162. if (victim == &youmonst) 163. Your("%s %s%s%s!", ostr, action[type], 164. plural ? "" : "s", 165. erosion+1 == MAX_ERODE ? " completely" : 166. erosion ? " further" : ""); 167. else if (vismon) 168. pline("%s's %s %s%s%s!", Monnam(victim), ostr, action[type], 169. plural ? "" : "s", 170. erosion+1 == MAX_ERODE ? " completely" : 171. erosion ? " further" : ""); 172. if (is_primary) 173. otmp->oeroded++; 174. else 175. otmp->oeroded2++; 176. } 177. } else { 178. if (flags.verbose) { 179. if (victim == &youmonst) 180. Your("%s %s%s completely %s.", ostr, 181. Blind ? "feel" : "look", 182. plural ? "" : "s", msg[type]); 183. else if (vismon) 184. pline("%s's %s look%s completely %s.", 185. Monnam(victim), ostr, 186. plural ? "" : "s", msg[type]); 187. } 188. } 189. return(TRUE); 190. } 191. 192. void 193. grease_protect(otmp,ostr,plu,victim) 194. register struct obj *otmp; 195. register const char *ostr; 196. register boolean plu; 197. struct monst *victim; 198. { 199. static const char txt[] = "protected by the layer of grease!"; 200. boolean vismon = (victim != &youmonst) && canseemon(victim); 201. 202. if (ostr) { 203. if (victim == &youmonst) 204. Your("%s %s %s",ostr,plu ? "are" : "is", txt); 205. else if (vismon) 206. pline("%s's %s %s %s", Monnam(victim), 207. ostr, plu ? "are" : "is", txt); 208. } else { 209. if (victim == &youmonst) 210. Your("%s %s",aobjnam(otmp,"are"), txt); 211. else if (vismon) 212. pline("%s's %s %s", Monnam(victim), aobjnam(otmp,"are"), txt); 213. } 214. if (!rn2(2)) { 215. pline_The("grease dissolves."); 216. otmp->greased = 0; 217. } 218. } 219. 220. struct trap * 221. maketrap(x,y,typ) 222. register int x, y, typ; 223. { 224. register struct trap *ttmp; 225. register struct rm *lev; 226. register boolean oldplace; 227. 228. if ((ttmp = t_at(x,y)) != 0) { 229. if (ttmp->ttyp == MAGIC_PORTAL) return (struct trap *)0; 230. oldplace = TRUE; 231. if (u.utrap && (x == u.ux) && (y == u.uy) && 232. ((u.utraptype == TT_BEARTRAP && typ != BEAR_TRAP) || 233. (u.utraptype == TT_WEB && typ != WEB) || 234. (u.utraptype == TT_PIT && typ != PIT && typ != SPIKED_PIT))) 235. u.utrap = 0; 236. } else { 237. oldplace = FALSE; 238. ttmp = newtrap(); 239. ttmp->tx = x; 240. ttmp->ty = y; 241. ttmp->launch.x = -1; /* force error if used before set */ 242. ttmp->launch.y = -1; 243. } 244. ttmp->ttyp = typ; 245. switch(typ) { 246. case STATUE_TRAP: /* create a "living" statue */ 247. { struct monst *mtmp; 248. struct obj *otmp, *statue; 249. 250. statue = mkcorpstat(STATUE, (struct monst *)0, 251. &mons[rndmonnum()], x, y, FALSE); 252. mtmp = makemon(&mons[statue->corpsenm], 0, 0, NO_MM_FLAGS); 253. if (!mtmp) break; /* should never happen */ 254. while(mtmp->minvent) { 255. otmp = mtmp->minvent; 256. otmp->owornmask = 0; 257. obj_extract_self(otmp); 258. add_to_container(statue, otmp); 259. } 260. mongone(mtmp); 261. break; 262. } 263. case ROLLING_BOULDER_TRAP: /* boulder will roll towards trigger */ 264. (void) mkroll_launch(ttmp, x, y, BOULDER, 1L); 265. break; 266. case HOLE: 267. case PIT: 268. case SPIKED_PIT: 269. case TRAPDOOR: 270. lev = &levl[x][y]; 271. if (*in_rooms(x, y, SHOPBASE) && 272. ((typ == HOLE || typ == TRAPDOOR) || IS_DOOR(lev->typ))) 273. add_damage(x, y, /* schedule repair */ 274. (IS_DOOR(lev->typ) && !flags.mon_moving) ? 200L : 0L); 275. lev->doormask = 0; /* subsumes altarmask, icedpool... */ 276. if (IS_ROOM(lev->typ)) /* && !IS_AIR(lev->typ) */ 277. lev->typ = ROOM; 278. 279. /* 280. * some cases which can happen when digging 281. * down while phazing thru solid areas 282. */ 283. else if (lev->typ == STONE || lev->typ == SCORR) 284. lev->typ = CORR; 285. else if (IS_WALL(lev->typ) || lev->typ == SDOOR) 286. lev->typ = level.flags.is_maze_lev ? ROOM : 287. level.flags.is_cavernous_lev ? CORR : DOOR; 288. 289. unearth_objs(x, y); 290. break; 291. } 292. if (ttmp->ttyp == HOLE) ttmp->tseen = 1; /* You can't hide a hole */ 293. else ttmp->tseen = 0; 294. ttmp->once = 0; 295. ttmp->madeby_u = 0; 296. ttmp->dst.dnum = -1; 297. ttmp->dst.dlevel = -1; 298. if (!oldplace) { 299. ttmp->ntrap = ftrap; 300. ftrap = ttmp; 301. } 302. return(ttmp); 303. } 304. 305. void 306. fall_through(td) 307. boolean td; /* td == TRUE : trapdoor or hole */ 308. { 309. d_level dtmp; 310. char msgbuf[BUFSZ]; 311. const char *dont_fall = 0; 312. register int newlevel = dunlev(&u.uz); 313. 314. /* KMH -- You can't escape the Sokoban level traps */ 315. if(Blind && Levitation && !In_sokoban(&u.uz)) return; 316. 317. do { 318. newlevel++; 319. } while(!rn2(4) && newlevel < dunlevs_in_dungeon(&u.uz)); 320. 321. if(td) { 322. struct trap *t=t_at(u.ux,u.uy); 323. if (t->ttyp == TRAPDOOR) 324. pline("A trap door opens up under you!"); 325. else 326. pline("There's a gaping hole under you!"); 327. } else pline_The("%s opens up under you!", surface(u.ux,u.uy)); 328. 329. if (In_sokoban(&u.uz) && Can_fall_thru(&u.uz)) 330. ; /* KMH -- You can't escape the Sokoban level traps */ 331. else if(Levitation || u.ustuck || !Can_fall_thru(&u.uz) 332. || Flying || is_clinger(youmonst.data) 333. || (Inhell && !u.uevent.invoked && 334. newlevel == dunlevs_in_dungeon(&u.uz)) 335. ) { 336. dont_fall = "don't fall in."; 337. } else if (youmonst.data->msize >= MZ_HUGE) { 338. dont_fall = "don't fit through."; 339. } else if (!next_to_u()) { 340. dont_fall = "are jerked back by your pet!"; 341. } 342. if (dont_fall) { 343. You(dont_fall); 344. /* hero didn't fall through, but any objects here might */ 345. impact_drop((struct obj *)0, u.ux, u.uy, 0); 346. if (!td) { 347. display_nhwindow(WIN_MESSAGE, FALSE); 348. pline_The("opening under you closes up."); 349. } 350. return; 351. } 352. 353. if(*u.ushops) shopdig(1); 354. if (Is_stronghold(&u.uz)) { 355. find_hell(&dtmp); 356. } else { 357. dtmp.dnum = u.uz.dnum; 358. dtmp.dlevel = newlevel; 359. } 360. if (!td) 361. Sprintf(msgbuf, "The hole in the %s above you closes up.", 362. ceiling(u.ux,u.uy)); 363. schedule_goto(&dtmp, FALSE, TRUE, 0, 364. (char *)0, !td ? msgbuf : (char *)0); 365. } 366. 367. /* 368. * Animate the given statue. May have been via shatter attempt, trap, 369. * or stone to flesh spell. Return a monster if successfully animated. 370. * If the monster is animated, the object is deleted. If fail_reason 371. * is non-null, then fill in the reason for failure (or success). 372. * 373. * The cause of animation is: 374. * 375. * ANIMATE_NORMAL - hero "finds" the monster 376. * ANIMATE_SHATTER - hero tries to destroy the statue 377. * ANIMATE_SPELL - stone to flesh spell hits the statue 378. * 379. * Perhaps x, y is not needed if we can use get_obj_location() to find 380. * the statue's location... ??? 381. */ 382. struct monst * 383. animate_statue(statue, x, y, cause, fail_reason) 384. struct obj *statue; 385. xchar x, y; 386. int cause; 387. int *fail_reason; 388. { 389. struct permonst *mptr; 390. struct monst *mon = 0; 391. struct obj *item; 392. 393. /* 394. * Guard against someone wishing for a statue of a unique monster 395. * (which is allowed in normal play) and then tossing it onto the 396. * [detected or guessed] location of a statue trap. Normally the 397. * uppermost statue is the one which would be activated. 398. */ 399. mptr = &mons[statue->corpsenm]; 400. if (mptr->geno & G_UNIQ) { 401. if (fail_reason) *fail_reason = AS_MON_IS_UNIQUE; 402. return (struct monst *)0; 403. } 404. 405. if ((mon = makemon(mptr, x, y, NO_MINVENT)) == 0) { 406. if (fail_reason) *fail_reason = AS_NO_MON; 407. return (struct monst *)0; 408. } 409. 410. /* if statue has been named, give same name to the monster */ 411. if (statue->onamelth) 412. mon = christen_monst(mon, ONAME(statue)); 413. /* transfer any statue contents to monster's inventory */ 414. while ((item = statue->cobj) != 0) { 415. obj_extract_self(item); 416. add_to_minv(mon, item); 417. } 418. m_dowear(mon, TRUE); 419. delobj(statue); 420. /* mimic statue becomes seen mimic; other hiders won't be hidden */ 421. if (mon->m_ap_type) seemimic(mon); 422. else mon->mundetected = FALSE; 423. if ((x == u.ux && y == u.uy) || cause == ANIMATE_SPELL) 424. pline_The("statue comes to life!"); 425. else if (cause == ANIMATE_SHATTER) 426. pline("Instead of shattering, the statue suddenly comes alive!"); 427. else /* cause == ANIMATE_NORMAL */ 428. You("find %s posing as a statue.", a_monnam(mon)); 429. /* avoid hiding under nothing */ 430. if (x == u.ux && y == u.uy && 431. Upolyd && hides_under(youmonst.data) && !OBJ_AT(x, y)) 432. u.uundetected = 0; 433. 434. if (fail_reason) *fail_reason = AS_OK; 435. return mon; 436. } 437. 438. /* 439. * You've either stepped onto a statue trap's location or you've triggered a 440. * statue trap by searching next to it or by trying to break it with a wand 441. * or pick-axe. 442. */ 443. struct monst * 444. activate_statue_trap(trap, x, y, shatter) 445. struct trap *trap; 446. xchar x, y; 447. boolean shatter; 448. { 449. struct monst *mtmp = (struct monst *)0; 450. struct obj *otmp = sobj_at(STATUE, x, y); 451. int fail_reason; 452. 453. /* 454. * Try to animate the first valid statue. Stop the loop when we 455. * actually create something or the failure cause is not because 456. * the mon was unique. 457. */ 458. deltrap(trap); 459. while (otmp) { 460. mtmp = animate_statue(otmp, x, y, 461. shatter ? ANIMATE_SHATTER : ANIMATE_NORMAL, &fail_reason); 462. if (mtmp || fail_reason != AS_MON_IS_UNIQUE) break; 463. 464. while ((otmp = otmp->nexthere) != 0) 465. if (otmp->otyp == STATUE) break; 466. } 467. 468. if (Blind) feel_location(x, y); 469. else newsym(x, y); 470. return mtmp; 471. } 472. 473. void 474. dotrap(trap) 475. register struct trap *trap; 476. { 477. register int ttype = trap->ttyp; 478. register struct obj *otmp; 479. boolean already_seen = trap->tseen; 480. 481. nomul(0); 482. 483. /* KMH -- You can't escape the Sokoban level traps */ 484. if (In_sokoban(&u.uz) && 485. (ttype == PIT || ttype == SPIKED_PIT || ttype == HOLE || 486. ttype == TRAPDOOR)) { 487. if (Levitation || Flying) 488. pline("Air currents pull you down!"); 489. /* then proceed to normal trap effect */ 490. } else if (already_seen) { 491. if ((Levitation || Flying) && 492. (ttype == PIT || ttype == SPIKED_PIT || ttype == HOLE || 493. ttype == BEAR_TRAP)) { 494. You("%s over %s %s.", 495. Levitation ? "float" : "fly", 496. a_your[trap->madeby_u], 497. defsyms[trap_to_defsym(ttype)].explanation); 498. return; 499. } 500. if(!Fumbling && ttype != MAGIC_PORTAL && ttype != ANTI_MAGIC && 501. (!rn2(5) || 502. ((ttype == PIT || ttype == SPIKED_PIT) && is_clinger(youmonst.data)))) { 503. You("escape %s %s.", 504. (ttype == ARROW_TRAP && !trap->madeby_u) ? "an" : 505. a_your[trap->madeby_u], 506. defsyms[trap_to_defsym(ttype)].explanation); 507. return; 508. } 509. } 510. 511. switch(ttype) { 512. case ARROW_TRAP: 513. seetrap(trap); 514. pline("An arrow shoots out at you!"); 515. otmp = mksobj(ARROW, TRUE, FALSE); 516. otmp->quan = 1L; 517. otmp->owt = weight(otmp); 518. if (thitu(8, dmgval(otmp, &youmonst), otmp, "arrow")) { 519. obfree(otmp, (struct obj *)0); 520. } else { 521. place_object(otmp, u.ux, u.uy); 522. if (!Blind) otmp->dknown = 1; 523. stackobj(otmp); 524. newsym(u.ux, u.uy); 525. } 526. break; 527. case DART_TRAP: 528. seetrap(trap); 529. pline("A little dart shoots out at you!"); 530. otmp = mksobj(DART, TRUE, FALSE); 531. otmp->quan = 1L; 532. otmp->owt = weight(otmp); 533. if (!rn2(6)) otmp->opoisoned = 1; 534. if (thitu(7, dmgval(otmp, &youmonst), otmp, "little dart")) { 535. if (otmp->opoisoned) 536. poisoned("dart",A_CON,"poison dart",10); 537. obfree(otmp, (struct obj *)0); 538. } else { 539. place_object(otmp, u.ux, u.uy); 540. if (!Blind) otmp->dknown = 1; 541. stackobj(otmp); 542. newsym(u.ux, u.uy); 543. } 544. break; 545. case ROCKTRAP: 546. { 547. int dmg = d(2,6); /* should be std ROCK dmg? */ 548. 549. seetrap(trap); 550. otmp = mksobj_at(ROCK, u.ux, u.uy, TRUE); 551. otmp->quan = 1L; 552. otmp->owt = weight(otmp); 553. 554. pline("A trap door in the %s opens and a rock falls on your %s!", 555. ceiling(u.ux,u.uy), 556. body_part(HEAD)); 557. 558. if (uarmh) { 559. if(is_metallic(uarmh)) { 560. pline("Fortunately, you are wearing a hard helmet."); 561. dmg = 2; 562. } else if (flags.verbose) { 563. Your("%s does not protect you.", xname(uarmh)); 564. } 565. } 566. 567. if (!Blind) otmp->dknown = 1; 568. stackobj(otmp); 569. newsym(u.ux,u.uy); /* map the rock */ 570. 571. losehp(dmg, "falling rock", KILLED_BY_AN); 572. exercise(A_STR, FALSE); 573. } 574. break; 575. 576. case SQKY_BOARD: /* stepped on a squeaky board */ 577. if (Levitation || Flying) { 578. if (!Blind) { 579. seetrap(trap); 580. if (Hallucination) 581. You("notice a crease in the linoleum."); 582. else 583. You("notice a loose board below you."); 584. } 585. } else { 586. seetrap(trap); 587. pline("A board beneath you squeaks loudly."); 588. wake_nearby(); 589. } 590. break; 591. 592. case BEAR_TRAP: 593. if(Levitation || Flying) break; 594. seetrap(trap); 595. if(amorphous(youmonst.data) || is_whirly(youmonst.data) || 596. unsolid(youmonst.data)) { 597. pline("%s bear trap closes harmlessly through you.", 598. A_Your[trap->madeby_u]); 599. break; 600. } 601. if(youmonst.data->msize <= MZ_SMALL) { 602. pline("%s bear trap closes harmlessly over you.", 603. A_Your[trap->madeby_u]); 604. break; 605. } 606. u.utrap = rn1(4, 4); 607. u.utraptype = TT_BEARTRAP; 608. #ifdef STEED 609. if (u.usteed) { 610. pline("%s bear trap closes on %s %s!", 611. A_Your[trap->madeby_u], s_suffix(mon_nam(u.usteed)), 612. body_part(FOOT)); 613. } else 614. #endif 615. { 616. pline("%s bear trap closes on your %s!", 617. A_Your[trap->madeby_u], body_part(FOOT)); 618. if(u.umonnum == PM_OWLBEAR || u.umonnum == PM_BUGBEAR) 619. You("howl in anger!"); 620. } 621. exercise(A_DEX, FALSE); 622. break; 623. 624. case SLP_GAS_TRAP: 625. seetrap(trap); 626. if(Sleep_resistance) { 627. You("are enveloped in a cloud of gas!"); 628. break; 629. } 630. pline("A cloud of gas puts you to sleep!"); 631. flags.soundok = 0; 632. fall_asleep(-rnd(25), TRUE); 633. afternmv = Hear_again; 634. break; 635. 636. case RUST_TRAP: 637. seetrap(trap); 638. if (u.umonnum == PM_IRON_GOLEM) { 639. pline("%s you!", A_gush_of_water_hits); 640. You("are covered with rust!"); 641. rehumanize(); 642. break; 643. } else if (u.umonnum == PM_GREMLIN && rn2(3)) { 644. pline("%s you!", A_gush_of_water_hits); 645. (void)split_mon(&youmonst, (struct monst *)0); 646. break; 647. } 648. 649. /* Unlike monsters, traps cannot aim their rust attacks at 650. * you, so instead of looping through and taking either the 651. * first rustable one or the body, we take whatever we get, 652. * even if it is not rustable. 653. */ 654. switch (rn2(5)) { 655. case 0: 656. pline("%s you on the %s!", A_gush_of_water_hits, 657. body_part(HEAD)); 658. (void) rust_dmg(uarmh, "helmet", 1, TRUE, &youmonst); 659. break; 660. case 1: 661. pline("%s your left %s!", A_gush_of_water_hits, 662. body_part(ARM)); 663. if (rust_dmg(uarms, "shield", 1, TRUE, &youmonst)) 664. break; 665. if (uwep && bimanual(uwep)) 666. goto two_hand; 667. /* Two goto statements in a row--aaarrrgggh! */ 668. glovecheck: (void) rust_dmg(uarmg, "gauntlets", 1, TRUE, &youmonst); 669. /* Not "metal gauntlets" since it gets called 670. * even if it's leather for the message 671. */ 672. break; 673. case 2: 674. pline("%s your right %s!", A_gush_of_water_hits, 675. body_part(ARM)); 676. two_hand: erode_weapon(&youmonst, FALSE); 677. goto glovecheck; 678. default: 679. pline("%s you!", A_gush_of_water_hits); 680. for (otmp=invent; otmp; otmp = otmp->nobj) 681. (void) snuff_lit(otmp); 682. if (uarmc) 683. (void) rust_dmg(uarmc, "cloak", 1, TRUE, &youmonst); 684. else if (uarm) 685. (void) rust_dmg(uarm, "armor", 1, TRUE, &youmonst); 686. #ifdef TOURIST 687. else if (uarmu) 688. (void) rust_dmg(uarmu, "shirt", 1, TRUE, &youmonst); 689. #endif 690. } 691. break; 692. 693. case FIRE_TRAP: 694. seetrap(trap); 695. dofiretrap((struct obj *)0); 696. break; 697. 698. case PIT: 699. case SPIKED_PIT: 700. /* KMH -- You can't escape the Sokoban level traps */ 701. if (!In_sokoban(&u.uz) && (Levitation || Flying)) break; 702. seetrap(trap); 703. if (is_clinger(youmonst.data)) { 704. if(trap->tseen) { 705. You("see %s %spit below you.", a_your[trap->madeby_u], 706. ttype == SPIKED_PIT ? "spiked " : ""); 707. } else { 708. pline("%s pit %sopens up under you!", 709. A_Your[trap->madeby_u], 710. ttype == SPIKED_PIT ? "full of spikes " : ""); 711. You("don't fall in!"); 712. } 713. break; 714. } 715. You("fall into %s pit!", a_your[trap->madeby_u]); 716. if (ttype == SPIKED_PIT) 717. You("land on a set of sharp iron spikes!"); 718. if (!Passes_walls) 719. u.utrap = rn1(6,2); 720. u.utraptype = TT_PIT; 721. if (ttype == SPIKED_PIT) { 722. losehp(rnd(10),"fell into a pit of iron spikes", 723. NO_KILLER_PREFIX); 724. if (!rn2(6)) 725. poisoned("spikes", A_STR, "fall onto poison spikes", 8); 726. } else 727. losehp(rnd(6),"fell into a pit", NO_KILLER_PREFIX); 728. if (Punished && !carried(uball)) { 729. unplacebc(); 730. ballfall(); 731. placebc(); 732. } 733. selftouch("Falling, you"); 734. vision_full_recalc = 1; /* vision limits change */ 735. exercise(A_STR, FALSE); 736. exercise(A_DEX, FALSE); 737. break; 738. case HOLE: 739. case TRAPDOOR: 740. seetrap(trap); 741. if (!Can_fall_thru(&u.uz)) { 742. impossible("dotrap: %ss cannot exist on this level.", 743. defsyms[trap_to_defsym(ttype)].explanation); 744. break; /* don't activate it after all */ 745. } 746. fall_through(TRUE); 747. break; 748. 749. case TELEP_TRAP: 750. seetrap(trap); 751. tele_trap(trap); 752. break; 753. case LEVEL_TELEP: 754. seetrap(trap); 755. level_tele_trap(trap); 756. break; 757. 758. case WEB: /* Our luckless player has stumbled into a web. */ 759. seetrap(trap); 760. if (amorphous(youmonst.data) || is_whirly(youmonst.data) || 761. unsolid(youmonst.data)) { 762. if (acidic(youmonst.data) || u.umonnum == PM_GELATINOUS_CUBE || 763. u.umonnum == PM_FIRE_ELEMENTAL) { 764. You("%s %s spider web!", 765. (u.umonnum == PM_FIRE_ELEMENTAL) ? "burn" : "dissolve", 766. a_your[trap->madeby_u]); 767. deltrap(trap); 768. newsym(u.ux,u.uy); 769. break; 770. } 771. You("flow through %s spider web.", 772. a_your[trap->madeby_u]); 773. break; 774. } 775. if (youmonst.data->mlet == S_SPIDER) { 776. pline(trap->madeby_u ? "You take a walk on your web." 777. : "There is a spider web here."); 778. break; 779. } 780. You("%s into %s spider web!", 781. Levitation ? (const char *)"float" : 782. locomotion(youmonst.data, "stumble"), 783. a_your[trap->madeby_u]); 784. u.utraptype = TT_WEB; 785. 786. /* Time stuck in the web depends on your strength. */ 787. { 788. register int str = ACURR(A_STR); 789. 790. if (str == 3) u.utrap = rn1(6,6); 791. else if (str < 6) u.utrap = rn1(6,4); 792. else if (str < 9) u.utrap = rn1(4,4); 793. else if (str < 12) u.utrap = rn1(4,2); 794. else if (str < 15) u.utrap = rn1(2,2); 795. else if (str < 18) u.utrap = rnd(2); 796. else if (str < 69) u.utrap = 1; 797. else { 798. u.utrap = 0; 799. You("tear through %s web!", a_your[trap->madeby_u]); 800. deltrap(trap); 801. newsym(u.ux,u.uy); /* get rid of trap symbol */ 802. } 803. } 804. break; 805. 806. case STATUE_TRAP: 807. (void) activate_statue_trap(trap, u.ux, u.uy, FALSE); 808. break; 809. 810. case MAGIC_TRAP: /* A magic trap. */ 811. seetrap(trap); 812. if (!rn2(30)) { 813. deltrap(trap); 814. newsym(u.ux,u.uy); /* update position */ 815. You("are caught in a magical explosion!"); 816. losehp(rnd(10), "magical explosion", KILLED_BY_AN); 817. Your("body absorbs some of the magical energy!"); 818. u.uen = (u.uenmax += 2); 819. } else domagictrap(); 820. break; 821. 822. case ANTI_MAGIC: 823. seetrap(trap); 824. if(Antimagic) { 825. shieldeff(u.ux, u.uy); 826. You_feel("momentarily lethargic."); 827. } else drain_en(rnd(u.ulevel) + 1); 828. break; 829. 830. case POLY_TRAP: 831. seetrap(trap); 832. You("%s onto a polymorph trap!", 833. Levitation ? (const char *)"float" : 834. locomotion(youmonst.data, "step")); 835. if(Antimagic || Unchanging) { 836. shieldeff(u.ux, u.uy); 837. You_feel("momentarily different."); 838. /* Trap did nothing; don't remove it --KAA */ 839. } else { 840. deltrap(trap); /* delete trap before polymorph */ 841. newsym(u.ux,u.uy); /* get rid of trap symbol */ 842. You_feel("a change coming over you."); 843. polyself(); 844. } 845. break; 846. 847. case LANDMINE: 848. if (Levitation || Flying) { 849. if (!already_seen && rn2(3)) break; 850. seetrap(trap); 851. pline("%s %s in a pile of soil below you.", 852. already_seen ? "There is" : "You discover", 853. trap->madeby_u ? "the trigger of your mine" : 854. "a trigger"); 855. if (already_seen && rn2(3)) break; 856. pline("KAABLAMM!!! The air currents set %s%s off!", 857. already_seen ? a_your[trap->madeby_u] : "", 858. already_seen ? " land mine" : "it"); 859. } else { 860. seetrap(trap); 861. pline("KAABLAMM!!! You triggered %s land mine!", 862. a_your[trap->madeby_u]); 863. set_wounded_legs(LEFT_SIDE, rn1(35, 41)); 864. set_wounded_legs(RIGHT_SIDE, rn1(35, 41)); 865. exercise(A_DEX, FALSE); 866. } 867. blow_up_landmine(trap); 868. newsym(u.ux,u.uy); /* update trap symbol */ 869. losehp(rnd(16), "land mine", KILLED_BY_AN); 870. /* fall recursively into the pit... */ 871. if ((trap = t_at(u.ux, u.uy)) != 0) dotrap(trap); 872. break; 873. 874. case ROLLING_BOULDER_TRAP: 875. seetrap(trap); 876. pline("Click! You trigger a rolling boulder trap!"); 877. if(!launch_obj(BOULDER, trap->launch.x, trap->launch.y, 878. trap->launch2.x,trap->launch2.y, ROLL)) { 879. deltrap(trap); 880. newsym(u.ux,u.uy); /* get rid of trap symbol */ 881. pline("Fortunately for you, no boulder was released."); 882. } 883. break; 884. 885. case MAGIC_PORTAL: 886. seetrap(trap); 887. domagicportal(trap); 888. break; 889. 890. default: 891. seetrap(trap); 892. impossible("You hit a trap of type %u", trap->ttyp); 893. } 894. } 895. 896. /* some actions common to both player and monsters for triggered landmine */ 897. STATIC_OVL void 898. blow_up_landmine(trap) 899. struct trap *trap; 900. { 901. scatter(trap->tx, trap->ty, 4, 902. MAY_DESTROY | MAY_HIT | MAY_FRACTURE | VIS_EFFECTS, 903. (struct obj *)0); 904. del_engr_at(trap->tx, trap->ty); 905. wake_nearto(trap->tx, trap->ty, 400); 906. if (IS_DOOR(levl[trap->tx][trap->ty].typ)) 907. levl[trap->tx][trap->ty].doormask = D_BROKEN; 908. /* TODO: destroy drawbridge if present; 909. sometimes delete trap instead of always leaving a pit */ 910. trap->ttyp = PIT; /* explosion creates a pit */ 911. trap->madeby_u = FALSE; /* resulting pit isn't yours */ 912. } 913. 914. #endif /* OVLB */ 915. #ifdef OVL3 916. 917. /* 918. * Move obj from (x1,y1) to (x2,y2) 919. * 920. * Return 0 if no object was launched. 921. * 1 if an object was launched and placed somewhere. 922. * 2 if an object was launched, but used up. 923. */ 924. int 925. launch_obj(otyp, x1, y1, x2, y2, style) 926. short otyp; 927. register int x1,y1,x2,y2; 928. int style; 929. { 930. register struct monst *mtmp; 931. register struct obj *otmp; 932. register int dx,dy; 933. struct obj *singleobj; 934. boolean used_up = FALSE; 935. boolean otherside = FALSE; 936. int dist; 937. int tmp; 938. int delaycnt = 0; 939. 940. otmp = sobj_at(otyp, x1, y1); 941. /* Try the other side too, for rolling boulder traps */ 942. if (!otmp && otyp == BOULDER) { 943. otherside = TRUE; 944. otmp = sobj_at(otyp, x2, y2); 945. } 946. if (!otmp) return 0; 947. if (otherside) { /* swap 'em */ 948. int tx, ty; 949. 950. tx = x1; ty = y1; 951. x1 = x2; y1 = y2; 952. x2 = tx; y2 = ty; 953. } 954. 955. if (otmp->quan == 1L) { 956. obj_extract_self(otmp); 957. singleobj = otmp; 958. otmp = (struct obj *) 0; 959. } else { 960. singleobj = splitobj(otmp, otmp->quan - 1L); 961. obj_extract_self(singleobj); 962. } 963. newsym(x1,y1); 964. /* in case you're using a pick-axe to chop the boulder that's being 965. launched (perhaps a monster triggered it), destroy context so that 966. next dig attempt never thinks you're resuming previous effort */ 967. if ((otyp == BOULDER || otyp == STATUE) && 968. singleobj->ox == digging.pos.x && singleobj->oy == digging.pos.y) 969. (void) memset((genericptr_t)&digging, 0, sizeof digging); 970. 971. dist = distmin(x1,y1,x2,y2); 972. bhitpos.x = x1; 973. bhitpos.y = y1; 974. dx = sgn(x2 - x1); 975. dy = sgn(y2 - y1); 976. switch (style) { 977. case ROLL: 978. delaycnt = 2; 979. /* fall through */ 980. default: 981. if (!delaycnt) delaycnt = 1; 982. if (!cansee(bhitpos.x,bhitpos.y)) curs_on_u(); 983. tmp_at(DISP_FLASH, obj_to_glyph(singleobj)); 984. tmp_at(bhitpos.x, bhitpos.y); 985. } 986. 987. /* Set the object in motion */ 988. while(dist-- > 0 && !used_up) { 989. tmp_at(bhitpos.x, bhitpos.y); 990. tmp = delaycnt; 991. 992. /* dstage@u.washington.edu -- Delay only if hero sees it */ 993. if (cansee(bhitpos.x, bhitpos.y)) 994. while (tmp-- > 0) delay_output(); 995. 996. bhitpos.x += dx; 997. bhitpos.y += dy; 998. 999. if ((mtmp = m_at(bhitpos.x, bhitpos.y)) != 0) { 1000. if (otyp == BOULDER && throws_rocks(mtmp->data)) { 1001. if (rn2(3)) { 1002. pline("%s snatches the boulder.", 1003. Monnam(mtmp)); 1004. mpickobj(mtmp, singleobj); 1005. used_up = TRUE; 1006. break; 1007. } 1008. } 1009. if (ohitmon(mtmp,singleobj, 1010. (style==ROLL) ? -1 : dist, FALSE)) { 1011. used_up = TRUE; 1012. break; 1013. } 1014. } else if (bhitpos.x==u.ux && bhitpos.y==u.uy) { 1015. int hitvalu, hitu; 1016. if (multi) nomul(0); 1017. hitvalu = 9 + singleobj->spe; 1018. hitu = thitu(hitvalu, 1019. dmgval(singleobj, &youmonst), 1020. singleobj, 1021. xname(singleobj)); 1022. if (hitu) stop_occupation(); 1023. } 1024. if (style == ROLL) { 1025. if (down_gate(bhitpos.x, bhitpos.y) != -1) { 1026. if (ship_object(singleobj, bhitpos.x, bhitpos.y, FALSE)){ 1027. used_up = TRUE; 1028. break; 1029. } 1030. } 1031. if (flooreffects(singleobj, bhitpos.x, bhitpos.y, "fall")) { 1032. used_up = TRUE; 1033. break; 1034. } 1035. } 1036. if (otyp == BOULDER && closed_door(bhitpos.x,bhitpos.y)) { 1037. if (cansee(bhitpos.x, bhitpos.y)) 1038. pline_The("boulder crashes through a door."); 1039. levl[bhitpos.x][bhitpos.y].doormask = D_BROKEN; 1040. } 1041. } 1042. tmp_at(DISP_END, 0); 1043. if (!used_up) { 1044. place_object(singleobj, x2,y2); 1045. newsym(x2,y2); 1046. return 1; 1047. } else 1048. return 2; 1049. } 1050. #endif /* OVL3 */ 1051. #ifdef OVLB 1052. 1053. void 1054. seetrap(trap) 1055. register struct trap *trap; 1056. { 1057. if(!trap->tseen) { 1058. trap->tseen = 1; 1059. newsym(trap->tx, trap->ty); 1060. } 1061. } 1062. 1063. #endif /* OVLB */ 1064. #ifdef OVL3 1065. 1066. STATIC_OVL int 1067. mkroll_launch(ttmp, x, y, otyp, ocount) 1068. struct trap *ttmp; 1069. xchar x,y; 1070. short otyp; 1071. long ocount; 1072. { 1073. struct obj *otmp; 1074. register int tmp; 1075. schar dx,dy; 1076. int distance; 1077. coord cc; 1078. coord bcc; 1079. int trycount = 0; 1080. boolean success = FALSE; 1081. int mindist = 4; 1082. 1083. if (ttmp->ttyp == ROLLING_BOULDER_TRAP) mindist = 2; 1084. distance = rn1(5,4); /* 4..8 away */ 1085. tmp = rn2(8); /* randomly pick a direction to try first */ 1086. while (distance >= mindist) { 1087. dx = xdir[tmp]; 1088. dy = ydir[tmp]; 1089. cc.x = x; cc.y = y; 1090. /* Prevent boulder from being placed on water */ 1091. if (ttmp->ttyp == ROLLING_BOULDER_TRAP 1092. && is_pool(x+distance*dx,y+distance*dy)) 1093. success = FALSE; 1094. else success = isclearpath(&cc, distance, dx, dy); 1095. if (ttmp->ttyp == ROLLING_BOULDER_TRAP) { 1096. boolean success_otherway; 1097. bcc.x = x; bcc.y = y; 1098. success_otherway = isclearpath(&bcc, distance, 1099. -(dx), -(dy)); 1100. if (!success_otherway) success = FALSE; 1101. } 1102. if (success) break; 1103. if (++tmp > 7) tmp = 0; 1104. if ((++trycount % 8) == 0) --distance; 1105. } 1106. if (!success) { 1107. /* create the trap without any ammo, launch pt at trap location */ 1108. cc.x = bcc.x = x; 1109. cc.y = bcc.y = y; 1110. } else { 1111. otmp = mksobj(otyp, TRUE, FALSE); 1112. otmp->quan = ocount; 1113. otmp->owt = weight(otmp); 1114. place_object(otmp, cc.x, cc.y); 1115. stackobj(otmp); 1116. } 1117. ttmp->launch.x = cc.x; 1118. ttmp->launch.y = cc.y; 1119. if (ttmp->ttyp == ROLLING_BOULDER_TRAP) { 1120. ttmp->launch2.x = bcc.x; 1121. ttmp->launch2.y = bcc.y; 1122. } else 1123. ttmp->launch_otyp = otyp; 1124. newsym(ttmp->launch.x, ttmp->launch.y); 1125. return 1; 1126. } 1127. 1128. STATIC_OVL boolean 1129. isclearpath(cc,distance,dx,dy) 1130. coord *cc; 1131. int distance; 1132. schar dx,dy; 1133. { 1134. uchar typ; 1135. xchar x, y; 1136. 1137. x = cc->x; 1138. y = cc->y; 1139. while (distance-- > 0) { 1140. x += dx; 1141. y += dy; 1142. typ = levl[x][y].typ; 1143. if (!isok(x,y) || !ZAP_POS(typ) || closed_door(x,y)) 1144. return FALSE; 1145. } 1146. cc->x = x; 1147. cc->y = y; 1148. return TRUE; 1149. } 1150. #endif /* OVL3 */ 1151. #ifdef OVL1 1152. 1153. int 1154. mintrap(mtmp) 1155. register struct monst *mtmp; 1156. { 1157. register struct trap *trap = t_at(mtmp->mx, mtmp->my); 1158. boolean trapkilled = FALSE; 1159. struct permonst *mptr = mtmp->data; 1160. struct obj *otmp; 1161. 1162. if (!trap) { 1163. mtmp->mtrapped = 0; /* perhaps teleported? */ 1164. } else if (mtmp->mtrapped) { /* is currently in the trap */ 1165. if (!rn2(40)) { 1166. if (sobj_at(BOULDER, mtmp->mx, mtmp->my) && 1167. (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT)) { 1168. if (!rn2(2)) { 1169. mtmp->mtrapped = 0; 1170. if (canseemon(mtmp)) 1171. pline("%s pulls free...", Monnam(mtmp)); 1172. fill_pit(mtmp->mx, mtmp->my); 1173. } 1174. } else { 1175. mtmp->mtrapped = 0; 1176. } 1177. } else if (trap->ttyp == BEAR_TRAP && metallivorous(mptr)) { 1178. if (canseemon(mtmp)) 1179. pline("%s eats a bear trap!", Monnam(mtmp)); 1180. deltrap(trap); 1181. mtmp->meating = 5; 1182. mtmp->mtrapped = 0; 1183. } 1184. } else { 1185. register int tt = trap->ttyp; 1186. boolean in_sight, tear_web, see_it, 1187. inescapable = ((tt == HOLE || tt == PIT) && 1188. In_sokoban(&u.uz) && !trap->madeby_u); 1189. const char *fallverb; 1190. 1191. if (!inescapable && 1192. ((mtmp->mtrapseen & (1 << (tt-1))) != 0 || 1193. (tt == HOLE && !mindless(mtmp->data)))) { 1194. /* it has been in such a trap - perhaps it escapes */ 1195. if(rn2(4)) return(0); 1196. } else { 1197. mtmp->mtrapseen |= (1 << (tt-1)); 1198. } 1199. /* Monster is aggravated by being trapped by you. 1200. Recognizing who made the trap isn't completely 1201. unreasonable; everybody has their own style. */ 1202. if (trap->madeby_u && rnl(5)) setmangry(mtmp); 1203. 1204. /* bug? `in_sight' ought to be split to distinguish between 1205. trap_in_sight and can_see_victim to handle invisible monsters */ 1206. in_sight = canseemon(mtmp); 1207. switch (tt) { 1208. case ARROW_TRAP: 1209. otmp = mksobj(ARROW, TRUE, FALSE); 1210. otmp->quan = 1L; 1211. otmp->owt = weight(otmp); 1212. if (in_sight) seetrap(trap); 1213. if(thitm(8, mtmp, otmp, 0)) trapkilled = TRUE; 1214. break; 1215. case DART_TRAP: 1216. otmp = mksobj(DART, TRUE, FALSE); 1217. otmp->quan = 1L; 1218. otmp->owt = weight(otmp); 1219. if (!rn2(6)) otmp->opoisoned = 1; 1220. if (in_sight) seetrap(trap); 1221. if(thitm(7, mtmp, otmp, 0)) trapkilled = TRUE; 1222. break; 1223. case ROCKTRAP: 1224. otmp = mksobj(ROCK, TRUE, FALSE); 1225. otmp->quan = 1L; 1226. otmp->owt = weight(otmp); 1227. if (in_sight) seetrap(trap); 1228. if (thitm(0, mtmp, otmp, d(2, 6))) 1229. trapkilled = TRUE; 1230. break; 1231. 1232. case SQKY_BOARD: 1233. if(is_flyer(mptr)) break; 1234. /* stepped on a squeaky board */ 1235. if (in_sight) { 1236. pline("A board beneath %s squeaks loudly.", mon_nam(mtmp)); 1237. seetrap(trap); 1238. } else 1239. You_hear("a distant squeak."); 1240. /* wake up nearby monsters */ 1241. wake_nearto(mtmp->mx, mtmp->my, 40); 1242. break; 1243. 1244. case BEAR_TRAP: 1245. if(mptr->msize > MZ_SMALL && 1246. !amorphous(mptr) && !is_flyer(mptr) && 1247. !is_whirly(mptr) && !unsolid(mptr)) { 1248. mtmp->mtrapped = 1; 1249. if(in_sight) { 1250. pline("%s is caught in %s bear trap!", 1251. Monnam(mtmp), a_your[trap->madeby_u]); 1252. seetrap(trap); 1253. } else { 1254. if((mptr == &mons[PM_OWLBEAR] 1255. || mptr == &mons[PM_BUGBEAR]) 1256. && flags.soundok) 1257. You_hear("the roaring of an angry bear!"); 1258. } 1259. } 1260. break; 1261. 1262. case SLP_GAS_TRAP: 1263. if (!resists_sleep(mtmp) && 1264. !mtmp->msleeping && mtmp->mcanmove) { 1265. mtmp->mcanmove = 0; 1266. mtmp->mfrozen = rnd(25); 1267. if (in_sight) { 1268. pline("%s suddenly falls asleep!", 1269. Monnam(mtmp)); 1270. seetrap(trap); 1271. } 1272. } 1273. break; 1274. 1275. case RUST_TRAP: 1276. { 1277. struct obj *target; 1278. 1279. if (in_sight) 1280. seetrap(trap); 1281. switch (rn2(5)) { 1282. case 0: 1283. if (in_sight) 1284. pline("%s %s on the %s!", A_gush_of_water_hits, 1285. mon_nam(mtmp), mbodypart(mtmp, HEAD)); 1286. target = which_armor(mtmp, W_ARMH); 1287. (void) rust_dmg(target, "helmet", 1, TRUE, mtmp); 1288. break; 1289. case 1: 1290. if (in_sight) 1291. pline("%s %s's left %s!", A_gush_of_water_hits, 1292. mon_nam(mtmp), mbodypart(mtmp, ARM)); 1293. target = which_armor(mtmp, W_ARMS); 1294. if (rust_dmg(target, "shield", 1, TRUE, mtmp)) 1295. break; 1296. target = MON_WEP(mtmp); 1297. if (target && bimanual(target)) 1298. goto two_hand; 1299. glovecheck: target = which_armor(mtmp, W_ARMG); 1300. (void) rust_dmg(target, "gauntlets", 1, TRUE, mtmp); 1301. break; 1302. case 2: 1303. if (in_sight) 1304. pline("%s %s's right %s!", A_gush_of_water_hits, 1305. mon_nam(mtmp), mbodypart(mtmp, ARM)); 1306. two_hand: erode_weapon(mtmp, FALSE); 1307. goto glovecheck; 1308. default: 1309. if (in_sight) 1310. pline("%s %s!", A_gush_of_water_hits, 1311. mon_nam(mtmp)); 1312. for (otmp=mtmp->minvent; otmp; otmp = otmp->nobj) 1313. (void) snuff_lit(otmp); 1314. target = which_armor(mtmp, W_ARMC); 1315. if (target) 1316. (void) rust_dmg(target, "cloak", 1, TRUE, mtmp); 1317. else { 1318. target = which_armor(mtmp, W_ARM); 1319. if (target) 1320. (void) rust_dmg(target, "armor", 1, TRUE, mtmp); 1321. #ifdef TOURIST 1322. else { 1323. target = which_armor(mtmp, W_ARMU); 1324. (void) rust_dmg(target, "shirt", 1, TRUE, mtmp); 1325. } 1326. #endif 1327. } 1328. } 1329. if (mptr == &mons[PM_IRON_GOLEM]) { 1330. if (in_sight) 1331. pline("%s falls to pieces!", Monnam(mtmp)); 1332. else if(mtmp->mtame) 1333. pline("May %s rust in peace.", 1334. mon_nam(mtmp)); 1335. mondied(mtmp); 1336. if (mtmp->mhp <= 0) 1337. trapkilled = TRUE; 1338. } else if (mptr == &mons[PM_GREMLIN] && rn2(3)) { 1339. (void)split_mon(mtmp, (struct monst *)0); 1340. } 1341. break; 1342. } 1343. case FIRE_TRAP: 1344. mfiretrap: 1345. see_it = cansee(mtmp->mx, mtmp->my); 1346. if (in_sight) 1347. pline("A %s erupts from the %s under %s!", 1348. tower_of_flame, 1349. surface(mtmp->mx,mtmp->my), mon_nam(mtmp)); 1350. else if (see_it) /* evidently `mtmp' is invisible */ 1351. You("see a %s erupt from the %s!", 1352. tower_of_flame, surface(mtmp->mx,mtmp->my)); 1353. 1354. if (resists_fire(mtmp)) { 1355. if (in_sight) { 1356. shieldeff(mtmp->mx,mtmp->my); 1357. pline("%s is uninjured.", Monnam(mtmp)); 1358. } 1359. } else { 1360. int num = d(2,4); 1361. 1362. if (thitm(0, mtmp, (struct obj *)0, num)) 1363. trapkilled = TRUE; 1364. else 1365. /* we know mhp is at least `num' below mhpmax, 1366. so no (mhp > mhpmax) check is needed here */ 1367. mtmp->mhpmax -= rn2(num + 1); 1368. } 1369. if (burnarmor(mtmp) || rn2(3)) { 1370. (void) destroy_mitem(mtmp, SCROLL_CLASS, AD_FIRE); 1371. (void) destroy_mitem(mtmp, SPBOOK_CLASS, AD_FIRE); 1372. (void) destroy_mitem(mtmp, POTION_CLASS, AD_FIRE); 1373. } 1374. if (burn_floor_paper(mtmp->mx, mtmp->my, see_it) && 1375. !see_it && distu(mtmp->mx, mtmp->my) <= 3*3) 1376. You("smell smoke."); 1377. if (is_ice(mtmp->mx,mtmp->my)) 1378. melt_ice(mtmp->mx,mtmp->my); 1379. if (see_it) seetrap(trap); 1380. break; 1381. 1382. case PIT: 1383. case SPIKED_PIT: 1384. fallverb = "falls"; 1385. if (is_flyer(mptr) || is_floater(mptr) || 1386. (mtmp->wormno && count_wsegs(mtmp) > 5) || 1387. is_clinger(mptr)) { 1388. if (!inescapable) break; /* avoids trap */ 1389. fallverb = "is dragged"; /* sokoban pit */ 1390. } 1391. if (!passes_walls(mptr)) 1392. mtmp->mtrapped = 1; 1393. if (in_sight) { 1394. pline("%s %s into %s pit!", 1395. Monnam(mtmp), fallverb, 1396. a_your[trap->madeby_u]); 1397. seetrap(trap); 1398. } 1399. mselftouch(mtmp, "Falling, ", FALSE); 1400. if (mtmp->mhp <= 0 || 1401. thitm(0, mtmp, (struct obj *)0, 1402. rnd((tt == PIT) ? 6 : 10))) 1403. trapkilled = TRUE; 1404. break; 1405. case HOLE: 1406. case TRAPDOOR: 1407. if (!Can_fall_thru(&u.uz)) { 1408. impossible("mintrap: %ss cannot exist on this level.", 1409. defsyms[trap_to_defsym(tt)].explanation); 1410. break; /* don't activate it after all */ 1411. } 1412. if (is_flyer(mptr) || is_floater(mptr) || 1413. mptr == &mons[PM_WUMPUS] || 1414. (mtmp->wormno && count_wsegs(mtmp) > 5) || 1415. mptr->msize >= MZ_HUGE) { 1416. if (inescapable) { /* sokoban hole */ 1417. if (in_sight) { 1418. pline("%s seems to be yanked down!", 1419. Monnam(mtmp)); 1420. /* suppress message in mlevel_tele_trap() */ 1421. in_sight = FALSE; 1422. seetrap(trap); 1423. } 1424. } else 1425. break; 1426. } 1427. /* Fall through */ 1428. case LEVEL_TELEP: 1429. case MAGIC_PORTAL: 1430. { 1431. int mlev_res; 1432. mlev_res = mlevel_tele_trap(mtmp, trap, 1433. inescapable, in_sight); 1434. if (mlev_res) return(mlev_res); 1435. } 1436. break; 1437. 1438. case TELEP_TRAP: 1439. mtele_trap(mtmp, trap, in_sight); 1440. break; 1441. 1442. case WEB: 1443. /* Monster in a web. */ 1444. if (mptr->mlet == S_SPIDER) break; 1445. if (amorphous(mptr) || is_whirly(mptr) || unsolid(mptr)){ 1446. if(acidic(mptr) || 1447. mptr == &mons[PM_GELATINOUS_CUBE] || 1448. mptr == &mons[PM_FIRE_ELEMENTAL]) { 1449. if (in_sight) 1450. pline("%s %s %s spider web!", 1451. Monnam(mtmp), 1452. (mptr == &mons[PM_FIRE_ELEMENTAL]) ? 1453. "burns" : "dissolves", 1454. a_your[trap->madeby_u]); 1455. deltrap(trap); 1456. newsym(mtmp->mx, mtmp->my); 1457. break; 1458. } 1459. if (in_sight) { 1460. pline("%s flows through %s spider web.", 1461. Monnam(mtmp), 1462. a_your[trap->madeby_u]); 1463. seetrap(trap); 1464. } 1465. break; 1466. } 1467. tear_web = FALSE; 1468. switch (monsndx(mptr)) { 1469. case PM_OWLBEAR: /* Eric Backus */ 1470. case PM_BUGBEAR: 1471. if (!in_sight) { 1472. You_hear("the roaring of a confused bear!"); 1473. mtmp->mtrapped = 1; 1474. break; 1475. } 1476. /* fall though */ 1477. default: 1478. if (mptr->mlet == S_GIANT || 1479. (mptr->mlet == S_DRAGON && 1480. extra_nasty(mptr)) || /* excl. babies */ 1481. (mtmp->wormno && count_wsegs(mtmp) > 5)) { 1482. tear_web = TRUE; 1483. } else if (in_sight) { 1484. pline("%s is caught in %s spider web.", 1485. Monnam(mtmp), 1486. a_your[trap->madeby_u]); 1487. seetrap(trap); 1488. } 1489. mtmp->mtrapped = tear_web ? 0 : 1; 1490. break; 1491. /* this list is fairly arbitrary; it deliberately 1492. excludes wumpus & giant/ettin zombies/mummies */ 1493. case PM_TITANOTHERE: 1494. case PM_BALUCHITHERIUM: 1495. case PM_PURPLE_WORM: 1496. case PM_JABBERWOCK: 1497. case PM_IRON_GOLEM: 1498. case PM_BALROG: 1499. case PM_KRAKEN: 1500. tear_web = TRUE; 1501. break; 1502. } 1503. if (tear_web) { 1504. if (in_sight) 1505. pline("%s tears through %s spider web!", 1506. Monnam(mtmp), a_your[trap->madeby_u]); 1507. deltrap(trap); 1508. newsym(mtmp->mx, mtmp->my); 1509. } 1510. break; 1511. 1512. case STATUE_TRAP: 1513. break; 1514. 1515. case MAGIC_TRAP: 1516. /* A magic trap. Monsters usually immune. */ 1517. if (!rn2(21)) goto mfiretrap; 1518. break; 1519. case ANTI_MAGIC: 1520. break; 1521. 1522. case LANDMINE: 1523. if(rn2(3)) 1524. break; /* monsters usually don't set it off */ 1525. if(is_flyer(mptr)) { 1526. boolean already_seen = trap->tseen; 1527. if (in_sight && !already_seen) { 1528. pline("A trigger appears in a pile of soil below %s.", mon_nam(mtmp)); 1529. seetrap(trap); 1530. } 1531. if (rn2(3)) break; 1532. if (in_sight) { 1533. newsym(mtmp->mx, mtmp->my); 1534. pline_The("air currents set %s off!", 1535. already_seen ? "a land mine" : "it"); 1536. } 1537. } else if(in_sight) { 1538. newsym(mtmp->mx, mtmp->my); 1539. pline("KAABLAMM!!! %s triggers %s land mine!", 1540. Monnam(mtmp), a_your[trap->madeby_u]); 1541. } 1542. if (!in_sight) 1543. pline("Kaablamm! You hear an explosion in the distance!"); 1544. blow_up_landmine(trap); 1545. if(thitm(0, mtmp, (struct obj *)0, rnd(16))) 1546. trapkilled = TRUE; 1547. else { 1548. /* monsters recursively fall into new pit */ 1549. if (mintrap(mtmp) == 2) trapkilled=TRUE; 1550. } 1551. if (unconscious()) { 1552. multi = -1; 1553. nomovemsg="The explosion awakens you!"; 1554. } 1555. break; 1556. 1557. case POLY_TRAP: 1558. if (resists_magm(mtmp)) { 1559. shieldeff(mtmp->mx, mtmp->my); 1560. } else if (!resist(mtmp, WAND_CLASS, 0, NOTELL)) { 1561. (void) newcham(mtmp, (struct permonst *)0); 1562. if (in_sight) seetrap(trap); 1563. } 1564. break; 1565. 1566. case ROLLING_BOULDER_TRAP: 1567. if (!is_flyer(mptr)) { 1568. newsym(mtmp->mx,mtmp->my); 1569. if (in_sight) 1570. pline("Click! %s triggers %s.", Monnam(mtmp), 1571. trap->tseen ? 1572. "a rolling boulder trap" : 1573. something); 1574. if (launch_obj(BOULDER, trap->launch.x, trap->launch.y, 1575. trap->launch2.x, trap->launch2.y, ROLL)) { 1576. if (in_sight) trap->tseen = TRUE; 1577. else You_hear(Hallucination ? 1578. "someone bowling." : 1579. "rumbling in the distance."); 1580. if (mtmp->mhp <= 0) trapkilled = TRUE; 1581. } else { 1582. deltrap(trap); 1583. newsym(mtmp->mx,mtmp->my); 1584. } 1585. } 1586. break; 1587. 1588. default: 1589. impossible("Some monster encountered a strange trap of type %d.", tt); 1590. } 1591. } 1592. if(trapkilled) return 2; 1593. return mtmp->mtrapped; 1594. } 1595. 1596. #endif /* OVL1 */ 1597. #ifdef OVLB 1598. 1599. /* Combine cockatrice checks into single functions to avoid repeating code. */ 1600. void 1601. instapetrify(str) 1602. const char *str; 1603. { 1604. if (Stone_resistance) return; 1605. if (poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM)) 1606. return; 1607. You("turn to stone..."); 1608. killer_format = KILLED_BY; 1609. killer = str; 1610. done(STONING); 1611. } 1612. 1613. void 1614. minstapetrify(mon,byplayer) 1615. struct monst *mon; 1616. boolean byplayer; 1617. { 1618. if (resists_ston(mon)) return; 1619. if (cansee(mon->mx, mon->my)) 1620. pline("%s turns to stone.", Monnam(mon)); 1621. if (poly_when_stoned(mon->data)) { 1622. mon_to_stone(mon); 1623. return; 1624. } 1625. if (byplayer) { 1626. stoned = TRUE; 1627. xkilled(mon,0); 1628. } else monstone(mon); 1629. } 1630. 1631. void 1632. selftouch(arg) 1633. const char *arg; 1634. { 1635. char kbuf[BUFSZ]; 1636. 1637. if(uwep && uwep->otyp == CORPSE && touch_petrifies(&mons[uwep->corpsenm]) 1638. && !Stone_resistance) { 1639. pline("%s touch the %s corpse.", arg, 1640. mons[uwep->corpsenm].mname); 1641. Sprintf(kbuf, "%s corpse", an(mons[uwep->corpsenm].mname)); 1642. instapetrify(kbuf); 1643. } 1644. /* Or your secondary weapon, if wielded */ 1645. if(u.twoweap && uswapwep && uswapwep->otyp == CORPSE && 1646. touch_petrifies(&mons[uswapwep->corpsenm]) && !Stone_resistance){ 1647. pline("%s touch the %s corpse.", arg, 1648. mons[uswapwep->corpsenm].mname); 1649. Sprintf(kbuf, "%s corpse", an(mons[uswapwep->corpsenm].mname)); 1650. instapetrify(kbuf); 1651. } 1652. } 1653. 1654. void 1655. mselftouch(mon,arg,byplayer) 1656. struct monst *mon; 1657. const char *arg; 1658. boolean byplayer; 1659. { 1660. struct obj *mwep = MON_WEP(mon); 1661. 1662. if (mwep && mwep->otyp == CORPSE && touch_petrifies(&mons[mwep->corpsenm])) { 1663. if (cansee(mon->mx, mon->my)) { 1664. pline("%s%s touches the %s corpse.", 1665. arg ? arg : "", arg ? mon_nam(mon) : Monnam(mon), 1666. mons[mwep->corpsenm].mname); 1667. } 1668. minstapetrify(mon, byplayer); 1669. } 1670. } 1671. 1672. void 1673. float_up() 1674. { 1675. if(u.utrap) { 1676. if(u.utraptype == TT_PIT) { 1677. u.utrap = 0; 1678. You("float up, out of the pit!"); 1679. vision_full_recalc = 1; /* vision limits change */ 1680. fill_pit(u.ux, u.uy); 1681. } else if (u.utraptype == TT_INFLOOR) { 1682. Your("body pulls upward, but your %s are still stuck.", 1683. makeplural(body_part(LEG))); 1684. } else { 1685. You("float up, only your %s is still stuck.", 1686. body_part(LEG)); 1687. } 1688. } 1689. else if(Is_waterlevel(&u.uz)) 1690. pline("It feels as though you've lost some weight."); 1691. else if(u.uinwater) 1692. spoteffects(); 1693. else if(u.uswallow) 1694. You(is_animal(u.ustuck->data) ? 1695. "float away from the %s." : 1696. "spiral up into %s.", 1697. is_animal(u.ustuck->data) ? 1698. surface(u.ux, u.uy) : 1699. mon_nam(u.ustuck)); 1700. else if (Hallucination) 1701. pline("Up, up, and awaaaay! You're walking on air!"); 1702. else if(Is_airlevel(&u.uz)) 1703. You("gain control over your movements."); 1704. else 1705. You("start to float in the air!"); 1706. #ifdef STEED 1707. if (u.usteed && !is_floater(u.usteed->data) && !is_flyer(u.usteed->data)) 1708. if (Lev_at_will) 1709. pline("%s magically floats up!", Monnam(u.usteed)); 1710. else { 1711. You("cannot stay on %s.", mon_nam(u.usteed)); 1712. dismount_steed(DISMOUNT_GENERIC); 1713. } 1714. #endif 1715. return; 1716. } 1717. 1718. void 1719. fill_pit(x, y) 1720. int x, y; 1721. { 1722. struct obj *otmp; 1723. struct trap *t; 1724. 1725. if ((t = t_at(x, y)) && 1726. ((t->ttyp == PIT) || (t->ttyp == SPIKED_PIT)) && 1727. (otmp = sobj_at(BOULDER, x, y))) { 1728. obj_extract_self(otmp); 1729. (void) flooreffects(otmp, x, y, "settle"); 1730. } 1731. } 1732. 1733. int 1734. float_down(hmask, emask) 1735. long hmask, emask; /* might cancel timeout */ 1736. { 1737. register struct trap *trap = (struct trap *)0; 1738. d_level current_dungeon_level; 1739. boolean no_msg = FALSE; 1740. 1741. HLevitation &= ~hmask; 1742. ELevitation &= ~emask; 1743. if(Levitation) return(0); /* maybe another ring/potion/boots */ 1744. 1745. if (Punished && !carried(uball) && 1746. (is_pool(uball->ox, uball->oy) || 1747. ((trap = t_at(uball->ox, uball->oy)) && 1748. ((trap->ttyp == PIT) || (trap->ttyp == SPIKED_PIT) || 1749. (trap->ttyp == TRAPDOOR) || (trap->ttyp == HOLE))))) { 1750. u.ux0 = u.ux; 1751. u.uy0 = u.uy; 1752. u.ux = uball->ox; 1753. u.uy = uball->oy; 1754. movobj(uchain, uball->ox, uball->oy); 1755. newsym(u.ux0, u.uy0); 1756. vision_full_recalc = 1; /* in case the hero moved. */ 1757. } 1758. /* check for falling into pool - added by GAN 10/20/86 */ 1759. if(!Flying) { 1760. /* kludge alert: 1761. * drown() and lava_effects() print various messages almost 1762. * every time they're called which conflict with the "fall 1763. * into" message below. Thus, we want to avoid printing 1764. * confusing, duplicate or out-of-order messages. 1765. * Use knowledge of the two routines as a hack -- this 1766. * should really handled differently -dlc 1767. */ 1768. if(is_pool(u.ux,u.uy) && !Wwalking && !Swimming && !u.uinwater) 1769. no_msg = drown(); 1770. 1771. if(is_lava(u.ux,u.uy)) { 1772. (void) lava_effects(); 1773. no_msg = TRUE; 1774. } 1775. } 1776. if (!trap) { 1777. if(Is_airlevel(&u.uz)) 1778. You("begin to tumble in place."); 1779. else if (Is_waterlevel(&u.uz) && !no_msg) 1780. You_feel("heavier."); 1781. /* u.uinwater msgs already in spoteffects()/drown() */ 1782. else if (!u.uinwater && !no_msg) { 1783. if (Hallucination) 1784. pline("Bummer! You've %s.", 1785. is_pool(u.ux,u.uy) ? 1786. "splashed down" : "hit the ground"); 1787. else 1788. #ifdef STEED 1789. if (!(emask & W_SADDLE)) 1790. #endif 1791. You("float gently to the %s.", 1792. surface(u.ux, u.uy)); 1793. } 1794. trap = t_at(u.ux,u.uy); 1795. } 1796. 1797. /* can't rely on u.uz0 for detecting trap door-induced level change; 1798. it gets changed to reflect the new level before we can check it */ 1799. assign_level(&current_dungeon_level, &u.uz); 1800. 1801. if(trap) 1802. switch(trap->ttyp) { 1803. case STATUE_TRAP: 1804. break; 1805. case HOLE: 1806. case TRAPDOOR: 1807. if(!Can_fall_thru(&u.uz) || u.ustuck) 1808. break; 1809. /* fall into next case */ 1810. default: 1811. dotrap(trap); 1812. } 1813. 1814. if (!Is_airlevel(&u.uz) && !Is_waterlevel(&u.uz) && !u.uswallow && 1815. /* falling through trap door calls goto_level, 1816. and goto_level does its own pickup() call */ 1817. on_level(&u.uz, &current_dungeon_level)) 1818. pickup(1); 1819. return 1; 1820. } 1821. 1822. STATIC_OVL void 1823. dofiretrap(box) 1824. struct obj *box; /* null for floor trap */ 1825. { 1826. boolean see_it = !Blind; 1827. int num; 1828. 1829. /* Bug: for box case, the equivalent of burn_floor_paper() ought 1830. * to be done upon its contents. 1831. */ 1832. 1833. if ((box && !carried(box)) ? is_pool(box->ox, box->oy) : Underwater) { 1834. pline("A cascade of steamy bubbles erupts from %s!", 1835. the(box ? xname(box) : surface(u.ux,u.uy))); 1836. if (Fire_resistance) You("are uninjured."); 1837. else losehp(rnd(3), "boiling water", KILLED_BY); 1838. return; 1839. } 1840. pline("A %s %s from %s!", tower_of_flame, 1841. box ? "bursts" : "erupts", 1842. the(box ? xname(box) : surface(u.ux,u.uy))); 1843. if (Fire_resistance) { 1844. shieldeff(u.ux, u.uy); 1845. num = rn2(2); 1846. } else { 1847. num = d(2,4); 1848. if (u.uhpmax > u.ulevel) 1849. u.uhpmax -= rn2(min(u.uhpmax,num + 1)), flags.botl = 1; 1850. } 1851. if (!num) 1852. You("are uninjured."); 1853. else 1854. losehp(num, tower_of_flame, KILLED_BY_AN); 1855. burn_away_slime(); 1856. 1857. if (burnarmor(&youmonst) || rn2(3)) { 1858. destroy_item(SCROLL_CLASS, AD_FIRE); 1859. destroy_item(SPBOOK_CLASS, AD_FIRE); 1860. destroy_item(POTION_CLASS, AD_FIRE); 1861. } 1862. if (!box && burn_floor_paper(u.ux, u.uy, see_it) && !see_it) 1863. You("smell paper burning."); 1864. if (is_ice(u.ux, u.uy)) 1865. melt_ice(u.ux, u.uy); 1866. } 1867. 1868. STATIC_OVL void 1869. domagictrap() 1870. { 1871. register int fate = rnd(20); 1872. 1873. /* What happened to the poor sucker? */ 1874. 1875. if (fate < 10) { 1876. /* Most of the time, it creates some monsters. */ 1877. register int cnt = rnd(4); 1878. 1879. if (!resists_blnd(&youmonst)) { 1880. You("are momentarily blinded by a flash of light!"); 1881. make_blinded((long)rn1(5,10),FALSE); 1882. } else if (!Blind) { 1883. You("see a flash of light!"); 1884. } else 1885. You_hear("a deafening roar!"); 1886. while(cnt--) 1887. (void) makemon((struct permonst *) 0, u.ux, u.uy, NO_MM_FLAGS); 1888. } 1889. else 1890. switch (fate) { 1891. 1892. case 10: 1893. case 11: 1894. /* sometimes nothing happens */ 1895. break; 1896. case 12: /* a flash of fire */ 1897. dofiretrap((struct obj *)0); 1898. break; 1899. 1900. /* odd feelings */ 1901. case 13: pline("A shiver runs up and down your %s!", 1902. body_part(SPINE)); 1903. break; 1904. case 14: You_hear(Hallucination ? 1905. "the moon howling at you." : 1906. "distant howling."); 1907. break; 1908. case 15: if (on_level(&u.uz, &qstart_level)) 1909. You_feel("%slike the prodigal son.", 1910. (flags.female || (Upolyd && is_neuter(youmonst.data))) ? 1911. "oddly " : ""); 1912. else 1913. You("suddenly yearn for %s.", 1914. Hallucination ? "Cleveland" : 1915. (In_quest(&u.uz) || at_dgn_entrance("The Quest")) ? 1916. "your nearby homeland" : 1917. "your distant homeland"); 1918. break; 1919. case 16: Your("pack shakes violently!"); 1920. break; 1921. case 17: You(Hallucination ? 1922. "smell hamburgers." : 1923. "smell charred flesh."); 1924. break; 1925. case 18: You_feel("tired."); 1926. break; 1927. 1928. /* very occasionally something nice happens. */ 1929. 1930. case 19: 1931. /* tame nearby monsters */ 1932. { register int i,j; 1933. register struct monst *mtmp; 1934. 1935. (void) adjattrib(A_CHA,1,FALSE); 1936. for(i = -1; i <= 1; i++) for(j = -1; j <= 1; j++) { 1937. if(!isok(u.ux+i, u.uy+j)) continue; 1938. mtmp = m_at(u.ux+i, u.uy+j); 1939. if(mtmp) 1940. (void) tamedog(mtmp, (struct obj *)0); 1941. } 1942. break; 1943. } 1944. 1945. case 20: 1946. /* uncurse stuff */ 1947. { register struct obj *obj; 1948. 1949. /* below plines added by GAN 10/30/86 */ 1950. You_feel(Hallucination ? 1951. "in touch with the Universal Oneness." : 1952. "like someone is helping you."); 1953. for(obj = invent; obj ; obj = obj->nobj) 1954. if(obj->owornmask || obj->otyp == LOADSTONE) 1955. uncurse(obj); 1956. if(Punished) unpunish(); 1957. break; 1958. } 1959. default: break; 1960. } 1961. } 1962. 1963. void 1964. water_damage(obj, force, here) 1965. register struct obj *obj; 1966. register boolean force, here; 1967. { 1968. /* Scrolls, spellbooks, potions, weapons and 1969. pieces of armor may get affected by the water */ 1970. for (; obj; obj = (here ? obj->nexthere : obj->nobj)) { 1971. 1972. (void) snuff_lit(obj); 1973. 1974. if(obj->greased) { 1975. if (force || !rn2(2)) obj->greased = 0; 1976. } else if(Is_container(obj) && !Is_box(obj) && 1977. (obj->otyp != OILSKIN_SACK || (obj->cursed && !rn2(3)))) { 1978. water_damage(obj->cobj, force, FALSE); 1979. } else if (!force && (Luck + 5) > rn2(20)) { 1980. /* chance per item of sustaining damage: 1981. * max luck (full moon): 5% 1982. * max luck (elsewhen): 10% 1983. * avg luck (Luck==0): 75% 1984. * awful luck (Luck<-4): 100% 1985. */ 1986. continue; 1987. } else if (obj->oclass == SCROLL_CLASS) { 1988. #ifdef MAIL 1989. if (obj->otyp != SCR_MAIL) 1990. #endif 1991. obj->otyp = SCR_BLANK_PAPER; 1992. obj->spe = 0; 1993. } else if (obj->oclass == SPBOOK_CLASS) { 1994. if (obj->otyp == SPE_BOOK_OF_THE_DEAD) 1995. pline("Steam rises from %s.", the(xname(obj))); 1996. else obj->otyp = SPE_BLANK_PAPER; 1997. } else if (obj->oclass == POTION_CLASS) { 1998. if (obj->odiluted) { 1999. obj->otyp = POT_WATER; 2000. obj->blessed = obj->cursed = 0; 2001. obj->odiluted = 0; 2002. } else if (obj->otyp != POT_WATER) 2003. obj->odiluted++; 2004. } else if (is_rustprone(obj) && obj->oeroded < MAX_ERODE && 2005. !(obj->oerodeproof || (obj->blessed && !rnl(4)))) { 2006. /* all metal stuff and armor except (body armor 2007. protected by oilskin cloak) */ 2008. if(obj->oclass != ARMOR_CLASS || obj != uarm || 2009. !uarmc || uarmc->otyp != OILSKIN_CLOAK || 2010. (uarmc->cursed && !rn2(3))) 2011. obj->oeroded++; 2012. } 2013. } 2014. } 2015. 2016. /* 2017. * This function is potentially expensive - rolling 2018. * inventory list multiple times. Luckily it's seldom needed. 2019. * Returns TRUE if disrobing made player unencumbered enough to 2020. * crawl out of the current predicament. 2021. */ 2022. STATIC_OVL boolean 2023. emergency_disrobe(lostsome) 2024. boolean *lostsome; 2025. { 2026. int invc = inv_cnt(); 2027. 2028. 2029. while (near_capacity() > (Punished ? UNENCUMBERED : SLT_ENCUMBER)) { 2030. register struct obj *obj, *otmp = (struct obj *)0; 2031. register int i; 2032. 2033. /* Pick a random object */ 2034. if (invc > 0) { 2035. i = rn2(invc); 2036. for (obj = invent; obj; obj = obj->nobj) { 2037. /* 2038. * Undroppables are: body armor, boots, gloves, 2039. * amulets, and rings because of the time and effort 2040. * in removing them + loadstone and other cursed stuff 2041. * for obvious reasons. 2042. */ 2043. if (!((obj->otyp == LOADSTONE && obj->cursed) || 2044. obj == uamul || obj == uleft || obj == uright || 2045. obj == ublindf || obj == uarm || obj == uarmc || 2046. obj == uarmg || obj == uarmf || 2047. #ifdef TOURIST 2048. obj == uarmu || 2049. #endif 2050. (obj->cursed && (obj == uarmh || obj == uarms)) || 2051. welded(obj))) 2052. otmp = obj; 2053. /* reached the mark and found some stuff to drop? */ 2054. if (--i < 0 && otmp) break; 2055. 2056. /* else continue */ 2057. } 2058. } 2059. 2060. if (!otmp) { 2061. /* Nothing available left to drop; try gold */ 2062. if (u.ugold) { 2063. pline("In desperation, you drop your purse."); 2064. /* Hack: gold is not in the inventory, so make a gold object 2065. * and put it at the head of the inventory list. 2066. */ 2067. obj = mkgoldobj(u.ugold); /* removes from u.ugold */ 2068. u.ugold = obj->quan; /* put the gold back */ 2069. assigninvlet(obj); /* might end up as NOINVSYM */ 2070. obj->nobj = invent; 2071. invent = obj; 2072. dropx(obj); 2073. continue; /* Try again */ 2074. } 2075. /* We can't even drop gold! */ 2076. return (FALSE); 2077. } 2078. 2079. if (otmp == uarmh) (void) Helmet_off(); 2080. else if (otmp == uarms) (void) Shield_off(); 2081. else if (otmp == uwep) setuwep((struct obj *)0); 2082. *lostsome = TRUE; 2083. dropx(otmp); 2084. invc--; 2085. } 2086. return(TRUE); 2087. } 2088. 2089. /* 2090. * return(TRUE) == player relocated 2091. */ 2092. boolean 2093. drown() 2094. { 2095. boolean inpool_ok = FALSE, crawl_ok; 2096. int i, x, y; 2097. 2098. /* happily wading in the same contiguous pool */ 2099. if (u.uinwater && is_pool(u.ux-u.dx,u.uy-u.dy) && 2100. (Swimming || Amphibious)) { 2101. /* water effects on objects every now and then */ 2102. if (!rn2(5)) inpool_ok = TRUE; 2103. else return(FALSE); 2104. } 2105. 2106. if (!u.uinwater) { 2107. You("%s into the water%c", 2108. Is_waterlevel(&u.uz) ? "plunge" : "fall", 2109. Amphibious || Swimming ? '.' : '!'); 2110. if (!Swimming && !Is_waterlevel(&u.uz)) 2111. You("sink like %s.", 2112. Hallucination ? "the Titanic" : "a rock"); 2113. } 2114. 2115. water_damage(invent, FALSE, FALSE); 2116. 2117. if (u.umonnum == PM_GREMLIN && rn2(3)) 2118. (void)split_mon(&youmonst, (struct monst *)0); 2119. if (inpool_ok) return(FALSE); 2120. 2121. if ((i = number_leashed()) > 0) { 2122. pline_The("leash%s slip%s loose.", 2123. (i > 1) ? "es" : "", 2124. (i > 1) ? "" : "s"); 2125. unleash_all(); 2126. } 2127. 2128. if (Amphibious || Swimming) { 2129. if (Amphibious) { 2130. if (flags.verbose) 2131. pline("But you aren't drowning."); 2132. if (!Is_waterlevel(&u.uz)) 2133. if (Hallucination) 2134. Your("keel hits the bottom."); 2135. else 2136. You("touch bottom."); 2137. } 2138. if (Punished) { 2139. unplacebc(); 2140. placebc(); 2141. } 2142. vision_recalc(2); /* unsee old position */ 2143. u.uinwater = 1; 2144. under_water(1); 2145. vision_full_recalc = 1; 2146. return(FALSE); 2147. } 2148. if((Teleportation || can_teleport(youmonst.data)) && 2149. (Teleport_control || rn2(3) < Luck+2)) { 2150. You("attempt a teleport spell."); /* utcsri!carroll */ 2151. (void) dotele(); 2152. if(!is_pool(u.ux,u.uy)) 2153. return(TRUE); 2154. } 2155. #ifdef STEED 2156. if (u.usteed) { 2157. dismount_steed(DISMOUNT_GENERIC); 2158. if(!is_pool(u.ux,u.uy)) 2159. return(TRUE); 2160. } 2161. #endif 2162. crawl_ok = FALSE; 2163. /* look around for a place to crawl to */ 2164. for (i = 0; i < 100; i++) { 2165. x = rn1(3,u.ux - 1); 2166. y = rn1(3,u.uy - 1); 2167. if (goodpos(x, y, &youmonst)) { 2168. crawl_ok = TRUE; 2169. goto crawl; 2170. } 2171. } 2172. /* one more scan */ 2173. for (x = u.ux - 1; x <= u.ux + 1; x++) 2174. for (y = u.uy - 1; y <= u.uy + 1; y++) 2175. if (goodpos(x, y, &youmonst)) { 2176. crawl_ok = TRUE; 2177. goto crawl; 2178. } 2179. crawl:; 2180. if (crawl_ok) { 2181. boolean lost = FALSE; 2182. /* time to do some strip-tease... */ 2183. boolean succ = Is_waterlevel(&u.uz) ? TRUE : 2184. emergency_disrobe(&lost); 2185. 2186. You("try to crawl out of the water."); 2187. if (lost) 2188. You("dump some of your gear to lose weight..."); 2189. if (succ) { 2190. pline("Pheew! That was close."); 2191. teleds(x,y); 2192. return(TRUE); 2193. } 2194. /* still too much weight */ 2195. pline("But in vain."); 2196. } 2197. u.uinwater = 1; 2198. You("drown."); 2199. killer_format = KILLED_BY_AN; 2200. killer = (levl[u.ux][u.uy].typ == POOL || Is_medusa_level(&u.uz)) ? 2201. "pool of water" : "moat"; 2202. done(DROWNING); 2203. /* oops, we're still alive. better get out of the water. */ 2204. while (!safe_teleds()) { 2205. pline("You're still drowning."); 2206. done(DROWNING); 2207. } 2208. u.uinwater = 0; 2209. You("find yourself back %s.", Is_waterlevel(&u.uz) ? 2210. "in an air bubble" : "on land"); 2211. return(TRUE); 2212. } 2213. 2214. void 2215. drain_en(n) 2216. register int n; 2217. { 2218. if (!u.uenmax) return; 2219. You_feel("your magical energy drain away!"); 2220. u.uen -= n; 2221. if(u.uen < 0) { 2222. u.uenmax += u.uen; 2223. if(u.uenmax < 0) u.uenmax = 0; 2224. u.uen = 0; 2225. } 2226. flags.botl = 1; 2227. } 2228. 2229. int 2230. dountrap() /* disarm a trap */ 2231. { 2232. if (near_capacity() >= HVY_ENCUMBER) { 2233. pline("You're too strained to do that."); 2234. return 0; 2235. } 2236. if (nohands(youmonst.data) || !youmonst.data->mmove) { 2237. pline("And just how do you expect to do that?"); 2238. return 0; 2239. } else if (u.ustuck && sticks(youmonst.data)) { 2240. pline("You'll have to let go of %s first.", mon_nam(u.ustuck)); 2241. return 0; 2242. } 2243. if (u.ustuck || (welded(uwep) && bimanual(uwep))) { 2244. Your("%s seem to be too busy for that.", 2245. makeplural(body_part(HAND))); 2246. return 0; 2247. } 2248. return untrap(FALSE); 2249. } 2250. #endif /* OVLB */ 2251. #ifdef OVL2 2252. 2253. /* Probability of disabling a trap. Helge Hafting */ 2254. STATIC_OVL int 2255. untrap_prob(ttmp) 2256. struct trap *ttmp; 2257. { 2258. int chance = 3; 2259. 2260. if (Confusion || Hallucination) chance++; 2261. if (Blind) chance++; 2262. if (Stunned) chance += 2; 2263. if (Fumbling) chance *= 2; 2264. /* Your own traps are better known than others. */ 2265. if (ttmp && ttmp->madeby_u) chance--; 2266. if (Role_if(PM_ROGUE)) { 2267. if (rn2(2 * MAXULEV) < u.ulevel) chance--; 2268. if (u.uhave.questart && chance > 1) chance--; 2269. } else if (Role_if(PM_RANGER)) chance--; 2270. return rn2(chance); 2271. } 2272. 2273. /* Replace trap with object(s). Helge Hafting */ 2274. STATIC_OVL void 2275. cnv_trap_obj(otyp, cnt, ttmp) 2276. int otyp; 2277. int cnt; 2278. struct trap *ttmp; 2279. { 2280. struct obj *otmp = mksobj(otyp, TRUE, FALSE); 2281. otmp->quan=cnt; 2282. otmp->owt = weight(otmp); 2283. place_object(otmp, ttmp->tx, ttmp->ty); 2284. /* Sell your own traps only... */ 2285. if (ttmp->madeby_u) sellobj(otmp, ttmp->tx, ttmp->ty); 2286. stackobj(otmp); 2287. newsym(ttmp->tx, ttmp->ty); 2288. deltrap(ttmp); 2289. } 2290. 2291. /* while attempting to disarm an adjacent trap, we've fallen into it */ 2292. STATIC_OVL void 2293. move_into_trap(ttmp) 2294. struct trap *ttmp; 2295. { 2296. int bc; 2297. xchar x = ttmp->tx, y = ttmp->ty, bx, by, cx, cy; 2298. boolean unused; 2299. 2300. /* we know there's no monster in the way, and we're not trapped */ 2301. if (!Punished || drag_ball(x, y, &bc, &bx, &by, &cx, &cy, &unused)) { 2302. u.ux0 = u.ux, u.uy0 = u.uy; 2303. u.ux = x, u.uy = y; 2304. u.umoved = TRUE; 2305. newsym(u.ux0, u.uy0); 2306. vision_recalc(1); 2307. check_leash(u.ux0, u.uy0); 2308. if (Punished) move_bc(0, bc, bx, by, cx, cy); 2309. spoteffects(); /* dotrap() */ 2310. exercise(A_WIS, FALSE); 2311. } 2312. } 2313. 2314. /* 0: doesn't even try 2315. * 1: tries and fails 2316. * 2: succeeds 2317. */ 2318. STATIC_OVL int 2319. try_disarm(ttmp, force_failure) 2320. struct trap *ttmp; 2321. boolean force_failure; 2322. { 2323. struct monst *mtmp = m_at(ttmp->tx,ttmp->ty); 2324. int ttype = ttmp->ttyp; 2325. boolean under_u = (!u.dx && !u.dy); 2326. 2327. /* Test for monster first, monsters are displayed instead of trap. */ 2328. if (mtmp && (!mtmp->mtrapped || ttype != BEAR_TRAP)) { 2329. pline("%s is in the way.", Monnam(mtmp)); 2330. return 0; 2331. } 2332. /* We might be forced to move onto the trap's location. */ 2333. if (sobj_at(BOULDER, ttmp->tx, ttmp->ty) 2334. && !Passes_walls && !under_u) { 2335. pline("There is a boulder in your way."); 2336. return 0; 2337. } 2338. /* untrappable traps are located on the ground. */ 2339. if (!can_reach_floor()) { 2340. #ifdef STEED 2341. if (u.usteed && P_SKILL(P_RIDING) < P_BASIC) 2342. You("aren't skilled enough to reach from %s.", 2343. mon_nam(u.usteed)); 2344. else 2345. #endif 2346. You("are unable to reach the %s!", 2347. defsyms[trap_to_defsym(ttype)].explanation); 2348. return 0; 2349. } 2350. 2351. /* Will our hero succeed? */ 2352. if (force_failure || untrap_prob(ttmp)) { 2353. if (rnl(5)) { 2354. pline("Whoops..."); 2355. if (mtmp) { /* must be a bear trap */ 2356. if (mtmp->mtame) abuse_dog(mtmp); 2357. if ((mtmp->mhp -= rnd(4)) <= 0) killed(mtmp); 2358. } else if (under_u) { 2359. dotrap(ttmp); 2360. } else { 2361. move_into_trap(ttmp); 2362. } 2363. } else { 2364. pline("%s %s is difficult to disarm.", 2365. ttmp->madeby_u ? "Your" : under_u ? "This" : "That", 2366. defsyms[trap_to_defsym(ttype)].explanation); 2367. } 2368. return 1; 2369. } 2370. return 2; 2371. } 2372. 2373. STATIC_OVL void 2374. reward_untrap(ttmp, mtmp) 2375. struct trap *ttmp; 2376. struct monst *mtmp; 2377. { 2378. if (!ttmp->madeby_u) { 2379. if (rnl(10)<8 && !mtmp->mpeaceful && 2380. mtmp->data->mlet != S_HUMAN) { 2381. mtmp->mpeaceful = 1; 2382. set_malign(mtmp); /* reset alignment */ 2383. pline("%s is grateful.", Monnam(mtmp)); 2384. } 2385. /* Helping someone out of a trap is a nice thing to do, 2386. * A lawful may be rewarded, but not too often. */ 2387. if (!rn2(3) && !rnl(8) && u.ualign.type == A_LAWFUL) { 2388. adjalign(1); 2389. You_feel("that you did the right thing."); 2390. } 2391. } 2392. } 2393. 2394. STATIC_OVL int 2395. disarm_beartrap(ttmp) /* Helge Hafting */ 2396. struct trap *ttmp; 2397. { 2398. struct monst *mtmp; 2399. int fails = try_disarm(ttmp, FALSE); 2400. 2401. if (fails < 2) return fails; 2402. 2403. /* ok, disarm it. */ 2404. 2405. /* untrap the monster, if any. 2406. There's no need for a cockatrice test, only the trap is touched */ 2407. if ((mtmp = m_at(ttmp->tx,ttmp->ty)) != 0) { 2408. mtmp->mtrapped = 0; 2409. You("remove %s bear trap from %s.", the_your[ttmp->madeby_u], 2410. mon_nam(mtmp)); 2411. reward_untrap(ttmp, mtmp); 2412. } else You("disarm %s bear trap.", the_your[ttmp->madeby_u]); 2413. cnv_trap_obj(BEARTRAP, 1, ttmp); 2414. return 1; 2415. } 2416. 2417. STATIC_OVL int 2418. disarm_landmine(ttmp) /* Helge Hafting */ 2419. struct trap *ttmp; 2420. { 2421. int fails = try_disarm(ttmp, FALSE); 2422. 2423. if (fails < 2) return fails; 2424. You("disarm %s land mine.", the_your[ttmp->madeby_u]); 2425. cnv_trap_obj(LAND_MINE, 1, ttmp); 2426. return 1; 2427. } 2428. 2429. /* getobj will filter down to cans of grease and known potions of oil */ 2430. static NEARDATA const char oil[] = { ALL_CLASSES, TOOL_CLASS, POTION_CLASS, 0 }; 2431. 2432. /* it may not make much sense to use grease on floor boards, but so what? */ 2433. STATIC_OVL int 2434. disarm_squeaky_board(ttmp) 2435. struct trap *ttmp; 2436. { 2437. struct obj *obj; 2438. boolean bad_tool; 2439. int fails; 2440. 2441. obj = getobj(oil, "untrap with"); 2442. if (!obj) return 0; 2443. 2444. bad_tool = (obj->cursed || 2445. ((obj->otyp != POT_OIL || obj->lamplit) && 2446. (obj->otyp != CAN_OF_GREASE || !obj->spe))); 2447. 2448. fails = try_disarm(ttmp, bad_tool); 2449. if (fails < 2) return fails; 2450. 2451. /* successfully used oil or grease to fix squeaky board */ 2452. if (obj->otyp == CAN_OF_GREASE) { 2453. check_unpaid(obj); 2454. obj->spe--; 2455. } else { 2456. useup(obj); /* oil */ 2457. makeknown(POT_OIL); 2458. } 2459. You("repair the squeaky board."); /* no madeby_u */ 2460. deltrap(ttmp); 2461. newsym(u.ux + u.dx, u.uy + u.dy); 2462. more_experienced(1, 5); 2463. return 1; 2464. } 2465. 2466. /* removes traps that shoot arrows, darts, etc. */ 2467. STATIC_OVL int 2468. disarm_shooting_trap(ttmp, otyp) 2469. struct trap *ttmp; 2470. int otyp; 2471. { 2472. int fails = try_disarm(ttmp, FALSE); 2473. 2474. if (fails < 2) return fails; 2475. You("disarm %s trap.", the_your[ttmp->madeby_u]); 2476. cnv_trap_obj(otyp, 50-rnl(50), ttmp); 2477. return 1; 2478. } 2479. 2480. /* Is the weight too heavy? 2481. * Formula as in near_capacity() & check_capacity() */ 2482. STATIC_OVL int 2483. try_lift(mtmp, ttmp, wt, stuff) 2484. struct monst *mtmp; 2485. struct trap *ttmp; 2486. int wt; 2487. boolean stuff; 2488. { 2489. int wc = weight_cap(); 2490. 2491. if ((((wt<<1) / wc)+1) >= EXT_ENCUMBER) { 2492. pline("%s is %s for you to lift.", Monnam(mtmp), 2493. stuff ? "carrying too much" : "too heavy"); 2494. if (!ttmp->madeby_u && !mtmp->mpeaceful 2495. && mtmp->data->mlet != S_HUMAN && rnl(10) < 3) { 2496. mtmp->mpeaceful = 1; 2497. set_malign(mtmp); /* reset alignment */ 2498. pline("%s thinks it was nice of you to try.", Monnam(mtmp)); 2499. } 2500. return 0; 2501. } 2502. return 1; 2503. } 2504. 2505. /* Help trapped monster (out of a (spiked) pit) */ 2506. STATIC_OVL int 2507. help_monster_out(mtmp, ttmp) 2508. struct monst *mtmp; 2509. struct trap *ttmp; 2510. { 2511. int wt; 2512. struct obj *otmp; 2513. 2514. /* 2515. * This works when levitating too -- consistent with the ability 2516. * to hit monsters while levitating. 2517. * 2518. * Should perhaps check that our hero has arms/hands at the 2519. * moment. Helping can also be done by engulfing... 2520. * 2521. * Test the monster first - monsters are displayed before traps. 2522. */ 2523. if (!mtmp->mtrapped) { 2524. pline("%s isn't trapped.", Monnam(mtmp)); 2525. return 0; 2526. } 2527. /* Do you have the necessary capacity to lift anything? */ 2528. if (check_capacity((char *)0)) return 1; 2529. 2530. /* Will our hero succeed? */ 2531. if (untrap_prob(ttmp)) { 2532. You("try to reach out your %s, but %s backs away skeptically.", 2533. makeplural(body_part(ARM)), 2534. mon_nam(mtmp)); 2535. return 1; 2536. } 2537. 2538. 2539. /* is it a cockatrice?... */ 2540. if (touch_petrifies(mtmp->data) && !uarmg && !Stone_resistance) { 2541. You("grab the trapped %s using your bare %s.", 2542. mtmp->data->mname, makeplural(body_part(HAND))); 2543. 2544. if (poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM)) 2545. display_nhwindow(WIN_MESSAGE, FALSE); 2546. else { 2547. char kbuf[BUFSZ]; 2548. 2549. Sprintf(kbuf, "trying to help %s out of a pit", 2550. an(mtmp->data->mname)); 2551. instapetrify(kbuf); 2552. return 1; 2553. } 2554. } 2555. You("reach out your %s and grab %s.", 2556. makeplural(body_part(ARM)), mon_nam(mtmp)); 2557. 2558. /* is the monster too heavy? */ 2559. wt = inv_weight() + mtmp->data->cwt; 2560. if (!try_lift(mtmp, ttmp, wt, FALSE)) return 1; 2561. 2562. /* is the monster with inventory too heavy? */ 2563. for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj) 2564. wt += otmp->owt; 2565. if (!try_lift(mtmp, ttmp, wt, TRUE)) return 1; 2566. 2567. You("pull %s out of the pit.", mon_nam(mtmp)); 2568. mtmp->mtrapped = 0; 2569. fill_pit(mtmp->mx, mtmp->my); 2570. reward_untrap(ttmp, mtmp); 2571. return 1; 2572. } 2573. 2574. int 2575. untrap(force) 2576. boolean force; 2577. { 2578. register struct obj *otmp; 2579. register boolean confused = (Confusion > 0 || Hallucination > 0); 2580. register int x,y; 2581. int ch; 2582. struct trap *ttmp; 2583. struct monst *mtmp; 2584. boolean trap_skipped = FALSE; 2585. 2586. if(!getdir((char *)0)) return(0); 2587. x = u.ux + u.dx; 2588. y = u.uy + u.dy; 2589. 2590. if ((ttmp = t_at(x,y)) && ttmp->tseen) { 2591. if (u.utrap) { 2592. You("cannot deal with traps while trapped!"); 2593. return 1; 2594. } 2595. switch(ttmp->ttyp) { 2596. case BEAR_TRAP: 2597. return disarm_beartrap(ttmp); 2598. case LANDMINE: 2599. return disarm_landmine(ttmp); 2600. case SQKY_BOARD: 2601. return disarm_squeaky_board(ttmp); 2602. case DART_TRAP: 2603. return disarm_shooting_trap(ttmp, DART); 2604. case ARROW_TRAP: 2605. return disarm_shooting_trap(ttmp, ARROW); 2606. case PIT: 2607. case SPIKED_PIT: 2608. if (!u.dx && !u.dy) { 2609. You("are already on the edge of the pit."); 2610. return 0; 2611. } 2612. if (!(mtmp = m_at(x,y))) { 2613. pline("Try filling the pit instead."); 2614. return 0; 2615. } 2616. return help_monster_out(mtmp, ttmp); 2617. default: 2618. You("cannot disable %s trap.", (u.dx || u.dy) ? "that" : "this"); 2619. return 0; 2620. } /* end switch */ 2621. } /* end if */ 2622. 2623. if(!u.dx && !u.dy) { 2624. for(otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere) 2625. if(Is_box(otmp)) { 2626. pline("There is %s here.", doname(otmp)); 2627. 2628. switch (ynq("Check for traps?")) { 2629. case 'q': return(0); 2630. case 'n': continue; 2631. } 2632. 2633. if((otmp->otrapped && (force || (!confused 2634. && rn2(MAXULEV + 1 - u.ulevel) < 10))) 2635. || (!force && confused && !rn2(3))) { 2636. You("find a trap on %s!", the(xname(otmp))); 2637. exercise(A_WIS, TRUE); 2638. 2639. switch (ynq("Disarm it?")) { 2640. case 'q': return(1); 2641. case 'n': trap_skipped = TRUE; continue; 2642. } 2643. 2644. if(otmp->otrapped) { 2645. exercise(A_DEX, TRUE); 2646. ch = ACURR(A_DEX) + u.ulevel; 2647. if (Role_if(PM_ROGUE)) ch *= 2; 2648. if(!force && (confused || Fumbling || 2649. rnd(75+level_difficulty()/2) > ch)) { 2650. (void) chest_trap(otmp, FINGER, TRUE); 2651. } else { 2652. You("disarm it!"); 2653. otmp->otrapped = 0; 2654. } 2655. } else pline("That %s was not trapped.", xname(otmp)); 2656. return(1); 2657. } else { 2658. You("find no traps on %s.", the(xname(otmp))); 2659. return(1); 2660. } 2661. } 2662. 2663. You(trap_skipped ? "find no other traps here." 2664. : "know of no traps here."); 2665. return(0); 2666. } 2667. 2668. if ((mtmp = m_at(x,y)) && 2669. mtmp->m_ap_type == M_AP_FURNITURE && 2670. (mtmp->mappearance == S_hcdoor || 2671. mtmp->mappearance == S_vcdoor) && 2672. !Protection_from_shape_changers) { 2673. 2674. stumble_onto_mimic(mtmp); 2675. return(1); 2676. } 2677. 2678. if (!IS_DOOR(levl[x][y].typ)) { 2679. if ((ttmp = t_at(x,y)) && ttmp->tseen) 2680. You("cannot disable that trap."); 2681. else 2682. You("know of no traps there."); 2683. return(0); 2684. } 2685. 2686. switch (levl[x][y].doormask) { 2687. case D_NODOOR: 2688. You("%s no door there.", Blind ? "feel" : "see"); 2689. return(0); 2690. case D_ISOPEN: 2691. pline("This door is safely open."); 2692. return(0); 2693. case D_BROKEN: 2694. pline("This door is broken."); 2695. return(0); 2696. } 2697. 2698. if ((levl[x][y].doormask & D_TRAPPED 2699. && (force || 2700. (!confused && rn2(MAXULEV - u.ulevel + 11) < 10))) 2701. || (!force && confused && !rn2(3))) { 2702. You("find a trap on the door!"); 2703. exercise(A_WIS, TRUE); 2704. if (ynq("Disarm it?") != 'y') return(1); 2705. if (levl[x][y].doormask & D_TRAPPED) { 2706. ch = 15 + (Role_if(PM_ROGUE) ? u.ulevel*3 : u.ulevel); 2707. exercise(A_DEX, TRUE); 2708. if(!force && (confused || Fumbling || 2709. rnd(75+level_difficulty()/2) > ch)) { 2710. You("set it off!"); 2711. b_trapped("door", FINGER); 2712. levl[x][y].doormask = D_NODOOR; 2713. unblock_point(x, y); 2714. newsym(x, y); 2715. /* (probably ought to charge for this damage...) */ 2716. if (*in_rooms(x, y, SHOPBASE)) add_damage(x, y, 0L); 2717. } else { 2718. You("disarm it!"); 2719. levl[x][y].doormask &= ~D_TRAPPED; 2720. } 2721. } else pline("This door was not trapped."); 2722. return(1); 2723. } else { 2724. You("find no traps on the door."); 2725. return(1); 2726. } 2727. } 2728. #endif /* OVL2 */ 2729. #ifdef OVLB 2730. 2731. /* only called when the player is doing something to the chest directly */ 2732. boolean 2733. chest_trap(obj, bodypart, disarm) 2734. register struct obj *obj; 2735. register int bodypart; 2736. boolean disarm; 2737. { 2738. register struct obj *otmp = obj, *otmp2; 2739. char buf[80]; 2740. const char *msg; 2741. coord cc; 2742. 2743. if (get_obj_location(obj, &cc.x, &cc.y, 0)) /* might be carried */ 2744. obj->ox = cc.x, obj->oy = cc.y; 2745. 2746. otmp->otrapped = 0; /* trap is one-shot; clear flag first in case 2747. chest kills you and ends up in bones file */ 2748. You(disarm ? "set it off!" : "trigger a trap!"); 2749. display_nhwindow(WIN_MESSAGE, FALSE); 2750. if (Luck > -13 && rn2(13+Luck) > 7) { /* saved by luck */ 2751. /* trap went off, but good luck prevents damage */ 2752. switch (rn2(13)) { 2753. case 12: 2754. case 11: msg = "explosive charge is a dud"; break; 2755. case 10: 2756. case 9: msg = "electric charge is grounded"; break; 2757. case 8: 2758. case 7: msg = "flame fizzles out"; break; 2759. case 6: 2760. case 5: 2761. case 4: msg = "poisoned needle misses"; break; 2762. case 3: 2763. case 2: 2764. case 1: 2765. case 0: msg = "gas cloud blows away"; break; 2766. default: impossible("chest disarm bug"); msg = (char *)0; 2767. break; 2768. } 2769. if (msg) pline("But luckily the %s!", msg); 2770. } else { 2771. switch(rn2(20) ? ((Luck >= 13) ? 0 : rn2(13-Luck)) : rn2(26)) { 2772. case 25: 2773. case 24: 2774. case 23: 2775. case 22: 2776. case 21: { 2777. struct monst *shkp = 0; 2778. long loss = 0L; 2779. boolean costly, insider; 2780. register xchar ox = obj->ox, oy = obj->oy; 2781. 2782. /* the obj location need not be that of player */ 2783. costly = (costly_spot(ox, oy) && 2784. (shkp = shop_keeper(*in_rooms(ox, oy, 2785. SHOPBASE))) != (struct monst *)0); 2786. insider = (*u.ushops && inside_shop(u.ux, u.uy) && 2787. *in_rooms(ox, oy, SHOPBASE) == *u.ushops); 2788. 2789. pline("%s explodes!", The(xname(obj))); 2790. Sprintf(buf, "exploding %s", xname(obj)); 2791. 2792. if(costly) 2793. loss += stolen_value(obj, ox, oy, 2794. (boolean)shkp->mpeaceful, TRUE); 2795. delete_contents(obj); 2796. for(otmp = level.objects[u.ux][u.uy]; 2797. otmp; otmp = otmp2) { 2798. otmp2 = otmp->nexthere; 2799. if(costly) 2800. loss += stolen_value(otmp, otmp->ox, 2801. otmp->oy, (boolean)shkp->mpeaceful, 2802. TRUE); 2803. delobj(otmp); 2804. } 2805. wake_nearby(); 2806. losehp(d(6,6), buf, KILLED_BY_AN); 2807. exercise(A_STR, FALSE); 2808. if(costly && loss) { 2809. if(insider) 2810. You("owe %ld zorkmids for objects destroyed.", 2811. loss); 2812. else { 2813. You("caused %ld zorkmids worth of damage!", 2814. loss); 2815. make_angry_shk(shkp, ox, oy); 2816. } 2817. } 2818. return TRUE; 2819. } 2820. case 20: 2821. case 19: 2822. case 18: 2823. case 17: 2824. pline("A cloud of noxious gas billows from %s.", 2825. the(xname(obj))); 2826. poisoned("gas cloud", A_STR, "cloud of poison gas",15); 2827. exercise(A_CON, FALSE); 2828. break; 2829. case 16: 2830. case 15: 2831. case 14: 2832. case 13: 2833. You_feel("a needle prick your %s.",body_part(bodypart)); 2834. poisoned("needle", A_CON, "poisoned needle",10); 2835. exercise(A_CON, FALSE); 2836. break; 2837. case 12: 2838. case 11: 2839. case 10: 2840. case 9: 2841. dofiretrap(obj); 2842. break; 2843. case 8: 2844. case 7: 2845. case 6: { 2846. int dmg; 2847. 2848. You("are jolted by a surge of electricity!"); 2849. if(Shock_resistance) { 2850. shieldeff(u.ux, u.uy); 2851. You("don't seem to be affected."); 2852. dmg = 0; 2853. } else 2854. dmg = d(4, 4); 2855. destroy_item(RING_CLASS, AD_ELEC); 2856. destroy_item(WAND_CLASS, AD_ELEC); 2857. if (dmg) losehp(dmg, "electric shock", KILLED_BY_AN); 2858. break; 2859. } 2860. case 5: 2861. case 4: 2862. case 3: 2863. if (!Free_action) { 2864. pline("Suddenly you are frozen in place!"); 2865. nomul(-d(5, 6)); 2866. exercise(A_DEX, FALSE); 2867. nomovemsg = You_can_move_again; 2868. } else You("momentarily stiffen."); 2869. break; 2870. case 2: 2871. case 1: 2872. case 0: 2873. pline("A cloud of %s gas billows from %s.", 2874. hcolor((char *)0), 2875. the(xname(obj))); 2876. if(!Stunned) { 2877. if (Hallucination) 2878. pline("What a groovy feeling!"); 2879. else if (Blind) 2880. You("stagger and get dizzy..."); 2881. else 2882. You("stagger and your vision blurs..."); 2883. } 2884. make_stunned(HStun + rn1(7, 16),FALSE); 2885. make_hallucinated(HHallucination + rn1(5, 16),FALSE,0L); 2886. break; 2887. default: impossible("bad chest trap"); 2888. break; 2889. } 2890. bot(); /* to get immediate botl re-display */ 2891. } 2892. 2893. return FALSE; 2894. } 2895. 2896. #endif /* OVLB */ 2897. #ifdef OVL0 2898. 2899. struct trap * 2900. t_at(x,y) 2901. register int x, y; 2902. { 2903. register struct trap *trap = ftrap; 2904. while(trap) { 2905. if(trap->tx == x && trap->ty == y) return(trap); 2906. trap = trap->ntrap; 2907. } 2908. return((struct trap *)0); 2909. } 2910. 2911. #endif /* OVL0 */ 2912. #ifdef OVLB 2913. 2914. void 2915. deltrap(trap) 2916. register struct trap *trap; 2917. { 2918. register struct trap *ttmp; 2919. 2920. if(trap == ftrap) 2921. ftrap = ftrap->ntrap; 2922. else { 2923. for(ttmp = ftrap; ttmp->ntrap != trap; ttmp = ttmp->ntrap) ; 2924. ttmp->ntrap = trap->ntrap; 2925. } 2926. dealloc_trap(trap); 2927. } 2928. 2929. boolean delfloortrap(ttmp) 2930. register struct trap *ttmp; 2931. { 2932. /* Destroy a trap that emanates from the floor. */ 2933. /* some of these are arbitrary -dlc */ 2934. if (ttmp && ((ttmp->ttyp == SQKY_BOARD) || 2935. (ttmp->ttyp == BEAR_TRAP) || 2936. (ttmp->ttyp == LANDMINE) || 2937. (ttmp->ttyp == FIRE_TRAP) || 2938. (ttmp->ttyp == PIT) || 2939. (ttmp->ttyp == SPIKED_PIT) || 2940. (ttmp->ttyp == HOLE) || 2941. (ttmp->ttyp == TRAPDOOR) || 2942. (ttmp->ttyp == TELEP_TRAP) || 2943. (ttmp->ttyp == LEVEL_TELEP) || 2944. (ttmp->ttyp == WEB) || 2945. (ttmp->ttyp == MAGIC_TRAP) || 2946. (ttmp->ttyp == ANTI_MAGIC))) { 2947. register struct monst *mtmp; 2948. 2949. if (ttmp->tx == u.ux && ttmp->ty == u.uy) { 2950. u.utrap = 0; 2951. u.utraptype = 0; 2952. } else if ((mtmp = m_at(ttmp->tx, ttmp->ty)) != 0) { 2953. mtmp->mtrapped = 0; 2954. } 2955. deltrap(ttmp); 2956. return TRUE; 2957. } else 2958. return FALSE; 2959. } 2960. 2961. /* used for doors (also tins). can be used for anything else that opens. */ 2962. void 2963. b_trapped(item, bodypart) 2964. register const char *item; 2965. register int bodypart; 2966. { 2967. register int lvl = level_difficulty(); 2968. int dmg = rnd(5 + (lvl < 5 ? lvl : 2+lvl/2)); 2969. 2970. pline("KABOOM!! %s was booby-trapped!", The(item)); 2971. wake_nearby(); 2972. losehp(dmg, "explosion", KILLED_BY_AN); 2973. exercise(A_STR, FALSE); 2974. if (bodypart) exercise(A_CON, FALSE); 2975. make_stunned(HStun + dmg, TRUE); 2976. } 2977. 2978. /* Monster is hit by trap. */ 2979. /* Note: doesn't work if both obj and d_override are null */ 2980. STATIC_OVL boolean 2981. thitm(tlev, mon, obj, d_override) 2982. register int tlev; 2983. register struct monst *mon; 2984. register struct obj *obj; 2985. int d_override; 2986. { 2987. register int strike; 2988. register boolean trapkilled = FALSE; 2989. 2990. if (d_override) strike = 1; 2991. else if (obj) strike = (find_mac(mon) + tlev + obj->spe <= rnd(20)); 2992. else strike = (find_mac(mon) + tlev <= rnd(20)); 2993. 2994. /* Actually more accurate than thitu, which doesn't take 2995. * obj->spe into account. 2996. */ 2997. if(!strike) { 2998. if (cansee(mon->mx, mon->my)) 2999. pline("%s is almost hit by %s!", Monnam(mon), 3000. doname(obj)); 3001. } else { 3002. int dam = 1; 3003. 3004. if (obj && cansee(mon->mx, mon->my)) 3005. pline("%s is hit by %s!", Monnam(mon), doname(obj)); 3006. if (d_override) dam = d_override; 3007. else if (obj) { 3008. dam = dmgval(obj, mon); 3009. if (dam < 1) dam = 1; 3010. } 3011. if ((mon->mhp -= dam) <= 0) { 3012. int xx = mon->mx; 3013. int yy = mon->my; 3014. 3015. monkilled(mon, "", AD_PHYS); 3016. if (mon->mhp <= 0) { 3017. newsym(xx, yy); 3018. trapkilled = TRUE; 3019. } 3020. } 3021. } 3022. if (obj && (!strike || d_override)) { 3023. place_object(obj, mon->mx, mon->my); 3024. stackobj(obj); 3025. } else if (obj) dealloc_obj(obj); 3026. 3027. return trapkilled; 3028. } 3029. 3030. boolean 3031. unconscious() 3032. { 3033. return((boolean)(multi < 0 && (!nomovemsg || 3034. u.usleep || 3035. !strncmp(nomovemsg,"You regain con", 15) || 3036. !strncmp(nomovemsg,"You are consci", 15)))); 3037. } 3038. 3039. static char lava_killer[] = "molten lava"; 3040. 3041. boolean 3042. lava_effects() 3043. { 3044. register struct obj *obj, *obj2; 3045. int dmg; 3046. 3047. 3048. burn_away_slime(); 3049. if (likes_lava(youmonst.data)) return FALSE; 3050. 3051. if (!Fire_resistance) { 3052. if(Wwalking) { 3053. dmg = d(6,6); 3054. pline_The("lava here burns you!"); 3055. if(dmg < u.uhp) { 3056. losehp(dmg, lava_killer, KILLED_BY); 3057. goto burn_stuff; 3058. } 3059. } else 3060. You("fall into the lava!"); 3061. 3062. for(obj = invent; obj; obj = obj2) { 3063. obj2 = obj->nobj; 3064. if(is_organic(obj) && !obj->oerodeproof) { 3065. if(obj->owornmask) { 3066. if(obj == uarm) (void) Armor_gone(); 3067. else if(obj == uarmc) (void) Cloak_off(); 3068. else if(obj == uarmh) (void) Helmet_off(); 3069. else if(obj == uarms) (void) Shield_off(); 3070. else if(obj == uarmg) (void) Gloves_off(); 3071. else if(obj == uarmf) (void) Boots_off(); 3072. #ifdef TOURIST 3073. else if(obj == uarmu) setnotworn(obj); 3074. #endif 3075. else if(obj == uleft) Ring_gone(obj); 3076. else if(obj == uright) Ring_gone(obj); 3077. else if(obj == ublindf) Blindf_off(obj); 3078. else if(obj == uwep) uwepgone(); 3079. else if (obj == uquiver) uqwepgone(); 3080. else if (obj == uswapwep) uswapwepgone(); 3081. 3082. if(Lifesaved 3083. #ifdef WIZARD 3084. || wizard 3085. #endif 3086. ) Your("%s into flame!", aobjnam(obj, "burst")); 3087. } 3088. useup(obj); 3089. } 3090. } 3091. 3092. /* s/he died... */ 3093. u.uhp = -1; 3094. killer_format = KILLED_BY; 3095. killer = lava_killer; 3096. You("burn to a crisp..."); 3097. done(BURNING); 3098. while (!safe_teleds()) { 3099. pline("You're still burning."); 3100. done(BURNING); 3101. } 3102. You("find yourself back on solid %s.", surface(u.ux, u.uy)); 3103. return(TRUE); 3104. } 3105. 3106. if (!Wwalking) { 3107. u.utrap = rn1(4, 4) + (rn1(4, 12) << 8); 3108. u.utraptype = TT_LAVA; 3109. You("sink into the lava, but it only burns slightly!"); 3110. if (u.uhp > 1) 3111. losehp(1, lava_killer, KILLED_BY); 3112. } 3113. /* just want to burn boots, not all armor; destroy_item doesn't work on 3114. armor anyway */ 3115. burn_stuff: 3116. if(uarmf && !uarmf->oerodeproof && is_organic(uarmf)) { 3117. /* save uarmf value because Boots_off() sets uarmf to null */ 3118. obj = uarmf; 3119. Your("%s burst into flame!", xname(obj)); 3120. (void) Boots_off(); 3121. useup(obj); 3122. } 3123. destroy_item(SCROLL_CLASS, AD_FIRE); 3124. destroy_item(SPBOOK_CLASS, AD_FIRE); 3125. destroy_item(POTION_CLASS, AD_FIRE); 3126. return(FALSE); 3127. } 3128. 3129. #endif /* OVLB */ 3130. 3131. /*trap.c*/