Source:SLASH'EM 0.0.7E7F2/trap.c

Below is the full text to trap.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/trap.c#line123 ]], for example.

The latest source code for vanilla NetHack is at Source code.

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