Source:NetHack 3.2.0/lock.c

Below is the full text to lock.c from the source code of NetHack 3.2.0. To link to a particular line, write [[NetHack 3.2.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.2	95/10/04	*/ 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 const char *NDECL(lock_action); 20.  static boolean FDECL(obstructed,(int,int)); 21.  static 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 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(uasmon)) { 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(uasmon)) { 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-(int)uwep->oeroded*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(uasmon)) { 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(uasmon)) { 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_is('R'); 332. 			    break; 333. #endif 334. 			case LOCK_PICK: 335. 			    ch = 4*ACURR(A_DEX) + 25*Role_is('R'); 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_is('R'); 408. 			    break; 409. #endif 410. 			case LOCK_PICK: 411. 			    ch = 3*ACURR(A_DEX) + 30*Role_is('R'); 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.  	   (uwep->oclass != ROCK_CLASS && 441. 	    (objects[uwep->otyp].oc_wepcat == WEP_BOW ||  442.  	     objects[uwep->otyp].oc_wepcat == WEP_AMMO ||  443.  	     objects[uwep->otyp].oc_wepcat == WEP_MISSILE))  444.  	   || (uwep->otyp > QUARTERSTAFF && uwep->otyp < BULLWHIP)  445.  #ifdef KOPS  446.  	   || uwep->otyp == RUBBER_HOSE  447.  #endif  448.  	  ) { 449. 	    You_cant("force anything without a %sweapon.",  450.  		  (uwep) ? "proper " : ""); 451. 	    return(0); 452. 	}  453.   454.  	picktyp = is_blade(uwep); 455. 	if(xlock.usedtime && xlock.box && picktyp == xlock.picktyp) { 456. 	    You("resume your attempt to force the lock."); 457. 	    set_occupation(forcelock, "forcing the lock", 0); 458. 	    return(1); 459. 	}  460.   461.  	/* A lock is made only for the honest man, the thief will break it. */ 462.  	xlock.box = (struct obj *)0; 463. 	for(otmp = level.objects[u.ux][u.uy]; otmp; otmp = otmp->nexthere) 464. 	    if(Is_box(otmp)) { 465. 		if (otmp->obroken || !otmp->olocked) { 466. 		    pline("There is %s here, but its lock is already %s.",  467.  			  doname(otmp), otmp->obroken ? "broken" : "unlocked"); 468. 		    continue; 469. 		}  470.  		Sprintf(qbuf,"There is %s here, force its lock?", doname(otmp)); 471.  472.  		c = ynq(qbuf); 473. 		if(c == 'q') return(0); 474. 		if(c == 'n') continue; 475.  476.  		if(picktyp) 477. 		    You("force your %s into a crack and pry.", xname(uwep)); 478. 		else 479. 		    You("start bashing it with your %s.", xname(uwep)); 480. 		xlock.box = otmp; 481. 		xlock.chance = objects[otmp->otyp].oc_wldam * 2; 482. 		xlock.picktyp = picktyp; 483. 		xlock.usedtime = 0; 484. 		break; 485. 	    }  486.   487.  	if(xlock.box)	set_occupation(forcelock, "forcing the lock", 0); 488. 	else		You("decide not to force the issue."); 489. 	return(1); 490. }  491.   492.  int 493. doopen		/* try to open a door */ 494. {  495.  	register int x, y;  496. register struct rm *door; 497. 	struct monst *mtmp; 498.  499.  	if (u.utrap && u.utraptype == TT_PIT) { 500. 	    You_cant("reach over the edge of the pit."); 501. 	    return 0; 502. 	}  503.   504.  	if(!getdir((char *)0)) return(0); 505.  506.  	x = u.ux + u.dx; 507. 	y = u.uy + u.dy; 508. 	if((x == u.ux) && (y == u.uy)) return(0); 509.  510.  	if ((mtmp = m_at(x,y))				&&  511.  		mtmp->m_ap_type == M_AP_FURNITURE	&&  512.  		(mtmp->mappearance == S_hcdoor || 513. 			mtmp->mappearance == S_vcdoor)	&&  514.  		!Protection_from_shape_changers)	 { 515.  516.  	    stumble_onto_mimic(mtmp); 517. 	    return(1); 518. 	}  519.   520.  	door = &levl[x][y]; 521.  522.  	if(!IS_DOOR(door->typ)) { 523. 		if (is_db_wall(x,y)) { 524. 		    pline("There is no obvious way to open the drawbridge."); 525. 		    return(0); 526. 		}  527.  		You("%s no door there.",  528.  				Blind ? "feel" : "see"); 529. 		return(0); 530. 	}  531.   532.  	if(!(door->doormask & D_CLOSED)) { 533. 	  switch(door->doormask) { 534. 	     case D_BROKEN: pline("This door is broken."); break; 535. 	     case D_NODOOR: pline("This doorway has no door."); break; 536. 	     case D_ISOPEN: pline("This door is already open."); break; 537. 	     default:	    pline("This door is locked."); break; 538. 	  }  539.  	    if(Blind) feel_location(x,y); 540. 	  return(0); 541. 	}  542.   543.  	if(verysmall(uasmon)) { 544. 	    pline("You're too small to pull the door open."); 545. 	    return(0); 546. 	}  547.   548.  	/* door is known to be CLOSED */ 549. 	if (rnl(20) < (ACURRSTR+ACURR(A_DEX)+ACURR(A_CON))/3) { 550. 	    pline_The("door opens."); 551. 	    if(door->doormask & D_TRAPPED) { 552. 		b_trapped("door", FINGER); 553. 		door->doormask = D_NODOOR; 554. 		if (*in_rooms(x, y, SHOPBASE)) add_damage(x, y, 0L); 555. 	    } else 556. 		door->doormask = D_ISOPEN; 557. 	    if (Blind) 558. 		feel_location(x,y);	/* the hero knows she opened it  */ 559. 	    else 560. 		newsym(x,y); 561. 	    unblock_point(x,y);		/* vision: new see through there */ 562. 	} else { 563. 	    exercise(A_STR, TRUE); 564. 	    pline_The("door resists!"); 565. 	}  566.   567.  	return(1); 568. }  569.   570.  static 571. boolean 572. obstructed(x,y) 573. register int x, y;  574. { 575.  	register struct monst *mtmp = m_at(x, y); 576.  577.  	if(mtmp && mtmp->m_ap_type != M_AP_FURNITURE) { 578. 		if (mtmp->m_ap_type == M_AP_OBJECT) goto objhere; 579. 		pline("%s stands in the way!", Blind ?  580.  			"Some creature" : Monnam(mtmp)); 581. 		return(TRUE); 582. 	}  583.  	if (OBJ_AT(x, y)) { 584. objhere:	pline("%s's in the way.", Something); 585. 		return(TRUE); 586. 	}  587.  	return(FALSE); 588. }  589.   590.  int 591. doclose		/* try to close a door */ 592. {  593.  	register int x, y;  594. register struct rm *door; 595. 	struct monst *mtmp; 596.  597.  	if (u.utrap && u.utraptype == TT_PIT) { 598. 	    You_cant("reach over the edge of the pit."); 599. 	    return 0; 600. 	}  601.   602.  	if(!getdir((char *)0)) return(0); 603.  604.  	x = u.ux + u.dx; 605. 	y = u.uy + u.dy; 606. 	if((x == u.ux) && (y == u.uy)) { 607. 		You("are in the way!"); 608. 		return(1); 609. 	}  610.   611.  	if ((mtmp = m_at(x,y))				&&  612.  		mtmp->m_ap_type == M_AP_FURNITURE	&&  613.  		(mtmp->mappearance == S_hcdoor || 614. 			mtmp->mappearance == S_vcdoor)	&&  615.  		!Protection_from_shape_changers)	 { 616.  617.  	    stumble_onto_mimic(mtmp); 618. 	    return(1); 619. 	}  620.   621.  	door = &levl[x][y]; 622.  623.  	if(!IS_DOOR(door->typ)) { 624. 		if (door->typ == DRAWBRIDGE_DOWN) 625. 		    pline("There is no obvious way to close the drawbridge."); 626. 		else 627. 		    You("%s no door there.",  628.  				Blind ? "feel" : "see"); 629. 		return(0); 630. 	}  631.   632.  	if(door->doormask == D_NODOOR) { 633. 	    pline("This doorway has no door."); 634. 	    return(0); 635. 	}  636.   637.  	if(obstructed(x, y)) return(0); 638.  639.  	if(door->doormask == D_BROKEN) { 640. 	    pline("This door is broken."); 641. 	    return(0); 642. 	}  643.   644.  	if(door->doormask & (D_CLOSED | D_LOCKED)) { 645. 	    pline("This door is already closed."); 646. 	    return(0); 647. 	}  648.   649.  	if(door->doormask == D_ISOPEN) { 650. 	    if(verysmall(uasmon)) { 651. 		 pline("You're too small to push the door closed."); 652. 		 return(0); 653. 	    }  654.  	    if (rn2(25) < (ACURRSTR+ACURR(A_DEX)+ACURR(A_CON))/3) { 655. 		pline_The("door closes."); 656. 		door->doormask = D_CLOSED; 657. 		if (Blind) 658. 		    feel_location(x,y);	/* the hero knows she closed it */ 659. 		else 660. 		    newsym(x,y); 661. 		block_point(x,y);	/* vision:  no longer see there */ 662. 	    }  663.  	    else { 664. 	        exercise(A_STR, TRUE); 665. 	        pline_The("door resists!"); 666. 	    }  667.  	}  668.   669.  	return(1); 670. }  671.   672.  boolean			/* box obj was hit with spell effect otmp */ 673. boxlock(obj, otmp)	/* returns true if something happened */ 674. register struct obj *obj, *otmp;	/* obj *is* a box */ 675. {  676.  	register boolean res = 0; 677.  678.  	switch(otmp->otyp) { 679. 	case WAN_LOCKING: 680. 	case SPE_WIZARD_LOCK: 681. 	    if (!obj->olocked) {	/* lock it; fix if broken */ 682. 		pline("Klunk!"); 683. 		obj->olocked = 1; 684. 		obj->obroken = 0; 685. 		res = 1; 686. 	    } /* else already closed and locked */ 687. 	    break; 688. 	case WAN_OPENING: 689. 	case SPE_KNOCK: 690. 	    if (obj->olocked) {		/* unlock; couldn't be broken */ 691. 		pline("Klick!"); 692. 		obj->olocked = 0; 693. 		res = 1; 694. 	    } else			/* silently fix if broken */ 695. 		obj->obroken = 0; 696. 	    break; 697. 	case WAN_POLYMORPH: 698. 	case SPE_POLYMORPH: 699. 	    /* maybe start unlocking chest, get interrupted, then zap it; 700. 	       we must avoid any attempt to resume unlocking it */ 701. 	    if (xlock.box == obj) 702. 		reset_pick; 703. 	    break; 704. 	}  705.  	return res; 706. }  707.   708.  boolean			/* Door/secret door was hit with spell effect otmp */ 709. doorlock(otmp,x,y)	/* returns true if something happened */ 710. struct obj *otmp; 711. int x, y;  712. { 713.  	register struct rm *door = &levl[x][y]; 714. 	boolean res = TRUE; 715. 	int loudness = 0; 716. 	const char *msg = (const char *)0; 717. 	const char *dustcloud = "A cloud of dust"; 718. 	const char *quickly_dissipates = "quickly dissipates"; 719. 	  720.  	if (door->typ == SDOOR) { 721. 	    if (otmp->otyp == WAN_OPENING || otmp->otyp == SPE_KNOCK) { 722. 		door->typ = DOOR; 723. 		door->doormask = D_CLOSED | (door->doormask & D_TRAPPED); 724. 		if (cansee(x,y)) pline("A door appears in the wall!"); 725. 		newsym(x,y); 726. 		return TRUE; 727. 	    } else 728. 		return FALSE; 729. 	}  730.   731.  	switch(otmp->otyp) { 732. 	case WAN_LOCKING: 733. 	case SPE_WIZARD_LOCK: 734. #ifdef REINCARNATION 735. 	    if (Is_rogue_level(&u.uz)) { 736. 		/* Can't have real locking in Rogue, so just hide doorway */ 737. 		pline("%s springs up in the older, more primitive doorway.",  738.  			dustcloud); 739. 		if (obstructed(x,y)) { 740. 			pline_The("cloud %s.",quickly_dissipates); 741. 			return FALSE; 742. 		}  743.  		block_point(x, y); 744. 		door->typ = SDOOR; 745. 		if (cansee(x,y)) pline_The("doorway vanishes!"); 746. 		newsym(x,y); 747. 		return TRUE; 748. 	    }  749.  #endif 750. 	    if (obstructed(x,y)) return FALSE; 751. 	    /* Don't allow doors to close over traps. This is for pits */ 752. 	    /* & trap doors, but is it ever OK for anything else? */ 753.  	    if (t_at(x,y)) { 754. 		/* maketrap clears doormask, so it should be NODOOR */ 755. 		pline(  756.  		"%s springs up in the doorway, but %s.",  757.  		dustcloud, quickly_dissipates); 758. 		return FALSE; 759. 	    }  760.   761.  	    switch (door->doormask & ~D_TRAPPED) { 762. 	    case D_CLOSED: 763. 		msg = "The door locks!"; 764. 		break; 765. 	    case D_ISOPEN: 766. 		msg = "The door swings shut, and locks!"; 767. 		break; 768. 	    case D_BROKEN: 769. 		msg = "The broken door reassembles and locks!"; 770. 		break; 771. 	    case D_NODOOR: 772. 		msg = 773. 		"A cloud of dust springs up and assembles itself into a door!"; 774. 		break; 775. 	    default: 776. 		res = FALSE; 777. 		break; 778. 	    }  779.  	    block_point(x, y); 780. 	    door->doormask = D_LOCKED | (door->doormask & D_TRAPPED); 781. 	    newsym(x,y); 782. 	    break; 783. 	case WAN_OPENING: 784. 	case SPE_KNOCK: 785. 	    if (door->doormask & D_LOCKED) { 786. 		msg = "The door unlocks!"; 787. 		door->doormask = D_CLOSED | (door->doormask & D_TRAPPED); 788. 	    } else res = FALSE; 789. 	    break; 790. 	case WAN_STRIKING: 791. 	case SPE_FORCE_BOLT: 792. 	    if (door->doormask & (D_LOCKED | D_CLOSED)) { 793. 		if (door->doormask & D_TRAPPED) { 794. 		    if (MON_AT(x, y)) 795. 			(void) mb_trapped(m_at(x,y)); 796. 		    else if (flags.verbose) { 797. 			if (cansee(x,y)) 798. 			    pline("KABOOM!!  You see a door explode."); 799. 			else if (flags.soundok) 800. 			    You_hear("a distant explosion."); 801. 		    }  802.  		    door->doormask = D_NODOOR; 803. 		    unblock_point(x,y); 804. 		    newsym(x,y); 805. 		    loudness = 40; 806. 		    break; 807. 		}  808.  		door->doormask = D_BROKEN; 809. 		if (flags.verbose) { 810. 		    if (cansee(x,y)) 811. 			pline_The("door crashes open!"); 812. 		    else if (flags.soundok) 813. 			You_hear("a crashing sound."); 814. 		}  815.  		unblock_point(x,y); 816. 		newsym(x,y); 817. 		loudness = 20; 818. 	    } else res = FALSE; 819. 	    break; 820. 	default: impossible("magic (%d) attempted on door.", otmp->otyp); 821. 	    break; 822. 	}  823.  	if (msg && cansee(x,y)) pline(msg); 824. 	if (loudness > 0) { 825. 	    /* door was destroyed */ 826. 	    wake_nearto(x, y, loudness); 827. 	    if (*in_rooms(x, y, SHOPBASE)) add_damage(x, y, 0L); 828. 	}  829.   830.  	if (res && picking_at(x, y)) { 831. 	    /* maybe unseen monster zaps door you're unlocking */ 832. 	    stop_occupation; 833. 	    reset_pick; 834. 	}  835.  	return res; 836. }  837.   838.  static void 839. chest_shatter_msg(otmp) 840. struct obj *otmp; 841. {  842.  	const char *disposition, *article = (otmp->quan > 1L) ? "A" : "The"; 843. 	const char *thing; 844. 	long save_Blinded; 845.  846.  	if (otmp->oclass == POTION_CLASS) { 847. 		You("%s a flask shatter!", Blind ? "hear" : "see"); 848. 		potionbreathe(otmp); 849. 		return; 850. 	}  851.  	/* We have functions for distant and singular names, but not one */ 852. 	/* which does _both_... */ 853.  	save_Blinded = Blinded; 854. 	Blinded = 1; 855. 	thing = singular(otmp, xname); 856. 	Blinded = save_Blinded; 857. 	switch (objects[otmp->otyp].oc_material) { 858. 	case PAPER:	disposition = "is torn to shreds"; 859. 		break; 860. 	case WAX:	disposition = "is crushed"; 861. 		break; 862. 	case VEGGY:	disposition = "is pulped"; 863. 		break; 864. 	case FLESH:	disposition = "is mashed"; 865. 		break; 866. 	case GLASS:	disposition = "shatters"; 867. 		break; 868. 	case WOOD:	disposition = "splinters to fragments"; 869. 		break; 870. 	default:	disposition = "is destroyed"; 871. 		break; 872. 	}  873.  	pline("%s %s %s!", article, thing, disposition); 874. }  875.   876.  #endif /* OVLB */ 877.  878.  /*lock.c*/