Source:Trap.c

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