Source:NetHack 3.4.0/lock.c

Below is the full text to lock.c from the source code of NetHack 3.4.0. To link to a particular line, write [[NetHack 3.4.0/lock.c#line123 ]], for example.

Warning! This is the source code from an old release. For the latest release, see Source code

1.   /*	SCCS Id: @(#)lock.c	3.4	2000/02/06	*/ 2.   /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3.    /* NetHack may be freely redistributed. See license for details. */ 4.     5.    #include "hack.h"  6. 7.   STATIC_PTR int NDECL(picklock); 8.   STATIC_PTR int NDECL(forcelock); 9.    10.   /* at most one of `door' and `box' should be non-null at any given time */ 11.  STATIC_VAR NEARDATA struct xlock_s { 12.  	struct rm  *door; 13.  	struct obj *box; 14.  	int picktyp, chance, usedtime; 15.  } xlock; 16.   17.   #ifdef OVLB 18.   19.   STATIC_DCL const char *NDECL(lock_action); 20.  STATIC_DCL boolean FDECL(obstructed,(int,int)); 21.  STATIC_DCL void FDECL(chest_shatter_msg, (struct obj *)); 22.   23.   boolean 24.  picking_lock(x, y)  25. int *x, *y; 26.  {  27.   	if (occupation == picklock) { 28.  	    *x = u.ux + u.dx; 29.  	    *y = u.uy + u.dy; 30.  	    return TRUE; 31.  	} else { 32.  	    *x = *y = 0; 33.  	    return FALSE; 34.  	}  35.   }  36.    37.   boolean 38.  picking_at(x, y)  39. int x, y; 40. { 41.   	return (boolean)(occupation == picklock && xlock.door == &levl[x][y]); 42.  }  43.    44.   /* produce an occupation string appropriate for the current activity */ 45.  STATIC_OVL const char * 46.  lock_action 47.  {  48.   	/* "unlocking"+2 == "locking" */ 49.  	static const char *actions[] = { 50.  		/* [0] */	"unlocking the door", 51.  		/* [1] */	"unlocking the chest", 52.  		/* [2] */	"unlocking the box", 53.  		/* [3] */	"picking the lock" 54.  	};  55.    56.   	/* if the target is currently unlocked, we're trying to lock it now */ 57.  	if (xlock.door && !(xlock.door->doormask & D_LOCKED)) 58.  		return actions[0]+2;	/* "locking the door" */ 59.  	else if (xlock.box && !xlock.box->olocked) 60.  		return xlock.box->otyp == CHEST ? actions[1]+2 : actions[2]+2; 61.  	/* otherwise we're trying to unlock it */ 62.  	else if (xlock.picktyp == LOCK_PICK) 63.  		return actions[3];	/* "picking the lock" */ 64.  #ifdef TOURIST 65.  	else if (xlock.picktyp == CREDIT_CARD) 66.  		return actions[3];	/* same as lock_pick */ 67.  #endif 68.  	else if (xlock.door) 69.  		return actions[0];	/* "unlocking the door" */ 70.  	else 71.  		return xlock.box->otyp == CHEST ? actions[1] : actions[2]; 72.  }  73.    74.   STATIC_PTR 75.  int 76.  picklock	/* try to open/close a lock */ 77.  {  78.    79.   	if (xlock.box) { 80.  	    if((xlock.box->ox != u.ux) || (xlock.box->oy != u.uy)) { 81.  		return((xlock.usedtime = 0));		/* you or it moved */ 82.  	    }  83.   	} else {		/* door */ 84.  	    if(xlock.door != &(levl[u.ux+u.dx][u.uy+u.dy])) { 85.  		return((xlock.usedtime = 0));		/* you moved */ 86.  	    }  87.   	    switch (xlock.door->doormask) { 88.  		case D_NODOOR: 89.  		    pline("This doorway has no door."); 90.  		    return((xlock.usedtime = 0)); 91.  		case D_ISOPEN: 92.  		    You("cannot lock an open door."); 93.  		    return((xlock.usedtime = 0)); 94.  		case D_BROKEN: 95.  		    pline("This door is broken."); 96.  		    return((xlock.usedtime = 0)); 97.  	    }  98.   	}  99.    100.  	if (xlock.usedtime++ >= 50 || nohands(youmonst.data)) { 101. 	    You("give up your attempt at %s.", lock_action); 102. 	    exercise(A_DEX, TRUE);	/* even if you don't succeed */ 103. 	    return((xlock.usedtime = 0)); 104. 	}  105.   106.  	if(rn2(100) >= xlock.chance) return(1);		/* still busy */ 107.  108.  	You("succeed in %s.", lock_action); 109. 	if (xlock.door) { 110. 	    if(xlock.door->doormask & D_TRAPPED) { 111. 		    b_trapped("door", FINGER); 112. 		    xlock.door->doormask = D_NODOOR; 113. 		    unblock_point(u.ux+u.dx, u.uy+u.dy); 114. 		    if (*in_rooms(u.ux+u.dx, u.uy+u.dy, SHOPBASE)) 115. 			add_damage(u.ux+u.dx, u.uy+u.dy, 0L); 116. 		    newsym(u.ux+u.dx, u.uy+u.dy); 117. 	    } else if (xlock.door->doormask & D_LOCKED) 118. 		xlock.door->doormask = D_CLOSED; 119. 	    else xlock.door->doormask = D_LOCKED; 120. 	} else { 121. 	    xlock.box->olocked = !xlock.box->olocked; 122. 	    if(xlock.box->otrapped) 123. 		(void) chest_trap(xlock.box, FINGER, FALSE); 124. 	}  125.  	exercise(A_DEX, TRUE); 126. 	return((xlock.usedtime = 0)); 127. }  128.   129.  STATIC_PTR 130. int 131. forcelock	/* try to force a locked chest */ 132. {  133.   134.  	register struct obj *otmp; 135.  136.  	if((xlock.box->ox != u.ux) || (xlock.box->oy != u.uy)) 137. 		return((xlock.usedtime = 0));		/* you or it moved */ 138.  139.  	if (xlock.usedtime++ >= 50 || !uwep || nohands(youmonst.data)) { 140. 	    You("give up your attempt to force the lock."); 141. 	    if(xlock.usedtime >= 50)		/* you made the effort */ 142. 	      exercise((xlock.picktyp) ? A_DEX : A_STR, TRUE); 143. 	    return((xlock.usedtime = 0)); 144. 	}  145.   146.  	if(xlock.picktyp) {	/* blade */ 147.  148.  	    if(rn2(1000-(int)uwep->spe) > (992-greatest_erosion(uwep)*10) &&  149.  	       !uwep->cursed && !obj_resists(uwep, 0, 99)) { 150. 		/* for a +0 weapon, probability that it survives an unsuccessful 151. 		 * attempt to force the lock is (.992)^50 = .67 152. 		 */  153.  		pline("%sour %s broke!",  154.  		      (uwep->quan > 1L) ? "One of y" : "Y", xname(uwep)); 155. 		useup(uwep); 156. 		You("give up your attempt to force the lock."); 157. 		exercise(A_DEX, TRUE); 158. 		return((xlock.usedtime = 0)); 159. 	    }  160.  	} else			/* blunt */ 161. 	    wake_nearby;	/* due to hammering on the container */ 162.  163.  	if(rn2(100) >= xlock.chance) return(1);		/* still busy */ 164.  165.  	You("succeed in forcing the lock."); 166. 	xlock.box->olocked = 0; 167. 	xlock.box->obroken = 1; 168. 	if(!xlock.picktyp && !rn2(3)) { 169. 	    struct monst *shkp; 170. 	    boolean costly; 171. 	    long loss = 0L; 172.  173.  	    costly = (*u.ushops && costly_spot(u.ux, u.uy)); 174. 	    shkp = costly ? shop_keeper(*u.ushops) : 0; 175.  176.  	    pline("In fact, you've totally destroyed %s.",  177.  		  the(xname(xlock.box))); 178.  179.  	    /* Put the contents on ground at the hero's feet. */ 180.  	    while ((otmp = xlock.box->cobj) != 0) { 181. 		obj_extract_self(otmp); 182. 		if(!rn2(3) || otmp->oclass == POTION_CLASS) { 183. 		    chest_shatter_msg(otmp); 184. 		    if (costly) 185. 		        loss += stolen_value(otmp, u.ux, u.uy,  186.  					     (boolean)shkp->mpeaceful, TRUE); 187. 		    if (otmp->quan == 1L) { 188. 			obfree(otmp, (struct obj *) 0); 189. 			continue; 190. 		    }  191.  		    useup(otmp); 192. 		}  193.  		if (xlock.box->otyp == ICE_BOX && otmp->otyp == CORPSE) { 194. 		    otmp->age = monstermoves - otmp->age; /* actual age */ 195. 		    start_corpse_timeout(otmp); 196. 		}  197.  		place_object(otmp, u.ux, u.uy); 198. 		stackobj(otmp); 199. 	    }  200.   201.  	    if (costly) 202. 		loss += stolen_value(xlock.box, u.ux, u.uy,  203.  					     (boolean)shkp->mpeaceful, TRUE); 204. 	    if(loss) You("owe %ld %s for objects destroyed.", loss, currency(loss)); 205. 	    delobj(xlock.box); 206. 	}  207.  	exercise((xlock.picktyp) ? A_DEX : A_STR, TRUE); 208. 	return((xlock.usedtime = 0)); 209. }  210.   211.  #endif /* OVLB */ 212. #ifdef OVL0 213.  214.  void 215. reset_pick 216. {  217.  	xlock.usedtime = xlock.chance = xlock.picktyp = 0; 218. 	xlock.door = 0; 219. 	xlock.box = 0; 220. }  221.   222.  #endif /* OVL0 */ 223. #ifdef OVLB 224.  225.  int 226. pick_lock(pick) /* pick a lock with a given object */ 227. 	register struct	obj	*pick; 228. {  229.  	int x, y, picktyp, c, ch; 230. 	struct rm	*door; 231. 	struct obj	*otmp; 232. 	char qbuf[QBUFSZ]; 233.  234.  	picktyp = pick->otyp; 235.  236.  	/* check whether we're resuming an interrupted previous attempt */ 237. 	if (xlock.usedtime && picktyp == xlock.picktyp) { 238. 	    static char no_longer[] = "Unfortunately, you can no longer %s %s."; 239.  240.  	    if (nohands(youmonst.data)) { 241. 		const char *what = (picktyp == LOCK_PICK) ? "pick" : "key"; 242. #ifdef TOURIST 243. 		if (picktyp == CREDIT_CARD) what = "card"; 244. #endif 245. 		pline(no_longer, "hold the", what); 246. 		reset_pick; 247. 		return 0; 248. 	    } else if (xlock.box && !can_reach_floor) { 249. 		pline(no_longer, "reach the", "lock"); 250. 		reset_pick; 251. 		return 0; 252. 	    } else { 253. 		const char *action = lock_action; 254. 		You("resume your attempt at %s.", action); 255. 		set_occupation(picklock, action, 0); 256. 		return(1); 257. 	    }  258.  	}  259.   260.  	if(nohands(youmonst.data)) { 261. 		You_cant("hold %s -- you have no hands!", doname(pick)); 262. 		return(0); 263. 	}  264.   265.  	if((picktyp != LOCK_PICK && 266. #ifdef TOURIST 267. 	    picktyp != CREDIT_CARD && 268. #endif 269. 	    picktyp != SKELETON_KEY)) { 270. 		impossible("picking lock with object %d?", picktyp); 271. 		return(0); 272. 	}  273.  	if(!getdir((char *)0)) return(0); 274.  275.  	ch = 0;		/* lint suppression */ 276. 	x = u.ux + u.dx; 277. 	y = u.uy + u.dy; 278. 	if (x == u.ux && y == u.uy) {	/* pick lock on a container */ 279. 	    const char *verb; 280. 	    boolean it; 281. 	    int count; 282.  283.  	    if (u.dz < 0) { 284. 		There("isn't any sort of lock up %s.",  285.  		      Levitation ? "here" : "there"); 286. 		return 0; 287. 	    } else if (is_lava(u.ux, u.uy)) { 288. 		pline("Doing that would probably melt your %s.",  289.  		      xname(pick)); 290. 		return 0; 291. 	    } else if (is_pool(u.ux, u.uy) && !Underwater) { 292. 		pline_The("water has no lock."); 293. 		return 0; 294. 	    }  295.   296.  	    count = 0; 297. 	    c = 'n';			/* in case there are no boxes here */ 298. 	    for(otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere) 299. 		if (Is_box(otmp)) { 300. 		    ++count; 301. 		    if (!can_reach_floor) { 302. 			You_cant("reach %s from up here.", the(xname(otmp))); 303. 			return 0; 304. 		    }  305.  		    it = 0; 306. 		    if (otmp->obroken) verb = "fix"; 307. 		    else if (!otmp->olocked) verb = "lock", it = 1; 308. 		    else if (picktyp != LOCK_PICK) verb = "unlock", it = 1; 309. 		    else verb = "pick"; 310. 		    Sprintf(qbuf, "There is %s here, %s %s?",  311.  			    doname(otmp), verb, it ? "it" : "its lock"); 312.  313.  		    c = ynq(qbuf); 314. 		    if(c == 'q') return(0); 315. 		    if(c == 'n') continue; 316.  317.  		    if (otmp->obroken) { 318. 			You_cant("fix its broken lock with %s.", doname(pick)); 319. 			return 0; 320. 		    }  321.  #ifdef TOURIST 322. 		    else if (picktyp == CREDIT_CARD && !otmp->olocked) { 323. 			/* credit cards are only good for unlocking */ 324. 			You_cant("do that with %s.", doname(pick)); 325. 			return 0; 326. 		    }  327.  #endif 328. 		    switch(picktyp) { 329. #ifdef TOURIST 330. 			case CREDIT_CARD: 331. 			    ch = ACURR(A_DEX) + 20*Role_if(PM_ROGUE); 332. 			    break; 333. #endif 334. 			case LOCK_PICK: 335. 			    ch = 4*ACURR(A_DEX) + 25*Role_if(PM_ROGUE); 336. 			    break; 337. 			case SKELETON_KEY: 338. 			    ch = 75 + ACURR(A_DEX); 339. 			    break; 340. 			default:	ch = 0; 341. 		    }  342.  		    if(otmp->cursed) ch /= 2; 343.  344.  		    xlock.picktyp = picktyp; 345. 		    xlock.box = otmp; 346. 		    xlock.door = 0; 347. 		    break; 348. 		}  349.  	    if (c != 'y') { 350. 		if (!count) 351. 		    There("doesn't seem to be any sort of lock here."); 352. 		return(0);		/* decided against all boxes */ 353. 	    }  354.  	} else {			/* pick the lock in a door */ 355. 	    struct monst *mtmp; 356.  357.  	    door = &levl[x][y]; 358. 	    if ((mtmp = m_at(x, y)) && canseemon(mtmp)  359.  			&& mtmp->m_ap_type != M_AP_FURNITURE  360.  			&& mtmp->m_ap_type != M_AP_OBJECT) { 361. #ifdef TOURIST 362. 		if (picktyp == CREDIT_CARD &&  363.  		    (mtmp->isshk || mtmp->data == &mons[PM_ORACLE])) 364. 		    verbalize("No checks, no credit, no problem."); 365. 		else 366. #endif 367. 		    pline("I don't think %s would appreciate that.", mon_nam(mtmp)); 368. 		return(0); 369. 	    }  370.  	    if(!IS_DOOR(door->typ)) { 371. 		if (is_drawbridge_wall(x,y) >= 0) 372. 		    You("%s no lock on the drawbridge.",  373.  				Blind ? "feel" : "see"); 374. 		else 375. 		    You("%s no door there.",  376.  				Blind ? "feel" : "see"); 377. 		return(0); 378. 	    }  379.  	    switch (door->doormask) { 380. 		case D_NODOOR: 381. 		    pline("This doorway has no door."); 382. 		    return(0); 383. 		case D_ISOPEN: 384. 		    You("cannot lock an open door."); 385. 		    return(0); 386. 		case D_BROKEN: 387. 		    pline("This door is broken."); 388. 		    return(0); 389. 		default: 390. #ifdef TOURIST 391. 		    /* credit cards are only good for unlocking */ 392. 		    if(picktyp == CREDIT_CARD && !(door->doormask & D_LOCKED)) { 393. 			You_cant("lock a door with a credit card."); 394. 			return(0); 395. 		    }  396.  #endif 397.  398.  		    Sprintf(qbuf,"%sock it?",  399.  			(door->doormask & D_LOCKED) ? "Unl" : "L" ); 400.  401.  		    c = yn(qbuf); 402. 		    if(c == 'n') return(0); 403.  404.  		    switch(picktyp) { 405. #ifdef TOURIST 406. 			case CREDIT_CARD: 407. 			    ch = 2*ACURR(A_DEX) + 20*Role_if(PM_ROGUE); 408. 			    break; 409. #endif 410. 			case LOCK_PICK: 411. 			    ch = 3*ACURR(A_DEX) + 30*Role_if(PM_ROGUE); 412. 			    break; 413. 			case SKELETON_KEY: 414. 			    ch = 70 + ACURR(A_DEX); 415. 			    break; 416. 			default:    ch = 0; 417. 		    }  418.  		    xlock.door = door; 419. 		    xlock.box = 0; 420. 	    }  421.  	}  422.  	flags.move = 0; 423. 	xlock.chance = ch; 424. 	xlock.picktyp = picktyp; 425. 	xlock.usedtime = 0; 426. 	set_occupation(picklock, lock_action, 0); 427. 	return(1); 428. }  429.   430.  int 431. doforce		/* try to force a chest with your weapon */ 432. {  433.  	register struct obj *otmp; 434. 	register int c, picktyp; 435. 	char qbuf[QBUFSZ]; 436.  437.  	if(!uwep ||	/* proper type test */  438.  	   (uwep->oclass != WEAPON_CLASS && !is_weptool(uwep) && 439. 	    uwep->oclass != ROCK_CLASS) ||  440.  	   (objects[uwep->otyp].oc_skill < P_DAGGER) ||  441.  	   (objects[uwep->otyp].oc_skill > P_LANCE) ||  442.  	   uwep->otyp == FLAIL || uwep->otyp == AKLYS  443.  #ifdef KOPS  444.  	   || uwep->otyp == RUBBER_HOSE  445.  #endif  446.  	  ) { 447. 	    You_cant("force anything without a %sweapon.",  448.  		  (uwep) ? "proper " : ""); 449. 	    return(0); 450. 	}  451.   452.  	picktyp = is_blade(uwep); 453. 	if(xlock.usedtime && xlock.box && picktyp == xlock.picktyp) { 454. 	    You("resume your attempt to force the lock."); 455. 	    set_occupation(forcelock, "forcing the lock", 0); 456. 	    return(1); 457. 	}  458.   459.  	/* A lock is made only for the honest man, the thief will break it. */ 460.  	xlock.box = (struct obj *)0; 461. 	for(otmp = level.objects[u.ux][u.uy]; otmp; otmp = otmp->nexthere) 462. 	    if(Is_box(otmp)) { 463. 		if (otmp->obroken || !otmp->olocked) { 464. 		    There("is %s here, but its lock is already %s.",  465.  			  doname(otmp), otmp->obroken ? "broken" : "unlocked"); 466. 		    continue; 467. 		}  468.  		Sprintf(qbuf,"There is %s here, force its lock?", doname(otmp)); 469.  470.  		c = ynq(qbuf); 471. 		if(c == 'q') return(0); 472. 		if(c == 'n') continue; 473.  474.  		if(picktyp) 475. 		    You("force your %s into a crack and pry.", xname(uwep)); 476. 		else 477. 		    You("start bashing it with your %s.", xname(uwep)); 478. 		xlock.box = otmp; 479. 		xlock.chance = objects[uwep->otyp].oc_wldam * 2; 480. 		xlock.picktyp = picktyp; 481. 		xlock.usedtime = 0; 482. 		break; 483. 	    }  484.   485.  	if(xlock.box)	set_occupation(forcelock, "forcing the lock", 0); 486. 	else		You("decide not to force the issue."); 487. 	return(1); 488. }  489.   490.  int 491. doopen		/* try to open a door */ 492. {  493.  	register int x, y;  494. register struct rm *door; 495. 	struct monst *mtmp; 496.  497.  	if (nohands(youmonst.data)) { 498. 	    You_cant("open anything -- you have no hands!"); 499. 	    return 0; 500. 	}  501.   502.  	if (u.utrap && u.utraptype == TT_PIT) { 503. 	    You_cant("reach over the edge of the pit."); 504. 	    return 0; 505. 	}  506.   507.  	if(!getdir((char *)0)) return(0); 508.  509.  	x = u.ux + u.dx; 510. 	y = u.uy + u.dy; 511. 	if((x == u.ux) && (y == u.uy)) return(0); 512.  513.  	if ((mtmp = m_at(x,y))				&&  514.  		mtmp->m_ap_type == M_AP_FURNITURE	&&  515.  		(mtmp->mappearance == S_hcdoor || 516. 			mtmp->mappearance == S_vcdoor)	&&  517.  		!Protection_from_shape_changers)	 { 518.  519.  	    stumble_onto_mimic(mtmp); 520. 	    return(1); 521. 	}  522.   523.  	door = &levl[x][y]; 524.  525.  	if(!IS_DOOR(door->typ)) { 526. 		if (is_db_wall(x,y)) { 527. 		    There("is no obvious way to open the drawbridge."); 528. 		    return(0); 529. 		}  530.  		You("%s no door there.",  531.  				Blind ? "feel" : "see"); 532. 		return(0); 533. 	}  534.   535.  	if (!(door->doormask & D_CLOSED)) { 536. 	    const char *mesg; 537.  538.  	    switch (door->doormask) { 539. 	    case D_BROKEN: mesg = " is broken"; break; 540. 	    case D_NODOOR: mesg = "way has no door"; break; 541. 	    case D_ISOPEN: mesg = " is already open"; break; 542. 	    default:	   mesg = " is locked"; break; 543. 	    }  544.  	    pline("This door%s.", mesg); 545. 	    if (Blind) feel_location(x,y); 546. 	    return(0); 547. 	}  548.   549.  	if(verysmall(youmonst.data)) { 550. 	    pline("You're too small to pull the door open."); 551. 	    return(0); 552. 	}  553.   554.  	/* door is known to be CLOSED */ 555. 	if (rnl(20) < (ACURRSTR+ACURR(A_DEX)+ACURR(A_CON))/3) { 556. 	    pline_The("door opens."); 557. 	    if(door->doormask & D_TRAPPED) { 558. 		b_trapped("door", FINGER); 559. 		door->doormask = D_NODOOR; 560. 		if (*in_rooms(x, y, SHOPBASE)) add_damage(x, y, 0L); 561. 	    } else 562. 		door->doormask = D_ISOPEN; 563. 	    if (Blind) 564. 		feel_location(x,y);	/* the hero knows she opened it  */ 565. 	    else 566. 		newsym(x,y); 567. 	    unblock_point(x,y);		/* vision: new see through there */ 568. 	} else { 569. 	    exercise(A_STR, TRUE); 570. 	    pline_The("door resists!"); 571. 	}  572.   573.  	return(1); 574. }  575.   576.  STATIC_OVL 577. boolean 578. obstructed(x,y) 579. register int x, y;  580. { 581.  	register struct monst *mtmp = m_at(x, y); 582.  583.  	if(mtmp && mtmp->m_ap_type != M_AP_FURNITURE) { 584. 		if (mtmp->m_ap_type == M_AP_OBJECT) goto objhere; 585. 		pline("%s stands in the way!", !canspotmon(mtmp) ?  586.  			"Some creature" : Monnam(mtmp)); 587. 		if (!canspotmon(mtmp)) 588. 		    map_invisible(mtmp->mx, mtmp->my); 589. 		return(TRUE); 590. 	}  591.  	if (OBJ_AT(x, y)) { 592. objhere:	pline("%s's in the way.", Something); 593. 		return(TRUE); 594. 	}  595.  	return(FALSE); 596. }  597.   598.  int 599. doclose		/* try to close a door */ 600. {  601.  	register int x, y;  602. register struct rm *door; 603. 	struct monst *mtmp; 604.  605.  	if (nohands(youmonst.data)) { 606. 	    You_cant("close anything -- you have no hands!"); 607. 	    return 0; 608. 	}  609.   610.  	if (u.utrap && u.utraptype == TT_PIT) { 611. 	    You_cant("reach over the edge of the pit."); 612. 	    return 0; 613. 	}  614.   615.  	if(!getdir((char *)0)) return(0); 616.  617.  	x = u.ux + u.dx; 618. 	y = u.uy + u.dy; 619. 	if((x == u.ux) && (y == u.uy)) { 620. 		You("are in the way!"); 621. 		return(1); 622. 	}  623.   624.  	if ((mtmp = m_at(x,y))				&&  625.  		mtmp->m_ap_type == M_AP_FURNITURE	&&  626.  		(mtmp->mappearance == S_hcdoor || 627. 			mtmp->mappearance == S_vcdoor)	&&  628.  		!Protection_from_shape_changers)	 { 629.  630.  	    stumble_onto_mimic(mtmp); 631. 	    return(1); 632. 	}  633.   634.  	door = &levl[x][y]; 635.  636.  	if(!IS_DOOR(door->typ)) { 637. 		if (door->typ == DRAWBRIDGE_DOWN) 638. 		    There("is no obvious way to close the drawbridge."); 639. 		else 640. 		    You("%s no door there.",  641.  				Blind ? "feel" : "see"); 642. 		return(0); 643. 	}  644.   645.  	if(door->doormask == D_NODOOR) { 646. 	    pline("This doorway has no door."); 647. 	    return(0); 648. 	}  649.   650.  	if(obstructed(x, y)) return(0); 651.  652.  	if(door->doormask == D_BROKEN) { 653. 	    pline("This door is broken."); 654. 	    return(0); 655. 	}  656.   657.  	if(door->doormask & (D_CLOSED | D_LOCKED)) { 658. 	    pline("This door is already closed."); 659. 	    return(0); 660. 	}  661.   662.  	if(door->doormask == D_ISOPEN) { 663. 	    if(verysmall(youmonst.data)  664.  #ifdef STEED  665.  		&& !u.usteed  666.  #endif  667.  		) { 668. 		 pline("You're too small to push the door closed."); 669. 		 return(0); 670. 	    }  671.  	    if (  672.  #ifdef STEED  673.  		 u.usteed ||  674.  #endif  675.  		rn2(25) < (ACURRSTR+ACURR(A_DEX)+ACURR(A_CON))/3) { 676. 		pline_The("door closes."); 677. 		door->doormask = D_CLOSED; 678. 		if (Blind) 679. 		    feel_location(x,y);	/* the hero knows she closed it */ 680. 		else 681. 		    newsym(x,y); 682. 		block_point(x,y);	/* vision:  no longer see there */ 683. 	    }  684.  	    else { 685. 	        exercise(A_STR, TRUE); 686. 	        pline_The("door resists!"); 687. 	    }  688.  	}  689.   690.  	return(1); 691. }  692.   693.  boolean			/* box obj was hit with spell effect otmp */ 694. boxlock(obj, otmp)	/* returns true if something happened */ 695. register struct obj *obj, *otmp;	/* obj *is* a box */ 696. {  697.  	register boolean res = 0; 698.  699.  	switch(otmp->otyp) { 700. 	case WAN_LOCKING: 701. 	case SPE_WIZARD_LOCK: 702. 	    if (!obj->olocked) {	/* lock it; fix if broken */ 703. 		pline("Klunk!"); 704. 		obj->olocked = 1; 705. 		obj->obroken = 0; 706. 		res = 1; 707. 	    } /* else already closed and locked */ 708. 	    break; 709. 	case WAN_OPENING: 710. 	case SPE_KNOCK: 711. 	    if (obj->olocked) {		/* unlock; couldn't be broken */ 712. 		pline("Klick!"); 713. 		obj->olocked = 0; 714. 		res = 1; 715. 	    } else			/* silently fix if broken */ 716. 		obj->obroken = 0; 717. 	    break; 718. 	case WAN_POLYMORPH: 719. 	case SPE_POLYMORPH: 720. 	    /* maybe start unlocking chest, get interrupted, then zap it; 721. 	       we must avoid any attempt to resume unlocking it */ 722. 	    if (xlock.box == obj) 723. 		reset_pick; 724. 	    break; 725. 	}  726.  	return res; 727. }  728.   729.  boolean			/* Door/secret door was hit with spell effect otmp */ 730. doorlock(otmp,x,y)	/* returns true if something happened */ 731. struct obj *otmp; 732. int x, y;  733. { 734.  	register struct rm *door = &levl[x][y]; 735. 	boolean res = TRUE; 736. 	int loudness = 0; 737. 	const char *msg = (const char *)0; 738. 	const char *dustcloud = "A cloud of dust"; 739. 	const char *quickly_dissipates = "quickly dissipates"; 740. 	  741.  	if (door->typ == SDOOR) { 742. 	    switch (otmp->otyp) { 743. 	    case WAN_OPENING: 744. 	    case SPE_KNOCK: 745. 	    case WAN_STRIKING: 746. 	    case SPE_FORCE_BOLT: 747. 		door->typ = DOOR; 748. 		door->doormask = D_CLOSED | (door->doormask & D_TRAPPED); 749. 		newsym(x,y); 750. 		if (cansee(x,y)) pline("A door appears in the wall!"); 751. 		if (otmp->otyp == WAN_OPENING || otmp->otyp == SPE_KNOCK) 752. 		    return TRUE; 753. 		break;		/* striking: continue door handling below */ 754. 	    case WAN_LOCKING: 755. 	    case SPE_WIZARD_LOCK: 756. 	    default: 757. 		return FALSE; 758. 	    }  759.  	}  760.   761.  	switch(otmp->otyp) { 762. 	case WAN_LOCKING: 763. 	case SPE_WIZARD_LOCK: 764. #ifdef REINCARNATION 765. 	    if (Is_rogue_level(&u.uz)) { 766. 	    	boolean vis = cansee(x,y); 767. 		/* Can't have real locking in Rogue, so just hide doorway */ 768. 		if (vis) pline("%s springs up in the older, more primitive doorway.",  769.  			dustcloud); 770. 		else 771. 			You_hear("a swoosh."); 772. 		if (obstructed(x,y)) { 773. 			if (vis) pline_The("cloud %s.",quickly_dissipates); 774. 			return FALSE; 775. 		}  776.  		block_point(x, y); 777. 		door->typ = SDOOR; 778. 		if (vis) pline_The("doorway vanishes!"); 779. 		newsym(x,y); 780. 		return TRUE; 781. 	    }  782.  #endif 783. 	    if (obstructed(x,y)) return FALSE; 784. 	    /* Don't allow doors to close over traps. This is for pits */ 785. 	    /* & trap doors, but is it ever OK for anything else? */ 786.  	    if (t_at(x,y)) { 787. 		/* maketrap clears doormask, so it should be NODOOR */ 788. 		pline(  789.  		"%s springs up in the doorway, but %s.",  790.  		dustcloud, quickly_dissipates); 791. 		return FALSE; 792. 	    }  793.   794.  	    switch (door->doormask & ~D_TRAPPED) { 795. 	    case D_CLOSED: 796. 		msg = "The door locks!"; 797. 		break; 798. 	    case D_ISOPEN: 799. 		msg = "The door swings shut, and locks!"; 800. 		break; 801. 	    case D_BROKEN: 802. 		msg = "The broken door reassembles and locks!"; 803. 		break; 804. 	    case D_NODOOR: 805. 		msg = 806. 		"A cloud of dust springs up and assembles itself into a door!"; 807. 		break; 808. 	    default: 809. 		res = FALSE; 810. 		break; 811. 	    }  812.  	    block_point(x, y); 813. 	    door->doormask = D_LOCKED | (door->doormask & D_TRAPPED); 814. 	    newsym(x,y); 815. 	    break; 816. 	case WAN_OPENING: 817. 	case SPE_KNOCK: 818. 	    if (door->doormask & D_LOCKED) { 819. 		msg = "The door unlocks!"; 820. 		door->doormask = D_CLOSED | (door->doormask & D_TRAPPED); 821. 	    } else res = FALSE; 822. 	    break; 823. 	case WAN_STRIKING: 824. 	case SPE_FORCE_BOLT: 825. 	    if (door->doormask & (D_LOCKED | D_CLOSED)) { 826. 		if (door->doormask & D_TRAPPED) { 827. 		    if (MON_AT(x, y)) 828. 			(void) mb_trapped(m_at(x,y)); 829. 		    else if (flags.verbose) { 830. 			if (cansee(x,y)) 831. 			    pline("KABOOM!!  You see a door explode."); 832. 			else if (flags.soundok) 833. 			    You_hear("a distant explosion."); 834. 		    }  835.  		    door->doormask = D_NODOOR; 836. 		    unblock_point(x,y); 837. 		    newsym(x,y); 838. 		    loudness = 40; 839. 		    break; 840. 		}  841.  		door->doormask = D_BROKEN; 842. 		if (flags.verbose) { 843. 		    if (cansee(x,y)) 844. 			pline_The("door crashes open!"); 845. 		    else if (flags.soundok) 846. 			You_hear("a crashing sound."); 847. 		}  848.  		unblock_point(x,y); 849. 		newsym(x,y); 850. 		loudness = 20; 851. 	    } else res = FALSE; 852. 	    break; 853. 	default: impossible("magic (%d) attempted on door.", otmp->otyp); 854. 	    break; 855. 	}  856.  	if (msg && cansee(x,y)) pline(msg); 857. 	if (loudness > 0) { 858. 	    /* door was destroyed */ 859. 	    wake_nearto(x, y, loudness); 860. 	    if (*in_rooms(x, y, SHOPBASE)) add_damage(x, y, 0L); 861. 	}  862.   863.  	if (res && picking_at(x, y)) { 864. 	    /* maybe unseen monster zaps door you're unlocking */ 865. 	    stop_occupation; 866. 	    reset_pick; 867. 	}  868.  	return res; 869. }  870.   871.  STATIC_OVL void 872. chest_shatter_msg(otmp) 873. struct obj *otmp; 874. {  875.  	const char *disposition, *article = (otmp->quan > 1L) ? "A" : "The"; 876. 	const char *thing; 877. 	long save_Blinded; 878.  879.  	if (otmp->oclass == POTION_CLASS) { 880. 		You("%s a %s shatter!", Blind ? "hear" : "see", bottlename); 881. 		if (!breathless(youmonst.data) || haseyes(youmonst.data)) 882. 			potionbreathe(otmp); 883. 		return; 884. 	}  885.  	/* We have functions for distant and singular names, but not one */ 886. 	/* which does _both_... */ 887.  	save_Blinded = Blinded; 888. 	Blinded = 1; 889. 	thing = singular(otmp, xname); 890. 	Blinded = save_Blinded; 891. 	switch (objects[otmp->otyp].oc_material) { 892. 	case PAPER:	disposition = "is torn to shreds"; 893. 		break; 894. 	case WAX:	disposition = "is crushed"; 895. 		break; 896. 	case VEGGY:	disposition = "is pulped"; 897. 		break; 898. 	case FLESH:	disposition = "is mashed"; 899. 		break; 900. 	case GLASS:	disposition = "shatters"; 901. 		break; 902. 	case WOOD:	disposition = "splinters to fragments"; 903. 		break; 904. 	default:	disposition = "is destroyed"; 905. 		break; 906. 	}  907.  	pline("%s %s %s!", article, thing, disposition); 908. }  909.   910.  #endif /* OVLB */ 911.  912.  /*lock.c*/