abstract
| - Below is the full text to trap.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/trap.c#line123]], for example. The latest source code for vanilla NetHack is at Source code. 1. /* SCCS Id: @(#)trap.c 3.4 2003/10/20 */ 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. extern const char * const destroy_strings[]; /* from zap.c */ 8. 9. STATIC_DCL void FDECL(dofiretrap, (struct obj *)); 10. STATIC_DCL void NDECL(domagictrap); 11. STATIC_DCL boolean FDECL(emergency_disrobe,(boolean *)); 12. STATIC_DCL int FDECL(untrap_prob, (struct trap *ttmp)); 13. STATIC_DCL void FDECL(cnv_trap_obj, (int, int, struct trap *)); 14. STATIC_DCL void FDECL(move_into_trap, (struct trap *)); 15. STATIC_DCL int FDECL(try_disarm, (struct trap *,BOOLEAN_P)); 16. STATIC_DCL void FDECL(reward_untrap, (struct trap *, struct monst *)); 17. STATIC_DCL int FDECL(disarm_holdingtrap, (struct trap *)); 18. STATIC_DCL int FDECL(disarm_rust_trap, (struct trap *)); 19. STATIC_DCL int FDECL(disarm_fire_trap, (struct trap *)); 20. STATIC_DCL int FDECL(disarm_landmine, (struct trap *)); 21. STATIC_DCL int FDECL(disarm_squeaky_board, (struct trap *)); 22. STATIC_DCL int FDECL(disarm_shooting_trap, (struct trap *, int)); 23. STATIC_DCL int FDECL(try_lift, (struct monst *, struct trap *, int, BOOLEAN_P)); 24. STATIC_DCL int FDECL(help_monster_out, (struct monst *, struct trap *)); 25. STATIC_DCL boolean FDECL(thitm, (int,struct monst *,struct obj *,int,BOOLEAN_P)); 26. STATIC_DCL int FDECL(mkroll_launch, 27. (struct trap *,XCHAR_P,XCHAR_P,SHORT_P,long)); 28. STATIC_DCL boolean FDECL(isclearpath,(coord *, int, SCHAR_P, SCHAR_P)); 29. #ifdef STEED 30. STATIC_OVL int FDECL(steedintrap, (struct trap *, struct obj *)); 31. STATIC_OVL boolean FDECL(keep_saddle_with_steedcorpse, 32. (unsigned, struct obj *, struct obj *)); 33. #endif 34. 35. #ifndef OVLB 36. STATIC_VAR const char *a_your[2]; 37. STATIC_VAR const char *A_Your[2]; 38. STATIC_VAR const char tower_of_flame[]; 39. STATIC_VAR const char *A_gush_of_water_hits; 40. STATIC_VAR const char * const blindgas[6]; 41. 42. #else 43. 44. STATIC_VAR const char * const a_your[2] = { "a", "your" }; 45. STATIC_VAR const char * const A_Your[2] = { "A", "Your" }; 46. STATIC_VAR const char tower_of_flame[] = "tower of flame"; 47. STATIC_VAR const char * const A_gush_of_water_hits = "A gush of water hits"; 48. STATIC_VAR const char * const blindgas[6] = 49. {"humid", "odorless", "pungent", "chilling", "acrid", "biting"}; 50. 51. #endif /* OVLB */ 52. 53. #ifdef OVLB 54. 55. /* called when you're hit by fire (dofiretrap,buzz,zapyourself,explode) */ 56. boolean /* returns TRUE if hit on torso */ 57. burnarmor(victim) 58. struct monst *victim; 59. { 60. struct obj *item; 61. char buf[BUFSZ]; 62. int mat_idx; 63. 64. if (!victim) return 0; 65. #define burn_dmg(obj,descr) rust_dmg(obj, descr, 0, FALSE, victim) 66. while (1) { 67. switch (rn2(5)) { 68. case 0: 69. item = (victim == &youmonst) ? uarmh : which_armor(victim, W_ARMH); 70. if (item) { 71. mat_idx = objects[item->otyp].oc_material; 72. Sprintf(buf,"%s helmet", materialnm[mat_idx] ); 73. } 74. if (!burn_dmg(item, item ? buf : "helmet")) continue; 75. break; 76. case 1: 77. item = (victim == &youmonst) ? uarmc : which_armor(victim, W_ARMC); 78. if (item) { 79. (void) burn_dmg(item, cloak_simple_name(item)); 80. return TRUE; 81. } 82. item = (victim == &youmonst) ? uarm : which_armor(victim, W_ARM); 83. if (item) { 84. (void) burn_dmg(item, xname(item)); 85. return TRUE; 86. } 87. #ifdef TOURIST 88. item = (victim == &youmonst) ? uarmu : which_armor(victim, W_ARMU); 89. if (item) 90. (void) burn_dmg(item, "shirt"); 91. #endif 92. return TRUE; 93. case 2: 94. item = (victim == &youmonst) ? uarms : which_armor(victim, W_ARMS); 95. if (!burn_dmg(item, "wooden shield")) continue; 96. break; 97. case 3: 98. item = (victim == &youmonst) ? uarmg : which_armor(victim, W_ARMG); 99. if (!burn_dmg(item, "gloves")) continue; 100. break; 101. case 4: 102. item = (victim == &youmonst) ? uarmf : which_armor(victim, W_ARMF); 103. if (!burn_dmg(item, "boots")) continue; 104. break; 105. } 106. break; /* Out of while loop */ 107. } 108. return FALSE; 109. #undef burn_dmg 110. } 111. 112. 113. /* Generic rust-armor function. Returns TRUE if a message was printed; 114. * "print", if set, means to print a message (and thus to return TRUE) even 115. * if the item could not be rusted; otherwise a message is printed and TRUE is 116. * returned only for rustable items. 117. */ 118. boolean 119. rust_dmg(otmp, ostr, type, print, victim) 120. register struct obj *otmp; 121. register const char *ostr; 122. int type; 123. boolean print; 124. struct monst *victim; 125. { 126. static NEARDATA const char * const action[] = { "smoulder", "rust", "rot", "corrode" }; 127. static NEARDATA const char * const msg[] = { "burnt", "rusted", "rotten", "corroded" }; 128. boolean vulnerable = FALSE; 129. boolean grprot = FALSE; 130. boolean is_primary = TRUE; 131. boolean vismon = (victim != &youmonst) && canseemon(victim); 132. int erosion; 133. 134. if (!otmp) return(FALSE); 135. switch(type) { 136. case 0: vulnerable = is_flammable(otmp); 137. break; 138. case 1: vulnerable = is_rustprone(otmp); 139. grprot = TRUE; 140. break; 141. case 2: vulnerable = is_rottable(otmp); 142. is_primary = FALSE; 143. break; 144. case 3: vulnerable = is_corrodeable(otmp); 145. grprot = TRUE; 146. is_primary = FALSE; 147. break; 148. } 149. erosion = is_primary ? otmp->oeroded : otmp->oeroded2; 150. 151. if (!print && (!vulnerable || otmp->oerodeproof || erosion == MAX_ERODE)) 152. return FALSE; 153. 154. if (!vulnerable) { 155. if (flags.verbose) { 156. if (victim == &youmonst) 157. Your("%s %s not affected.", ostr, vtense(ostr, "are")); 158. else if (vismon) 159. pline("%s's %s %s not affected.", Monnam(victim), ostr, 160. vtense(ostr, "are")); 161. } 162. } else if (erosion < MAX_ERODE) { 163. if (grprot && otmp->greased) { 164. grease_protect(otmp,ostr,victim); 165. } else if (otmp->oerodeproof || (otmp->blessed && !rnl(4))) { 166. if (flags.verbose) { 167. if (victim == &youmonst) 168. pline("Somehow, your %s %s not affected.", 169. ostr, vtense(ostr, "are")); 170. else if (vismon) 171. pline("Somehow, %s's %s %s not affected.", 172. mon_nam(victim), ostr, vtense(ostr, "are")); 173. } 174. } else { 175. if (victim == &youmonst) 176. Your("%s %s%s!", ostr, 177. vtense(ostr, action[type]), 178. erosion+1 == MAX_ERODE ? " completely" : 179. erosion ? " further" : ""); 180. else if (vismon) 181. pline("%s's %s %s%s!", Monnam(victim), ostr, 182. vtense(ostr, action[type]), 183. erosion+1 == MAX_ERODE ? " completely" : 184. erosion ? " further" : ""); 185. if (is_primary) 186. otmp->oeroded++; 187. else 188. otmp->oeroded2++; 189. update_inventory(); 190. } 191. } else { 192. if (flags.verbose) { 193. if (victim == &youmonst) 194. Your("%s %s completely %s.", ostr, 195. vtense(ostr, Blind ? "feel" : "look"), 196. msg[type]); 197. else if (vismon) 198. pline("%s's %s %s completely %s.", 199. Monnam(victim), ostr, 200. vtense(ostr, "look"), msg[type]); 201. } 202. } 203. return(TRUE); 204. } 205. 206. void 207. grease_protect(otmp,ostr,victim) 208. register struct obj *otmp; 209. register const char *ostr; 210. struct monst *victim; 211. { 212. static const char txt[] = "protected by the layer of grease!"; 213. boolean vismon = victim && (victim != &youmonst) && canseemon(victim); 214. 215. if (ostr) { 216. if (victim == &youmonst) 217. Your("%s %s %s", ostr, vtense(ostr, "are"), txt); 218. else if (vismon) 219. pline("%s's %s %s %s", Monnam(victim), 220. ostr, vtense(ostr, "are"), txt); 221. } else { 222. if (victim == &youmonst) 223. Your("%s %s",aobjnam(otmp,"are"), txt); 224. else if (vismon) 225. pline("%s's %s %s", Monnam(victim), aobjnam(otmp,"are"), txt); 226. } 227. if (!rn2(2)) { 228. otmp->greased = 0; 229. if (carried(otmp)) { 230. pline_The("grease dissolves."); 231. update_inventory(); 232. } 233. } 234. } 235. 236. struct trap * 237. maketrap(x,y,typ) 238. register int x, y, typ; 239. { 240. register struct trap *ttmp; 241. register struct rm *lev; 242. register boolean oldplace; 243. 244. if ((ttmp = t_at(x,y)) != 0) { 245. if (ttmp->ttyp == MAGIC_PORTAL) return (struct trap *)0; 246. oldplace = TRUE; 247. if (u.utrap && (x == u.ux) && (y == u.uy) && 248. ((u.utraptype == TT_BEARTRAP && typ != BEAR_TRAP) || 249. (u.utraptype == TT_WEB && typ != WEB) || 250. (u.utraptype == TT_PIT && typ != PIT && typ != SPIKED_PIT))) 251. u.utrap = 0; 252. } else { 253. oldplace = FALSE; 254. ttmp = newtrap(); 255. ttmp->tx = x; 256. ttmp->ty = y; 257. ttmp->launch.x = -1; /* force error if used before set */ 258. ttmp->launch.y = -1; 259. } 260. ttmp->ttyp = typ; 261. switch(typ) { 262. case STATUE_TRAP: /* create a "living" statue */ 263. { struct monst *mtmp; 264. struct obj *otmp, *statue; 265. 266. statue = mkcorpstat(STATUE, (struct monst *)0, 267. &mons[rndmonnum()], x, y, FALSE); 268. mtmp = makemon(&mons[statue->corpsenm], 0, 0, NO_MM_FLAGS); 269. if (!mtmp) break; /* should never happen */ 270. while(mtmp->minvent) { 271. otmp = mtmp->minvent; 272. otmp->owornmask = 0; 273. obj_extract_self(otmp); 274. (void) add_to_container(statue, otmp); 275. } 276. statue->owt = weight(statue); 277. mongone(mtmp); 278. break; 279. } 280. case ROLLING_BOULDER_TRAP: /* boulder will roll towards trigger */ 281. (void) mkroll_launch(ttmp, x, y, BOULDER, 1L); 282. break; 283. case HOLE: 284. case PIT: 285. case SPIKED_PIT: 286. case TRAPDOOR: 287. lev = &levl[x][y]; 288. if (*in_rooms(x, y, SHOPBASE) && 289. ((typ == HOLE || typ == TRAPDOOR) || 290. IS_DOOR(lev->typ) || IS_WALL(lev->typ))) 291. add_damage(x, y, /* schedule repair */ 292. ((IS_DOOR(lev->typ) || IS_WALL(lev->typ)) 293. && !flags.mon_moving) ? 200L : 0L); 294. lev->doormask = 0; /* subsumes altarmask, icedpool... */ 295. if (IS_ROOM(lev->typ)) /* && !IS_AIR(lev->typ) */ 296. lev->typ = ROOM; 297. 298. /* 299. * some cases which can happen when digging 300. * down while phazing thru solid areas 301. */ 302. else if (lev->typ == STONE || lev->typ == SCORR) 303. lev->typ = CORR; 304. else if (IS_WALL(lev->typ) || lev->typ == SDOOR) 305. lev->typ = level.flags.is_maze_lev ? ROOM : 306. level.flags.is_cavernous_lev ? CORR : DOOR; 307. 308. unearth_objs(x, y); 309. break; 310. } 311. if (ttmp->ttyp == HOLE) ttmp->tseen = 1; /* You can't hide a hole */ 312. else ttmp->tseen = 0; 313. ttmp->once = 0; 314. ttmp->madeby_u = 0; 315. ttmp->dst.dnum = -1; 316. ttmp->dst.dlevel = -1; 317. if (!oldplace) { 318. ttmp->ntrap = ftrap; 319. ftrap = ttmp; 320. } 321. return(ttmp); 322. } 323. 324. void 325. fall_through(td) 326. boolean td; /* td == TRUE : trap door or hole */ 327. { 328. d_level dtmp; 329. char msgbuf[BUFSZ]; 330. const char *dont_fall = 0; 331. register int newlevel = dunlev(&u.uz); 332. 333. /* KMH -- You can't escape the Sokoban level traps */ 334. if(Blind && Levitation && !In_sokoban(&u.uz)) return; 335. 336. do { 337. newlevel++; 338. } while(!rn2(4) && newlevel < dunlevs_in_dungeon(&u.uz)); 339. 340. if(td) { 341. struct trap *t=t_at(u.ux,u.uy); 342. seetrap(t); 343. if (!In_sokoban(&u.uz)) { 344. if (t->ttyp == TRAPDOOR) 345. pline("A trap door opens up under you!"); 346. else 347. pline("There's a gaping hole under you!"); 348. } 349. } else pline_The("%s opens up under you!", surface(u.ux,u.uy)); 350. 351. if (In_sokoban(&u.uz) && Can_fall_thru(&u.uz)) 352. ; /* KMH -- You can't escape the Sokoban level traps */ 353. else if(Levitation || u.ustuck || !Can_fall_thru(&u.uz) 354. || Flying || is_clinger(youmonst.data) 355. || (Role_if(PM_ARCHEOLOGIST) && uwep && uwep->otyp == BULLWHIP) 356. || (Inhell && !u.uevent.invoked && 357. newlevel == dunlevs_in_dungeon(&u.uz)) 358. ) { 359. if (Role_if(PM_ARCHEOLOGIST) && uwep && uwep->otyp == BULLWHIP) 360. pline("But thanks to your trusty whip ..."); 361. dont_fall = "don't fall in."; 362. } else if (youmonst.data->msize >= MZ_HUGE) { 363. dont_fall = "don't fit through."; 364. } else if (!next_to_u()) { 365. dont_fall = "are jerked back by your pet!"; 366. } 367. if (dont_fall) { 368. You(dont_fall); 369. /* hero didn't fall through, but any objects here might */ 370. impact_drop((struct obj *)0, u.ux, u.uy, 0); 371. if (!td) { 372. display_nhwindow(WIN_MESSAGE, FALSE); 373. pline_The("opening under you closes up."); 374. } 375. return; 376. } 377. 378. if(*u.ushops) shopdig(1); 379. if (Is_stronghold(&u.uz)) { 380. find_hell(&dtmp); 381. } else { 382. dtmp.dnum = u.uz.dnum; 383. dtmp.dlevel = newlevel; 384. } 385. if (!td) 386. Sprintf(msgbuf, "The hole in the %s above you closes up.", 387. ceiling(u.ux,u.uy)); 388. schedule_goto(&dtmp, FALSE, TRUE, 0, 389. (char *)0, !td ? msgbuf : (char *)0); 390. } 391. 392. /* 393. * Animate the given statue. May have been via shatter attempt, trap, 394. * or stone to flesh spell. Return a monster if successfully animated. 395. * If the monster is animated, the object is deleted. If fail_reason 396. * is non-null, then fill in the reason for failure (or success). 397. * 398. * The cause of animation is: 399. * 400. * ANIMATE_NORMAL - hero "finds" the monster 401. * ANIMATE_SHATTER - hero tries to destroy the statue 402. * ANIMATE_SPELL - stone to flesh spell hits the statue 403. * 404. * Perhaps x, y is not needed if we can use get_obj_location() to find 405. * the statue's location... ??? 406. */ 407. struct monst * 408. animate_statue(statue, x, y, cause, fail_reason) 409. struct obj *statue; 410. xchar x, y; 411. int cause; 412. int *fail_reason; 413. { 414. struct permonst *mptr; 415. struct monst *mon = 0; 416. struct obj *item; 417. coord cc; 418. boolean historic = (Role_if(PM_ARCHEOLOGIST) && !flags.mon_moving && (statue->spe & STATUE_HISTORIC)); 419. char statuename[BUFSZ]; 420. 421. Strcpy(statuename,the(xname(statue))); 422. 423. if (statue->oxlth && statue->oattached == OATTACHED_MONST) { 424. cc.x = x, cc.y = y; 425. mon = montraits(statue, &cc); 426. if (mon && mon->mtame && !mon->isminion) 427. wary_dog(mon, TRUE); 428. } else { 429. /* statue of any golem hit with stone-to-flesh becomes flesh golem */ 430. if (is_golem(&mons[statue->corpsenm]) && cause == ANIMATE_SPELL) 431. mptr = &mons[PM_FLESH_GOLEM]; 432. else 433. mptr = &mons[statue->corpsenm]; 434. /* 435. * Guard against someone wishing for a statue of a unique monster 436. * (which is allowed in normal play) and then tossing it onto the 437. * [detected or guessed] location of a statue trap. Normally the 438. * uppermost statue is the one which would be activated. 439. */ 440. if ((mptr->geno & G_UNIQ) && cause != ANIMATE_SPELL) { 441. if (fail_reason) *fail_reason = AS_MON_IS_UNIQUE; 442. return (struct monst *)0; 443. } 444. if (cause == ANIMATE_SPELL && 445. ((mptr->geno & G_UNIQ) || mptr->msound == MS_GUARDIAN)) { 446. /* Statues of quest guardians or unique monsters 447. * will not stone-to-flesh as the real thing. 448. */ 449. mon = makemon(&mons[PM_DOPPELGANGER], x, y, 450. NO_MINVENT|MM_NOCOUNTBIRTH|MM_ADJACENTOK); 451. if (mon) { 452. /* makemon() will set mon->cham to 453. * CHAM_ORDINARY if hero is wearing 454. * ring of protection from shape changers 455. * when makemon() is called, so we have to 456. * check the field before calling newcham(). 457. */ 458. if (mon->cham == CHAM_DOPPELGANGER) 459. (void) newcham(mon, mptr, FALSE, FALSE); 460. } 461. } else 462. mon = makemon(mptr, x, y, (cause == ANIMATE_SPELL) ? 463. (NO_MINVENT | MM_ADJACENTOK) : NO_MINVENT); 464. } 465. 466. if (!mon) { 467. if (fail_reason) *fail_reason = AS_NO_MON; 468. return (struct monst *)0; 469. } 470. 471. /* in case statue is wielded and hero zaps stone-to-flesh at self */ 472. if (statue->owornmask) remove_worn_item(statue, TRUE); 473. 474. /* allow statues to be of a specific gender */ 475. if (statue->spe & STATUE_MALE) 476. mon->female = FALSE; 477. else if (statue->spe & STATUE_FEMALE) 478. mon->female = TRUE; 479. /* if statue has been named, give same name to the monster */ 480. if (statue->onamelth) 481. mon = christen_monst(mon, ONAME(statue)); 482. /* transfer any statue contents to monster's inventory */ 483. while ((item = statue->cobj) != 0) { 484. obj_extract_self(item); 485. (void) add_to_minv(mon, item); 486. } 487. m_dowear(mon, TRUE); 488. delobj(statue); 489. 490. /* mimic statue becomes seen mimic; other hiders won't be hidden */ 491. if (mon->m_ap_type) seemimic(mon); 492. else mon->mundetected = FALSE; 493. if ((x == u.ux && y == u.uy) || cause == ANIMATE_SPELL) { 494. const char *comes_to_life = nonliving(mon->data) ? 495. "moves" : "comes to life"; 496. if (cause == ANIMATE_SPELL) 497. pline("%s %s!", upstart(statuename), 498. canspotmon(mon) ? comes_to_life : "disappears"); 499. else 500. pline_The("statue %s!", 501. canspotmon(mon) ? comes_to_life : "disappears"); 502. if (historic) { 503. You_feel("guilty that the historic statue is now gone."); 504. adjalign(-1); 505. } 506. } else if (cause == ANIMATE_SHATTER) 507. pline("Instead of shattering, the statue suddenly %s!", 508. canspotmon(mon) ? "comes to life" : "disappears"); 509. else { /* cause == ANIMATE_NORMAL */ 510. You("find %s posing as a statue.", 511. canspotmon(mon) ? a_monnam(mon) : something); 512. stop_occupation(); 513. } 514. /* avoid hiding under nothing */ 515. if (x == u.ux && y == u.uy && 516. Upolyd && hides_under(youmonst.data) && !OBJ_AT(x, y)) 517. u.uundetected = 0; 518. 519. if (fail_reason) *fail_reason = AS_OK; 520. return mon; 521. } 522. 523. /* 524. * You've either stepped onto a statue trap's location or you've triggered a 525. * statue trap by searching next to it or by trying to break it with a wand 526. * or pick-axe. 527. */ 528. struct monst * 529. activate_statue_trap(trap, x, y, shatter) 530. struct trap *trap; 531. xchar x, y; 532. boolean shatter; 533. { 534. struct monst *mtmp = (struct monst *)0; 535. struct obj *otmp = sobj_at(STATUE, x, y); 536. int fail_reason; 537. 538. /* 539. * Try to animate the first valid statue. Stop the loop when we 540. * actually create something or the failure cause is not because 541. * the mon was unique. 542. */ 543. deltrap(trap); 544. while (otmp) { 545. mtmp = animate_statue(otmp, x, y, 546. shatter ? ANIMATE_SHATTER : ANIMATE_NORMAL, &fail_reason); 547. if (mtmp || fail_reason != AS_MON_IS_UNIQUE) break; 548. 549. while ((otmp = otmp->nexthere) != 0) 550. if (otmp->otyp == STATUE) break; 551. } 552. 553. if (Blind) feel_location(x, y); 554. else newsym(x, y); 555. return mtmp; 556. } 557. 558. #ifdef STEED 559. STATIC_OVL boolean 560. keep_saddle_with_steedcorpse(steed_mid, objchn, saddle) 561. unsigned steed_mid; 562. struct obj *objchn, *saddle; 563. { 564. if (!saddle) return FALSE; 565. while(objchn) { 566. if(objchn->otyp == CORPSE && 567. objchn->oattached == OATTACHED_MONST && objchn->oxlth) { 568. struct monst *mtmp = (struct monst *)objchn->oextra; 569. if (mtmp->m_id == steed_mid) { 570. /* move saddle */ 571. xchar x,y; 572. if (get_obj_location(objchn, &x, &y, 0)) { 573. obj_extract_self(saddle); 574. place_object(saddle, x, y); 575. stackobj(saddle); 576. } 577. return TRUE; 578. } 579. } 580. if (Has_contents(objchn) && 581. keep_saddle_with_steedcorpse(steed_mid, objchn->cobj, saddle)) 582. return TRUE; 583. objchn = objchn->nobj; 584. } 585. return FALSE; 586. } 587. #endif /*STEED*/ 588. 589. void 590. dotrap(trap, trflags) 591. register struct trap *trap; 592. unsigned trflags; 593. { 594. register int ttype = trap->ttyp; 595. register struct obj *otmp; 596. boolean already_seen = trap->tseen; 597. boolean webmsgok = (!(trflags & NOWEBMSG)); 598. boolean forcebungle = (trflags & FORCEBUNGLE); 599. 600. nomul(0); 601. 602. /* KMH -- You can't escape the Sokoban level traps */ 603. if (In_sokoban(&u.uz) && 604. (ttype == PIT || ttype == SPIKED_PIT || ttype == HOLE || 605. ttype == TRAPDOOR)) { 606. /* The "air currents" message is still appropriate -- even when 607. * the hero isn't flying or levitating -- because it conveys the 608. * reason why the player cannot escape the trap with a dexterity 609. * check, clinging to the ceiling, etc. 610. */ 611. pline("Air currents pull you down into %s %s!", 612. a_your[trap->madeby_u], 613. defsyms[trap_to_defsym(ttype)].explanation); 614. /* then proceed to normal trap effect */ 615. } else if (already_seen) { 616. if ((Levitation || Flying) && 617. (ttype == PIT || ttype == SPIKED_PIT || ttype == HOLE || 618. ttype == BEAR_TRAP)) { 619. You("%s over %s %s.", 620. Levitation ? "float" : "fly", 621. a_your[trap->madeby_u], 622. defsyms[trap_to_defsym(ttype)].explanation); 623. return; 624. } 625. if(!Fumbling && ttype != MAGIC_PORTAL && 626. ttype != ANTI_MAGIC && !forcebungle && 627. (!rn2(5) || 628. ((ttype == PIT || ttype == SPIKED_PIT) && is_clinger(youmonst.data)))) { 629. You("escape %s %s.", 630. (ttype == ARROW_TRAP && !trap->madeby_u) ? "an" : 631. a_your[trap->madeby_u], 632. defsyms[trap_to_defsym(ttype)].explanation); 633. return; 634. } 635. } 636. 637. #ifdef STEED 638. if (u.usteed) u.usteed->mtrapseen |= (1 << (ttype-1)); 639. #endif 640. 641. switch(ttype) { 642. case ARROW_TRAP: 643. if (trap->once && trap->tseen && !rn2(15)) { 644. You_hear("a loud click!"); 645. deltrap(trap); 646. newsym(u.ux,u.uy); 647. break; 648. } 649. trap->once = 1; 650. seetrap(trap); 651. pline("An arrow shoots out at you!"); 652. otmp = mksobj(ARROW, TRUE, FALSE); 653. otmp->quan = 1L; 654. otmp->owt = weight(otmp); 655. otmp->opoisoned = 0; 656. #ifdef STEED 657. if (u.usteed && !rn2(2) && steedintrap(trap, otmp)) /* nothing */; 658. else 659. #endif 660. if (thitu(8, dmgval(otmp, &youmonst), otmp, "arrow")) { 661. obfree(otmp, (struct obj *)0); 662. } else { 663. place_object(otmp, u.ux, u.uy); 664. if (!Blind) otmp->dknown = 1; 665. stackobj(otmp); 666. newsym(u.ux, u.uy); 667. } 668. break; 669. case DART_TRAP: 670. if (trap->once && trap->tseen && !rn2(15)) { 671. You_hear("a soft click."); 672. deltrap(trap); 673. newsym(u.ux,u.uy); 674. break; 675. } 676. trap->once = 1; 677. seetrap(trap); 678. pline("A little dart shoots out at you!"); 679. otmp = mksobj(DART, TRUE, FALSE); 680. otmp->quan = 1L; 681. otmp->owt = weight(otmp); 682. if (!rn2(6)) otmp->opoisoned = 1; 683. #ifdef STEED 684. if (u.usteed && !rn2(2) && steedintrap(trap, otmp)) /* nothing */; 685. else 686. #endif 687. if (thitu(7, dmgval(otmp, &youmonst), otmp, "little dart")) { 688. if (otmp->opoisoned) 689. poisoned("dart", A_CON, "little dart", -10); 690. obfree(otmp, (struct obj *)0); 691. } else { 692. place_object(otmp, u.ux, u.uy); 693. if (!Blind) otmp->dknown = 1; 694. stackobj(otmp); 695. newsym(u.ux, u.uy); 696. } 697. break; 698. case ROCKTRAP: 699. if (trap->once && trap->tseen && !rn2(15)) { 700. pline("A trap door in %s opens, but nothing falls out!", 701. the(ceiling(u.ux,u.uy))); 702. deltrap(trap); 703. newsym(u.ux,u.uy); 704. } else { 705. int dmg = d(2,6); /* should be std ROCK dmg? */ 706. 707. trap->once = 1; 708. seetrap(trap); 709. otmp = mksobj_at(ROCK, u.ux, u.uy, TRUE, FALSE); 710. otmp->quan = 1L; 711. otmp->owt = weight(otmp); 712. 713. pline("A trap door in %s opens and %s falls on your %s!", 714. the(ceiling(u.ux,u.uy)), 715. an(xname(otmp)), 716. body_part(HEAD)); 717. 718. if (uarmh) { 719. if(is_metallic(uarmh)) { 720. pline("Fortunately, you are wearing a hard helmet."); 721. dmg = 2; 722. } else if (flags.verbose) { 723. Your("%s does not protect you.", xname(uarmh)); 724. } 725. } 726. 727. if (!Blind) otmp->dknown = 1; 728. stackobj(otmp); 729. newsym(u.ux,u.uy); /* map the rock */ 730. 731. losehp(dmg, "falling rock", KILLED_BY_AN); 732. exercise(A_STR, FALSE); 733. } 734. break; 735. 736. case SQKY_BOARD: /* stepped on a squeaky board */ 737. if (Levitation || Flying) { 738. if (!Blind) { 739. seetrap(trap); 740. if (Hallucination) 741. You("notice a crease in the linoleum."); 742. else 743. You("notice a loose board below you."); 744. } 745. } else { 746. seetrap(trap); 747. pline("A board beneath you squeaks loudly."); 748. wake_nearby(); 749. } 750. break; 751. 752. case BEAR_TRAP: 753. if(Levitation || Flying) break; 754. seetrap(trap); 755. if(amorphous(youmonst.data) || is_whirly(youmonst.data) || 756. unsolid(youmonst.data)) { 757. pline("%s bear trap closes harmlessly through you.", 758. A_Your[trap->madeby_u]); 759. break; 760. } 761. if( 762. #ifdef STEED 763. !u.usteed && 764. #endif 765. youmonst.data->msize <= MZ_SMALL) { 766. pline("%s bear trap closes harmlessly over you.", 767. A_Your[trap->madeby_u]); 768. break; 769. } 770. u.utrap = rn1(4, 4); 771. u.utraptype = TT_BEARTRAP; 772. #ifdef STEED 773. if (u.usteed) { 774. pline("%s bear trap closes on %s %s!", 775. A_Your[trap->madeby_u], s_suffix(mon_nam(u.usteed)), 776. mbodypart(u.usteed, FOOT)); 777. } else 778. #endif 779. { 780. pline("%s bear trap closes on your %s!", 781. A_Your[trap->madeby_u], body_part(FOOT)); 782. if(u.umonnum == PM_OWLBEAR || u.umonnum == PM_BUGBEAR) 783. You("howl in anger!"); 784. } 785. exercise(A_DEX, FALSE); 786. break; 787. 788. case SLP_GAS_TRAP: 789. seetrap(trap); 790. if(Sleep_resistance || breathless(youmonst.data)) { 791. You("are enveloped in a cloud of gas!"); 792. break; 793. } 794. pline("A cloud of gas puts you to sleep!"); 795. fall_asleep(-rnd(25), TRUE); 796. #ifdef STEED 797. (void) steedintrap(trap, (struct obj *)0); 798. #endif 799. break; 800. 801. case RUST_TRAP: 802. seetrap(trap); 803. if (u.umonnum == PM_IRON_GOLEM) { 804. int dam = u.mhmax; 805. 806. pline("%s you!", A_gush_of_water_hits); 807. You("are covered with rust!"); 808. if (Half_physical_damage) dam = (dam+1) / 2; 809. losehp(dam, "rusting away", KILLED_BY); 810. break; 811. } else if (u.umonnum == PM_FLAMING_SPHERE) { 812. int dam = u.mhmax; 813. 814. pline("%s you!", A_gush_of_water_hits); 815. You("are extinguished!"); 816. if (Half_physical_damage) dam = (dam+1) / 2; 817. losehp(dam, "drenching", KILLED_BY); 818. break; 819. } else if (u.umonnum == PM_GREMLIN && rn2(3)) { 820. pline("%s you!", A_gush_of_water_hits); 821. (void)split_mon(&youmonst, (struct monst *)0); 822. break; 823. } 824. 825. /* Unlike monsters, traps cannot aim their rust attacks at 826. * you, so instead of looping through and taking either the 827. * first rustable one or the body, we take whatever we get, 828. * even if it is not rustable. 829. */ 830. switch (rn2(5)) { 831. case 0: 832. pline("%s you on the %s!", A_gush_of_water_hits, 833. body_part(HEAD)); 834. (void) rust_dmg(uarmh, "helmet", 1, TRUE, &youmonst); 835. break; 836. case 1: 837. pline("%s your left %s!", A_gush_of_water_hits, 838. body_part(ARM)); 839. if (rust_dmg(uarms, "shield", 1, TRUE, &youmonst)) 840. break; 841. if (u.twoweap || (uwep && bimanual(uwep))) { 842. otmp = u.twoweap ? uswapwep : uwep; 843. if (otmp && !snuff_lit(otmp)) 844. erode_obj(otmp, FALSE, TRUE); 845. } 846. glovecheck: (void) rust_dmg(uarmg, "gauntlets", 1, TRUE, &youmonst); 847. /* Not "metal gauntlets" since it gets called 848. * even if it's leather for the message 849. */ 850. break; 851. case 2: 852. pline("%s your right %s!", A_gush_of_water_hits, 853. body_part(ARM)); 854. if (uwep && !snuff_lit(uwep)) 855. erode_obj(uwep, FALSE, TRUE); 856. goto glovecheck; 857. default: 858. pline("%s you!", A_gush_of_water_hits); 859. for (otmp=invent; otmp; otmp = otmp->nobj) 860. (void) snuff_lit(otmp); 861. if (uarmc) 862. (void) rust_dmg(uarmc, cloak_simple_name(uarmc), 863. 1, TRUE, &youmonst); 864. else if (uarm) 865. (void) rust_dmg(uarm, "armor", 1, TRUE, &youmonst); 866. #ifdef TOURIST 867. else if (uarmu) 868. (void) rust_dmg(uarmu, "shirt", 1, TRUE, &youmonst); 869. #endif 870. } 871. update_inventory(); 872. break; 873. 874. case FIRE_TRAP: 875. seetrap(trap); 876. dofiretrap((struct obj *)0); 877. break; 878. 879. case PIT: 880. case SPIKED_PIT: 881. /* KMH -- You can't escape the Sokoban level traps */ 882. if (!In_sokoban(&u.uz) && (Levitation || Flying)) break; 883. seetrap(trap); 884. if (!In_sokoban(&u.uz) && is_clinger(youmonst.data)) { 885. if(trap->tseen) { 886. You("see %s %spit below you.", a_your[trap->madeby_u], 887. ttype == SPIKED_PIT ? "spiked " : ""); 888. } else { 889. pline("%s pit %sopens up under you!", 890. A_Your[trap->madeby_u], 891. ttype == SPIKED_PIT ? "full of spikes " : ""); 892. You("don't fall in!"); 893. } 894. break; 895. } 896. if (!In_sokoban(&u.uz)) { 897. char verbbuf[BUFSZ]; 898. #ifdef STEED 899. if (u.usteed) { 900. if ((trflags & RECURSIVETRAP) != 0) 901. Sprintf(verbbuf, "and %s fall", 902. x_monnam(u.usteed, 903. u.usteed->mnamelth ? ARTICLE_NONE : ARTICLE_THE, 904. (char *)0, SUPPRESS_SADDLE, FALSE)); 905. else 906. Sprintf(verbbuf,"lead %s", 907. x_monnam(u.usteed, 908. u.usteed->mnamelth ? ARTICLE_NONE : ARTICLE_THE, 909. "poor", SUPPRESS_SADDLE, FALSE)); 910. } else 911. #endif 912. Strcpy(verbbuf,"fall"); 913. You("%s into %s pit!", verbbuf, a_your[trap->madeby_u]); 914. } 915. /* wumpus reference */ 916. if (Role_if(PM_RANGER) && !trap->madeby_u && !trap->once && 917. In_quest(&u.uz) && Is_qlocate(&u.uz)) { 918. pline("Fortunately it has a bottom after all..."); 919. trap->once = 1; 920. } else if (u.umonnum == PM_PIT_VIPER || 921. u.umonnum == PM_PIT_FIEND) 922. pline("How pitiful. Isn't that the pits?"); 923. if (ttype == SPIKED_PIT) { 924. const char *predicament = "on a set of sharp iron spikes"; 925. #ifdef STEED 926. if (u.usteed) { 927. pline("%s lands %s!", 928. upstart(x_monnam(u.usteed, 929. u.usteed->mnamelth ? ARTICLE_NONE : ARTICLE_THE, 930. "poor", SUPPRESS_SADDLE, FALSE)), 931. predicament); 932. } else 933. #endif 934. You("land %s!", predicament); 935. } 936. if (!Passes_walls) 937. u.utrap = rn1(6,2); 938. u.utraptype = TT_PIT; 939. #ifdef STEED 940. if (!steedintrap(trap, (struct obj *)0)) { 941. #endif 942. if (ttype == SPIKED_PIT) { 943. losehp(rnd(10),"fell into a pit of iron spikes", 944. NO_KILLER_PREFIX); 945. if (!rn2(6)) 946. poisoned("spikes", A_STR, "fall onto poison spikes", 8); 947. } else 948. losehp(rnd(6),"fell into a pit", NO_KILLER_PREFIX); 949. if (Punished && !carried(uball)) { 950. unplacebc(); 951. ballfall(); 952. placebc(); 953. } 954. selftouch("Falling, you"); 955. vision_full_recalc = 1; /* vision limits change */ 956. exercise(A_STR, FALSE); 957. exercise(A_DEX, FALSE); 958. #ifdef STEED 959. } 960. #endif 961. break; 962. case HOLE: 963. case TRAPDOOR: 964. if (!Can_fall_thru(&u.uz)) { 965. seetrap(trap); /* normally done in fall_through */ 966. impossible("dotrap: %ss cannot exist on this level.", 967. defsyms[trap_to_defsym(ttype)].explanation); 968. break; /* don't activate it after all */ 969. } 970. fall_through(TRUE); 971. break; 972. 973. case TELEP_TRAP: 974. seetrap(trap); 975. tele_trap(trap); 976. break; 977. case LEVEL_TELEP: 978. seetrap(trap); 979. level_tele_trap(trap); 980. break; 981. 982. case WEB: /* Our luckless player has stumbled into a web. */ 983. seetrap(trap); 984. if (amorphous(youmonst.data) || is_whirly(youmonst.data) || 985. unsolid(youmonst.data)) { 986. if (acidic(youmonst.data) || u.umonnum == PM_GELATINOUS_CUBE || 987. u.umonnum == PM_FIRE_ELEMENTAL) { 988. if (webmsgok) 989. You("%s %s spider web!", 990. (u.umonnum == PM_FIRE_ELEMENTAL) ? "burn" : "dissolve", 991. a_your[trap->madeby_u]); 992. deltrap(trap); 993. newsym(u.ux,u.uy); 994. break; 995. } 996. if (webmsgok) You("flow through %s spider web.", 997. a_your[trap->madeby_u]); 998. break; 999. } 1000. if (webmaker(youmonst.data)) { 1001. if (webmsgok) 1002. pline(trap->madeby_u ? "You take a walk on your web." 1003. : "There is a spider web here."); 1004. break; 1005. } 1006. if (webmsgok) { 1007. char verbbuf[BUFSZ]; 1008. verbbuf[0] = '\0'; 1009. #ifdef STEED 1010. if (u.usteed) 1011. Sprintf(verbbuf,"lead %s", 1012. x_monnam(u.usteed, 1013. u.usteed->mnamelth ? ARTICLE_NONE : ARTICLE_THE, 1014. "poor", SUPPRESS_SADDLE, FALSE)); 1015. else 1016. #endif 1017. 1018. Sprintf(verbbuf, "%s", Levitation ? (const char *)"float" : 1019. locomotion(youmonst.data, "stumble")); 1020. You("%s into %s spider web!", 1021. verbbuf, a_your[trap->madeby_u]); 1022. } 1023. u.utraptype = TT_WEB; 1024. 1025. /* Time stuck in the web depends on your/steed strength. */ 1026. { 1027. register int str = ACURR(A_STR); 1028. 1029. #ifdef STEED 1030. /* If mounted, the steed gets trapped. Use mintrap 1031. * to do all the work. If mtrapped is set as a result, 1032. * unset it and set utrap instead. In the case of a 1033. * strongmonst and mintrap said it's trapped, use a 1034. * short but non-zero trap time. Otherwise, monsters 1035. * have no specific strength, so use player strength. 1036. * This gets skipped for webmsgok, which implies that 1037. * the steed isn't a factor. 1038. */ 1039. if (u.usteed && webmsgok) { 1040. /* mtmp location might not be up to date */ 1041. u.usteed->mx = u.ux; 1042. u.usteed->my = u.uy; 1043. 1044. /* mintrap currently does not return 2(died) for webs */ 1045. if (mintrap(u.usteed)) { 1046. u.usteed->mtrapped = 0; 1047. if (strongmonst(u.usteed->data)) str = 17; 1048. } else { 1049. break; 1050. } 1051. 1052. webmsgok = FALSE; /* mintrap printed the messages */ 1053. } 1054. #endif 1055. if (str <= 3) u.utrap = rn1(6,6); 1056. else if (str < 6) u.utrap = rn1(6,4); 1057. else if (str < 9) u.utrap = rn1(4,4); 1058. else if (str < 12) u.utrap = rn1(4,2); 1059. else if (str < 15) u.utrap = rn1(2,2); 1060. else if (str < 18) u.utrap = rnd(2); 1061. else if (str < 69) u.utrap = 1; 1062. else { 1063. u.utrap = 0; 1064. if (webmsgok) 1065. You("tear through %s web!", a_your[trap->madeby_u]); 1066. deltrap(trap); 1067. newsym(u.ux,u.uy); /* get rid of trap symbol */ 1068. } 1069. } 1070. break; 1071. 1072. case STATUE_TRAP: 1073. activate_statue_trap(trap, u.ux, u.uy, FALSE); 1074. break; 1075. 1076. case MAGIC_TRAP: /* A magic trap. */ 1077. seetrap(trap); 1078. if (!rn2(30)) { 1079. deltrap(trap); 1080. newsym(u.ux,u.uy); /* update position */ 1081. You("are caught in a magical explosion!"); 1082. losehp(rnd(10), "magical explosion", KILLED_BY_AN); 1083. Your("body absorbs some of the magical energy!"); 1084. u.uen = (u.uenmax += 2); 1085. } else domagictrap(); 1086. #ifdef STEED 1087. (void) steedintrap(trap, (struct obj *)0); 1088. #endif 1089. break; 1090. 1091. case ANTI_MAGIC: 1092. seetrap(trap); 1093. if(Antimagic) { 1094. shieldeff(u.ux, u.uy); 1095. You_feel("momentarily lethargic."); 1096. } else drain_en(rnd(u.ulevel) + 1); 1097. break; 1098. 1099. case POLY_TRAP: { 1100. char verbbuf[BUFSZ]; 1101. seetrap(trap); 1102. #ifdef STEED 1103. if (u.usteed) 1104. Sprintf(verbbuf, "lead %s", 1105. x_monnam(u.usteed, 1106. u.usteed->mnamelth ? ARTICLE_NONE : ARTICLE_THE, 1107. (char *)0, SUPPRESS_SADDLE, FALSE)); 1108. else 1109. #endif 1110. Sprintf(verbbuf,"%s", 1111. Levitation ? (const char *)"float" : 1112. locomotion(youmonst.data, "step")); 1113. You("%s onto a polymorph trap!", verbbuf); 1114. if(Antimagic || Unchanging) { 1115. shieldeff(u.ux, u.uy); 1116. You_feel("momentarily different."); 1117. /* Trap did nothing; don't remove it --KAA */ 1118. } else { 1119. #ifdef STEED 1120. (void) steedintrap(trap, (struct obj *)0); 1121. #endif 1122. deltrap(trap); /* delete trap before polymorph */ 1123. newsym(u.ux,u.uy); /* get rid of trap symbol */ 1124. You_feel("a change coming over you."); 1125. polyself(FALSE); 1126. } 1127. break; 1128. } 1129. case LANDMINE: { 1130. #ifdef STEED 1131. unsigned steed_mid = 0; 1132. struct obj *saddle = 0; 1133. #endif 1134. if (Levitation || Flying) { 1135. if (!already_seen && rn2(3)) break; 1136. seetrap(trap); 1137. pline("%s %s in a pile of soil below you.", 1138. already_seen ? "There is" : "You discover", 1139. trap->madeby_u ? "the trigger of your mine" : 1140. "a trigger"); 1141. if (already_seen && rn2(3)) break; 1142. pline("KAABLAMM!!! %s %s%s off!", 1143. forcebungle ? "Your inept attempt sets" : 1144. "The air currents set", 1145. already_seen ? a_your[trap->madeby_u] : "", 1146. already_seen ? " land mine" : "it"); 1147. } else { 1148. #ifdef STEED 1149. /* prevent landmine from killing steed, throwing you to 1150. * the ground, and you being affected again by the same 1151. * mine because it hasn't been deleted yet 1152. */ 1153. static boolean recursive_mine = FALSE; 1154. 1155. if (recursive_mine) break; 1156. #endif 1157. seetrap(trap); 1158. pline("KAABLAMM!!! You triggered %s land mine!", 1159. a_your[trap->madeby_u]); 1160. #ifdef STEED 1161. if (u.usteed) steed_mid = u.usteed->m_id; 1162. recursive_mine = TRUE; 1163. (void) steedintrap(trap, (struct obj *)0); 1164. recursive_mine = FALSE; 1165. saddle = sobj_at(SADDLE,u.ux, u.uy); 1166. #endif 1167. set_wounded_legs(LEFT_SIDE, rn1(35, 41)); 1168. set_wounded_legs(RIGHT_SIDE, rn1(35, 41)); 1169. exercise(A_DEX, FALSE); 1170. } 1171. blow_up_landmine(trap); 1172. #ifdef STEED 1173. if (steed_mid && saddle && !u.usteed) 1174. (void)keep_saddle_with_steedcorpse(steed_mid, fobj, saddle); 1175. #endif 1176. newsym(u.ux,u.uy); /* update trap symbol */ 1177. losehp(rnd(16), "land mine", KILLED_BY_AN); 1178. /* fall recursively into the pit... */ 1179. if ((trap = t_at(u.ux, u.uy)) != 0) dotrap(trap, RECURSIVETRAP); 1180. fill_pit(u.ux, u.uy); 1181. break; 1182. } 1183. case ROLLING_BOULDER_TRAP: { 1184. int style = ROLL | (trap->tseen ? LAUNCH_KNOWN : 0); 1185. 1186. seetrap(trap); 1187. pline("Click! You trigger a rolling boulder trap!"); 1188. if(!launch_obj(BOULDER, trap->launch.x, trap->launch.y, 1189. trap->launch2.x, trap->launch2.y, style)) { 1190. deltrap(trap); 1191. newsym(u.ux,u.uy); /* get rid of trap symbol */ 1192. pline("Fortunately for you, no boulder was released."); 1193. } 1194. break; 1195. } 1196. case MAGIC_PORTAL: 1197. seetrap(trap); 1198. #if defined(BLACKMARKET) && defined(STEED) 1199. if (u.usteed && 1200. (Is_blackmarket(&trap->dst) || Is_blackmarket(&u.uz))) 1201. pline("%s seems to shimmer for a moment.", 1202. Monnam(u.usteed)); 1203. else 1204. #endif 1205. domagicportal(trap); 1206. break; 1207. 1208. default: 1209. seetrap(trap); 1210. impossible("You hit a trap of type %u", trap->ttyp); 1211. } 1212. } 1213. 1214. #ifdef STEED 1215. STATIC_OVL int 1216. steedintrap(trap, otmp) 1217. struct trap *trap; 1218. struct obj *otmp; 1219. { 1220. struct monst *mtmp = u.usteed; 1221. struct permonst *mptr; 1222. int tt; 1223. boolean in_sight; 1224. boolean trapkilled = FALSE; 1225. boolean steedhit = FALSE; 1226. 1227. if (!u.usteed || !trap) return 0; 1228. mptr = mtmp->data; 1229. tt = trap->ttyp; 1230. mtmp->mx = u.ux; 1231. mtmp->my = u.uy; 1232. 1233. in_sight = !Blind; 1234. switch (tt) { 1235. case ARROW_TRAP: 1236. if(!otmp) { 1237. impossible("steed hit by non-existant arrow?"); 1238. return 0; 1239. } 1240. if (thitm(8, mtmp, otmp, 0, FALSE)) trapkilled = TRUE; 1241. steedhit = TRUE; 1242. break; 1243. case DART_TRAP: 1244. if(!otmp) { 1245. impossible("steed hit by non-existant dart?"); 1246. return 0; 1247. } 1248. if (thitm(7, mtmp, otmp, 0, FALSE)) trapkilled = TRUE; 1249. steedhit = TRUE; 1250. break; 1251. case SLP_GAS_TRAP: 1252. if (!resists_sleep(mtmp) && !breathless(mptr) && 1253. !mtmp->msleeping && mtmp->mcanmove) { 1254. mtmp->mcanmove = 0; 1255. mtmp->mfrozen = rnd(25); 1256. if (in_sight) { 1257. pline("%s suddenly falls asleep!", 1258. Monnam(mtmp)); 1259. } 1260. } 1261. steedhit = TRUE; 1262. break; 1263. case LANDMINE: 1264. if (thitm(0, mtmp, (struct obj *)0, rnd(16), FALSE)) 1265. trapkilled = TRUE; 1266. steedhit = TRUE; 1267. break; 1268. case PIT: 1269. case SPIKED_PIT: 1270. if (mtmp->mhp <= 0 || 1271. thitm(0, mtmp, (struct obj *)0, 1272. rnd((tt == PIT) ? 6 : 10), FALSE)) 1273. trapkilled = TRUE; 1274. steedhit = TRUE; 1275. break; 1276. case POLY_TRAP: 1277. if (!resists_magm(mtmp)) { 1278. if (!resist(mtmp, WAND_CLASS, 0, NOTELL)) { 1279. (void) mon_spec_poly(mtmp, (struct permonst *)0, 0L, FALSE, FALSE, FALSE, TRUE); 1280. if (!can_saddle(mtmp) || !can_ride(mtmp)) { 1281. dismount_steed(DISMOUNT_POLY); 1282. } else { 1283. You("have to adjust yourself in the saddle on %s.", 1284. x_monnam(mtmp, 1285. mtmp->mnamelth ? ARTICLE_NONE : ARTICLE_A, 1286. (char *)0, SUPPRESS_SADDLE, FALSE)); 1287. } 1288. } 1289. steedhit = TRUE; 1290. } 1291. break; 1292. default: 1293. return 0; 1294. } 1295. if(trapkilled) { 1296. dismount_steed(DISMOUNT_POLY); 1297. return 2; 1298. } 1299. else if(steedhit) return 1; 1300. else return 0; 1301. } 1302. #endif /*STEED*/ 1303. 1304. /* some actions common to both player and monsters for triggered landmine */ 1305. void 1306. blow_up_landmine(trap) 1307. struct trap *trap; 1308. { 1309. (void)scatter(trap->tx, trap->ty, 4, 1310. MAY_DESTROY | MAY_HIT | MAY_FRACTURE | VIS_EFFECTS, 1311. (struct obj *)0); 1312. del_engr_at(trap->tx, trap->ty); 1313. wake_nearto(trap->tx, trap->ty, 400); 1314. /* ALI - artifact doors */ 1315. if (IS_DOOR(levl[trap->tx][trap->ty].typ) && 1316. !artifact_door(trap->tx, trap->ty)) 1317. levl[trap->tx][trap->ty].doormask = D_BROKEN; 1318. /* TODO: destroy drawbridge if present */ 1319. /* caller may subsequently fill pit, e.g. with a boulder */ 1320. trap->ttyp = PIT; /* explosion creates a pit */ 1321. trap->madeby_u = FALSE; /* resulting pit isn't yours */ 1322. seetrap(trap); /* and it isn't concealed */ 1323. } 1324. 1325. #endif /* OVLB */ 1326. #ifdef OVL3 1327. 1328. /* 1329. * Move obj from (x1,y1) to (x2,y2) 1330. * 1331. * Return 0 if no object was launched. 1332. * 1 if an object was launched and placed somewhere. 1333. * 2 if an object was launched, but used up. 1334. */ 1335. int 1336. launch_obj(otyp, x1, y1, x2, y2, style) 1337. short otyp; 1338. register int x1,y1,x2,y2; 1339. int style; 1340. { 1341. register struct monst *mtmp; 1342. register struct obj *otmp, *otmp2; 1343. register int dx,dy; 1344. struct obj *singleobj; 1345. boolean used_up = FALSE; 1346. boolean otherside = FALSE; 1347. int dist; 1348. int tmp; 1349. int delaycnt = 0; 1350. 1351. otmp = sobj_at(otyp, x1, y1); 1352. /* Try the other side too, for rolling boulder traps */ 1353. if (!otmp && otyp == BOULDER) { 1354. otherside = TRUE; 1355. otmp = sobj_at(otyp, x2, y2); 1356. } 1357. if (!otmp) return 0; 1358. if (otherside) { /* swap 'em */ 1359. int tx, ty; 1360. 1361. tx = x1; ty = y1; 1362. x1 = x2; y1 = y2; 1363. x2 = tx; y2 = ty; 1364. } 1365. 1366. if (otmp->quan == 1L) { 1367. obj_extract_self(otmp); 1368. singleobj = otmp; 1369. otmp = (struct obj *) 0; 1370. } else { 1371. singleobj = splitobj(otmp, 1L); 1372. obj_extract_self(singleobj); 1373. } 1374. newsym(x1,y1); 1375. /* in case you're using a pick-axe to chop the boulder that's being 1376. launched (perhaps a monster triggered it), destroy context so that 1377. next dig attempt never thinks you're resuming previous effort */ 1378. if ((otyp == BOULDER || otyp == STATUE) && 1379. singleobj->ox == digging.pos.x && singleobj->oy == digging.pos.y) 1380. (void) memset((genericptr_t)&digging, 0, sizeof digging); 1381. 1382. dist = distmin(x1,y1,x2,y2); 1383. bhitpos.x = x1; 1384. bhitpos.y = y1; 1385. dx = sgn(x2 - x1); 1386. dy = sgn(y2 - y1); 1387. switch (style) { 1388. case ROLL|LAUNCH_UNSEEN: 1389. if (otyp == BOULDER) { 1390. You_hear(Hallucination ? 1391. "someone bowling." : 1392. "rumbling in the distance."); 1393. } 1394. style &= ~LAUNCH_UNSEEN; 1395. goto roll; 1396. case ROLL|LAUNCH_KNOWN: 1397. /* use otrapped as a flag to ohitmon */ 1398. singleobj->otrapped = 1; 1399. style &= ~LAUNCH_KNOWN; 1400. /* fall through */ 1401. roll: 1402. case ROLL: 1403. delaycnt = 2; 1404. /* fall through */ 1405. default: 1406. if (!delaycnt) delaycnt = 1; 1407. if (!cansee(bhitpos.x,bhitpos.y)) curs_on_u(); 1408. tmp_at(DISP_FLASH, obj_to_glyph(singleobj)); 1409. tmp_at(bhitpos.x, bhitpos.y); 1410. } 1411. 1412. /* Set the object in motion */ 1413. while(dist-- > 0 && !used_up) { 1414. struct trap *t; 1415. tmp_at(bhitpos.x, bhitpos.y); 1416. tmp = delaycnt; 1417. 1418. /* dstage@u.washington.edu -- Delay only if hero sees it */ 1419. if (cansee(bhitpos.x, bhitpos.y)) 1420. while (tmp-- > 0) delay_output(); 1421. 1422. bhitpos.x += dx; 1423. bhitpos.y += dy; 1424. t = t_at(bhitpos.x, bhitpos.y); 1425. 1426. if ((mtmp = m_at(bhitpos.x, bhitpos.y)) != 0) { 1427. if (otyp == BOULDER && throws_rocks(mtmp->data)) { 1428. if (rn2(3)) { 1429. if (cansee(bhitpos.x, bhitpos.y)) 1430. pline("%s snatches the boulder.", 1431. Monnam(mtmp)); 1432. else 1433. You_hear("a rumbling stop abruptly."); 1434. singleobj->otrapped = 0; 1435. (void) mpickobj(mtmp, singleobj); 1436. used_up = TRUE; 1437. break; 1438. } 1439. } 1440. if (ohitmon((struct monst *) 0, mtmp,singleobj, 1441. (style==ROLL) ? -1 : dist, FALSE)) { 1442. used_up = TRUE; 1443. break; 1444. } 1445. } else if (bhitpos.x == u.ux && bhitpos.y == u.uy) { 1446. if (multi) nomul(0); 1447. if (thitu(9 + singleobj->spe, 1448. dmgval(singleobj, &youmonst), 1449. singleobj, (char *)0)) 1450. stop_occupation(); 1451. } 1452. if (style == ROLL) { 1453. if (down_gate(bhitpos.x, bhitpos.y) != -1) { 1454. if(ship_object(singleobj, bhitpos.x, bhitpos.y, FALSE)){ 1455. used_up = TRUE; 1456. break; 1457. } 1458. } 1459. if (t && otyp == BOULDER) { 1460. switch(t->ttyp) { 1461. case LANDMINE: 1462. if (rn2(10) > 2) { 1463. pline( 1464. "KAABLAMM!!!%s", 1465. cansee(bhitpos.x, bhitpos.y) ? 1466. " The rolling boulder triggers a land mine." : ""); 1467. deltrap(t); 1468. del_engr_at(bhitpos.x,bhitpos.y); 1469. place_object(singleobj, bhitpos.x, bhitpos.y); 1470. singleobj->otrapped = 0; 1471. fracture_rock(singleobj); 1472. (void)scatter(bhitpos.x,bhitpos.y, 4, 1473. MAY_DESTROY|MAY_HIT|MAY_FRACTURE|VIS_EFFECTS, 1474. (struct obj *)0); 1475. if (cansee(bhitpos.x,bhitpos.y)) 1476. newsym(bhitpos.x,bhitpos.y); 1477. used_up = TRUE; 1478. } 1479. break; 1480. case LEVEL_TELEP: 1481. case TELEP_TRAP: 1482. if (cansee(bhitpos.x, bhitpos.y)) 1483. pline("Suddenly the rolling boulder disappears!"); 1484. else 1485. You_hear("a rumbling stop abruptly."); 1486. singleobj->otrapped = 0; 1487. if (t->ttyp == TELEP_TRAP) 1488. rloco(singleobj); 1489. else { 1490. int newlev = random_teleport_level(); 1491. d_level dest; 1492. 1493. if (newlev == depth(&u.uz) || In_endgame(&u.uz)) 1494. continue; 1495. add_to_migration(singleobj); 1496. get_level(&dest, newlev); 1497. singleobj->ox = dest.dnum; 1498. singleobj->oy = dest.dlevel; 1499. singleobj->owornmask = (long)MIGR_RANDOM; 1500. } 1501. seetrap(t); 1502. used_up = TRUE; 1503. break; 1504. case PIT: 1505. case SPIKED_PIT: 1506. case HOLE: 1507. case TRAPDOOR: 1508. /* the boulder won't be used up if there is a 1509. monster in the trap; stop rolling anyway */ 1510. x2 = bhitpos.x, y2 = bhitpos.y; /* stops here */ 1511. if (flooreffects(singleobj, x2, y2, "fall")) 1512. used_up = TRUE; 1513. dist = -1; /* stop rolling immediately */ 1514. break; 1515. } 1516. if (used_up || dist == -1) break; 1517. } 1518. if (flooreffects(singleobj, bhitpos.x, bhitpos.y, "fall")) { 1519. used_up = TRUE; 1520. break; 1521. } 1522. if (otyp == BOULDER && 1523. (otmp2 = sobj_at(BOULDER, bhitpos.x, bhitpos.y)) != 0) { 1524. const char *bmsg = 1525. " as one boulder sets another in motion"; 1526. 1527. if (!isok(bhitpos.x + dx, bhitpos.y + dy) || !dist || 1528. IS_ROCK(levl[bhitpos.x + dx][bhitpos.y + dy].typ)) 1529. bmsg = " as one boulder hits another"; 1530. 1531. You_hear("a loud crash%s!", 1532. cansee(bhitpos.x, bhitpos.y) ? bmsg : ""); 1533. obj_extract_self(otmp2); 1534. /* pass off the otrapped flag to the next boulder */ 1535. otmp2->otrapped = singleobj->otrapped; 1536. singleobj->otrapped = 0; 1537. place_object(singleobj, bhitpos.x, bhitpos.y); 1538. singleobj = otmp2; 1539. otmp2 = (struct obj *)0; 1540. wake_nearto(bhitpos.x, bhitpos.y, 10*10); 1541. } 1542. } 1543. if (otyp == BOULDER && closed_door(bhitpos.x,bhitpos.y)) { 1544. if (cansee(bhitpos.x, bhitpos.y)) 1545. pline_The("boulder crashes through a door."); 1546. levl[bhitpos.x][bhitpos.y].doormask = D_BROKEN; 1547. if (dist) unblock_point(bhitpos.x, bhitpos.y); 1548. } 1549. 1550. /* if about to hit iron bars, do so now */ 1551. if (dist > 0 && isok(bhitpos.x + dx,bhitpos.y + dy) && 1552. levl[bhitpos.x + dx][bhitpos.y + dy].typ == IRONBARS) { 1553. x2 = bhitpos.x, y2 = bhitpos.y; /* object stops here */ 1554. if (hits_bars(&singleobj, x2, y2, !rn2(20), 0)) { 1555. if (!singleobj) used_up = TRUE; 1556. break; 1557. } 1558. } 1559. } 1560. tmp_at(DISP_END, 0); 1561. if (!used_up) { 1562. singleobj->otrapped = 0; 1563. place_object(singleobj, x2,y2); 1564. newsym(x2,y2); 1565. return 1; 1566. } else 1567. return 2; 1568. } 1569. 1570. #endif /* OVL3 */ 1571. #ifdef OVLB 1572. 1573. void 1574. seetrap(trap) 1575. register struct trap *trap; 1576. { 1577. if(!trap->tseen) { 1578. trap->tseen = 1; 1579. newsym(trap->tx, trap->ty); 1580. } 1581. } 1582. 1583. #endif /* OVLB */ 1584. #ifdef OVL3 1585. 1586. STATIC_OVL int 1587. mkroll_launch(ttmp, x, y, otyp, ocount) 1588. struct trap *ttmp; 1589. xchar x,y; 1590. short otyp; 1591. long ocount; 1592. { 1593. struct obj *otmp; 1594. register int tmp; 1595. schar dx,dy; 1596. int distance; 1597. coord cc; 1598. coord bcc; 1599. int trycount = 0; 1600. boolean success = FALSE; 1601. int mindist = 4; 1602. 1603. if (ttmp->ttyp == ROLLING_BOULDER_TRAP) mindist = 2; 1604. distance = rn1(5,4); /* 4..8 away */ 1605. tmp = rn2(8); /* randomly pick a direction to try first */ 1606. while (distance >= mindist) { 1607. dx = xdir[tmp]; 1608. dy = ydir[tmp]; 1609. cc.x = x; cc.y = y; 1610. /* Prevent boulder from being placed on water */ 1611. if (ttmp->ttyp == ROLLING_BOULDER_TRAP 1612. && is_pool(x+distance*dx,y+distance*dy)) 1613. success = FALSE; 1614. else success = isclearpath(&cc, distance, dx, dy); 1615. if (ttmp->ttyp == ROLLING_BOULDER_TRAP) { 1616. boolean success_otherway; 1617. bcc.x = x; bcc.y = y; 1618. success_otherway = isclearpath(&bcc, distance, 1619. -(dx), -(dy)); 1620. if (!success_otherway) success = FALSE; 1621. } 1622. if (success) break; 1623. if (++tmp > 7) tmp = 0; 1624. if ((++trycount % 8) == 0) --distance; 1625. } 1626. if (!success) { 1627. /* create the trap without any ammo, launch pt at trap location */ 1628. cc.x = bcc.x = x; 1629. cc.y = bcc.y = y; 1630. } else { 1631. otmp = mksobj(otyp, TRUE, FALSE); 1632. otmp->quan = ocount; 1633. otmp->owt = weight(otmp); 1634. place_object(otmp, cc.x, cc.y); 1635. stackobj(otmp); 1636. } 1637. ttmp->launch.x = cc.x; 1638. ttmp->launch.y = cc.y; 1639. if (ttmp->ttyp == ROLLING_BOULDER_TRAP) { 1640. ttmp->launch2.x = bcc.x; 1641. ttmp->launch2.y = bcc.y; 1642. } else 1643. ttmp->launch_otyp = otyp; 1644. newsym(ttmp->launch.x, ttmp->launch.y); 1645. return 1; 1646. } 1647. 1648. STATIC_OVL boolean 1649. isclearpath(cc,distance,dx,dy) 1650. coord *cc; 1651. int distance; 1652. schar dx,dy; 1653. { 1654. uchar typ; 1655. xchar x, y; 1656. 1657. x = cc->x; 1658. y = cc->y; 1659. while (distance-- > 0) { 1660. x += dx; 1661. y += dy; 1662. typ = levl[x][y].typ; 1663. if (!isok(x,y) || !ZAP_POS(typ) || closed_door(x,y)) 1664. return FALSE; 1665. } 1666. cc->x = x; 1667. cc->y = y; 1668. return TRUE; 1669. } 1670. #endif /* OVL3 */ 1671. #ifdef OVL1 1672. 1673. void 1674. mon_drain_en(mtmp, n) 1675. struct monst *mtmp; 1676. register int n; 1677. { 1678. if (!mtmp->m_enmax) return; 1679. if (canseemon(mtmp)) 1680. pline("%s looks less powerful!", Monnam(mtmp)); 1681. mtmp->m_en -= n; 1682. if(mtmp->m_en < 0) { 1683. mtmp->m_enmax += mtmp->m_en; 1684. if(mtmp->m_enmax < 0) mtmp->m_enmax = 0; 1685. mtmp->m_en = 0; 1686. } 1687. } 1688. 1689. 1690. int 1691. mintrap(mtmp) 1692. register struct monst *mtmp; 1693. { 1694. register struct trap *trap = t_at(mtmp->mx, mtmp->my); 1695. boolean trapkilled = FALSE; 1696. struct permonst *mptr = mtmp->data; 1697. struct obj *otmp; 1698. 1699. if (!trap) { 1700. mtmp->mtrapped = 0; /* perhaps teleported? */ 1701. } else if (mtmp->mtrapped) { /* is currently in the trap */ 1702. if (!trap->tseen && 1703. cansee(mtmp->mx, mtmp->my) && canseemon(mtmp) && 1704. (trap->ttyp == SPIKED_PIT || trap->ttyp == BEAR_TRAP || 1705. trap->ttyp == HOLE || trap->ttyp == PIT || 1706. trap->ttyp == WEB)) { 1707. /* If you come upon an obviously trapped monster, then 1708. * you must be able to see the trap it's in too. 1709. */ 1710. seetrap(trap); 1711. } 1712. 1713. if (!rn2(40)) { 1714. if (sobj_at(BOULDER, mtmp->mx, mtmp->my) && 1715. (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT)) { 1716. if (!rn2(2)) { 1717. mtmp->mtrapped = 0; 1718. if (canseemon(mtmp)) 1719. pline("%s pulls free...", Monnam(mtmp)); 1720. fill_pit(mtmp->mx, mtmp->my); 1721. } 1722. } else { 1723. mtmp->mtrapped = 0; 1724. } 1725. } else if (metallivorous(mptr)) { 1726. if (trap->ttyp == BEAR_TRAP) { 1727. if (canseemon(mtmp)) 1728. pline("%s eats a bear trap!", Monnam(mtmp)); 1729. deltrap(trap); 1730. mtmp->meating = 5; 1731. mtmp->mtrapped = 0; 1732. } else if (trap->ttyp == SPIKED_PIT) { 1733. if (canseemon(mtmp)) 1734. pline("%s munches on some spikes!", Monnam(mtmp)); 1735. trap->ttyp = PIT; 1736. mtmp->meating = 5; 1737. } 1738. } 1739. } else { 1740. register int tt = trap->ttyp; 1741. boolean in_sight, tear_web, see_it, 1742. inescapable = ((tt == HOLE || tt == PIT) && 1743. In_sokoban(&u.uz) && !trap->madeby_u); 1744. const char *fallverb; 1745. 1746. #ifdef STEED 1747. /* true when called from dotrap, inescapable is not an option */ 1748. if (mtmp == u.usteed) inescapable = TRUE; 1749. #endif 1750. if (!inescapable && 1751. ((mtmp->mtrapseen & (1 << (tt-1))) != 0 || 1752. (tt == HOLE && !mindless(mtmp->data)))) { 1753. /* it has been in such a trap - perhaps it escapes */ 1754. if(rn2(4)) return(0); 1755. } else { 1756. mtmp->mtrapseen |= (1 << (tt-1)); 1757. } 1758. /* Monster is aggravated by being trapped by you. 1759. Recognizing who made the trap isn't completely 1760. unreasonable; everybody has their own style. */ 1761. if (trap->madeby_u && rnl(5)) setmangry(mtmp); 1762. 1763. in_sight = canseemon(mtmp); 1764. see_it = cansee(mtmp->mx, mtmp->my); 1765. #ifdef STEED 1766. /* assume hero can tell what's going on for the steed */ 1767. if (mtmp == u.usteed) in_sight = TRUE; 1768. #endif 1769. switch (tt) { 1770. case ARROW_TRAP: 1771. if (trap->once && trap->tseen && !rn2(15)) { 1772. if (in_sight && see_it) 1773. pline("%s triggers a trap but nothing happens.", 1774. Monnam(mtmp)); 1775. deltrap(trap); 1776. newsym(mtmp->mx, mtmp->my); 1777. break; 1778. } 1779. trap->once = 1; 1780. otmp = mksobj(ARROW, TRUE, FALSE); 1781. otmp->quan = 1L; 1782. otmp->owt = weight(otmp); 1783. otmp->opoisoned = 0; 1784. if (in_sight) seetrap(trap); 1785. if (thitm(8, mtmp, otmp, 0, FALSE)) trapkilled = TRUE; 1786. break; 1787. case DART_TRAP: 1788. if (trap->once && trap->tseen && !rn2(15)) { 1789. if (in_sight && see_it) 1790. pline("%s triggers a trap but nothing happens.", 1791. Monnam(mtmp)); 1792. deltrap(trap); 1793. newsym(mtmp->mx, mtmp->my); 1794. break; 1795. } 1796. trap->once = 1; 1797. otmp = mksobj(DART, TRUE, FALSE); 1798. otmp->quan = 1L; 1799. otmp->owt = weight(otmp); 1800. if (!rn2(6)) otmp->opoisoned = 1; 1801. if (in_sight) seetrap(trap); 1802. if (thitm(7, mtmp, otmp, 0, FALSE)) trapkilled = TRUE; 1803. break; 1804. case ROCKTRAP: 1805. if (trap->once && trap->tseen && !rn2(15)) { 1806. if (in_sight && see_it) 1807. pline("A trap door above %s opens, but nothing falls out!", 1808. mon_nam(mtmp)); 1809. deltrap(trap); 1810. newsym(mtmp->mx, mtmp->my); 1811. break; 1812. } 1813. trap->once = 1; 1814. otmp = mksobj(ROCK, TRUE, FALSE); 1815. otmp->quan = 1L; 1816. otmp->owt = weight(otmp); 1817. otmp->opoisoned = 0; 1818. if (in_sight) seetrap(trap); 1819. if (thitm(0, mtmp, otmp, d(2, 6), FALSE)) 1820. trapkilled = TRUE; 1821. break; 1822. 1823. case SQKY_BOARD: 1824. if(is_flyer(mptr)) break; 1825. /* stepped on a squeaky board */ 1826. if (in_sight) { 1827. pline("A board beneath %s squeaks loudly.", mon_nam(mtmp)); 1828. seetrap(trap); 1829. } else 1830. You_hear("a distant squeak."); 1831. /* wake up nearby monsters */ 1832. wake_nearto(mtmp->mx, mtmp->my, 40); 1833. break; 1834. 1835. case BEAR_TRAP: 1836. if(mptr->msize > MZ_SMALL && 1837. !amorphous(mptr) && !is_flyer(mptr) && 1838. !is_whirly(mptr) && !unsolid(mptr)) { 1839. mtmp->mtrapped = 1; 1840. if(in_sight) { 1841. pline("%s is caught in %s bear trap!", 1842. Monnam(mtmp), a_your[trap->madeby_u]); 1843. seetrap(trap); 1844. } else { 1845. if((mptr == &mons[PM_OWLBEAR] 1846. || mptr == &mons[PM_BUGBEAR]) 1847. && flags.soundok) 1848. You_hear("the roaring of an angry bear!"); 1849. } 1850. } 1851. break; 1852. 1853. case SLP_GAS_TRAP: 1854. if (!resists_sleep(mtmp) && !breathless(mptr) && 1855. !mtmp->msleeping && mtmp->mcanmove) { 1856. mtmp->mcanmove = 0; 1857. mtmp->mfrozen = rnd(25); 1858. if (in_sight) { 1859. pline("%s suddenly falls asleep!", 1860. Monnam(mtmp)); 1861. seetrap(trap); 1862. } 1863. } 1864. break; 1865. 1866. case RUST_TRAP: 1867. { 1868. struct obj *target; 1869. 1870. if (in_sight) 1871. seetrap(trap); 1872. switch (rn2(5)) { 1873. case 0: 1874. if (in_sight) 1875. pline("%s %s on the %s!", A_gush_of_water_hits, 1876. mon_nam(mtmp), mbodypart(mtmp, HEAD)); 1877. target = which_armor(mtmp, W_ARMH); 1878. (void) rust_dmg(target, "helmet", 1, TRUE, mtmp); 1879. break; 1880. case 1: 1881. if (in_sight) 1882. pline("%s %s's left %s!", A_gush_of_water_hits, 1883. mon_nam(mtmp), mbodypart(mtmp, ARM)); 1884. target = which_armor(mtmp, W_ARMS); 1885. if (rust_dmg(target, "shield", 1, TRUE, mtmp)) 1886. break; 1887. target = MON_WEP(mtmp); 1888. if (target && bimanual(target)) 1889. erode_obj(target, FALSE, TRUE); 1890. glovecheck: target = which_armor(mtmp, W_ARMG); 1891. (void) rust_dmg(target, "gauntlets", 1, TRUE, mtmp); 1892. break; 1893. case 2: 1894. if (in_sight) 1895. pline("%s %s's right %s!", A_gush_of_water_hits, 1896. mon_nam(mtmp), mbodypart(mtmp, ARM)); 1897. if (MON_WEP(mtmp) && !snuff_lit(MON_WEP(mtmp))) 1898. erode_obj(MON_WEP(mtmp), FALSE, TRUE); 1899. goto glovecheck; 1900. default: 1901. if (in_sight) 1902. pline("%s %s!", A_gush_of_water_hits, 1903. mon_nam(mtmp)); 1904. for (otmp=mtmp->minvent; otmp; otmp = otmp->nobj) 1905. (void) snuff_lit(otmp); 1906. target = which_armor(mtmp, W_ARMC); 1907. if (target) 1908. (void) rust_dmg(target, cloak_simple_name(target), 1909. 1, TRUE, mtmp); 1910. else { 1911. target = which_armor(mtmp, W_ARM); 1912. if (target) 1913. (void) rust_dmg(target, "armor", 1, TRUE, mtmp); 1914. #ifdef TOURIST 1915. else { 1916. target = which_armor(mtmp, W_ARMU); 1917. (void) rust_dmg(target, "shirt", 1, TRUE, mtmp); 1918. } 1919. #endif 1920. } 1921. } 1922. if (mptr == &mons[PM_IRON_GOLEM]) { 1923. if (in_sight) 1924. pline("%s falls to pieces!", Monnam(mtmp)); 1925. else if(mtmp->mtame) 1926. pline("May %s rust in peace.", 1927. mon_nam(mtmp)); 1928. mondied(mtmp); 1929. if (mtmp->mhp <= 0) 1930. trapkilled = TRUE; 1931. } else if (mptr == &mons[PM_FLAMING_SPHERE]) { 1932. if (in_sight) 1933. pline("%s is extinguished!", Monnam(mtmp)); 1934. mondied(mtmp); 1935. if (mtmp->mhp <= 0) 1936. trapkilled = TRUE; 1937. } else if (mptr == &mons[PM_GREMLIN] && rn2(3)) { 1938. (void)split_mon(mtmp, (struct monst *)0); 1939. } 1940. break; 1941. } 1942. case FIRE_TRAP: 1943. mfiretrap: 1944. if (in_sight) 1945. pline("A %s erupts from the %s under %s!", 1946. tower_of_flame, 1947. surface(mtmp->mx,mtmp->my), mon_nam(mtmp)); 1948. else if (see_it) /* evidently `mtmp' is invisible */ 1949. You("see a %s erupt from the %s!", 1950. tower_of_flame, surface(mtmp->mx,mtmp->my)); 1951. if (Slimed) { 1952. pline("The slime that covers you is burned away!"); 1953. Slimed = 0; 1954. } 1955. 1956. if (resists_fire(mtmp)) { 1957. if (in_sight) { 1958. shieldeff(mtmp->mx,mtmp->my); 1959. pline("%s is uninjured.", Monnam(mtmp)); 1960. } 1961. } else { 1962. int num = d(2,4), alt; 1963. boolean immolate = FALSE; 1964. 1965. /* paper burns very fast, assume straw is tightly 1966. * packed and burns a bit slower */ 1967. switch (monsndx(mtmp->data)) { 1968. case PM_PAPER_GOLEM: immolate = TRUE; 1969. alt = mtmp->mhpmax; break; 1970. case PM_STRAW_GOLEM: alt = mtmp->mhpmax / 2; break; 1971. case PM_WOOD_GOLEM: alt = mtmp->mhpmax / 4; break; 1972. case PM_LEATHER_GOLEM: alt = mtmp->mhpmax / 8; break; 1973. default: alt = 0; break; 1974. } 1975. if (alt > num) num = alt; 1976. 1977. if (thitm(0, mtmp, (struct obj *)0, num, immolate)) 1978. trapkilled = TRUE; 1979. else 1980. /* we know mhp is at least `num' below mhpmax, 1981. so no (mhp > mhpmax) check is needed here */ 1982. mtmp->mhpmax -= rn2(num + 1); 1983. } 1984. if (burnarmor(mtmp) || rn2(3)) { 1985. (void) destroy_mitem(mtmp, SCROLL_CLASS, AD_FIRE); 1986. (void) destroy_mitem(mtmp, SPBOOK_CLASS, AD_FIRE); 1987. (void) destroy_mitem(mtmp, POTION_CLASS, AD_FIRE); 1988. } 1989. if (burn_floor_paper(mtmp->mx, mtmp->my, see_it, FALSE) && 1990. !see_it && distu(mtmp->mx, mtmp->my) <= 3*3) 1991. You("smell smoke."); 1992. if (is_ice(mtmp->mx,mtmp->my)) 1993. melt_ice(mtmp->mx,mtmp->my); 1994. if (see_it) seetrap(trap); 1995. break; 1996. 1997. case PIT: 1998. case SPIKED_PIT: 1999. fallverb = "falls"; 2000. if (is_flyer(mptr) || is_floater(mptr) || 2001. (mtmp->wormno && count_wsegs(mtmp) > 5) || 2002. is_clinger(mptr)) { 2003. if (!inescapable) break; /* avoids trap */ 2004. fallverb = "is dragged"; /* sokoban pit */ 2005. } 2006. if (!passes_walls(mptr)) 2007. mtmp->mtrapped = 1; 2008. if(in_sight) { 2009. pline("%s %s into %s pit!", 2010. Monnam(mtmp), fallverb, 2011. a_your[trap->madeby_u]); 2012. if (mptr == &mons[PM_PIT_VIPER] || mptr == &mons[PM_PIT_FIEND]) 2013. pline("How pitiful. Isn't that the pits?"); 2014. seetrap(trap); 2015. } 2016. mselftouch(mtmp, "Falling, ", FALSE); 2017. if (mtmp->mhp <= 0 || 2018. thitm(0, mtmp, (struct obj *)0, 2019. rnd((tt == PIT) ? 6 : 10), FALSE)) 2020. trapkilled = TRUE; 2021. break; 2022. case HOLE: 2023. case TRAPDOOR: 2024. if (!Can_fall_thru(&u.uz)) { 2025. impossible("mintrap: %ss cannot exist on this level.", 2026. defsyms[trap_to_defsym(tt)].explanation); 2027. break; /* don't activate it after all */ 2028. } 2029. if (is_flyer(mptr) || is_floater(mptr) || 2030. mptr == &mons[PM_WUMPUS] || 2031. (mtmp->wormno && count_wsegs(mtmp) > 5) || 2032. mptr->msize >= MZ_HUGE) { 2033. if (inescapable) { /* sokoban hole */ 2034. if (in_sight) { 2035. pline("%s seems to be yanked down!", 2036. Monnam(mtmp)); 2037. /* suppress message in mlevel_tele_trap() */ 2038. in_sight = FALSE; 2039. seetrap(trap); 2040. } 2041. } else 2042. break; 2043. } 2044. /* Fall through */ 2045. case LEVEL_TELEP: 2046. case MAGIC_PORTAL: 2047. { 2048. int mlev_res; 2049. mlev_res = mlevel_tele_trap(mtmp, trap, 2050. inescapable, in_sight); 2051. if (mlev_res) return(mlev_res); 2052. } 2053. break; 2054. 2055. case TELEP_TRAP: 2056. mtele_trap(mtmp, trap, in_sight); 2057. break; 2058. 2059. case WEB: 2060. /* Monster in a web. */ 2061. if (webmaker(mptr)) break; 2062. if (amorphous(mptr) || is_whirly(mptr) || unsolid(mptr)){ 2063. if(acidic(mptr) || 2064. mptr == &mons[PM_GELATINOUS_CUBE] || 2065. mptr == &mons[PM_FIRE_ELEMENTAL]) { 2066. if (in_sight) 2067. pline("%s %s %s spider web!", 2068. Monnam(mtmp), 2069. (mptr == &mons[PM_FIRE_ELEMENTAL]) ? 2070. "burns" : "dissolves", 2071. a_your[trap->madeby_u]); 2072. deltrap(trap); 2073. newsym(mtmp->mx, mtmp->my); 2074. break; 2075. } 2076. if (in_sight) { 2077. pline("%s flows through %s spider web.", 2078. Monnam(mtmp), 2079. a_your[trap->madeby_u]); 2080. seetrap(trap); 2081. } 2082. break; 2083. } 2084. tear_web = FALSE; 2085. switch (monsndx(mptr)) { 2086. case PM_OWLBEAR: /* Eric Backus */ 2087. case PM_BUGBEAR: 2088. if (!in_sight) { 2089. You_hear("the roaring of a confused bear!"); 2090. mtmp->mtrapped = 1; 2091. break; 2092. } 2093. /* fall though */ 2094. default: 2095. if (mptr->mlet == S_GIANT || 2096. (mptr->mlet == S_DRAGON && 2097. extra_nasty(mptr)) || /* excl. babies */ 2098. (mtmp->wormno && count_wsegs(mtmp) > 5)) { 2099. tear_web = TRUE; 2100. } else if (in_sight) { 2101. pline("%s is caught in %s spider web.", 2102. Monnam(mtmp), 2103. a_your[trap->madeby_u]); 2104. seetrap(trap); 2105. } 2106. mtmp->mtrapped = tear_web ? 0 : 1; 2107. break; 2108. /* this list is fairly arbitrary; it deliberately 2109. excludes wumpus & giant/ettin zombies/mummies */ 2110. case PM_TITANOTHERE: 2111. case PM_BALUCHITHERIUM: 2112. case PM_PURPLE_WORM: 2113. case PM_JABBERWOCK: 2114. case PM_IRON_GOLEM: 2115. case PM_BALROG: 2116. case PM_KRAKEN: 2117. case PM_MASTODON: 2118. tear_web = TRUE; 2119. break; 2120. } 2121. if (tear_web) { 2122. if (in_sight) 2123. pline("%s tears through %s spider web!", 2124. Monnam(mtmp), a_your[trap->madeby_u]); 2125. deltrap(trap); 2126. newsym(mtmp->mx, mtmp->my); 2127. } 2128. break; 2129. 2130. case STATUE_TRAP: 2131. break; 2132. 2133. case MAGIC_TRAP: 2134. /* A magic trap. Monsters usually immune. */ 2135. if (!rn2(30)) { 2136. deltrap(trap); 2137. newsym(mtmp->mx, mtmp->my); 2138. if (in_sight) 2139. pline("%s is caught in a magical explosion.", 2140. Monnam(mtmp)); 2141. if (thitm(0, mtmp, (struct obj *)0, rnd(10), FALSE)) 2142. trapkilled = TRUE; 2143. else { 2144. if (in_sight) 2145. pline("%s looks filled with power.", 2146. Monnam(mtmp)); 2147. mtmp->m_en = (mtmp->m_enmax += 2); 2148. } 2149. } else if (!rn2(21)) goto mfiretrap; 2150. break; 2151. case ANTI_MAGIC: 2152. if (in_sight) seetrap(trap); 2153. if (resists_magm(mtmp)) { 2154. if (in_sight) { 2155. shieldeff(mtmp->mx,mtmp->my); 2156. pline("%s is uninjured.", Monnam(mtmp)); 2157. } 2158. } else { 2159. mon_drain_en(mtmp, 2160. ((mtmp->m_lev > 0) ? (rnd(mtmp->m_lev)) : 0) + 1); 2161. } 2162. break; 2163. case LANDMINE: 2164. if(rn2(3)) 2165. break; /* monsters usually don't set it off */ 2166. if(is_flyer(mptr)) { 2167. boolean already_seen = trap->tseen; 2168. if (in_sight && !already_seen) { 2169. pline("A trigger appears in a pile of soil below %s.", mon_nam(mtmp)); 2170. seetrap(trap); 2171. } 2172. if (rn2(3)) break; 2173. if (in_sight) { 2174. newsym(mtmp->mx, mtmp->my); 2175. pline_The("air currents set %s off!", 2176. already_seen ? "a land mine" : "it"); 2177. } 2178. } else if(in_sight) { 2179. newsym(mtmp->mx, mtmp->my); 2180. pline("KAABLAMM!!! %s triggers %s land mine!", 2181. Monnam(mtmp), a_your[trap->madeby_u]); 2182. } 2183. if (!in_sight) 2184. pline("Kaablamm! You hear an explosion in the distance!"); 2185. blow_up_landmine(trap); 2186. if (thitm(0, mtmp, (struct obj *)0, rnd(16), FALSE)) 2187. trapkilled = TRUE; 2188. else { 2189. /* monsters recursively fall into new pit */ 2190. if (mintrap(mtmp) == 2) trapkilled=TRUE; 2191. } 2192. /* a boulder may fill the new pit, crushing monster */ 2193. fill_pit(trap->tx, trap->ty); 2194. if (mtmp->mhp <= 0) trapkilled = TRUE; 2195. if (unconscious()) { 2196. multi = -1; 2197. nomovemsg="The explosion awakens you!"; 2198. } 2199. break; 2200. 2201. case POLY_TRAP: 2202. if (resists_magm(mtmp)) { 2203. shieldeff(mtmp->mx, mtmp->my); 2204. } else if (!resist(mtmp, WAND_CLASS, 0, NOTELL)) { 2205. /* (void) newcham(mtmp, (struct permonst *)0, FALSE);*/ 2206. /* WAC use polymorph code from zap.c*/ 2207. #if 0 2208. if (!rn2(25) || !mon_poly(mtmp)) { 2209. if (in_sight) { 2210. pline("%s shudders!", Monnam(mtmp)); 2211. seetrap(trap); 2212. } 2213. /* no corpse after system shock */ 2214. mtmp->mhp -= rnd(30); 2215. if (mtmp->mhp < 0) mondead(mtmp); 2216. } else { 2217. #endif 2218. mon_poly(mtmp, FALSE, "%s changes!"); 2219. if (in_sight) seetrap(trap); 2220. } 2221. break; 2222. 2223. case ROLLING_BOULDER_TRAP: 2224. if (!is_flyer(mptr)) { 2225. int style = ROLL | (in_sight ? 0 : LAUNCH_UNSEEN); 2226. 2227. newsym(mtmp->mx,mtmp->my); 2228. if (in_sight) 2229. pline("Click! %s triggers %s.", Monnam(mtmp), 2230. trap->tseen ? 2231. "a rolling boulder trap" : 2232. something); 2233. if (launch_obj(BOULDER, trap->launch.x, trap->launch.y, 2234. trap->launch2.x, trap->launch2.y, style)) { 2235. if (in_sight) trap->tseen = TRUE; 2236. if (mtmp->mhp <= 0) trapkilled = TRUE; 2237. } else { 2238. deltrap(trap); 2239. newsym(mtmp->mx,mtmp->my); 2240. } 2241. } 2242. break; 2243. 2244. default: 2245. impossible("Some monster encountered a strange trap of type %d.", tt); 2246. } 2247. } 2248. if(trapkilled) return 2; 2249. return mtmp->mtrapped; 2250. } 2251. 2252. #endif /* OVL1 */ 2253. #ifdef OVLB 2254. 2255. /* Combine cockatrice checks into single functions to avoid repeating code. */ 2256. void 2257. instapetrify(str) 2258. const char *str; 2259. { 2260. if (Stone_resistance) return; 2261. if (poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM)) 2262. return; 2263. You("turn to stone..."); 2264. killer_format = KILLED_BY_AN; 2265. killer = str; 2266. done(STONING); 2267. } 2268. 2269. void 2270. minstapetrify(mon,byplayer) 2271. struct monst *mon; 2272. boolean byplayer; 2273. { 2274. if (resists_ston(mon)) return; 2275. if (poly_when_stoned(mon->data)) { 2276. mon_to_stone(mon); 2277. return; 2278. } 2279. 2280. /* give a " is slowing down" message and also remove 2281. intrinsic speed (comparable to similar effect on the hero) */ 2282. mon_adjust_speed(mon, -3, (struct obj *)0); 2283. 2284. if (cansee(mon->mx, mon->my)) 2285. pline("%s turns to stone.", Monnam(mon)); 2286. if (byplayer) { 2287. stoned = TRUE; 2288. xkilled(mon,0); 2289. } else monstone(mon); 2290. } 2291. 2292. void 2293. selftouch(arg) 2294. const char *arg; 2295. { 2296. char kbuf[BUFSZ]; 2297. 2298. if(uwep && uwep->otyp == CORPSE && touch_petrifies(&mons[uwep->corpsenm]) 2299. && !Stone_resistance) { 2300. pline("%s touch the %s corpse.", arg, 2301. mons[uwep->corpsenm].mname); 2302. Sprintf(kbuf, "%s corpse", an(mons[uwep->corpsenm].mname)); 2303. instapetrify(kbuf); 2304. } 2305. /* Or your secondary weapon, if wielded */ 2306. if(u.twoweap && uswapwep && uswapwep->otyp == CORPSE && 2307. touch_petrifies(&mons[uswapwep->corpsenm]) && !Stone_resistance){ 2308. pline("%s touch the %s corpse.", arg, 2309. mons[uswapwep->corpsenm].mname); 2310. Sprintf(kbuf, "%s corpse", an(mons[uswapwep->corpsenm].mname)); 2311. instapetrify(kbuf); 2312. } 2313. } 2314. 2315. void 2316. mselftouch(mon,arg,byplayer) 2317. struct monst *mon; 2318. const char *arg; 2319. boolean byplayer; 2320. { 2321. struct obj *mwep = MON_WEP(mon); 2322. 2323. if (mwep && mwep->otyp == CORPSE && touch_petrifies(&mons[mwep->corpsenm])) { 2324. if (cansee(mon->mx, mon->my)) { 2325. pline("%s%s touches the %s corpse.", 2326. arg ? arg : "", arg ? mon_nam(mon) : Monnam(mon), 2327. mons[mwep->corpsenm].mname); 2328. } 2329. minstapetrify(mon, byplayer); 2330. } 2331. } 2332. 2333. /* KMH, balance patch -- several ways for the player to fix stoning */ 2334. int 2335. uunstone() 2336. { 2337. if (Stoned) { 2338. Stoned = 0; 2339. if (!Hallucination) 2340. You_feel("limber!"); 2341. else 2342. pline("What a pity - you just ruined a future piece of %sart!", 2343. ACURR(A_CHA) > 15 ? "fine " : ""); 2344. /* The problem was fixed */ 2345. return (1); 2346. } 2347. /* No problem to fix */ 2348. return (0); 2349. } 2350. 2351. 2352. void 2353. float_up() 2354. { 2355. if(u.utrap) { 2356. if(u.utraptype == TT_PIT) { 2357. u.utrap = 0; 2358. You("float up, out of the pit!"); 2359. vision_full_recalc = 1; /* vision limits change */ 2360. fill_pit(u.ux, u.uy); 2361. } else if (u.utraptype == TT_INFLOOR) { 2362. Your("body pulls upward, but your %s are still stuck.", 2363. makeplural(body_part(LEG))); 2364. } else { 2365. You("float up, only your %s is still stuck.", 2366. body_part(LEG)); 2367. } 2368. } 2369. else if(Is_waterlevel(&u.uz)) 2370. pline("It feels as though you've lost some weight."); 2371. else if(u.uinwater) 2372. spoteffects(TRUE); 2373. else if(u.uswallow) 2374. You(is_animal(u.ustuck->data) ? 2375. "float away from the %s." : 2376. "spiral up into %s.", 2377. is_animal(u.ustuck->data) ? 2378. surface(u.ux, u.uy) : 2379. mon_nam(u.ustuck)); 2380. else if (Hallucination) 2381. pline("Up, up, and awaaaay! You're walking on air!"); 2382. else if(Is_airlevel(&u.uz)) 2383. You("gain control over your movements."); 2384. else 2385. You("start to float in the air!"); 2386. #ifdef STEED 2387. if (u.usteed && !is_floater(u.usteed->data) && 2388. !is_flyer(u.usteed->data)) { 2389. if (Lev_at_will) 2390. pline("%s magically floats up!", Monnam(u.usteed)); 2391. else { 2392. You("cannot stay on %s.", mon_nam(u.usteed)); 2393. dismount_steed(DISMOUNT_GENERIC); 2394. } 2395. } 2396. #endif 2397. return; 2398. } 2399. 2400. void 2401. fill_pit(x, y) 2402. int x, y; 2403. { 2404. struct obj *otmp; 2405. struct trap *t; 2406. 2407. if ((t = t_at(x, y)) && 2408. ((t->ttyp == PIT) || (t->ttyp == SPIKED_PIT)) && 2409. (otmp = sobj_at(BOULDER, x, y))) { 2410. obj_extract_self(otmp); 2411. (void) flooreffects(otmp, x, y, "settle"); 2412. } 2413. } 2414. 2415. int 2416. float_down(hmask, emask) 2417. long hmask, emask; /* might cancel timeout */ 2418. { 2419. register struct trap *trap = (struct trap *)0; 2420. d_level current_dungeon_level; 2421. boolean no_msg = FALSE; 2422. 2423. HLevitation &= ~hmask; 2424. ELevitation &= ~emask; 2425. if(Levitation) return(0); /* maybe another ring/potion/boots */ 2426. if(u.uswallow) { 2427. You("float down, but you are still %s.", 2428. is_animal(u.ustuck->data) ? "swallowed" : "engulfed"); 2429. return(1); 2430. } 2431. 2432. if (Punished && !carried(uball) && 2433. (is_pool(uball->ox, uball->oy) || 2434. ((trap = t_at(uball->ox, uball->oy)) && 2435. ((trap->ttyp == PIT) || (trap->ttyp == SPIKED_PIT) || 2436. (trap->ttyp == TRAPDOOR) || (trap->ttyp == HOLE))))) { 2437. u.ux0 = u.ux; 2438. u.uy0 = u.uy; 2439. u.ux = uball->ox; 2440. u.uy = uball->oy; 2441. movobj(uchain, uball->ox, uball->oy); 2442. newsym(u.ux0, u.uy0); 2443. vision_full_recalc = 1; /* in case the hero moved. */ 2444. } 2445. /* check for falling into pool - added by GAN 10/20/86 */ 2446. if(!Flying) { 2447. if (!u.uswallow && u.ustuck) { 2448. if (sticks(youmonst.data)) 2449. You("aren't able to maintain your hold on %s.", 2450. mon_nam(u.ustuck)); 2451. else 2452. pline("Startled, %s can no longer hold you!", 2453. mon_nam(u.ustuck)); 2454. u.ustuck = 0; 2455. } 2456. /* kludge alert: 2457. * drown() and lava_effects() print various messages almost 2458. * every time they're called which conflict with the "fall 2459. * into" message below. Thus, we want to avoid printing 2460. * confusing, duplicate or out-of-order messages. 2461. * Use knowledge of the two routines as a hack -- this 2462. * should really be handled differently -dlc 2463. */ 2464. if(is_pool(u.ux,u.uy) && !Wwalking && !Swimming && !u.uinwater) 2465. no_msg = drown(); 2466. 2467. if(is_lava(u.ux,u.uy)) { 2468. (void) lava_effects(); 2469. no_msg = TRUE; 2470. } 2471. } 2472. if (!trap) { 2473. trap = t_at(u.ux,u.uy); 2474. if(Is_airlevel(&u.uz)) 2475. You("begin to tumble in place."); 2476. else if (Is_waterlevel(&u.uz) && !no_msg) 2477. You_feel("heavier."); 2478. /* u.uinwater msgs already in spoteffects()/drown() */ 2479. else if (!u.uinwater && !no_msg) { 2480. #ifdef STEED 2481. if (!(emask & W_SADDLE)) 2482. #endif 2483. { 2484. boolean sokoban_trap = (In_sokoban(&u.uz) && trap); 2485. if (Hallucination) 2486. pline("Bummer! You've %s.", 2487. is_pool(u.ux,u.uy) ? 2488. "splashed down" : sokoban_trap ? "crashed" : 2489. "hit the ground"); 2490. else { 2491. if (!sokoban_trap) 2492. You("float gently to the %s.", 2493. surface(u.ux, u.uy)); 2494. else { 2495. /* Justification elsewhere for Sokoban traps 2496. * is based on air currents. This is 2497. * consistent with that. 2498. * The unexpected additional force of the 2499. * air currents once leviation 2500. * ceases knocks you off your feet. 2501. */ 2502. You("fall over."); 2503. losehp(rnd(2), "dangerous winds", KILLED_BY); 2504. #ifdef STEED 2505. if (u.usteed) dismount_steed(DISMOUNT_FELL); 2506. #endif 2507. selftouch("As you fall, you"); 2508. } 2509. } 2510. } 2511. } 2512. } 2513. 2514. /* can't rely on u.uz0 for detecting trap door-induced level change; 2515. it gets changed to reflect the new level before we can check it */ 2516. assign_level(¤t_dungeon_level, &u.uz); 2517. 2518. if(trap) 2519. switch(trap->ttyp) { 2520. case STATUE_TRAP: 2521. break; 2522. case HOLE: 2523. case TRAPDOOR: 2524. if(!Can_fall_thru(&u.uz) || u.ustuck) 2525. break; 2526. /* fall into next case */ 2527. default: 2528. if (!u.utrap) /* not already in the trap */ 2529. dotrap(trap, 0); 2530. } 2531. 2532. if (!Is_airlevel(&u.uz) && !Is_waterlevel(&u.uz) && !u.uswallow && 2533. /* falling through trap door calls goto_level, 2534. and goto_level does its own pickup() call */ 2535. on_level(&u.uz, ¤t_dungeon_level)) 2536. (void) pickup(1); 2537. return 1; 2538. } 2539. 2540. STATIC_OVL void 2541. dofiretrap(box) 2542. struct obj *box; /* null for floor trap */ 2543. { 2544. boolean see_it = !Blind; 2545. int num, alt; 2546. 2547. /* Bug: for box case, the equivalent of burn_floor_paper() ought 2548. * to be done upon its contents. 2549. */ 2550. 2551. if ((box && !carried(box)) ? is_pool(box->ox, box->oy) : Underwater) { 2552. pline("A cascade of steamy bubbles erupts from %s!", 2553. the(box ? xname(box) : surface(u.ux,u.uy))); 2554. if (Fire_resistance) You("are uninjured."); 2555. else losehp(rnd(3), "boiling water", KILLED_BY); 2556. return; 2557. } 2558. pline("A %s %s from %s!", tower_of_flame, 2559. box ? "bursts" : "erupts", 2560. the(box ? xname(box) : surface(u.ux,u.uy))); 2561. if (Slimed) { 2562. pline("The slime that covers you is burned away!"); 2563. Slimed = 0; 2564. } 2565. if (Fire_resistance) { 2566. shieldeff(u.ux, u.uy); 2567. num = rn2(2); 2568. } else if (Upolyd) { 2569. num = d(2,4); 2570. switch (u.umonnum) { 2571. case PM_PAPER_GOLEM: alt = u.mhmax; break; 2572. case PM_STRAW_GOLEM: alt = u.mhmax / 2; break; 2573. case PM_WOOD_GOLEM: alt = u.mhmax / 4; break; 2574. case PM_LEATHER_GOLEM: alt = u.mhmax / 8; break; 2575. default: alt = 0; break; 2576. } 2577. if (alt > num) num = alt; 2578. if (u.mhmax > mons[u.umonnum].mlevel) 2579. u.mhmax -= rn2(min(u.mhmax,num + 1)), flags.botl = 1; 2580. } else { 2581. num = d(2,4); 2582. if (u.uhpmax > u.ulevel) 2583. u.uhpmax -= rn2(min(u.uhpmax,num + 1)), flags.botl = 1; 2584. } 2585. if (!num) 2586. You("are uninjured."); 2587. else 2588. losehp(num, tower_of_flame, KILLED_BY_AN); 2589. burn_away_slime(); 2590. 2591. if (burnarmor(&youmonst) || rn2(3)) { 2592. destroy_item(SCROLL_CLASS, AD_FIRE); 2593. destroy_item(SPBOOK_CLASS, AD_FIRE); 2594. destroy_item(POTION_CLASS, AD_FIRE); 2595. } 2596. if (!box && burn_floor_paper(u.ux, u.uy, see_it, TRUE) && !see_it) 2597. You("smell paper burning."); 2598. if (is_ice(u.ux, u.uy)) 2599. melt_ice(u.ux, u.uy); 2600. } 2601. 2602. STATIC_OVL void 2603. domagictrap() 2604. { 2605. register int fate = rnd(20); 2606. 2607. /* What happened to the poor sucker? */ 2608. 2609. if (fate < 10) { 2610. /* Most of the time, it creates some monsters. */ 2611. register int cnt = rnd(4); 2612. 2613. if (!resists_blnd(&youmonst)) { 2614. You("are momentarily blinded by a flash of light!"); 2615. make_blinded((long)rn1(5,10),FALSE); 2616. if (!Blind) Your(vision_clears); 2617. } else if (!Blind) { 2618. You("see a flash of light!"); 2619. } else 2620. You_hear("a deafening roar!"); 2621. while(cnt--) 2622. (void) makemon((struct permonst *) 0, u.ux, u.uy, NO_MM_FLAGS); 2623. } 2624. else 2625. switch (fate) { 2626. 2627. case 10: 2628. case 11: 2629. /* sometimes nothing happens */ 2630. break; 2631. case 12: /* a flash of fire */ 2632. dofiretrap((struct obj *)0); 2633. break; 2634. 2635. /* odd feelings */ 2636. case 13: pline("A shiver runs up and down your %s!", 2637. body_part(SPINE)); 2638. break; 2639. case 14: You_hear(Hallucination ? 2640. "the moon howling at you." : 2641. "distant howling."); 2642. break; 2643. case 15: if (on_level(&u.uz, &qstart_level)) 2644. You_feel("%slike the prodigal son.", 2645. (flags.female || (Upolyd && is_neuter(youmonst.data))) ? 2646. "oddly " : ""); 2647. else 2648. You("suddenly yearn for %s.", 2649. Hallucination ? "Cleveland" : 2650. (In_quest(&u.uz) || at_dgn_entrance("The Quest")) ? 2651. "your nearby homeland" : 2652. "your distant homeland"); 2653. break; 2654. case 16: 2655. { 2656. int dmg; 2657. 2658. Your("pack shakes violently!"); 2659. /* KMH, balance patch -- Idea by Wolfgang von Hansen */ 2660. dmg = jumble_pack(); 2661. if (dmg) 2662. losehp(dmg, "violence", KILLED_BY); 2663. break; 2664. } 2665. case 17: You(Hallucination ? 2666. "smell hamburgers." : 2667. "smell charred flesh."); 2668. break; 2669. case 18: You_feel("tired."); 2670. break; 2671. 2672. /* very occasionally something nice happens. */ 2673. 2674. case 19: 2675. /* tame nearby monsters */ 2676. { register int i,j; 2677. register struct monst *mtmp; 2678. 2679. (void) adjattrib(A_CHA,1,FALSE); 2680. for(i = -1; i <= 1; i++) for(j = -1; j <= 1; j++) { 2681. if(!isok(u.ux+i, u.uy+j)) continue; 2682. mtmp = m_at(u.ux+i, u.uy+j); 2683. if(mtmp) 2684. (void) tamedog(mtmp, (struct obj *)0); 2685. } 2686. break; 2687. } 2688. 2689. case 20: 2690. /* uncurse stuff */ 2691. { struct obj pseudo; 2692. long save_conf = HConfusion; 2693. 2694. pseudo = zeroobj; /* neither cursed nor blessed */ 2695. pseudo.otyp = SCR_REMOVE_CURSE; 2696. HConfusion = 0L; 2697. (void) seffects(&pseudo); 2698. HConfusion = save_conf; 2699. break; 2700. } 2701. default: break; 2702. } 2703. } 2704. 2705. /* 2706. * Scrolls, spellbooks, potions, and flammable items 2707. * may get affected by the fire. 2708. * 2709. * Return number of objects destroyed. --ALI 2710. */ 2711. int 2712. fire_damage(chain, force, here, x, y) 2713. struct obj *chain; 2714. boolean force, here; 2715. xchar x, y; 2716. { 2717. int chance; 2718. struct obj *obj, *otmp, *nobj, *ncobj; 2719. int retval = 0; 2720. int in_sight = !Blind && couldsee(x, y); /* Don't care if it's lit */ 2721. int dindx; 2722. 2723. for (obj = chain; obj; obj = nobj) { 2724. nobj = here ? obj->nexthere : obj->nobj; 2725. 2726. /* object might light in a controlled manner */ 2727. if (catch_lit(obj)) 2728. continue; 2729. 2730. if (Is_container(obj)) { 2731. switch (obj->otyp) { 2732. case ICE_BOX: 2733. continue; /* Immune */ 2734. /*NOTREACHED*/ 2735. break; 2736. case CHEST: 2737. chance = 40; 2738. break; 2739. case LARGE_BOX: 2740. chance = 30; 2741. break; 2742. default: 2743. chance = 20; 2744. break; 2745. } 2746. if (!force && (Luck + 5) > rn2(chance)) 2747. continue; 2748. /* Container is burnt up - dump contents out */ 2749. if (in_sight) pline("%s catches fire and burns.", Yname2(obj)); 2750. if (Has_contents(obj)) { 2751. if (in_sight) pline("Its contents fall out."); 2752. for (otmp = obj->cobj; otmp; otmp = ncobj) { 2753. ncobj = otmp->nobj; 2754. obj_extract_self(otmp); 2755. if (!flooreffects(otmp, x, y, "")) 2756. place_object(otmp, x, y); 2757. } 2758. } 2759. delobj(obj); 2760. retval++; 2761. } else if (!force && (Luck + 5) > rn2(20)) { 2762. /* chance per item of sustaining damage: 2763. * max luck (full moon): 5% 2764. * max luck (elsewhen): 10% 2765. * avg luck (Luck==0): 75% 2766. * awful luck (Luck<-4): 100% 2767. */ 2768. continue; 2769. } else if (obj->oclass == SCROLL_CLASS || obj->oclass == SPBOOK_CLASS) { 2770. if (obj->otyp == SCR_FIRE || obj->otyp == SPE_FIREBALL) 2771. continue; 2772. if (obj->otyp == SPE_BOOK_OF_THE_DEAD) { 2773. if (in_sight) pline("Smoke rises from %s.", the(xname(obj))); 2774. continue; 2775. } 2776. dindx = (obj->oclass == SCROLL_CLASS) ? 2 : 3; 2777. if (in_sight) 2778. pline("%s %s.", Yname2(obj), (obj->quan > 1) ? 2779. destroy_strings[dindx*3 + 1] : destroy_strings[dindx*3]); 2780. delobj(obj); 2781. retval++; 2782. } else if (obj->oclass == POTION_CLASS) { 2783. dindx = 1; 2784. if (in_sight) 2785. pline("%s %s.", Yname2(obj), (obj->quan > 1) ? 2786. destroy_strings[dindx*3 + 1] : destroy_strings[dindx*3]); 2787. delobj(obj); 2788. retval++; 2789. } else if (is_flammable(obj) && obj->oeroded < MAX_ERODE && 2790. !(obj->oerodeproof || (obj->blessed && !rnl(4)))) { 2791. if (in_sight) { 2792. pline("%s %s%s.", Yname2(obj), otense(obj, "burn"), 2793. obj->oeroded+1 == MAX_ERODE ? " completely" : 2794. obj->oeroded ? " further" : ""); 2795. } 2796. obj->oeroded++; 2797. } 2798. } 2799. 2800. if (retval && !in_sight) 2801. You("smell smoke."); 2802. return retval; 2803. } 2804. 2805. void 2806. water_damage(obj, force, here) 2807. register struct obj *obj; 2808. register boolean force, here; 2809. { 2810. /* Dips in the Lethe are a very poor idea */ 2811. int luckpenalty = level.flags.lethe? 7 : 0; 2812. struct obj *otmp; 2813. 2814. /* Scrolls, spellbooks, potions, weapons and 2815. pieces of armor may get affected by the water */ 2816. for (; obj; obj = otmp) { 2817. otmp = here ? obj->nexthere : obj->nobj; 2818. 2819. (void) snuff_lit(obj); 2820. 2821. if(obj->otyp == CAN_OF_GREASE && obj->spe > 0) { 2822. continue; 2823. } else if(obj->greased) { 2824. if (force || !rn2(2)) obj->greased = 0; 2825. } else if(Is_container(obj) && !Is_box(obj) && 2826. (obj->otyp != OILSKIN_SACK || (obj->cursed && !rn2(3)))) { 2827. water_damage(obj->cobj, force, FALSE); 2828. } else if (!force && (Luck - luckpenalty + 5) > rn2(20)) { 2829. /* chance per item of sustaining damage: 2830. * max luck (full moon): 5% 2831. * max luck (elsewhen): 10% 2832. * avg luck (Luck==0): 75% 2833. * awful luck (Luck<-4): 100% 2834. * If this is the Lethe, things are much worse. 2835. */ 2836. continue; 2837. /* An oil skin cloak protects your body armor */ 2838. } else if( obj->oclass == ARMOR_CLASS 2839. && obj == uarm 2840. && uarmc 2841. && uarmc->otyp == OILSKIN_CLOAK 2842. && (!uarmc->cursed || rn2(3))) { 2843. continue; 2844. } else { 2845. /* The Lethe strips blessed and cursed status... */ 2846. if (level.flags.lethe) { 2847. uncurse(obj); 2848. unbless(obj); 2849. } 2850. 2851. switch (obj->oclass) { 2852. case SCROLL_CLASS: 2853. #ifdef MAIL 2854. if (obj->otyp != SCR_MAIL) 2855. #endif 2856. { 2857. /* The Lethe sometimes does a little rewrite */ 2858. obj->otyp = (level.flags.lethe && !rn2(10)) ? 2859. SCR_AMNESIA : SCR_BLANK_PAPER; 2860. obj->spe = 0; 2861. } 2862. break; 2863. case SPBOOK_CLASS: 2864. /* Spell books get blanked... */ 2865. if (obj->otyp == SPE_BOOK_OF_THE_DEAD) 2866. pline("Steam rises from %s.", the(xname(obj))); 2867. else obj->otyp = SPE_BLANK_PAPER; 2868. break; 2869. case POTION_CLASS: 2870. if (obj->otyp == POT_ACID) { 2871. /* damage player/monster? */ 2872. pline("A potion explodes!"); 2873. delobj(obj); 2874. continue; 2875. } else 2876. /* Potions turn to water or amnesia... */ 2877. if (level.flags.lethe) { 2878. if (obj->otyp == POT_WATER) 2879. obj->otyp = POT_AMNESIA; 2880. else if (obj->otyp != POT_AMNESIA) { 2881. obj->otyp = POT_WATER; 2882. obj->odiluted = 0; 2883. } 2884. } else if (obj->odiluted || obj->otyp == POT_AMNESIA) { 2885. obj->otyp = POT_WATER; 2886. obj->blessed = obj->cursed = 0; 2887. obj->odiluted = 0; 2888. } else if (obj->otyp != POT_WATER) 2889. obj->odiluted++; 2890. break; 2891. case GEM_CLASS: 2892. if (level.flags.lethe && (obj->otyp == LUCKSTONE 2893. || obj->otyp == LOADSTONE 2894. || obj->otyp == HEALTHSTONE 2895. || obj->otyp == TOUCHSTONE)) 2896. obj->otyp = FLINT; 2897. break; 2898. case TOOL_CLASS: 2899. if (level.flags.lethe) { 2900. switch (obj->otyp) { 2901. case MAGIC_LAMP: 2902. obj->otyp = OIL_LAMP; 2903. break; 2904. case MAGIC_CANDLE: 2905. obj->otyp = rn2(2)? WAX_CANDLE : TALLOW_CANDLE; 2906. break; 2907. case MAGIC_WHISTLE: 2908. obj->otyp = TIN_WHISTLE; 2909. break; 2910. case MAGIC_FLUTE: 2911. obj->otyp = WOODEN_FLUTE; 2912. obj->spe = 0; 2913. break; 2914. case MAGIC_HARP: 2915. obj->otyp = WOODEN_HARP; 2916. obj->spe = 0; 2917. break; 2918. case FIRE_HORN: 2919. case FROST_HORN: 2920. case HORN_OF_PLENTY: 2921. obj->otyp = TOOLED_HORN; 2922. obj->spe = 0; 2923. break; 2924. case DRUM_OF_EARTHQUAKE: 2925. obj->otyp = LEATHER_DRUM; 2926. obj->spe = 0; 2927. break; 2928. } 2929. } 2930. 2931. /* Drop through */ 2932. /* Weapons, armor and tools may be disenchanted... */ 2933. /* Wands and rings lose a charge... */ 2934. case WEAPON_CLASS: 2935. case ARMOR_CLASS: 2936. case WAND_CLASS: 2937. case RING_CLASS: 2938. if ( level.flags.lethe 2939. && ( obj->oclass == WEAPON_CLASS 2940. || obj->oclass == ARMOR_CLASS 2941. || obj->oclass == WAND_CLASS 2942. || obj->oclass == RING_CLASS 2943. || is_weptool(obj) )) { 2944. 2945. /* Shift enchantment one step closer to 0 */ 2946. if (obj->spe > 0) drain_item(obj); 2947. } 2948. 2949. /* Magic markers run... */ 2950. if ( level.flags.lethe 2951. && obj->otyp == MAGIC_MARKER ) { 2952. obj->spe -= (3 + rn2(10)); 2953. if (obj->spe < 0) obj->spe = 0; 2954. } 2955. 2956. /* Drop through for rusting effects... */ 2957. /* Weapons, armor, tools and other things may rust... */ 2958. default: 2959. if (is_rustprone(obj) && obj->oeroded < MAX_ERODE && 2960. !(obj->oerodeproof || 2961. (obj->blessed && !rnl(4)))) 2962. obj->oeroded++; 2963. /* The Lethe may unfooproof the item... */ 2964. if (level.flags.lethe 2965. && obj->oerodeproof && !rn2(5)) 2966. obj->oerodeproof = FALSE; 2967. } 2968. } 2969. } 2970. } 2971. 2972. /* 2973. * This function is potentially expensive - rolling 2974. * inventory list multiple times. Luckily it's seldom needed. 2975. * Returns TRUE if disrobing made player unencumbered enough to 2976. * crawl out of the current predicament. 2977. */ 2978. STATIC_OVL boolean 2979. emergency_disrobe(lostsome) 2980. boolean *lostsome; 2981. { 2982. int invc = inv_cnt(); 2983. 2984. while (near_capacity() > (Punished ? UNENCUMBERED : SLT_ENCUMBER)) { 2985. register struct obj *obj, *otmp = (struct obj *)0; 2986. register int i; 2987. 2988. /* Pick a random object */ 2989. if (invc > 0) { 2990. i = rn2(invc); 2991. for (obj = invent; obj; obj = obj->nobj) { 2992. /* 2993. * Undroppables are: body armor, boots, gloves, 2994. * amulets, and rings because of the time and effort 2995. * in removing them + loadstone and other cursed stuff 2996. * for obvious reasons. 2997. */ 2998. if (!((obj->otyp == LOADSTONE && obj->cursed) || 2999. obj == uamul || obj == uleft || obj == uright || 3000. obj == ublindf || obj == uarm || obj == uarmc || 3001. obj == uarmg || obj == uarmf || 3002. #ifdef TOURIST 3003. obj == uarmu || 3004. #endif 3005. (obj->cursed && (obj == uarmh || obj == uarms)) || 3006. welded(obj))) 3007. otmp = obj; 3008. /* reached the mark and found some stuff to drop? */ 3009. if (--i < 0 && otmp) break; 3010. 3011. /* else continue */ 3012. } 3013. } 3014. #ifndef GOLDOBJ 3015. if (!otmp) { 3016. /* Nothing available left to drop; try gold */ 3017. if (u.ugold) { 3018. pline("In desperation, you drop your purse."); 3019. /* Hack: gold is not in the inventory, so make a gold object 3020. * and put it at the head of the inventory list. 3021. */ 3022. obj = mkgoldobj(u.ugold); /* removes from u.ugold */ 3023. obj->in_use = TRUE; 3024. u.ugold = obj->quan; /* put the gold back */ 3025. assigninvlet(obj); /* might end up as NOINVSYM */ 3026. obj->nobj = invent; 3027. invent = obj; 3028. *lostsome = TRUE; 3029. dropx(obj); 3030. continue; /* Try again */ 3031. } 3032. /* We can't even drop gold! */ 3033. return (FALSE); 3034. } 3035. #else 3036. if (!otmp) return (FALSE); /* nothing to drop! */ 3037. #endif 3038. if (otmp->owornmask) remove_worn_item(otmp, FALSE); 3039. *lostsome = TRUE; 3040. dropx(otmp); 3041. invc--; 3042. } 3043. return(TRUE); 3044. } 3045. 3046. /* 3047. * return(TRUE) == player relocated 3048. */ 3049. boolean 3050. drown() 3051. { 3052. boolean inpool_ok = FALSE, crawl_ok; 3053. int i, x, y; 3054. const char *sparkle = level.flags.lethe? "sparkling " : ""; 3055. 3056. /* happily wading in the same contiguous pool */ 3057. if (u.uinwater && is_pool(u.ux-u.dx,u.uy-u.dy) && 3058. (Swimming || Amphibious)) { 3059. /* water effects on objects every now and then */ 3060. if (!rn2(5)) inpool_ok = TRUE; 3061. else return(FALSE); 3062. } 3063. 3064. if (!u.uinwater) { 3065. You("%s into the %swater%c", 3066. Is_waterlevel(&u.uz) ? "plunge" : "fall", 3067. sparkle, 3068. Amphibious || Swimming ? '.' : '!'); 3069. if (!Swimming && !Is_waterlevel(&u.uz)) 3070. You("sink like %s.", 3071. Hallucination ? "the Titanic" : "a rock"); 3072. } 3073. 3074. if (level.flags.lethe) { 3075. /* Bad idea */ 3076. You_feel("the sparkling waters of the Lethe sweep away your " 3077. "cares!"); 3078. forget(25); 3079. } 3080. 3081. water_damage(invent, FALSE, FALSE); 3082. 3083. if (u.umonnum == PM_GREMLIN && rn2(3)) 3084. (void)split_mon(&youmonst, (struct monst *)0); 3085. else if (u.umonnum == PM_IRON_GOLEM) { 3086. You("rust!"); 3087. i = d(2,6); 3088. if (u.mhmax > i) u.mhmax -= i; 3089. losehp(i, "rusting away", KILLED_BY); 3090. } 3091. if (inpool_ok) return(FALSE); 3092. 3093. if ((i = number_leashed()) > 0) { 3094. pline_The("leash%s slip%s loose.", 3095. (i > 1) ? "es" : "", 3096. (i > 1) ? "" : "s"); 3097. unleash_all(); 3098. } 3099. 3100. if (Amphibious || Swimming) { 3101. if (Amphibious) { 3102. if (flags.verbose) 3103. pline("But you aren't drowning."); 3104. if (!Is_waterlevel(&u.uz)) { 3105. if (Hallucination) 3106. Your("keel hits the bottom."); 3107. else 3108. You("touch bottom."); 3109. } 3110. } 3111. if (Punished) { 3112. unplacebc(); 3113. placebc(); 3114. } 3115. vision_recalc(2); /* unsee old position */ 3116. u.uinwater = 1; 3117. under_water(1); 3118. vision_full_recalc = 1; 3119. return(FALSE); 3120. } 3121. else if (Swimming && !Is_waterlevel(&u.uz)) { 3122. if (Punished) { 3123. unplacebc(); 3124. placebc(); 3125. } 3126. u.uinwater = 1; 3127. under_water(1); 3128. vision_full_recalc = 1; 3129. return(FALSE); 3130. } 3131. if ((Teleportation || can_teleport(youmonst.data)) && 3132. !u.usleep && (Teleport_control || rn2(3) < Luck+2)) { 3133. You("attempt a teleport spell."); /* utcsri!carroll */ 3134. if (!level.flags.noteleport) { 3135. (void) dotele(); 3136. if(!is_pool(u.ux,u.uy)) 3137. return(TRUE); 3138. } else pline_The("attempted teleport spell fails."); 3139. } 3140. #ifdef STEED 3141. if (u.usteed) { 3142. dismount_steed(DISMOUNT_GENERIC); 3143. if(!is_pool(u.ux,u.uy)) 3144. return(TRUE); 3145. } 3146. #endif 3147. crawl_ok = FALSE; 3148. x = y = 0; /* lint suppression */ 3149. /* if sleeping, wake up now so that we don't crawl out of water 3150. while still asleep; we can't do that the same way that waking 3151. due to combat is handled; note unmul() clears u.usleep */ 3152. if (u.usleep) unmul("Suddenly you wake up!"); 3153. /* can't crawl if unable to move (crawl_ok flag stays false) */ 3154. if (multi < 0 || (Upolyd && !youmonst.data->mmove)) goto crawl; 3155. /* look around for a place to crawl to */ 3156. for (i = 0; i < 100; i++) { 3157. x = rn1(3,u.ux - 1); 3158. y = rn1(3,u.uy - 1); 3159. if (goodpos(x, y, &youmonst, 0)) { 3160. crawl_ok = TRUE; 3161. goto crawl; 3162. } 3163. } 3164. /* one more scan */ 3165. for (x = u.ux - 1; x <= u.ux + 1; x++) 3166. for (y = u.uy - 1; y <= u.uy + 1; y++) 3167. if (goodpos(x, y, &youmonst, 0)) { 3168. crawl_ok = TRUE; 3169. goto crawl; 3170. } 3171. crawl: 3172. if (crawl_ok) { 3173. boolean lost = FALSE; 3174. /* time to do some strip-tease... */ 3175. boolean succ = Is_waterlevel(&u.uz) ? TRUE : 3176. emergency_disrobe(&lost); 3177. 3178. You("try to crawl out of the water."); 3179. if (lost) 3180. You("dump some of your gear to lose weight..."); 3181. if (succ) { 3182. pline("Pheew! That was close."); 3183. teleds(x,y,TRUE); 3184. return(TRUE); 3185. } 3186. /* still too much weight */ 3187. pline("But in vain."); 3188. } 3189. u.uinwater = 1; 3190. You("drown."); 3191. /* [ALI] Vampires return to vampiric form on drowning. 3192. */ 3193. if (Upolyd && !Unchanging && Race_if(PM_VAMPIRE)) { 3194. rehumanize(); 3195. u.uinwater = 0; 3196. You("fly up out of the water!"); 3197. return (TRUE); 3198. } 3199. killer_format = KILLED_BY_AN; 3200. killer = (levl[u.ux][u.uy].typ == POOL || Is_medusa_level(&u.uz)) ? 3201. "pool of water" : "moat"; 3202. done(DROWNING); 3203. /* oops, we're still alive. better get out of the water. */ 3204. while (!safe_teleds(TRUE)) { 3205. pline("You're still drowning."); 3206. done(DROWNING); 3207. } 3208. if (u.uinwater) { 3209. u.uinwater = 0; 3210. You("find yourself back %s.", Is_waterlevel(&u.uz) ? 3211. "in an air bubble" : "on land"); 3212. } 3213. return(TRUE); 3214. 3215. } 3216. 3217. void 3218. drain_en(n) 3219. register int n; 3220. { 3221. if (!u.uenmax) return; 3222. You_feel("your magical energy drain away!"); 3223. u.uen -= n; 3224. if(u.uen < 0) { 3225. u.uenmax += u.uen; 3226. if(u.uenmax < 0) u.uenmax = 0; 3227. u.uen = 0; 3228. } 3229. flags.botl = 1; 3230. } 3231. 3232. int 3233. dountrap() /* disarm a trap */ 3234. { 3235. if (near_capacity() >= HVY_ENCUMBER) { 3236. pline("You're too strained to do that."); 3237. return 0; 3238. } 3239. if ((nohands(youmonst.data) && !webmaker(youmonst.data)) || !youmonst.data->mmove) { 3240. pline("And just how do you expect to do that?"); 3241. return 0; 3242. } else if (u.ustuck && sticks(youmonst.data)) { 3243. pline("You'll have to let go of %s first.", mon_nam(u.ustuck)); 3244. return 0; 3245. } 3246. if (u.ustuck || (welded(uwep) && bimanual(uwep))) { 3247. Your("%s seem to be too busy for that.", 3248. makeplural(body_part(HAND))); 3249. return 0; 3250. } 3251. return untrap(FALSE); 3252. } 3253. #endif /* OVLB */ 3254. #ifdef OVL2 3255. 3256. /* Probability of disabling a trap. Helge Hafting */ 3257. STATIC_OVL int 3258. untrap_prob(ttmp) 3259. struct trap *ttmp; 3260. { 3261. int chance = 3; 3262. 3263. /* Only spiders know how to deal with webs reliably */ 3264. if (ttmp->ttyp == WEB && !webmaker(youmonst.data)) 3265. chance = 30; 3266. if (Confusion || Hallucination) chance++; 3267. if (Blind) chance++; 3268. if (Stunned) chance += 2; 3269. if (Fumbling) chance *= 2; 3270. /* Your own traps are better known than others. */ 3271. if (ttmp && ttmp->madeby_u) chance--; 3272. if (Role_if(PM_ROGUE)) { 3273. if (rn2(2 * MAXULEV) < u.ulevel) chance--; 3274. if (u.uhave.questart && chance > 1) chance--; 3275. } else if (Role_if(PM_RANGER) && chance > 1) chance--; 3276. return rn2(chance); 3277. } 3278. 3279. /* Replace trap with object(s). Helge Hafting */ 3280. STATIC_OVL void 3281. cnv_trap_obj(otyp, cnt, ttmp) 3282. int otyp; 3283. int cnt; 3284. struct trap *ttmp; 3285. { 3286. struct obj *otmp = mksobj(otyp, TRUE, FALSE); 3287. /* [ALI] Only dart traps are capable of being poisonous */ 3288. if (otyp != DART) 3289. otmp->opoisoned = 0; 3290. otmp->quan=cnt; 3291. otmp->owt = weight(otmp); 3292. /* Only dart traps are capable of being poisonous */ 3293. if (otyp != DART) 3294. otmp->opoisoned = 0; 3295. place_object(otmp, ttmp->tx, ttmp->ty); 3296. /* Sell your own traps only... */ 3297. if (ttmp->madeby_u) sellobj(otmp, ttmp->tx, ttmp->ty); 3298. stackobj(otmp); 3299. newsym(ttmp->tx, ttmp->ty); 3300. deltrap(ttmp); 3301. } 3302. 3303. /* while attempting to disarm an adjacent trap, we've fallen into it */ 3304. STATIC_OVL void 3305. move_into_trap(ttmp) 3306. struct trap *ttmp; 3307. { 3308. int bc; 3309. xchar x = ttmp->tx, y = ttmp->ty, bx, by, cx, cy; 3310. boolean unused; 3311. 3312. /* we know there's no monster in the way, and we're not trapped */ 3313. if (!Punished || drag_ball(x, y, &bc, &bx, &by, &cx, &cy, &unused, 3314. TRUE)) { 3315. u.ux0 = u.ux, u.uy0 = u.uy; 3316. u.ux = x, u.uy = y; 3317. u.umoved = TRUE; 3318. newsym(u.ux0, u.uy0); 3319. vision_recalc(1); 3320. check_leash(u.ux0, u.uy0); 3321. if (Punished) move_bc(0, bc, bx, by, cx, cy); 3322. spoteffects(FALSE); /* dotrap() */ 3323. exercise(A_WIS, FALSE); 3324. } 3325. } 3326. 3327. /* 0: doesn't even try 3328. * 1: tries and fails 3329. * 2: succeeds 3330. */ 3331. STATIC_OVL int 3332. try_disarm(ttmp, force_failure) 3333. struct trap *ttmp; 3334. boolean force_failure; 3335. { 3336. struct monst *mtmp = m_at(ttmp->tx,ttmp->ty); 3337. int ttype = ttmp->ttyp; 3338. boolean under_u = (!u.dx && !u.dy); 3339. boolean holdingtrap = (ttype == BEAR_TRAP || ttype == WEB); 3340. 3341. /* Test for monster first, monsters are displayed instead of trap. */ 3342. if (mtmp && (!mtmp->mtrapped || !holdingtrap)) { 3343. pline("%s is in the way.", Monnam(mtmp)); 3344. return 0; 3345. } 3346. /* We might be forced to move onto the trap's location. */ 3347. if (sobj_at(BOULDER, ttmp->tx, ttmp->ty) 3348. && !Passes_walls && !under_u) { 3349. There("is a boulder in your way."); 3350. return 0; 3351. } 3352. /* duplicate tight-space checks from test_move */ 3353. if (u.dx && u.dy && 3354. bad_rock(&youmonst, u.ux, ttmp->ty) && 3355. bad_rock(&youmonst, ttmp->tx, u.uy)) { 3356. if ((invent && (inv_weight() + weight_cap() > 600)) || 3357. bigmonst(youmonst.data)) { 3358. /* don't allow untrap if they can't get thru to it */ 3359. You("are unable to reach the %s!", 3360. defsyms[trap_to_defsym(ttype)].explanation); 3361. return 0; 3362. } 3363. } 3364. /* untrappable traps are located on the ground. */ 3365. if (!can_reach_floor()) { 3366. #ifdef STEED 3367. if (u.usteed && P_SKILL(P_RIDING) < P_BASIC) 3368. You("aren't skilled enough to reach from %s.", 3369. mon_nam(u.usteed)); 3370. else 3371. #endif 3372. You("are unable to reach the %s!", 3373. defsyms[trap_to_defsym(ttype)].explanation); 3374. return 0; 3375. } 3376. 3377. /* Will our hero succeed? */ 3378. if (force_failure || untrap_prob(ttmp)) { 3379. if (rnl(5)) { 3380. pline("Whoops..."); 3381. if (mtmp) { /* must be a trap that holds monsters */ 3382. if (ttype == BEAR_TRAP) { 3383. if (mtmp->mtame) abuse_dog(mtmp); 3384. if ((mtmp->mhp -= rnd(4)) <= 0) killed(mtmp); 3385. } else if (ttype == WEB) { 3386. if (!webmaker(youmonst.data)) { 3387. struct trap *ttmp2 = maketrap(u.ux, u.uy, WEB); 3388. if (ttmp2) { 3389. pline_The("webbing sticks to you. You're caught too!"); 3390. dotrap(ttmp2, NOWEBMSG); 3391. #ifdef STEED 3392. if (u.usteed && u.utrap) { 3393. /* you, not steed, are trapped */ 3394. dismount_steed(DISMOUNT_FELL); 3395. } 3396. #endif 3397. } 3398. } else 3399. pline("%s remains entangled.", Monnam(mtmp)); 3400. } 3401. } else if (under_u) { 3402. dotrap(ttmp, 0); 3403. } else { 3404. move_into_trap(ttmp); 3405. } 3406. } else { 3407. pline("%s %s is difficult to %s.", 3408. ttmp->madeby_u ? "Your" : under_u ? "This" : "That", 3409. defsyms[trap_to_defsym(ttype)].explanation, 3410. (ttype == WEB) ? "remove" : "disarm"); 3411. } 3412. return 1; 3413. } 3414. return 2; 3415. } 3416. 3417. STATIC_OVL void 3418. reward_untrap(ttmp, mtmp) 3419. struct trap *ttmp; 3420. struct monst *mtmp; 3421. { 3422. if (!ttmp->madeby_u) { 3423. if (rnl(10) < 8 && !mtmp->mpeaceful && 3424. !mtmp->msleeping && !mtmp->mfrozen && 3425. !mindless(mtmp->data) && 3426. mtmp->data->mlet != S_HUMAN) { 3427. mtmp->mpeaceful = 1; 3428. set_malign(mtmp); /* reset alignment */ 3429. pline("%s is grateful.", Monnam(mtmp)); 3430. } 3431. /* Helping someone out of a trap is a nice thing to do, 3432. * A lawful may be rewarded, but not too often. */ 3433. if (!rn2(3) && !rnl(8) && u.ualign.type == A_LAWFUL) { 3434. adjalign(1); 3435. You_feel("that you did the right thing."); 3436. } 3437. } 3438. } 3439. 3440. STATIC_OVL int 3441. disarm_holdingtrap(ttmp) /* Helge Hafting */ 3442. struct trap *ttmp; 3443. { 3444. struct monst *mtmp; 3445. int fails = try_disarm(ttmp, FALSE); 3446. 3447. if (fails < 2) return fails; 3448. 3449. /* ok, disarm it. */ 3450. 3451. /* untrap the monster, if any. 3452. There's no need for a cockatrice test, only the trap is touched */ 3453. if ((mtmp = m_at(ttmp->tx,ttmp->ty)) != 0) { 3454. mtmp->mtrapped = 0; 3455. You("remove %s %s from %s.", the_your[ttmp->madeby_u], 3456. (ttmp->ttyp == BEAR_TRAP) ? "bear trap" : "webbing", 3457. mon_nam(mtmp)); 3458. reward_untrap(ttmp, mtmp); 3459. } else { 3460. if (ttmp->ttyp == BEAR_TRAP) { 3461. You("disarm %s bear trap.", the_your[ttmp->madeby_u]); 3462. cnv_trap_obj(BEARTRAP, 1, ttmp); 3463. } else /* if (ttmp->ttyp == WEB) */ { 3464. You("succeed in removing %s web.", the_your[ttmp->madeby_u]); 3465. deltrap(ttmp); 3466. } 3467. } 3468. newsym(u.ux + u.dx, u.uy + u.dy); 3469. return 1; 3470. } 3471. 3472. STATIC_OVL int 3473. disarm_landmine(ttmp) /* Helge Hafting */ 3474. struct trap *ttmp; 3475. { 3476. int fails = try_disarm(ttmp, FALSE); 3477. 3478. if (fails < 2) return fails; 3479. You("disarm %s land mine.", the_your[ttmp->madeby_u]); 3480. cnv_trap_obj(LAND_MINE, 1, ttmp); 3481. return 1; 3482. } 3483. 3484. STATIC_OVL int 3485. disarm_rust_trap(ttmp) /* Paul Sonier */ 3486. struct trap *ttmp; 3487. { 3488. xchar trapx = ttmp->tx, trapy = ttmp->ty; 3489. int fails = try_disarm(ttmp, FALSE); 3490. 3491. if (fails < 2) return fails; 3492. You("disarm the water trap!"); 3493. deltrap(ttmp); 3494. levl[trapx][trapy].typ = FOUNTAIN; 3495. newsym(trapx, trapy); 3496. level.flags.nfountains++; 3497. return 1; 3498. } 3499. 3500. /* getobj will filter down to cans of grease and known potions of oil */ 3501. 3502. static NEARDATA const char oil[] = { ALL_CLASSES, TOOL_CLASS, POTION_CLASS, 0 }; 3503. static NEARDATA const char disarmpotion[] = { ALL_CLASSES, POTION_CLASS, 0 }; 3504. 3505. /* water disarms, oil will explode */ 3506. STATIC_OVL int 3507. disarm_fire_trap(ttmp) /* Paul Sonier */ 3508. struct trap *ttmp; 3509. { 3510. int fails; 3511. struct obj *obj; 3512. boolean bad_tool; 3513. 3514. obj = getobj(disarmpotion, "untrap with"); 3515. if (!obj) return 0; 3516. 3517. if (obj->otyp == POT_OIL) 3518. { 3519. Your("potion of oil explodes!"); 3520. splatter_burning_oil(ttmp->tx,ttmp->ty); 3521. delobj(obj); 3522. return 1; 3523. } 3524. 3525. bad_tool = (obj->cursed || 3526. (obj->otyp != POT_WATER)); 3527. fails = try_disarm(ttmp, bad_tool); 3528. if (fails < 2) return fails; 3529. 3530. useup(obj); 3531. makeknown(POT_WATER); 3532. You("manage to extinguish the pilot light!"); 3533. cnv_trap_obj(POT_OIL, 4 - rnl(4), ttmp); 3534. more_experienced(1, 5); 3535. newexplevel(); 3536. return 1; 3537. } 3538. 3539. /* it may not make much sense to use grease on floor boards, but so what? */ 3540. STATIC_OVL int 3541. disarm_squeaky_board(ttmp) 3542. struct trap *ttmp; 3543. { 3544. struct obj *obj; 3545. boolean bad_tool; 3546. int fails, trapx = ttmp->tx, trapy = ttmp->ty; 3547. 3548. obj = getobj(oil, "untrap with"); 3549. if (!obj) return 0; 3550. 3551. bad_tool = (obj->cursed || 3552. ((obj->otyp != POT_OIL || obj->lamplit) && 3553. (obj->otyp != CAN_OF_GREASE || !obj->spe))); 3554. 3555. fails = try_disarm(ttmp, bad_tool); 3556. if (fails < 2) return fails; 3557. 3558. /* successfully used oil or grease to fix squeaky board */ 3559. if (obj->otyp == CAN_OF_GREASE) { 3560. consume_obj_charge(obj, TRUE); 3561. } else { 3562. useup(obj); /* oil */ 3563. makeknown(POT_OIL); 3564. } 3565. You("repair the squeaky board."); /* no madeby_u */ 3566. deltrap(ttmp); 3567. newsym(trapx, trapy); 3568. more_experienced(1, 5); 3569. return 1; 3570. } 3571. 3572. /* removes traps that shoot arrows, darts, etc. */ 3573. STATIC_OVL int 3574. disarm_shooting_trap(ttmp, otyp) 3575. struct trap *ttmp; 3576. int otyp; 3577. { 3578. int fails = try_disarm(ttmp, FALSE); 3579. 3580. if (fails < 2) return fails; 3581. You("disarm %s trap.", the_your[ttmp->madeby_u]); 3582. cnv_trap_obj(otyp, 50-rnl(50), ttmp); 3583. return 1; 3584. } 3585. 3586. /* Is the weight too heavy? 3587. * Formula as in near_capacity() & check_capacity() */ 3588. STATIC_OVL int 3589. try_lift(mtmp, ttmp, wt, stuff) 3590. struct monst *mtmp; 3591. struct trap *ttmp; 3592. int wt; 3593. boolean stuff; 3594. { 3595. int wc = weight_cap(); 3596. 3597. if (((wt * 2) / wc) >= HVY_ENCUMBER) { 3598. pline("%s is %s for you to lift.", Monnam(mtmp), 3599. stuff ? "carrying too much" : "too heavy"); 3600. if (!ttmp->madeby_u && !mtmp->mpeaceful && mtmp->mcanmove && 3601. !mindless(mtmp->data) && 3602. mtmp->data->mlet != S_HUMAN && rnl(10) < 3) { 3603. mtmp->mpeaceful = 1; 3604. set_malign(mtmp); /* reset alignment */ 3605. pline("%s thinks it was nice of you to try.", Monnam(mtmp)); 3606. } 3607. return 0; 3608. } 3609. return 1; 3610. } 3611. 3612. /* Help trapped monster (out of a (spiked) pit) */ 3613. STATIC_OVL int 3614. help_monster_out(mtmp, ttmp) 3615. struct monst *mtmp; 3616. struct trap *ttmp; 3617. { 3618. int wt; 3619. struct obj *otmp; 3620. boolean uprob; 3621. 3622. /* 3623. * This works when levitating too -- consistent with the ability 3624. * to hit monsters while levitating. 3625. * 3626. * Should perhaps check that our hero has arms/hands at the 3627. * moment. Helping can also be done by engulfing... 3628. * 3629. * Test the monster first - monsters are displayed before traps. 3630. */ 3631. if (!mtmp->mtrapped) { 3632. pline("%s isn't trapped.", Monnam(mtmp)); 3633. return 0; 3634. } 3635. /* Do you have the necessary capacity to lift anything? */ 3636. if (check_capacity((char *)0)) return 1; 3637. 3638. /* Will our hero succeed? */ 3639. if ((uprob = untrap_prob(ttmp)) && !mtmp->msleeping && mtmp->mcanmove) { 3640. You("try to reach out your %s, but %s backs away skeptically.", 3641. makeplural(body_part(ARM)), 3642. mon_nam(mtmp)); 3643. return 1; 3644. } 3645. 3646. 3647. /* is it a cockatrice?... */ 3648. if (touch_petrifies(mtmp->data) && !uarmg && !Stone_resistance) { 3649. You("grab the trapped %s using your bare %s.", 3650. mtmp->data->mname, makeplural(body_part(HAND))); 3651. 3652. if (poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM)) 3653. display_nhwindow(WIN_MESSAGE, FALSE); 3654. else { 3655. char kbuf[BUFSZ]; 3656. 3657. Sprintf(kbuf, "trying to help %s out of a pit", 3658. an(mtmp->data->mname)); 3659. instapetrify(kbuf); 3660. return 1; 3661. } 3662. } 3663. /* need to do cockatrice check first if sleeping or paralyzed */ 3664. if (uprob) { 3665. You("try to grab %s, but cannot get a firm grasp.", 3666. mon_nam(mtmp)); 3667. if (mtmp->msleeping) { 3668. mtmp->msleeping = 0; 3669. pline("%s awakens.", Monnam(mtmp)); 3670. } 3671. return 1; 3672. } 3673. 3674. You("reach out your %s and grab %s.", 3675. makeplural(body_part(ARM)), mon_nam(mtmp)); 3676. 3677. if (mtmp->msleeping) { 3678. mtmp->msleeping = 0; 3679. pline("%s awakens.", Monnam(mtmp)); 3680. } else if (mtmp->mfrozen && !rn2(mtmp->mfrozen)) { 3681. /* After such manhandling, perhaps the effect wears off */ 3682. mtmp->mcanmove = 1; 3683. mtmp->mfrozen = 0; 3684. pline("%s stirs.", Monnam(mtmp)); 3685. } 3686. 3687. /* is the monster too heavy? */ 3688. wt = inv_weight() + mtmp->data->cwt; 3689. if (!try_lift(mtmp, ttmp, wt, FALSE)) return 1; 3690. 3691. /* is the monster with inventory too heavy? */ 3692. for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj) 3693. wt += otmp->owt; 3694. if (!try_lift(mtmp, ttmp, wt, TRUE)) return 1; 3695. 3696. You("pull %s out of the pit.", mon_nam(mtmp)); 3697. mtmp->mtrapped = 0; 3698. fill_pit(mtmp->mx, mtmp->my); 3699. reward_untrap(ttmp, mtmp); 3700. return 1; 3701. } 3702. 3703. int 3704. untrap(force) 3705. boolean force; 3706. { 3707. register struct obj *otmp; 3708. register boolean confused = (Confusion > 0 || Hallucination > 0); 3709. register int x,y; 3710. int ch; 3711. struct trap *ttmp; 3712. struct monst *mtmp; 3713. boolean trap_skipped = FALSE; 3714. boolean box_here = FALSE; 3715. boolean deal_with_floor_trap = FALSE; 3716. char the_trap[BUFSZ], qbuf[QBUFSZ]; 3717. int containercnt = 0; 3718. 3719. if(!getdir((char *)0)) return(0); 3720. x = u.ux + u.dx; 3721. y = u.uy + u.dy; 3722. 3723. for(otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere) { 3724. if(Is_box(otmp) && !u.dx && !u.dy) { 3725. box_here = TRUE; 3726. containercnt++; 3727. if (containercnt > 1) break; 3728. } 3729. } 3730. 3731. if ((ttmp = t_at(x,y)) && ttmp->tseen) { 3732. deal_with_floor_trap = TRUE; 3733. Strcpy(the_trap, the(defsyms[trap_to_defsym(ttmp->ttyp)].explanation)); 3734. if (box_here) { 3735. if (ttmp->ttyp == PIT || ttmp->ttyp == SPIKED_PIT) { 3736. You_cant("do much about %s%s.", 3737. the_trap, u.utrap ? 3738. " that you're stuck in" : 3739. " while standing on the edge of it"); 3740. trap_skipped = TRUE; 3741. deal_with_floor_trap = FALSE; 3742. } else { 3743. Sprintf(qbuf, "There %s and %s here. %s %s?", 3744. (containercnt == 1) ? "is a container" : "are containers", 3745. an(defsyms[trap_to_defsym(ttmp->ttyp)].explanation), 3746. ttmp->ttyp == WEB ? "Remove" : "Disarm", the_trap); 3747. switch (ynq(qbuf)) { 3748. case 'q': return(0); 3749. case 'n': trap_skipped = TRUE; 3750. deal_with_floor_trap = FALSE; 3751. break; 3752. } 3753. } 3754. } 3755. if (deal_with_floor_trap) { 3756. if (u.utrap) { 3757. You("cannot deal with %s while trapped%s!", the_trap, 3758. (x == u.ux && y == u.uy) ? " in it" : ""); 3759. return 1; 3760. } 3761. switch(ttmp->ttyp) { 3762. case BEAR_TRAP: 3763. case WEB: 3764. return disarm_holdingtrap(ttmp); 3765. case LANDMINE: 3766. return disarm_landmine(ttmp); 3767. case SQKY_BOARD: 3768. return disarm_squeaky_board(ttmp); 3769. case DART_TRAP: 3770. return disarm_shooting_trap(ttmp, DART); 3771. case ARROW_TRAP: 3772. return disarm_shooting_trap(ttmp, ARROW); 3773. case RUST_TRAP: 3774. return disarm_rust_trap(ttmp); 3775. case FIRE_TRAP: 3776. return disarm_fire_trap(ttmp); 3777. case PIT: 3778. case SPIKED_PIT: 3779. if (!u.dx && !u.dy) { 3780. You("are already on the edge of the pit."); 3781. return 0; 3782. } 3783. if (!(mtmp = m_at(x,y))) { 3784. pline("Try filling the pit instead."); 3785. return 0; 3786. } 3787. return help_monster_out(mtmp, ttmp); 3788. default: 3789. You("cannot disable %s trap.", (u.dx || u.dy) ? "that" : "this"); 3790. return 0; 3791. } 3792. } 3793. } /* end if */ 3794. 3795. if(!u.dx && !u.dy) { 3796. for(otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere) 3797. if(Is_box(otmp)) { 3798. Sprintf(qbuf, "There is %s here. Check it for traps?", 3799. safe_qbuf("", sizeof("There is here. Check it for traps?"), 3800. doname(otmp), an(simple_typename(otmp->otyp)), "a box")); 3801. switch (ynq(qbuf)) { 3802. case 'q': return(0); 3803. case 'n': continue; 3804. } 3805. #ifdef STEED 3806. if (u.usteed && P_SKILL(P_RIDING) < P_BASIC) { 3807. You("aren't skilled enough to reach from %s.", 3808. mon_nam(u.usteed)); 3809. return(0); 3810. } 3811. #endif 3812. if((otmp->otrapped && (force || (!confused 3813. && rn2(MAXULEV + 1 - u.ulevel) < 10))) 3814. || (!force && confused && !rn2(3))) { 3815. You("find a trap on %s!", the(xname(otmp))); 3816. if (!confused) exercise(A_WIS, TRUE); 3817. 3818. switch (ynq("Disarm it?")) { 3819. case 'q': return(1); 3820. case 'n': trap_skipped = TRUE; continue; 3821. } 3822. 3823. if(otmp->otrapped) { 3824. exercise(A_DEX, TRUE); 3825. ch = ACURR(A_DEX) + u.ulevel; 3826. if (Role_if(PM_ROGUE)) ch *= 2; 3827. if(!force && (confused || Fumbling || 3828. rnd(75+level_difficulty()/2) > ch)) { 3829. (void) chest_trap(otmp, FINGER, TRUE); 3830. } else { 3831. You("disarm it!"); 3832. otmp->otrapped = 0; 3833. } 3834. } else pline("That %s was not trapped.", xname(otmp)); 3835. return(1); 3836. } else { 3837. You("find no traps on %s.", the(xname(otmp))); 3838. return(1); 3839. } 3840. } 3841. 3842. You(trap_skipped ? "find no other traps here." 3843. : "know of no traps here."); 3844. return(0); 3845. } 3846. 3847. if ((mtmp = m_at(x,y)) && 3848. mtmp->m_ap_type == M_AP_FURNITURE && 3849. (mtmp->mappearance == S_hcdoor || 3850. mtmp->mappearance == S_vcdoor) && 3851. !Protection_from_shape_changers) { 3852. 3853. stumble_onto_mimic(mtmp); 3854. return(1); 3855. } 3856. 3857. if (!IS_DOOR(levl[x][y].typ)) { 3858. if ((ttmp = t_at(x,y)) && ttmp->tseen) 3859. You("cannot disable that trap."); 3860. else 3861. You("know of no traps there."); 3862. return(0); 3863. } 3864. 3865. switch (levl[x][y].doormask) { 3866. case D_NODOOR: 3867. You("%s no door there.", Blind ? "feel" : "see"); 3868. return(0); 3869. case D_ISOPEN: 3870. pline("This door is safely open."); 3871. return(0); 3872. case D_BROKEN: 3873. pline("This door is broken."); 3874. return(0); 3875. } 3876. 3877. if ((levl[x][y].doormask & D_TRAPPED 3878. && (force || 3879. (!confused && rn2(MAXULEV - u.ulevel + 11) < 10))) 3880. || (!force && confused && !rn2(3))) { 3881. You("find a trap on the door!"); 3882. exercise(A_WIS, TRUE); 3883. if (ynq("Disarm it?") != 'y') return(1); 3884. if (levl[x][y].doormask & D_TRAPPED) { 3885. ch = 15 + (Role_if(PM_ROGUE) ? u.ulevel*3 : u.ulevel); 3886. exercise(A_DEX, TRUE); 3887. if(!force && (confused || Fumbling || 3888. rnd(75+level_difficulty()/2) > ch)) { 3889. You("set it off!"); 3890. b_trapped("door", FINGER); 3891. levl[x][y].doormask = D_NODOOR; 3892. unblock_point(x, y); 3893. newsym(x, y); 3894. /* (probably ought to charge for this damage...) */ 3895. if (*in_rooms(x, y, SHOPBASE)) add_damage(x, y, 0L); 3896. } else { 3897. You("disarm it!"); 3898. levl[x][y].doormask &= ~D_TRAPPED; 3899. } 3900. } else pline("This door was not trapped."); 3901. return(1); 3902. } else { 3903. You("find no traps on the door."); 3904. return(1); 3905. } 3906. } 3907. #endif /* OVL2 */ 3908. #ifdef OVLB 3909. 3910. /* only called when the player is doing something to the chest directly */ 3911. boolean 3912. chest_trap(obj, bodypart, disarm) 3913. register struct obj *obj; 3914. register int bodypart; 3915. boolean disarm; 3916. { 3917. register struct obj *otmp = obj, *otmp2; 3918. char buf[80]; 3919. const char *msg; 3920. coord cc; 3921. 3922. if (get_obj_location(obj, &cc.x, &cc.y, 0)) /* might be carried */ 3923. obj->ox = cc.x, obj->oy = cc.y; 3924. 3925. otmp->otrapped = 0; /* trap is one-shot; clear flag first in case 3926. chest kills you and ends up in bones file */ 3927. You(disarm ? "set it off!" : "trigger a trap!"); 3928. display_nhwindow(WIN_MESSAGE, FALSE); 3929. if (Luck > -13 && rn2(13+Luck) > 7) { /* saved by luck */ 3930. /* trap went off, but good luck prevents damage */ 3931. switch (rn2(13)) { 3932. case 12: 3933. case 11: msg = "explosive charge is a dud"; break; 3934. case 10: 3935. case 9: msg = "electric charge is grounded"; break; 3936. case 8: 3937. case 7: msg = "flame fizzles out"; break; 3938. case 6: 3939. case 5: 3940. case 4: msg = "poisoned needle misses"; break; 3941. case 3: 3942. case 2: 3943. case 1: 3944. case 0: msg = "gas cloud blows away"; break; 3945. default: impossible("chest disarm bug"); msg = (char *)0; 3946. break; 3947. } 3948. if (msg) pline("But luckily the %s!", msg); 3949. } else { 3950. switch(rn2(20) ? ((Luck >= 13) ? 0 : rn2(13-Luck)) : rn2(26)) { 3951. case 25: 3952. case 24: 3953. case 23: 3954. case 22: 3955. case 21: { 3956. struct monst *shkp = 0; 3957. long loss = 0L; 3958. boolean costly, insider; 3959. register xchar ox = obj->ox, oy = obj->oy; 3960. 3961. /* the obj location need not be that of player */ 3962. costly = (costly_spot(ox, oy) && 3963. (shkp = shop_keeper(*in_rooms(ox, oy, 3964. SHOPBASE))) != (struct monst *)0); 3965. insider = (*u.ushops && inside_shop(u.ux, u.uy) && 3966. *in_rooms(ox, oy, SHOPBASE) == *u.ushops); 3967. 3968. pline("%s!", Tobjnam(obj, "explode")); 3969. Sprintf(buf, "exploding %s", xname(obj)); 3970. 3971. if(costly) 3972. loss += stolen_value(obj, ox, oy, 3973. (boolean)shkp->mpeaceful, TRUE, TRUE); 3974. delete_contents(obj); 3975. /* we're about to delete all things at this location, 3976. * which could include the ball & chain. 3977. * If we attempt to call unpunish() in the 3978. * for-loop below we can end up with otmp2 3979. * being invalid once the chain is gone. 3980. * Deal with ball & chain right now instead. 3981. */ 3982. if (Punished && !carried(uball) && 3983. ((uchain->ox == u.ux && uchain->oy == u.uy) || 3984. (uball->ox == u.ux && uball->oy == u.uy))) 3985. unpunish(); 3986. 3987. for(otmp = level.objects[u.ux][u.uy]; 3988. otmp; otmp = otmp2) { 3989. otmp2 = otmp->nexthere; 3990. if(costly) 3991. loss += stolen_value(otmp, otmp->ox, 3992. otmp->oy, (boolean)shkp->mpeaceful, 3993. TRUE, TRUE); 3994. delobj(otmp); 3995. } 3996. wake_nearby(); 3997. losehp(d(6,6), buf, KILLED_BY_AN); 3998. exercise(A_STR, FALSE); 3999. if(costly && loss) { 4000. if(insider) 4001. You("owe %ld %s for objects destroyed.", 4002. loss, currency(loss)); 4003. else { 4004. You("caused %ld %s worth of damage!", 4005. loss, currency(loss)); 4006. make_angry_shk(shkp, ox, oy); 4007. } 4008. } 4009. return TRUE; 4010. } 4011. case 20: 4012. case 19: 4013. case 18: 4014. case 17: 4015. pline("A cloud of noxious gas billows from %s.", 4016. the(xname(obj))); 4017. poisoned("gas cloud", A_STR, "cloud of poison gas",15); 4018. exercise(A_CON, FALSE); 4019. break; 4020. case 16: 4021. case 15: 4022. case 14: 4023. case 13: 4024. You_feel("a needle prick your %s.",body_part(bodypart)); 4025. poisoned("needle", A_CON, "poisoned needle",10); 4026. exercise(A_CON, FALSE); 4027. break; 4028. case 12: 4029. case 11: 4030. case 10: 4031. case 9: 4032. dofiretrap(obj); 4033. break; 4034. case 8: 4035. case 7: 4036. case 6: { 4037. int dmg; 4038. 4039. You("are jolted by a surge of electricity!"); 4040. if(Shock_resistance) { 4041. shieldeff(u.ux, u.uy); 4042. You("don't seem to be affected."); 4043. dmg = 0; 4044. } else 4045. dmg = d(4, 4); 4046. destroy_item(RING_CLASS, AD_ELEC); 4047. destroy_item(WAND_CLASS, AD_ELEC); 4048. if (dmg) losehp(dmg, "electric shock", KILLED_BY_AN); 4049. break; 4050. } 4051. case 5: 4052. case 4: 4053. case 3: 4054. if (!Free_action) { 4055. if (!Free_action) { 4056. pline("Suddenly you are frozen in place!"); 4057. nomul(-d(5, 6)); 4058. exercise(A_DEX, FALSE); 4059. nomovemsg = You_can_move_again; 4060. } else You("momentarily stiffen."); 4061. } else You("momentarily stiffen."); 4062. break; 4063. case 2: 4064. case 1: 4065. case 0: 4066. pline("A cloud of %s gas billows from %s.", 4067. Blind ? blindgas[rn2(SIZE(blindgas))] : 4068. rndcolor(), the(xname(obj))); 4069. if(!Stunned) { 4070. if (Hallucination) 4071. pline("What a groovy feeling!"); 4072. else if (Blind) 4073. You("%s and get dizzy...", 4074. stagger(youmonst.data, "stagger")); 4075. else 4076. You("%s and your vision blurs...", 4077. stagger(youmonst.data, "stagger")); 4078. } 4079. make_stunned(HStun + rn1(7, 16),FALSE); 4080. (void) make_hallucinated(HHallucination + rn1(5, 16),FALSE,0L); 4081. break; 4082. default: impossible("bad chest trap"); 4083. break; 4084. } 4085. bot(); /* to get immediate botl re-display */ 4086. } 4087. return FALSE; 4088. } 4089. 4090. #endif /* OVLB */ 4091. #ifdef OVL0 4092. 4093. struct trap * 4094. t_at(x,y) 4095. register int x, y; 4096. { 4097. register struct trap *trap = ftrap; 4098. while(trap) { 4099. if(trap->tx == x && trap->ty == y) return(trap); 4100. trap = trap->ntrap; 4101. } 4102. return((struct trap *)0); 4103. } 4104. 4105. #endif /* OVL0 */ 4106. #ifdef OVLB 4107. 4108. void 4109. deltrap(trap) 4110. register struct trap *trap; 4111. { 4112. register struct trap *ttmp; 4113. 4114. if(trap == ftrap) 4115. ftrap = ftrap->ntrap; 4116. else { 4117. for(ttmp = ftrap; ttmp->ntrap != trap; ttmp = ttmp->ntrap) ; 4118. ttmp->ntrap = trap->ntrap; 4119. } 4120. dealloc_trap(trap); 4121. } 4122. 4123. boolean 4124. delfloortrap(ttmp) 4125. register struct trap *ttmp; 4126. { 4127. /* Destroy a trap that emanates from the floor. */ 4128. /* some of these are arbitrary -dlc */ 4129. if (ttmp && ((ttmp->ttyp == SQKY_BOARD) || 4130. (ttmp->ttyp == BEAR_TRAP) || 4131. (ttmp->ttyp == LANDMINE) || 4132. (ttmp->ttyp == FIRE_TRAP) || 4133. (ttmp->ttyp == PIT) || 4134. (ttmp->ttyp == SPIKED_PIT) || 4135. (ttmp->ttyp == HOLE) || 4136. (ttmp->ttyp == TRAPDOOR) || 4137. (ttmp->ttyp == TELEP_TRAP) || 4138. (ttmp->ttyp == LEVEL_TELEP) || 4139. (ttmp->ttyp == WEB) || 4140. (ttmp->ttyp == MAGIC_TRAP) || 4141. (ttmp->ttyp == ANTI_MAGIC))) { 4142. register struct monst *mtmp; 4143. 4144. if (ttmp->tx == u.ux && ttmp->ty == u.uy) { 4145. u.utrap = 0; 4146. u.utraptype = 0; 4147. } else if ((mtmp = m_at(ttmp->tx, ttmp->ty)) != 0) { 4148. mtmp->mtrapped = 0; 4149. } 4150. deltrap(ttmp); 4151. return TRUE; 4152. } else 4153. return FALSE; 4154. } 4155. 4156. /* used for doors (also tins). can be used for anything else that opens. */ 4157. void 4158. b_trapped(item, bodypart) 4159. register const char *item; 4160. register int bodypart; 4161. { 4162. register int lvl = level_difficulty(); 4163. int dmg = rnd(5 + (lvl < 5 ? lvl : 2+lvl/2)); 4164. 4165. pline("KABOOM!! %s was booby-trapped!", The(item)); 4166. wake_nearby(); 4167. losehp(dmg, "explosion", KILLED_BY_AN); 4168. exercise(A_STR, FALSE); 4169. if (bodypart) exercise(A_CON, FALSE); 4170. make_stunned(HStun + dmg, TRUE); 4171. } 4172. 4173. /* Monster is hit by trap. */ 4174. /* Note: doesn't work if both obj and d_override are null */ 4175. STATIC_OVL boolean 4176. thitm(tlev, mon, obj, d_override, nocorpse) 4177. int tlev; 4178. struct monst *mon; 4179. struct obj *obj; 4180. int d_override; 4181. boolean nocorpse; 4182. { 4183. int strike; 4184. boolean trapkilled = FALSE; 4185. 4186. if (d_override) strike = 1; 4187. else if (obj) strike = (find_mac(mon) + tlev + obj->spe <= rnd(20)); 4188. else strike = (find_mac(mon) + tlev <= rnd(20)); 4189. 4190. /* Actually more accurate than thitu, which doesn't take 4191. * obj->spe into account. 4192. */ 4193. if(!strike) { 4194. if (obj && cansee(mon->mx, mon->my)) 4195. pline("%s is almost hit by %s!", Monnam(mon), doname(obj)); 4196. } else { 4197. int dam = 1; 4198. 4199. if (obj && cansee(mon->mx, mon->my)) 4200. pline("%s is hit by %s!", Monnam(mon), doname(obj)); 4201. if (d_override) dam = d_override; 4202. else if (obj) { 4203. dam = dmgval(obj, mon); 4204. if (dam < 1) dam = 1; 4205. } 4206. if ((mon->mhp -= dam) <= 0) { 4207. int xx = mon->mx; 4208. int yy = mon->my; 4209. 4210. monkilled(mon, "", nocorpse ? -AD_RBRE : AD_PHYS); 4211. if (mon->mhp <= 0) { 4212. newsym(xx, yy); 4213. trapkilled = TRUE; 4214. } 4215. } 4216. } 4217. if (obj && (!strike || d_override)) { 4218. place_object(obj, mon->mx, mon->my); 4219. stackobj(obj); 4220. } else if (obj) dealloc_obj(obj); 4221. 4222. return trapkilled; 4223. } 4224. 4225. boolean 4226. unconscious() 4227. { 4228. return((boolean)(multi < 0 && (!nomovemsg || 4229. u.usleep || 4230. !strncmp(nomovemsg,"You regain con", 14) || 4231. !strncmp(nomovemsg,"You are consci", 14)))); 4232. } 4233. 4234. static const char lava_killer[] = "molten lava"; 4235. 4236. boolean 4237. lava_effects() 4238. { 4239. register struct obj *obj, *obj2; 4240. int dmg; 4241. boolean usurvive; 4242. 4243. burn_away_slime(); 4244. if (likes_lava(youmonst.data)) return FALSE; 4245. 4246. 4247. if (Slimed) { 4248. pline("The slime boils away!"); 4249. Slimed = 0; 4250. } 4251. 4252. if (!Fire_resistance) { 4253. 4254. if(Wwalking) { 4255. dmg = d(6,6); 4256. pline_The("lava here burns you!"); 4257. if(dmg < u.uhp) { 4258. losehp(dmg, lava_killer, KILLED_BY); 4259. goto burn_stuff; 4260. } 4261. } else 4262. You("fall into the lava!"); 4263. 4264. usurvive = Lifesaved || discover; 4265. #ifdef WIZARD 4266. if (wizard) usurvive = TRUE; 4267. #endif 4268. for(obj = invent; obj; obj = obj2) { 4269. obj2 = obj->nobj; 4270. if(is_organic(obj) && !obj->oerodeproof) { 4271. if(obj->owornmask) { 4272. if (usurvive) 4273. Your("%s into flame!", aobjnam(obj, "burst")); 4274. 4275. if(obj == uarm) (void) Armor_gone(); 4276. else if(obj == uarmc) (void) Cloak_off(); 4277. else if(obj == uarmh) (void) Helmet_off(); 4278. else if(obj == uarms) (void) Shield_off(); 4279. else if(obj == uarmg) (void) Gloves_off(); 4280. else if(obj == uarmf) (void) Boots_off(); 4281. #ifdef TOURIST 4282. else if(obj == uarmu) setnotworn(obj); 4283. #endif 4284. else if(obj == uleft) Ring_gone(obj); 4285. else if(obj == uright) Ring_gone(obj); 4286. else if(obj == ublindf) Blindf_off(obj); 4287. else if(obj == uamul) Amulet_off(); 4288. else if(obj == uwep) uwepgone(); 4289. else if (obj == uquiver) uqwepgone(); 4290. else if (obj == uswapwep) uswapwepgone(); 4291. } 4292. useupall(obj); 4293. } 4294. } 4295. 4296. /* s/he died... */ 4297. u.uhp = -1; 4298. killer_format = KILLED_BY; 4299. killer = lava_killer; 4300. You("burn to a crisp..."); 4301. done(BURNING); 4302. while (!safe_teleds(TRUE)) { 4303. pline("You're still burning."); 4304. done(BURNING); 4305. } 4306. You("find yourself back on solid %s.", surface(u.ux, u.uy)); 4307. return(TRUE); 4308. } 4309. 4310. if (!Wwalking) { 4311. u.utrap = rn1(4, 4) + (rn1(4, 12) << 8); 4312. u.utraptype = TT_LAVA; 4313. You("sink into the lava, but it only burns slightly!"); 4314. if (u.uhp > 1) 4315. losehp(1, lava_killer, KILLED_BY); 4316. } 4317. /* just want to burn boots, not all armor; destroy_item doesn't work on 4318. armor anyway */ 4319. burn_stuff: 4320. if(uarmf && !uarmf->oerodeproof && is_organic(uarmf)) { 4321. /* save uarmf value because Boots_off() sets uarmf to null */ 4322. obj = uarmf; 4323. Your("%s bursts into flame!", xname(obj)); 4324. (void) Boots_off(); 4325. useup(obj); 4326. } 4327. destroy_item(SCROLL_CLASS, AD_FIRE); 4328. destroy_item(SPBOOK_CLASS, AD_FIRE); 4329. destroy_item(POTION_CLASS, AD_FIRE); 4330. return(FALSE); 4331. } 4332. 4333. #endif /* OVLB */ 4334. 4335. /*trap.c*/
|