Source:Lock.c

Below is the full text to src/lock.c from NetHack 3.4.3. To link to a particular line, write [[lock.c#line123 ]], for example. 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 picktyp, c, ch; 230. 	coord cc; 231. 	struct rm	*door; 232. 	struct obj	*otmp; 233. 	char qbuf[QBUFSZ]; 234.  235.  	picktyp = pick->otyp; 236.  237.  	/* check whether we're resuming an interrupted previous attempt */ 238. 	if (xlock.usedtime && picktyp == xlock.picktyp) { 239. 	    static char no_longer[] = "Unfortunately, you can no longer %s %s."; 240.  241.  	    if (nohands(youmonst.data)) { 242. 		const char *what = (picktyp == LOCK_PICK) ? "pick" : "key"; 243. #ifdef TOURIST 244. 		if (picktyp == CREDIT_CARD) what = "card"; 245. #endif 246. 		pline(no_longer, "hold the", what); 247. 		reset_pick; 248. 		return 0; 249. 	    } else if (xlock.box && !can_reach_floor) { 250. 		pline(no_longer, "reach the", "lock"); 251. 		reset_pick; 252. 		return 0; 253. 	    } else { 254. 		const char *action = lock_action; 255. 		You("resume your attempt at %s.", action); 256. 		set_occupation(picklock, action, 0); 257. 		return(1); 258. 	    }  259.  	}  260.   261.  	if(nohands(youmonst.data)) { 262. 		You_cant("hold %s -- you have no hands!", doname(pick)); 263. 		return(0); 264. 	}  265.   266.  	if((picktyp != LOCK_PICK && 267. #ifdef TOURIST 268. 	    picktyp != CREDIT_CARD && 269. #endif 270. 	    picktyp != SKELETON_KEY)) { 271. 		impossible("picking lock with object %d?", picktyp); 272. 		return(0); 273. 	}  274.  	ch = 0;		/* lint suppression */ 275.  276.  	if(!get_adjacent_loc((char *)0, "Invalid location!", u.ux, u.uy, &cc)) return 0; 277. 	if (cc.x == u.ux && cc.y == u.uy) {	/* pick lock on a container */ 278. 	    const char *verb; 279. 	    boolean it; 280. 	    int count; 281.  282.  	    if (u.dz < 0) { 283. 		There("isn't any sort of lock up %s.",  284.  		      Levitation ? "here" : "there"); 285. 		return 0; 286. 	    } else if (is_lava(u.ux, u.uy)) { 287. 		pline("Doing that would probably melt your %s.",  288.  		      xname(pick)); 289. 		return 0; 290. 	    } else if (is_pool(u.ux, u.uy) && !Underwater) { 291. 		pline_The("water has no lock."); 292. 		return 0; 293. 	    }  294.   295.  	    count = 0; 296. 	    c = 'n';			/* in case there are no boxes here */ 297. 	    for(otmp = level.objects[cc.x][cc.y]; otmp; otmp = otmp->nexthere) 298. 		if (Is_box(otmp)) { 299. 		    ++count; 300. 		    if (!can_reach_floor) { 301. 			You_cant("reach %s from up here.", the(xname(otmp))); 302. 			return 0; 303. 		    }  304.  		    it = 0; 305. 		    if (otmp->obroken) verb = "fix"; 306. 		    else if (!otmp->olocked) verb = "lock", it = 1; 307. 		    else if (picktyp != LOCK_PICK) verb = "unlock", it = 1; 308. 		    else verb = "pick"; 309. 		    Sprintf(qbuf, "There is %s here, %s %s?",  310.  		    	    safe_qbuf("", sizeof("There is  here, unlock its lock?"), 311. 			    	doname(otmp), an(simple_typename(otmp->otyp)), "a box"),  312.  			    verb, it ? "it" : "its lock"); 313.  314.  		    c = ynq(qbuf); 315. 		    if(c == 'q') return(0); 316. 		    if(c == 'n') continue; 317.  318.  		    if (otmp->obroken) { 319. 			You_cant("fix its broken lock with %s.", doname(pick)); 320. 			return 0; 321. 		    }  322.  #ifdef TOURIST 323. 		    else if (picktyp == CREDIT_CARD && !otmp->olocked) { 324. 			/* credit cards are only good for unlocking */ 325. 			You_cant("do that with %s.", doname(pick)); 326. 			return 0; 327. 		    }  328.  #endif 329. 		    switch(picktyp) { 330. #ifdef TOURIST 331. 			case CREDIT_CARD: 332. 			    ch = ACURR(A_DEX) + 20*Role_if(PM_ROGUE); 333. 			    break; 334. #endif 335. 			case LOCK_PICK: 336. 			    ch = 4*ACURR(A_DEX) + 25*Role_if(PM_ROGUE); 337. 			    break; 338. 			case SKELETON_KEY: 339. 			    ch = 75 + ACURR(A_DEX); 340. 			    break; 341. 			default:	ch = 0; 342. 		    }  343.  		    if(otmp->cursed) ch /= 2; 344.  345.  		    xlock.picktyp = picktyp; 346. 		    xlock.box = otmp; 347. 		    xlock.door = 0; 348. 		    break; 349. 		}  350.  	    if (c != 'y') { 351. 		if (!count) 352. 		    There("doesn't seem to be any sort of lock here."); 353. 		return(0);		/* decided against all boxes */ 354. 	    }  355.  	} else {			/* pick the lock in a door */ 356. 	    struct monst *mtmp; 357.  358.  	    if (u.utrap && u.utraptype == TT_PIT) { 359. 		You_cant("reach over the edge of the pit."); 360. 		return(0); 361. 	    }  362.   363.  	    door = &levl[cc.x][cc.y]; 364. 	    if ((mtmp = m_at(cc.x, cc.y)) && canseemon(mtmp)  365.  			&& mtmp->m_ap_type != M_AP_FURNITURE  366.  			&& mtmp->m_ap_type != M_AP_OBJECT) { 367. #ifdef TOURIST 368. 		if (picktyp == CREDIT_CARD &&  369.  		    (mtmp->isshk || mtmp->data == &mons[PM_ORACLE])) 370. 		    verbalize("No checks, no credit, no problem."); 371. 		else 372. #endif 373. 		    pline("I don't think %s would appreciate that.", mon_nam(mtmp)); 374. 		return(0); 375. 	    }  376.  	    if(!IS_DOOR(door->typ)) { 377. 		if (is_drawbridge_wall(cc.x,cc.y) >= 0) 378. 		    You("%s no lock on the drawbridge.",  379.  				Blind ? "feel" : "see"); 380. 		else 381. 		    You("%s no door there.",  382.  				Blind ? "feel" : "see"); 383. 		return(0); 384. 	    }  385.  	    switch (door->doormask) { 386. 		case D_NODOOR: 387. 		    pline("This doorway has no door."); 388. 		    return(0); 389. 		case D_ISOPEN: 390. 		    You("cannot lock an open door."); 391. 		    return(0); 392. 		case D_BROKEN: 393. 		    pline("This door is broken."); 394. 		    return(0); 395. 		default: 396. #ifdef TOURIST 397. 		    /* credit cards are only good for unlocking */ 398. 		    if(picktyp == CREDIT_CARD && !(door->doormask & D_LOCKED)) { 399. 			You_cant("lock a door with a credit card."); 400. 			return(0); 401. 		    }  402.  #endif 403.  404.  		    Sprintf(qbuf,"%sock it?",  405.  			(door->doormask & D_LOCKED) ? "Unl" : "L" ); 406.  407.  		    c = yn(qbuf); 408. 		    if(c == 'n') return(0); 409.  410.  		    switch(picktyp) { 411. #ifdef TOURIST 412. 			case CREDIT_CARD: 413. 			    ch = 2*ACURR(A_DEX) + 20*Role_if(PM_ROGUE); 414. 			    break; 415. #endif 416. 			case LOCK_PICK: 417. 			    ch = 3*ACURR(A_DEX) + 30*Role_if(PM_ROGUE); 418. 			    break; 419. 			case SKELETON_KEY: 420. 			    ch = 70 + ACURR(A_DEX); 421. 			    break; 422. 			default:    ch = 0; 423. 		    }  424.  		    xlock.door = door; 425. 		    xlock.box = 0; 426. 	    }  427.  	}  428.  	flags.move = 0; 429. 	xlock.chance = ch; 430. 	xlock.picktyp = picktyp; 431. 	xlock.usedtime = 0; 432. 	set_occupation(picklock, lock_action, 0); 433. 	return(1); 434. }  435.   436.  int 437. doforce		/* try to force a chest with your weapon */ 438. {  439.  	register struct obj *otmp; 440. 	register int c, picktyp; 441. 	char qbuf[QBUFSZ]; 442.  443.  	if(!uwep ||	/* proper type test */  444.  	   (uwep->oclass != WEAPON_CLASS && !is_weptool(uwep) && 445. 	    uwep->oclass != ROCK_CLASS) ||  446.  	   (objects[uwep->otyp].oc_skill < P_DAGGER) ||  447.  	   (objects[uwep->otyp].oc_skill > P_LANCE) ||  448.  	   uwep->otyp == FLAIL || uwep->otyp == AKLYS  449.  #ifdef KOPS  450.  	   || uwep->otyp == RUBBER_HOSE  451.  #endif  452.  	  ) { 453. 	    You_cant("force anything without a %sweapon.",  454.  		  (uwep) ? "proper " : ""); 455. 	    return(0); 456. 	}  457.   458.  	picktyp = is_blade(uwep); 459. 	if(xlock.usedtime && xlock.box && picktyp == xlock.picktyp) { 460. 	    You("resume your attempt to force the lock."); 461. 	    set_occupation(forcelock, "forcing the lock", 0); 462. 	    return(1); 463. 	}  464.   465.  	/* A lock is made only for the honest man, the thief will break it. */ 466.  	xlock.box = (struct obj *)0; 467. 	for(otmp = level.objects[u.ux][u.uy]; otmp; otmp = otmp->nexthere) 468. 	    if(Is_box(otmp)) { 469. 		if (otmp->obroken || !otmp->olocked) { 470. 		    There("is %s here, but its lock is already %s.",  471.  			  doname(otmp), otmp->obroken ? "broken" : "unlocked"); 472. 		    continue; 473. 		}  474.  		Sprintf(qbuf,"There is %s here, force its lock?",  475.  			safe_qbuf("", sizeof("There is  here, force its lock?"), 476. 				doname(otmp), an(simple_typename(otmp->otyp)), 477. 				"a box")); 478.  479.  		c = ynq(qbuf); 480. 		if(c == 'q') return(0); 481. 		if(c == 'n') continue; 482.  483.  		if(picktyp) 484. 		    You("force your %s into a crack and pry.", xname(uwep)); 485. 		else 486. 		    You("start bashing it with your %s.", xname(uwep)); 487. 		xlock.box = otmp; 488. 		xlock.chance = objects[uwep->otyp].oc_wldam * 2; 489. 		xlock.picktyp = picktyp; 490. 		xlock.usedtime = 0; 491. 		break; 492. 	    }  493.   494.  	if(xlock.box)	set_occupation(forcelock, "forcing the lock", 0); 495. 	else		You("decide not to force the issue."); 496. 	return(1); 497. }  498.   499.  int 500. doopen		/* try to open a door */ 501. {  502.  	coord cc; 503. 	register struct rm *door; 504. 	struct monst *mtmp; 505.  506.  	if (nohands(youmonst.data)) { 507. 	    You_cant("open anything -- you have no hands!"); 508. 	    return 0; 509. 	}  510.   511.  	if (u.utrap && u.utraptype == TT_PIT) { 512. 	    You_cant("reach over the edge of the pit."); 513. 	    return 0; 514. 	}  515.   516.  	if(!get_adjacent_loc((char *)0, (char *)0, u.ux, u.uy, &cc)) return(0); 517.  518.  	if((cc.x == u.ux) && (cc.y == u.uy)) return(0); 519.  520.  	if ((mtmp = m_at(cc.x,cc.y))			&&  521.  		mtmp->m_ap_type == M_AP_FURNITURE	&&  522.  		(mtmp->mappearance == S_hcdoor || 523. 			mtmp->mappearance == S_vcdoor)	&&  524.  		!Protection_from_shape_changers)	 { 525.  526.  	    stumble_onto_mimic(mtmp); 527. 	    return(1); 528. 	}  529.   530.  	door = &levl[cc.x][cc.y]; 531.  532.  	if(!IS_DOOR(door->typ)) { 533. 		if (is_db_wall(cc.x,cc.y)) { 534. 		    There("is no obvious way to open the drawbridge."); 535. 		    return(0); 536. 		}  537.  		You("%s no door there.",  538.  				Blind ? "feel" : "see"); 539. 		return(0); 540. 	}  541.   542.  	if (!(door->doormask & D_CLOSED)) { 543. 	    const char *mesg; 544.  545.  	    switch (door->doormask) { 546. 	    case D_BROKEN: mesg = " is broken"; break; 547. 	    case D_NODOOR: mesg = "way has no door"; break; 548. 	    case D_ISOPEN: mesg = " is already open"; break; 549. 	    default:	   mesg = " is locked"; break; 550. 	    }  551.  	    pline("This door%s.", mesg); 552. 	    if (Blind) feel_location(cc.x,cc.y); 553. 	    return(0); 554. 	}  555.   556.  	if(verysmall(youmonst.data)) { 557. 	    pline("You're too small to pull the door open."); 558. 	    return(0); 559. 	}  560.   561.  	/* door is known to be CLOSED */ 562. 	if (rnl(20) < (ACURRSTR+ACURR(A_DEX)+ACURR(A_CON))/3) { 563. 	    pline_The("door opens."); 564. 	    if(door->doormask & D_TRAPPED) { 565. 		b_trapped("door", FINGER); 566. 		door->doormask = D_NODOOR; 567. 		if (*in_rooms(cc.x, cc.y, SHOPBASE)) add_damage(cc.x, cc.y, 0L); 568. 	    } else 569. 		door->doormask = D_ISOPEN; 570. 	    if (Blind) 571. 		feel_location(cc.x,cc.y);	/* the hero knows she opened it  */ 572. 	    else 573. 		newsym(cc.x,cc.y); 574. 	    unblock_point(cc.x,cc.y);		/* vision: new see through there */ 575. 	} else { 576. 	    exercise(A_STR, TRUE); 577. 	    pline_The("door resists!"); 578. 	}  579.   580.  	return(1); 581. }  582.   583.  STATIC_OVL 584. boolean 585. obstructed(x,y) 586. register int x, y;  587. { 588.  	register struct monst *mtmp = m_at(x, y); 589.  590.  	if(mtmp && mtmp->m_ap_type != M_AP_FURNITURE) { 591. 		if (mtmp->m_ap_type == M_AP_OBJECT) goto objhere; 592. 		pline("%s stands in the way!", !canspotmon(mtmp) ?  593.  			"Some creature" : Monnam(mtmp)); 594. 		if (!canspotmon(mtmp)) 595. 		    map_invisible(mtmp->mx, mtmp->my); 596. 		return(TRUE); 597. 	}  598.  	if (OBJ_AT(x, y)) { 599. objhere:	pline("%s's in the way.", Something); 600. 		return(TRUE); 601. 	}  602.  	return(FALSE); 603. }  604.   605.  int 606. doclose		/* try to close a door */ 607. {  608.  	register int x, y;  609. register struct rm *door; 610. 	struct monst *mtmp; 611.  612.  	if (nohands(youmonst.data)) { 613. 	    You_cant("close anything -- you have no hands!"); 614. 	    return 0; 615. 	}  616.   617.  	if (u.utrap && u.utraptype == TT_PIT) { 618. 	    You_cant("reach over the edge of the pit."); 619. 	    return 0; 620. 	}  621.   622.  	if(!getdir((char *)0)) return(0); 623.  624.  	x = u.ux + u.dx; 625. 	y = u.uy + u.dy; 626. 	if((x == u.ux) && (y == u.uy)) { 627. 		You("are in the way!"); 628. 		return(1); 629. 	}  630.   631.  	if ((mtmp = m_at(x,y))				&&  632.  		mtmp->m_ap_type == M_AP_FURNITURE	&&  633.  		(mtmp->mappearance == S_hcdoor || 634. 			mtmp->mappearance == S_vcdoor)	&&  635.  		!Protection_from_shape_changers)	 { 636.  637.  	    stumble_onto_mimic(mtmp); 638. 	    return(1); 639. 	}  640.   641.  	door = &levl[x][y]; 642.  643.  	if(!IS_DOOR(door->typ)) { 644. 		if (door->typ == DRAWBRIDGE_DOWN) 645. 		    There("is no obvious way to close the drawbridge."); 646. 		else 647. 		    You("%s no door there.",  648.  				Blind ? "feel" : "see"); 649. 		return(0); 650. 	}  651.   652.  	if(door->doormask == D_NODOOR) { 653. 	    pline("This doorway has no door."); 654. 	    return(0); 655. 	}  656.   657.  	if(obstructed(x, y)) return(0); 658.  659.  	if(door->doormask == D_BROKEN) { 660. 	    pline("This door is broken."); 661. 	    return(0); 662. 	}  663.   664.  	if(door->doormask & (D_CLOSED | D_LOCKED)) { 665. 	    pline("This door is already closed."); 666. 	    return(0); 667. 	}  668.   669.  	if(door->doormask == D_ISOPEN) { 670. 	    if(verysmall(youmonst.data)  671.  #ifdef STEED  672.  		&& !u.usteed  673.  #endif  674.  		) { 675. 		 pline("You're too small to push the door closed."); 676. 		 return(0); 677. 	    }  678.  	    if (  679.  #ifdef STEED  680.  		 u.usteed ||  681.  #endif  682.  		rn2(25) < (ACURRSTR+ACURR(A_DEX)+ACURR(A_CON))/3) { 683. 		pline_The("door closes."); 684. 		door->doormask = D_CLOSED; 685. 		if (Blind) 686. 		    feel_location(x,y);	/* the hero knows she closed it */ 687. 		else 688. 		    newsym(x,y); 689. 		block_point(x,y);	/* vision:  no longer see there */ 690. 	    }  691.  	    else { 692. 	        exercise(A_STR, TRUE); 693. 	        pline_The("door resists!"); 694. 	    }  695.  	}  696.   697.  	return(1); 698. }  699.   700.  boolean			/* box obj was hit with spell effect otmp */ 701. boxlock(obj, otmp)	/* returns true if something happened */ 702. register struct obj *obj, *otmp;	/* obj *is* a box */ 703. {  704.  	register boolean res = 0; 705.  706.  	switch(otmp->otyp) { 707. 	case WAN_LOCKING: 708. 	case SPE_WIZARD_LOCK: 709. 	    if (!obj->olocked) {	/* lock it; fix if broken */ 710. 		pline("Klunk!"); 711. 		obj->olocked = 1; 712. 		obj->obroken = 0; 713. 		res = 1; 714. 	    } /* else already closed and locked */ 715. 	    break; 716. 	case WAN_OPENING: 717. 	case SPE_KNOCK: 718. 	    if (obj->olocked) {		/* unlock; couldn't be broken */ 719. 		pline("Klick!"); 720. 		obj->olocked = 0; 721. 		res = 1; 722. 	    } else			/* silently fix if broken */ 723. 		obj->obroken = 0; 724. 	    break; 725. 	case WAN_POLYMORPH: 726. 	case SPE_POLYMORPH: 727. 	    /* maybe start unlocking chest, get interrupted, then zap it; 728. 	       we must avoid any attempt to resume unlocking it */ 729. 	    if (xlock.box == obj) 730. 		reset_pick; 731. 	    break; 732. 	}  733.  	return res; 734. }  735.   736.  boolean			/* Door/secret door was hit with spell effect otmp */ 737. doorlock(otmp,x,y)	/* returns true if something happened */ 738. struct obj *otmp; 739. int x, y;  740. { 741.  	register struct rm *door = &levl[x][y]; 742. 	boolean res = TRUE; 743. 	int loudness = 0; 744. 	const char *msg = (const char *)0; 745. 	const char *dustcloud = "A cloud of dust"; 746. 	const char *quickly_dissipates = "quickly dissipates"; 747. 	  748.  	if (door->typ == SDOOR) { 749. 	    switch (otmp->otyp) { 750. 	    case WAN_OPENING: 751. 	    case SPE_KNOCK: 752. 	    case WAN_STRIKING: 753. 	    case SPE_FORCE_BOLT: 754. 		door->typ = DOOR; 755. 		door->doormask = D_CLOSED | (door->doormask & D_TRAPPED); 756. 		newsym(x,y); 757. 		if (cansee(x,y)) pline("A door appears in the wall!"); 758. 		if (otmp->otyp == WAN_OPENING || otmp->otyp == SPE_KNOCK) 759. 		    return TRUE; 760. 		break;		/* striking: continue door handling below */ 761. 	    case WAN_LOCKING: 762. 	    case SPE_WIZARD_LOCK: 763. 	    default: 764. 		return FALSE; 765. 	    }  766.  	}  767.   768.  	switch(otmp->otyp) { 769. 	case WAN_LOCKING: 770. 	case SPE_WIZARD_LOCK: 771. #ifdef REINCARNATION 772. 	    if (Is_rogue_level(&u.uz)) { 773. 	    	boolean vis = cansee(x,y); 774. 		/* Can't have real locking in Rogue, so just hide doorway */ 775. 		if (vis) pline("%s springs up in the older, more primitive doorway.",  776.  			dustcloud); 777. 		else 778. 			You_hear("a swoosh."); 779. 		if (obstructed(x,y)) { 780. 			if (vis) pline_The("cloud %s.",quickly_dissipates); 781. 			return FALSE; 782. 		}  783.  		block_point(x, y); 784. 		door->typ = SDOOR; 785. 		if (vis) pline_The("doorway vanishes!"); 786. 		newsym(x,y); 787. 		return TRUE; 788. 	    }  789.  #endif 790. 	    if (obstructed(x,y)) return FALSE; 791. 	    /* Don't allow doors to close over traps. This is for pits */ 792. 	    /* & trap doors, but is it ever OK for anything else? */ 793.  	    if (t_at(x,y)) { 794. 		/* maketrap clears doormask, so it should be NODOOR */ 795. 		pline(  796.  		"%s springs up in the doorway, but %s.",  797.  		dustcloud, quickly_dissipates); 798. 		return FALSE; 799. 	    }  800.   801.  	    switch (door->doormask & ~D_TRAPPED) { 802. 	    case D_CLOSED: 803. 		msg = "The door locks!"; 804. 		break; 805. 	    case D_ISOPEN: 806. 		msg = "The door swings shut, and locks!"; 807. 		break; 808. 	    case D_BROKEN: 809. 		msg = "The broken door reassembles and locks!"; 810. 		break; 811. 	    case D_NODOOR: 812. 		msg = 813. 		"A cloud of dust springs up and assembles itself into a door!"; 814. 		break; 815. 	    default: 816. 		res = FALSE; 817. 		break; 818. 	    }  819.  	    block_point(x, y); 820. 	    door->doormask = D_LOCKED | (door->doormask & D_TRAPPED); 821. 	    newsym(x,y); 822. 	    break; 823. 	case WAN_OPENING: 824. 	case SPE_KNOCK: 825. 	    if (door->doormask & D_LOCKED) { 826. 		msg = "The door unlocks!"; 827. 		door->doormask = D_CLOSED | (door->doormask & D_TRAPPED); 828. 	    } else res = FALSE; 829. 	    break; 830. 	case WAN_STRIKING: 831. 	case SPE_FORCE_BOLT: 832. 	    if (door->doormask & (D_LOCKED | D_CLOSED)) { 833. 		if (door->doormask & D_TRAPPED) { 834. 		    if (MON_AT(x, y)) 835. 			(void) mb_trapped(m_at(x,y)); 836. 		    else if (flags.verbose) { 837. 			if (cansee(x,y)) 838. 			    pline("KABOOM!!  You see a door explode."); 839. 			else if (flags.soundok) 840. 			    You_hear("a distant explosion."); 841. 		    }  842.  		    door->doormask = D_NODOOR; 843. 		    unblock_point(x,y); 844. 		    newsym(x,y); 845. 		    loudness = 40; 846. 		    break; 847. 		}  848.  		door->doormask = D_BROKEN; 849. 		if (flags.verbose) { 850. 		    if (cansee(x,y)) 851. 			pline_The("door crashes open!"); 852. 		    else if (flags.soundok) 853. 			You_hear("a crashing sound."); 854. 		}  855.  		unblock_point(x,y); 856. 		newsym(x,y); 857. 		/* force vision recalc before printing more messages */ 858. 		if (vision_full_recalc) vision_recalc(0); 859. 		loudness = 20; 860. 	    } else res = FALSE; 861. 	    break; 862. 	default: impossible("magic (%d) attempted on door.", otmp->otyp); 863. 	    break; 864. 	}  865.  	if (msg && cansee(x,y)) pline(msg); 866. 	if (loudness > 0) { 867. 	    /* door was destroyed */ 868. 	    wake_nearto(x, y, loudness); 869. 	    if (*in_rooms(x, y, SHOPBASE)) add_damage(x, y, 0L); 870. 	}  871.   872.  	if (res && picking_at(x, y)) { 873. 	    /* maybe unseen monster zaps door you're unlocking */ 874. 	    stop_occupation; 875. 	    reset_pick; 876. 	}  877.  	return res; 878. }  879.   880.  STATIC_OVL void 881. chest_shatter_msg(otmp) 882. struct obj *otmp; 883. {  884.  	const char *disposition; 885. 	const char *thing; 886. 	long save_Blinded; 887.  888.  	if (otmp->oclass == POTION_CLASS) { 889. 		You("%s %s shatter!", Blind ? "hear" : "see", an(bottlename)); 890. 		if (!breathless(youmonst.data) || haseyes(youmonst.data)) 891. 			potionbreathe(otmp); 892. 		return; 893. 	}  894.  	/* We have functions for distant and singular names, but not one */ 895. 	/* which does _both_... */ 896.  	save_Blinded = Blinded; 897. 	Blinded = 1; 898. 	thing = singular(otmp, xname); 899. 	Blinded = save_Blinded; 900. 	switch (objects[otmp->otyp].oc_material) { 901. 	case PAPER:	disposition = "is torn to shreds"; 902. 		break; 903. 	case WAX:	disposition = "is crushed"; 904. 		break; 905. 	case VEGGY:	disposition = "is pulped"; 906. 		break; 907. 	case FLESH:	disposition = "is mashed"; 908. 		break; 909. 	case GLASS:	disposition = "shatters"; 910. 		break; 911. 	case WOOD:	disposition = "splinters to fragments"; 912. 		break; 913. 	default:	disposition = "is destroyed"; 914. 		break; 915. 	}  916.  	pline("%s %s!", An(thing), disposition); 917. }  918.   919.  #endif /* OVLB */ 920.  921.  /*lock.c*/