Source:NetHack 3.3.0/lock.c

Below is the full text to lock.c from the source code of NetHack 3.3.0. To link to a particular line, write [[NetHack 3.3.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.3	96/05/31	*/ 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 zorkmids for objects destroyed.", 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. 		pline("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. 		    pline("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. 		    pline("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[otmp->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. 		    pline("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!", Blind ?  586.  			"Some creature" : Monnam(mtmp)); 587. 		return(TRUE); 588. 	}  589.  	if (OBJ_AT(x, y)) { 590. objhere:	pline("%s's in the way.", Something); 591. 		return(TRUE); 592. 	}  593.  	return(FALSE); 594. }  595.   596.  int 597. doclose		/* try to close a door */ 598. {  599.  	register int x, y;  600. register struct rm *door; 601. 	struct monst *mtmp; 602.  603.  	if (nohands(youmonst.data)) { 604. 	    You_cant("close anything -- you have no hands!"); 605. 	    return 0; 606. 	}  607.   608.  	if (u.utrap && u.utraptype == TT_PIT) { 609. 	    You_cant("reach over the edge of the pit."); 610. 	    return 0; 611. 	}  612.   613.  	if(!getdir((char *)0)) return(0); 614.  615.  	x = u.ux + u.dx; 616. 	y = u.uy + u.dy; 617. 	if((x == u.ux) && (y == u.uy)) { 618. 		You("are in the way!"); 619. 		return(1); 620. 	}  621.   622.  	if ((mtmp = m_at(x,y))				&&  623.  		mtmp->m_ap_type == M_AP_FURNITURE	&&  624.  		(mtmp->mappearance == S_hcdoor || 625. 			mtmp->mappearance == S_vcdoor)	&&  626.  		!Protection_from_shape_changers)	 { 627.  628.  	    stumble_onto_mimic(mtmp); 629. 	    return(1); 630. 	}  631.   632.  	door = &levl[x][y]; 633.  634.  	if(!IS_DOOR(door->typ)) { 635. 		if (door->typ == DRAWBRIDGE_DOWN) 636. 		    pline("There is no obvious way to close the drawbridge."); 637. 		else 638. 		    You("%s no door there.",  639.  				Blind ? "feel" : "see"); 640. 		return(0); 641. 	}  642.   643.  	if(door->doormask == D_NODOOR) { 644. 	    pline("This doorway has no door."); 645. 	    return(0); 646. 	}  647.   648.  	if(obstructed(x, y)) return(0); 649.  650.  	if(door->doormask == D_BROKEN) { 651. 	    pline("This door is broken."); 652. 	    return(0); 653. 	}  654.   655.  	if(door->doormask & (D_CLOSED | D_LOCKED)) { 656. 	    pline("This door is already closed."); 657. 	    return(0); 658. 	}  659.   660.  	if(door->doormask == D_ISOPEN) { 661. 	    if(verysmall(youmonst.data)  662.  #ifdef STEED  663.  		&& !u.usteed  664.  #endif  665.  		) { 666. 		 pline("You're too small to push the door closed."); 667. 		 return(0); 668. 	    }  669.  	    if (  670.  #ifdef STEED  671.  		 u.usteed ||  672.  #endif  673.  		rn2(25) < (ACURRSTR+ACURR(A_DEX)+ACURR(A_CON))/3) { 674. 		pline_The("door closes."); 675. 		door->doormask = D_CLOSED; 676. 		if (Blind) 677. 		    feel_location(x,y);	/* the hero knows she closed it */ 678. 		else 679. 		    newsym(x,y); 680. 		block_point(x,y);	/* vision:  no longer see there */ 681. 	    }  682.  	    else { 683. 	        exercise(A_STR, TRUE); 684. 	        pline_The("door resists!"); 685. 	    }  686.  	}  687.   688.  	return(1); 689. }  690.   691.  boolean			/* box obj was hit with spell effect otmp */ 692. boxlock(obj, otmp)	/* returns true if something happened */ 693. register struct obj *obj, *otmp;	/* obj *is* a box */ 694. {  695.  	register boolean res = 0; 696.  697.  	switch(otmp->otyp) { 698. 	case WAN_LOCKING: 699. 	case SPE_WIZARD_LOCK: 700. 	    if (!obj->olocked) {	/* lock it; fix if broken */ 701. 		pline("Klunk!"); 702. 		obj->olocked = 1; 703. 		obj->obroken = 0; 704. 		res = 1; 705. 	    } /* else already closed and locked */ 706. 	    break; 707. 	case WAN_OPENING: 708. 	case SPE_KNOCK: 709. 	    if (obj->olocked) {		/* unlock; couldn't be broken */ 710. 		pline("Klick!"); 711. 		obj->olocked = 0; 712. 		res = 1; 713. 	    } else			/* silently fix if broken */ 714. 		obj->obroken = 0; 715. 	    break; 716. 	case WAN_POLYMORPH: 717. 	case SPE_POLYMORPH: 718. 	    /* maybe start unlocking chest, get interrupted, then zap it; 719. 	       we must avoid any attempt to resume unlocking it */ 720. 	    if (xlock.box == obj) 721. 		reset_pick; 722. 	    break; 723. 	}  724.  	return res; 725. }  726.   727.  boolean			/* Door/secret door was hit with spell effect otmp */ 728. doorlock(otmp,x,y)	/* returns true if something happened */ 729. struct obj *otmp; 730. int x, y;  731. { 732.  	register struct rm *door = &levl[x][y]; 733. 	boolean res = TRUE; 734. 	int loudness = 0; 735. 	const char *msg = (const char *)0; 736. 	const char *dustcloud = "A cloud of dust"; 737. 	const char *quickly_dissipates = "quickly dissipates"; 738. 	  739.  	if (door->typ == SDOOR) { 740. 	    switch (otmp->otyp) { 741. 	    case WAN_OPENING: 742. 	    case SPE_KNOCK: 743. 	    case WAN_STRIKING: 744. 	    case SPE_FORCE_BOLT: 745. 		door->typ = DOOR; 746. 		door->doormask = D_CLOSED | (door->doormask & D_TRAPPED); 747. 		newsym(x,y); 748. 		if (cansee(x,y)) pline("A door appears in the wall!"); 749. 		if (otmp->otyp == WAN_OPENING || otmp->otyp == SPE_KNOCK) 750. 		    return TRUE; 751. 		break;		/* striking: continue door handling below */ 752. 	    case WAN_LOCKING: 753. 	    case SPE_WIZARD_LOCK: 754. 	    default: 755. 		return FALSE; 756. 	    }  757.  	}  758.   759.  	switch(otmp->otyp) { 760. 	case WAN_LOCKING: 761. 	case SPE_WIZARD_LOCK: 762. #ifdef REINCARNATION 763. 	    if (Is_rogue_level(&u.uz)) { 764. 		/* Can't have real locking in Rogue, so just hide doorway */ 765. 		pline("%s springs up in the older, more primitive doorway.",  766.  			dustcloud); 767. 		if (obstructed(x,y)) { 768. 			pline_The("cloud %s.",quickly_dissipates); 769. 			return FALSE; 770. 		}  771.  		block_point(x, y); 772. 		door->typ = SDOOR; 773. 		if (cansee(x,y)) pline_The("doorway vanishes!"); 774. 		newsym(x,y); 775. 		return TRUE; 776. 	    }  777.  #endif 778. 	    if (obstructed(x,y)) return FALSE; 779. 	    /* Don't allow doors to close over traps. This is for pits */ 780. 	    /* & trap doors, but is it ever OK for anything else? */ 781.  	    if (t_at(x,y)) { 782. 		/* maketrap clears doormask, so it should be NODOOR */ 783. 		pline(  784.  		"%s springs up in the doorway, but %s.",  785.  		dustcloud, quickly_dissipates); 786. 		return FALSE; 787. 	    }  788.   789.  	    switch (door->doormask & ~D_TRAPPED) { 790. 	    case D_CLOSED: 791. 		msg = "The door locks!"; 792. 		break; 793. 	    case D_ISOPEN: 794. 		msg = "The door swings shut, and locks!"; 795. 		break; 796. 	    case D_BROKEN: 797. 		msg = "The broken door reassembles and locks!"; 798. 		break; 799. 	    case D_NODOOR: 800. 		msg = 801. 		"A cloud of dust springs up and assembles itself into a door!"; 802. 		break; 803. 	    default: 804. 		res = FALSE; 805. 		break; 806. 	    }  807.  	    block_point(x, y); 808. 	    door->doormask = D_LOCKED | (door->doormask & D_TRAPPED); 809. 	    newsym(x,y); 810. 	    break; 811. 	case WAN_OPENING: 812. 	case SPE_KNOCK: 813. 	    if (door->doormask & D_LOCKED) { 814. 		msg = "The door unlocks!"; 815. 		door->doormask = D_CLOSED | (door->doormask & D_TRAPPED); 816. 	    } else res = FALSE; 817. 	    break; 818. 	case WAN_STRIKING: 819. 	case SPE_FORCE_BOLT: 820. 	    if (door->doormask & (D_LOCKED | D_CLOSED)) { 821. 		if (door->doormask & D_TRAPPED) { 822. 		    if (MON_AT(x, y)) 823. 			(void) mb_trapped(m_at(x,y)); 824. 		    else if (flags.verbose) { 825. 			if (cansee(x,y)) 826. 			    pline("KABOOM!!  You see a door explode."); 827. 			else if (flags.soundok) 828. 			    You_hear("a distant explosion."); 829. 		    }  830.  		    door->doormask = D_NODOOR; 831. 		    unblock_point(x,y); 832. 		    newsym(x,y); 833. 		    loudness = 40; 834. 		    break; 835. 		}  836.  		door->doormask = D_BROKEN; 837. 		if (flags.verbose) { 838. 		    if (cansee(x,y)) 839. 			pline_The("door crashes open!"); 840. 		    else if (flags.soundok) 841. 			You_hear("a crashing sound."); 842. 		}  843.  		unblock_point(x,y); 844. 		newsym(x,y); 845. 		loudness = 20; 846. 	    } else res = FALSE; 847. 	    break; 848. 	default: impossible("magic (%d) attempted on door.", otmp->otyp); 849. 	    break; 850. 	}  851.  	if (msg && cansee(x,y)) pline(msg); 852. 	if (loudness > 0) { 853. 	    /* door was destroyed */ 854. 	    wake_nearto(x, y, loudness); 855. 	    if (*in_rooms(x, y, SHOPBASE)) add_damage(x, y, 0L); 856. 	}  857.   858.  	if (res && picking_at(x, y)) { 859. 	    /* maybe unseen monster zaps door you're unlocking */ 860. 	    stop_occupation; 861. 	    reset_pick; 862. 	}  863.  	return res; 864. }  865.   866.  STATIC_OVL void 867. chest_shatter_msg(otmp) 868. struct obj *otmp; 869. {  870.  	const char *disposition, *article = (otmp->quan > 1L) ? "A" : "The"; 871. 	const char *thing; 872. 	long save_Blinded; 873.  874.  	if (otmp->oclass == POTION_CLASS) { 875. 		You("%s a flask shatter!", Blind ? "hear" : "see"); 876. 		potionbreathe(otmp); 877. 		return; 878. 	}  879.  	/* We have functions for distant and singular names, but not one */ 880. 	/* which does _both_... */ 881.  	save_Blinded = Blinded; 882. 	Blinded = 1; 883. 	thing = singular(otmp, xname); 884. 	Blinded = save_Blinded; 885. 	switch (objects[otmp->otyp].oc_material) { 886. 	case PAPER:	disposition = "is torn to shreds"; 887. 		break; 888. 	case WAX:	disposition = "is crushed"; 889. 		break; 890. 	case VEGGY:	disposition = "is pulped"; 891. 		break; 892. 	case FLESH:	disposition = "is mashed"; 893. 		break; 894. 	case GLASS:	disposition = "shatters"; 895. 		break; 896. 	case WOOD:	disposition = "splinters to fragments"; 897. 		break; 898. 	default:	disposition = "is destroyed"; 899. 		break; 900. 	}  901.  	pline("%s %s %s!", article, thing, disposition); 902. }  903.   904.  #endif /* OVLB */ 905.  906.  /*lock.c*/