Source:SLASH'EM 0.0.7E7F2/lock.c

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

The latest source code for vanilla NetHack is at 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.   STATIC_PTR int NDECL(forcedoor); 10.   11.   /* at most one of `door' and `box' should be non-null at any given time */ 12.  STATIC_VAR NEARDATA struct xlock_s { 13.  	struct rm  *door; 14.  	struct obj *box; 15.  	int picktyp, chance, usedtime; 16.  	/* ALI - Artifact doors */ 17.  	int key;			/* Key being used (doors only) */ 18.  } xlock; 19.   20.   #ifdef OVLB 21.   22.   STATIC_DCL const char *NDECL(lock_action); 23.  STATIC_DCL boolean FDECL(obstructed,(int,int)); 24.  STATIC_DCL void FDECL(chest_shatter_msg, (struct obj *)); 25.   26.   boolean 27.  picking_lock(x, y)  28. int *x, *y; 29.  {  30.   	if (occupation == picklock) { 31.  	    *x = u.ux + u.dx; 32.  	    *y = u.uy + u.dy; 33.  	    return TRUE; 34.  	} else { 35.  	    *x = *y = 0; 36.  	    return FALSE; 37.  	}  38.   }  39.    40.   boolean 41.  picking_at(x, y)  42. int x, y; 43. { 44.   	return (boolean)(occupation == picklock && xlock.door == &levl[x][y]); 45.  }  46.    47.   /* produce an occupation string appropriate for the current activity */ 48.  STATIC_OVL const char * 49.  lock_action 50.  {  51.   	/* "unlocking"+2 == "locking" */ 52.  	static const char *actions[] = { 53.  		/* [0] */	"unlocking the door", 54.  		/* [1] */	"unlocking the chest", 55.  		/* [2] */	"unlocking the box", 56.  		/* [3] */	"picking the lock" 57.  	};  58.    59.   	/* if the target is currently unlocked, we're trying to lock it now */ 60.  	if (xlock.door && !(xlock.door->doormask & D_LOCKED)) 61.  		return actions[0]+2;	/* "locking the door" */ 62.  	else if (xlock.box && !xlock.box->olocked) 63.  		return xlock.box->otyp == CHEST ? actions[1]+2 : actions[2]+2; 64.  	/* otherwise we're trying to unlock it */ 65.  	else if (xlock.picktyp == LOCK_PICK) 66.  		return actions[3];	/* "picking the lock" */ 67.  #ifdef TOURIST 68.  	else if (xlock.picktyp == CREDIT_CARD) 69.  		return actions[3];	/* same as lock_pick */ 70.  #endif 71.  	else if (xlock.door) 72.  		return actions[0];	/* "unlocking the door" */ 73.  	else 74.  		return xlock.box->otyp == CHEST ? actions[1] : actions[2]; 75.  }  76.    77.   STATIC_PTR 78.  int 79.  picklock	/* try to open/close a lock */ 80.  {  81.    82.   	if (xlock.box) { 83.  	    if((xlock.box->ox != u.ux) || (xlock.box->oy != u.uy)) { 84.  		return((xlock.usedtime = 0));		/* you or it moved */ 85.  	    }  86.   	} else {		/* door */ 87.  	    if(xlock.door != &(levl[u.ux+u.dx][u.uy+u.dy])) { 88.  		return((xlock.usedtime = 0));		/* you moved */ 89.  	    }  90.   	    switch (xlock.door->doormask) { 91.  		case D_NODOOR: 92.  		    pline("This doorway has no door."); 93.  		    return((xlock.usedtime = 0)); 94.  		case D_ISOPEN: 95.  		    You("cannot lock an open door."); 96.  		    return((xlock.usedtime = 0)); 97.  		case D_BROKEN: 98.  		    pline("This door is broken."); 99.  		    return((xlock.usedtime = 0)); 100. 	    }  101.  	}  102.   103.  	if (xlock.usedtime++ >= 50 || nohands(youmonst.data)) { 104. 	    You("give up your attempt at %s.", lock_action); 105. 	    exercise(A_DEX, TRUE);	/* even if you don't succeed */ 106. 	    return((xlock.usedtime = 0)); 107. 	}  108.   109.  	if(rn2(100) >= xlock.chance) return(1);		/* still busy */ 110.  111.  	You("succeed in %s.", lock_action); 112. 	if (xlock.door) { 113. 	    if(xlock.door->doormask & D_TRAPPED) { 114. 		    b_trapped("door", FINGER); 115. 		    xlock.door->doormask = D_NODOOR; 116. 		    unblock_point(u.ux+u.dx, u.uy+u.dy); 117. 		    if (*in_rooms(u.ux+u.dx, u.uy+u.dy, SHOPBASE)) 118. 			add_damage(u.ux+u.dx, u.uy+u.dy, 0L); 119. 		    newsym(u.ux+u.dx, u.uy+u.dy); 120. 	    } else if(xlock.door->doormask == D_LOCKED) 121. 		xlock.door->doormask = D_CLOSED; 122. 	    else xlock.door->doormask = D_LOCKED; 123. 	} else { 124. 	    xlock.box->olocked = !xlock.box->olocked; 125. 	    if(xlock.box->otrapped) 126. 		(void) chest_trap(xlock.box, FINGER, FALSE); 127. 	}  128.  	exercise(A_DEX, TRUE); 129. 	return((xlock.usedtime = 0)); 130. }  131.   132.  STATIC_PTR 133. int 134. forcelock	/* try to force a locked chest */ 135. {  136.   137.  	register struct obj *otmp; 138.  139.  	if((xlock.box->ox != u.ux) || (xlock.box->oy != u.uy)) 140. 		return((xlock.usedtime = 0));		/* you or it moved */ 141.  142.  	if (xlock.usedtime++ >= 50 || !uwep || nohands(youmonst.data)) { 143. 	    You("give up your attempt to force the lock."); 144. 	    if(xlock.usedtime >= 50)		/* you made the effort */ 145. 	      exercise((xlock.picktyp) ? A_DEX : A_STR, TRUE); 146. 	    return((xlock.usedtime = 0)); 147. 	}  148.   149.  	if(xlock.picktyp == 1) {     /* blade */ 150.  151.  	    if(rn2(1000-(int)uwep->spe) > (992-greatest_erosion(uwep)*10) &&  152.  	       !uwep->cursed && !obj_resists(uwep, 0, 99)) { 153. 		/* for a +0 weapon, probability that it survives an unsuccessful 154. 		 * attempt to force the lock is (.992)^50 = .67 155. 		 */  156.  		pline("%sour %s broke!",  157.  		      (uwep->quan > 1L) ? "One of y" : "Y", xname(uwep)); 158. 		useup(uwep); 159. 		You("give up your attempt to force the lock."); 160. 		exercise(A_DEX, TRUE); 161. 		return((xlock.usedtime = 0)); 162. 	    }  163.  	} else if(xlock.picktyp == 0)                 /* blunt */ 164. 	    wake_nearby;	/* due to hammering on the container */ 165.  166.  	if(rn2(100) >= xlock.chance) return(1);		/* still busy */ 167.  168.  	You("succeed in forcing the lock."); 169. 	xlock.box->olocked = 0; 170. 	xlock.box->obroken = 1; 171. 	if((xlock.picktyp == 0 && !rn2(3)) || (xlock.picktyp == 2 && !rn2(5))) { 172. 	    struct monst *shkp; 173. 	    boolean costly; 174. 	    long loss = 0L; 175.  176.  	    costly = (*u.ushops && costly_spot(u.ux, u.uy)); 177. 	    shkp = costly ? shop_keeper(*u.ushops) : 0; 178.  179.  	    pline("In fact, you've totally destroyed %s.",  180.  		  the(xname(xlock.box))); 181.  182.  	    /* Put the contents on ground at the hero's feet. */ 183.  	    while ((otmp = xlock.box->cobj) != 0) { 184. 		obj_extract_self(otmp); 185. 		/* [ALI] Allowing containers to be destroyed is complicated 186. 		 * (because they might contain indestructible objects). 187. 		 * Since this is very unlikely to occur in practice simply 188. 		 * avoid the possibility. 189. 		 */  190.  		if (!evades_destruction(otmp) && !Has_contents(otmp) &&  191.  		  (!rn2(3) || otmp->oclass == POTION_CLASS)) { 192. 		    chest_shatter_msg(otmp); 193. 		    if (costly) 194. 		        loss += stolen_value(otmp, u.ux, u.uy,  195.  					     (boolean)shkp->mpeaceful, TRUE,  196.  					     TRUE); 197. 		    if (otmp->quan == 1L) { 198. 			obfree(otmp, (struct obj *) 0); 199. 			continue; 200. 		    }  201.  		    useup(otmp); 202. 		}  203.  		if (xlock.box->otyp == ICE_BOX && otmp->otyp == CORPSE) { 204. 		    otmp->age = monstermoves - otmp->age; /* actual age */ 205. 		    start_corpse_timeout(otmp); 206. 		}  207.  		place_object(otmp, u.ux, u.uy); 208. 		stackobj(otmp); 209. 	    }  210.   211.  	    if (costly) 212. 		loss += stolen_value(xlock.box, u.ux, u.uy,  213.  				     (boolean)shkp->mpeaceful, TRUE, TRUE); 214. 	    if(loss) You("owe %ld %s for objects destroyed.", loss, currency(loss)); 215. 	    delobj(xlock.box); 216. 	}  217.  	exercise((xlock.picktyp) ? A_DEX : A_STR, TRUE); 218. 	return((xlock.usedtime = 0)); 219. }  220.   221.  STATIC_PTR 222. int 223. forcedoor      /* try to break/pry open a door */ 224. {  225.   226.  	if(xlock.door != &(levl[u.ux+u.dx][u.uy+u.dy])) { 227. 	    return((xlock.usedtime = 0));           /* you moved */ 228. 	}  229.  	switch (xlock.door->doormask) { 230. 	    case D_NODOOR: 231. 		pline("This doorway has no door."); 232. 		return((xlock.usedtime = 0)); 233. 	    case D_ISOPEN: 234. 		You("cannot lock an open door."); 235. 		return((xlock.usedtime = 0)); 236. 	    case D_BROKEN: 237. 		pline("This door is broken."); 238. 		return((xlock.usedtime = 0)); 239. 	}  240.  	  241.  	if (xlock.usedtime++ >= 50 || nohands(youmonst.data)) { 242. 	    You("give up your attempt at %s the door.",  243.  	    	(xlock.picktyp == 2 ? "melting" : xlock.picktyp == 1 ? 244. 	    		"prying open" : "breaking down")); 245. 	    exercise(A_STR, TRUE);      /* even if you don't succeed */ 246. 	    return((xlock.usedtime = 0)); 247. 	}  248.   249.  	if(rn2(100) > xlock.chance) return(1);          /* still busy */ 250.  251.  	You("succeed in %s the door.",  252.  	    	(xlock.picktyp == 2 ? "melting" : xlock.picktyp == 1 ? 253. 	    		"prying open" : "breaking down")); 254.  255.  	if(xlock.door->doormask & D_TRAPPED) { 256. 	    b_trapped("door", 0); 257. 	    xlock.door->doormask = D_NODOOR; 258. 	} else if (xlock.picktyp == 1) 259. 	    xlock.door->doormask = D_BROKEN; 260. 	else xlock.door->doormask = D_NODOOR; 261. 	unblock_point(u.ux+u.dx, u.uy+u.dy); 262. 	if (*in_rooms(u.ux+u.dx, u.uy+u.dy, SHOPBASE)) 263. 	    add_damage(u.ux+u.dx, u.uy+u.dy, 0L); 264. 	newsym(u.ux+u.dx, u.uy+u.dy); 265. 	  266.  	exercise(A_STR, TRUE); 267. 	return((xlock.usedtime = 0)); 268. }  269.   270.  #endif /* OVLB */ 271. #ifdef OVL0 272.  273.  void 274. reset_pick 275. {  276.  	xlock.usedtime = xlock.chance = xlock.picktyp = 0; 277. 	xlock.door = 0; 278. 	xlock.box = 0; 279. }  280.   281.  #endif /* OVL0 */ 282. #ifdef OVLB 283.  284.  int 285. pick_lock(pickp) /* pick a lock with a given object */ 286. 	struct	obj	**pickp; 287. {  288.  	int picktyp, c, ch; 289. 	coord cc; 290. 	int key; 291. 	struct rm	*door; 292. 	struct obj	*otmp; 293. 	struct	obj	*pick = *pickp; 294. 	char qbuf[QBUFSZ]; 295.  296.  	picktyp = pick->otyp; 297.  298.  	/* check whether we're resuming an interrupted previous attempt */ 299. 	if (xlock.usedtime && picktyp == xlock.picktyp) { 300. 	    static char no_longer[] = "Unfortunately, you can no longer %s %s."; 301.  302.  	    if (nohands(youmonst.data)) { 303. 		const char *what = (picktyp == LOCK_PICK) ? "pick" : "key"; 304. #ifdef TOURIST 305. 		if (picktyp == CREDIT_CARD) what = "card"; 306. #endif 307. 		pline(no_longer, "hold the", what); 308. 		reset_pick; 309. 		return 0; 310. 	    } else if (xlock.box && !can_reach_floor) { 311. 		pline(no_longer, "reach the", "lock"); 312. 		reset_pick; 313. 		return 0; 314. 	    } else if (!xlock.door || xlock.key == pick->oartifact) { 315. 		const char *action = lock_action; 316. 		You("resume your attempt at %s.", action); 317. 		set_occupation(picklock, action, 0); 318. 		return(1); 319. 	    }  320.  	}  321.   322.  	if(nohands(youmonst.data)) { 323. 		You_cant("hold %s -- you have no hands!", doname(pick)); 324. 		return(0); 325. 	}  326.   327.  	if((picktyp != LOCK_PICK && 328. #ifdef TOURIST 329. 	    picktyp != CREDIT_CARD && 330. #endif 331. 	    picktyp != SKELETON_KEY)) { 332. 		impossible("picking lock with object %d?", picktyp); 333. 		return(0); 334. 	}  335.  	ch = 0;		/* lint suppression */ 336.  337.  	if(!get_adjacent_loc((char *)0, "Invalid location!", u.ux, u.uy, &cc)) return 0; 338. 	if (cc.x == u.ux && cc.y == u.uy) {	/* pick lock on a container */ 339. 	    const char *verb; 340. 	    boolean it; 341. 	    int count; 342.  343.  	    if (u.dz < 0) { 344. 		There("isn't any sort of lock up %s.",  345.  		      Levitation ? "here" : "there"); 346. 		return 0; 347. 	    } else if (is_lava(u.ux, u.uy)) { 348. 		pline("Doing that would probably melt your %s.",  349.  		      xname(pick)); 350. 		return 0; 351. 	    } else if (is_pool(u.ux, u.uy) && !Underwater) { 352. 		pline_The("water has no lock."); 353. 		return 0; 354. 	    }  355.   356.  	    count = 0; 357. 	    c = 'n';			/* in case there are no boxes here */ 358. 	    for(otmp = level.objects[cc.x][cc.y]; otmp; otmp = otmp->nexthere) 359. 		if (Is_box(otmp)) { 360. 		    ++count; 361. 		    if (!can_reach_floor) { 362. 			You_cant("reach %s from up here.", the(xname(otmp))); 363. 			return 0; 364. 		    }  365.  		    it = 0; 366. 		    if (otmp->obroken) verb = "fix"; 367. 		    else if (!otmp->olocked) verb = "lock", it = 1; 368. 		    else if (picktyp != LOCK_PICK) verb = "unlock", it = 1; 369. 		    else verb = "pick"; 370. 		    Sprintf(qbuf, "There is %s here, %s %s?",  371.  		    	    safe_qbuf("", sizeof("There is  here, unlock its lock?"), 372. 			    	doname(otmp), an(simple_typename(otmp->otyp)), "a box"),  373.  			    verb, it ? "it" : "its lock"); 374.  375.  		    c = ynq(qbuf); 376. 		    if(c == 'q') return(0); 377. 		    if(c == 'n') continue; 378.  379.  		    if (otmp->obroken) { 380. 			You_cant("fix its broken lock with %s.", doname(pick)); 381. 			return 0; 382. 		    }  383.  #ifdef TOURIST 384. 		    else if (picktyp == CREDIT_CARD && !otmp->olocked) { 385. 			/* credit cards are only good for unlocking */ 386. 			You_cant("do that with %s.", doname(pick)); 387. 			return 0; 388. 		    }  389.  #endif 390. 		    switch(picktyp) { 391. #ifdef TOURIST 392. 			case CREDIT_CARD: 393. 			    if(!rn2(20) && !pick->blessed && !pick->oartifact) { 394. 				Your("credit card breaks in half!"); 395. 				useup(pick); 396. 				*pickp = (struct obj *)0; 397. 				return(1); 398. 			    }  399.  			    ch = ACURR(A_DEX) + 20*Role_if(PM_ROGUE); 400. 			    break; 401. #endif 402. 			case LOCK_PICK: 403. 			    if(!rn2(Role_if(PM_ROGUE) ? 40 : 30) && 404.  			    		!pick->blessed && !pick->oartifact) { 405. 				You("break your pick!"); 406. 				useup(pick); 407. 				*pickp = (struct obj *)0; 408. 				return(1); 409. 			    }  410.  			    ch = 4*ACURR(A_DEX) + 25*Role_if(PM_ROGUE); 411. 			    break; 412. 			case SKELETON_KEY: 413. 			    if(!rn2(15) && !pick->blessed && !pick->oartifact) { 414. 				Your("key didn't quite fit the lock and snapped!"); 415. 				useup(pick); 416. 				*pickp = (struct obj *)0; 417. 				return(1); 418. 			    }  419.  			    ch = 75 + ACURR(A_DEX); 420. 			    break; 421. 			default:	ch = 0; 422. 		    }  423.  		    if(otmp->cursed) ch /= 2; 424.  425.  		    xlock.picktyp = picktyp; 426. 		    xlock.box = otmp; 427. 		    xlock.door = 0; 428. 		    break; 429. 		}  430.  	    if (c != 'y') { 431. 		if (!count) 432. 		    There("doesn't seem to be any sort of lock here."); 433. 		return(0);		/* decided against all boxes */ 434. 	    }  435.  	} else {			/* pick the lock in a door */ 436. 	    struct monst *mtmp; 437.  438.  	    if (u.utrap && u.utraptype == TT_PIT) { 439. 		You_cant("reach over the edge of the pit."); 440. 		return(0); 441. 	    }  442.   443.  	    door = &levl[cc.x][cc.y]; 444. 	    if ((mtmp = m_at(cc.x, cc.y)) && canseemon(mtmp)  445.  			&& mtmp->m_ap_type != M_AP_FURNITURE  446.  			&& mtmp->m_ap_type != M_AP_OBJECT) { 447. #ifdef TOURIST 448. 		if (picktyp == CREDIT_CARD &&  449.  		    (mtmp->isshk || mtmp->data == &mons[PM_ORACLE])) 450. 		    verbalize("No checks, no credit, no problem."); 451. 		else 452. #endif 453. 		    pline("I don't think %s would appreciate that.", mon_nam(mtmp)); 454. 		return(0); 455. 	    }  456.  	    if(!IS_DOOR(door->typ)) { 457. 		if (is_drawbridge_wall(cc.x,cc.y) >= 0) 458. 		    You("%s no lock on the drawbridge.",  459.  				Blind ? "feel" : "see"); 460. 		else 461. 		    You("%s no door there.",  462.  				Blind ? "feel" : "see"); 463. 		return(0); 464. 	    }  465.  	    switch (door->doormask) { 466. 		case D_NODOOR: 467. 		    pline("This doorway has no door."); 468. 		    return(0); 469. 		case D_ISOPEN: 470. 		    You("cannot lock an open door."); 471. 		    return(0); 472. 		case D_BROKEN: 473. 		    pline("This door is broken."); 474. 		    return(0); 475. 		default: 476. #ifdef TOURIST 477. 		    /* credit cards are only good for unlocking */ 478. 		    if(picktyp == CREDIT_CARD && !(door->doormask & D_LOCKED)) { 479. 			You_cant("lock a door with a credit card."); 480. 			return(0); 481. 		    }  482.  #endif 483. 		    /* ALI - Artifact doors */ 484. 		    key = artifact_door(cc.x, cc.y); 485.  486.  		    Sprintf(qbuf,"%sock it?",  487.  			(door->doormask & D_LOCKED) ? "Unl" : "L" ); 488.  489.  		    c = yn(qbuf); 490. 		    if(c == 'n') return(0); 491.  492.  		    switch(picktyp) { 493. #ifdef TOURIST 494. 			case CREDIT_CARD: 495. 			    if(!rn2(Role_if(PM_TOURIST) ? 30 : 20) && 496.  				    !pick->blessed && !pick->oartifact) { 497. 				You("break your card off in the door!"); 498. 				useup(pick); 499. 				*pickp = (struct obj *)0; 500. 				return(0); 501. 			    }  502.  			    ch = 2*ACURR(A_DEX) + 20*Role_if(PM_ROGUE); 503. 			    break; 504. #endif 505. 			case LOCK_PICK: 506. 			    if(!rn2(Role_if(PM_ROGUE) ? 40 : 30) && 507.  				    !pick->blessed && !pick->oartifact) { 508. 				You("break your pick!"); 509. 				useup(pick); 510. 				*pickp = (struct obj *)0; 511. 				return(0); 512. 			    }  513.  			    ch = 3*ACURR(A_DEX) + 30*Role_if(PM_ROGUE); 514. 			    break; 515. 			case SKELETON_KEY: 516. 			    if(!rn2(15) && !pick->blessed && !pick->oartifact) { 517. 				Your("key wasn't designed for this door and broke!"); 518. 				useup(pick); 519. 				*pickp = (struct obj *)0; 520. 				return(0); 521. 			    }  522.  			    ch = 70 + ACURR(A_DEX); 523. 			    break; 524. 			default:    ch = 0; 525. 		    }  526.  		    xlock.door = door; 527. 		    xlock.box = 0; 528.  529.  		    /* ALI - Artifact doors */ 530. 		    xlock.key = pick->oartifact; 531. 		    if (key && xlock.key != key) { 532. 			if (picktyp == SKELETON_KEY) { 533. 			    Your("key doesn't seem to fit."); 534. 			    return(0); 535. 			}  536.  			else ch = -1;		/* -1 == 0% chance */ 537. 		    }  538.  	    }  539.  	}  540.  	flags.move = 0; 541. 	xlock.chance = ch; 542. 	xlock.picktyp = picktyp; 543. 	xlock.usedtime = 0; 544. 	set_occupation(picklock, lock_action, 0); 545. 	return(1); 546. }  547.   548.  int 549. doforce		/* try to force a chest with your weapon */ 550. {  551.  	register struct obj *otmp; 552. 	register int x, y, c, picktyp; 553. 	struct rm       *door; 554. 	char qbuf[QBUFSZ]; 555.  556.  	if (!uwep) { /* Might want to make this so you use your shoulder */ 557. 	    You_cant("force anything without a weapon."); 558. 	     return(0); 559. 	}  560.   561.  	if (u.utrap && u.utraptype == TT_WEB) { 562. 	    You("are entangled in a web!"); 563. 	    return(0); 564. #ifdef LIGHTSABERS 565. 	} else if (uwep && is_lightsaber(uwep)) { 566. 	    if (!uwep->lamplit) { 567. 		Your("lightsaber is deactivated!"); 568. 		return(0); 569. 	    }  570.  #endif 571. 	} else if(uwep->otyp == LOCK_PICK ||  572.  #ifdef TOURIST  573.  	    uwep->otyp == CREDIT_CARD ||  574.  #endif  575.  	    uwep->otyp == SKELETON_KEY) { 576. 	    	return pick_lock(&uwep); 577. 	/* not a lightsaber or lockpicking device*/ 578. 	} else if(!uwep ||     /* proper type test */  579.  	   (uwep->oclass != WEAPON_CLASS && !is_weptool(uwep) && 580. 	    uwep->oclass != ROCK_CLASS) ||  581.  	   (objects[uwep->otyp].oc_skill < P_DAGGER) ||  582.  	   (objects[uwep->otyp].oc_skill > P_LANCE) ||  583.  	   uwep->otyp == FLAIL || uwep->otyp == AKLYS  584.  #ifdef KOPS  585.  	   || uwep->otyp == RUBBER_HOSE  586.  #endif  587.  	  ) { 588. 	    You_cant("force anything without a %sweapon.",  589.  		  (uwep) ? "proper " : ""); 590. 	    return(0); 591. 	}  592.   593.  #ifdef LIGHTSABERS 594. 	if (is_lightsaber(uwep)) 595. 	    picktyp = 2; 596. 	else 597. #endif 598. 	picktyp = is_blade(uwep) ? 1 : 0; 599.  	if(xlock.usedtime && picktyp == xlock.picktyp) { 600. 	    if (xlock.box) { 601. 	    You("resume your attempt to force the lock."); 602. 	    set_occupation(forcelock, "forcing the lock", 0); 603. 	    return(1); 604. 	    } else if (xlock.door) { 605. 		You("resume your attempt to force the door."); 606. 		set_occupation(forcedoor, "forcing the door", 0); 607. 		return(1); 608. 	    }  609.  	}  610.   611.  	/* A lock is made only for the honest man, the thief will break it. */ 612.  	xlock.box = (struct obj *)0; 613.  614.  	if(!getdir((char *)0)) return(0); 615.  616.  	x = u.ux + u.dx; 617. 	y = u.uy + u.dy; 618. 	if (x == u.ux && y == u.uy && !u.dz) { 619. 	for(otmp = level.objects[u.ux][u.uy]; otmp; otmp = otmp->nexthere) 620. 	    if(Is_box(otmp)) { 621. 		if (otmp->obroken || !otmp->olocked) { 622. 		    There("is %s here, but its lock is already %s.",  623.  			  doname(otmp), otmp->obroken ? "broken" : "unlocked"); 624. 		    continue; 625. 		}  626.  		Sprintf(qbuf,"There is %s here, force its lock?",  627.  			safe_qbuf("", sizeof("There is  here, force its lock?"), 628. 				doname(otmp), an(simple_typename(otmp->otyp)), 629. 				"a box")); 630.  631.  		c = ynq(qbuf); 632. 		if(c == 'q') return(0); 633. 		if(c == 'n') continue; 634.  635.  #ifdef LIGHTSABERS 636. 		if(picktyp == 2) 637. 		    You("begin melting it with your %s.", xname(uwep)); 638. 		else 639. #endif 640. 		if(picktyp) 641. 		    You("force your %s into a crack and pry.", xname(uwep)); 642. 		else 643. 		    You("start bashing it with your %s.", xname(uwep)); 644. 		xlock.box = otmp; 645. #ifdef LIGHTSABERS 646. 		if (is_lightsaber(uwep)) 647. 		    xlock.chance = uwep->spe * 2 + 75; 648. 		else 649. #endif 650. 		    xlock.chance = (uwep->spe + objects[uwep->otyp].oc_wldam) * 2; 651. 		xlock.picktyp = picktyp; 652. 		xlock.usedtime = 0; 653. 		break; 654. 	    }  655.  	    if(xlock.box)   { 656. 	    	xlock.door = 0; 657. 	    	set_occupation(forcelock, "forcing the lock", 0); 658. 	    	return(1); 659. 	    }  660.  	} else {		/* break down/open door */ 661. 	    struct monst *mtmp; 662.  663.  	    door = &levl[x][y]; 664. 	    if ((mtmp = m_at(x, y)) && canseemon(mtmp)  665.  			&& mtmp->m_ap_type != M_AP_FURNITURE  666.  			&& mtmp->m_ap_type != M_AP_OBJECT) { 667.  668.  		if (mtmp->isshk || mtmp->data == &mons[PM_ORACLE]) 669. 		    verbalize("What do you think you are, a Jedi?"); /* Phantom Menace */ 670. 		else 671. 		    pline("I don't think %s would appreciate that.", mon_nam(mtmp)); 672. 		return(0); 673. 	    }  674.  	    /* Lightsabers dig through doors and walls via dig.c */ 675. 	    if (is_pick(uwep) ||  676.  #ifdef LIGHTSABERS  677.  		    is_lightsaber(uwep) ||  678.  #endif  679.  		    is_axe(uwep)) 680. 	    	return use_pick_axe2(uwep); 681.  682.  	    if(!IS_DOOR(door->typ)) { 683. 		if (is_drawbridge_wall(x,y) >= 0) 684. 		    pline("The drawbridge is too solid to force open."); 685. 		else 686. 		    You("%s no door there.",  687.  				Blind ? "feel" : "see"); 688. 		return(0); 689. 	    }  690.  	    /* ALI - artifact doors */ 691. 	    if (artifact_door(x, y)) { 692. 		pline("This door is too solid to force open."); 693. 		return 0; 694. 	    }  695.  	    switch (door->doormask) { 696. 		case D_NODOOR: 697. 		    pline("This doorway has no door."); 698. 		    return(0); 699. 		case D_ISOPEN: 700. 		    You("cannot force an open door."); 701. 		    return(0); 702. 		case D_BROKEN: 703. 		    pline("This door is broken."); 704. 		    return(0); 705. 		default: 706. 		    c = yn("Break down the door?"); 707. 		    if(c == 'n') return(0); 708.  709.  		    if(picktyp == 1) 710. 			You("force your %s into a crack and pry.", xname(uwep)); 711. 		    else 712. 			You("start bashing it with your %s.", xname(uwep)); 713. #ifdef LIGHTSABERS 714. 		    if (is_lightsaber(uwep)) 715. 			xlock.chance = uwep->spe + 38; 716. 		    else 717. #endif 718. 			xlock.chance = uwep->spe + objects[uwep->otyp].oc_wldam; 719. 		    xlock.picktyp = picktyp; 720. 		    xlock.usedtime = 0; 721. 		    xlock.door = door; 722. 		    xlock.box = 0; 723. 		    set_occupation(forcedoor, "forcing the door", 0); 724. 	return(1); 725. 	    }  726.  	}  727.  	You("decide not to force the issue."); 728. 	return(0); 729. }  730.   731.  int 732. doopen		/* try to open a door */ 733. {  734.  	coord cc; 735. 	register struct rm *door; 736. 	struct monst *mtmp; 737.  738.  	if (nohands(youmonst.data)) { 739. 	    You_cant("open anything -- you have no hands!"); 740. 	    return 0; 741. 	}  742.   743.  	if (u.utrap && u.utraptype == TT_PIT) { 744. 	    You_cant("reach over the edge of the pit."); 745. 	    return 0; 746. 	}  747.   748.  	if(!get_adjacent_loc((char *)0, (char *)0, u.ux, u.uy, &cc)) return(0); 749.  750.  	if((cc.x == u.ux) && (cc.y == u.uy)) return(0); 751.  752.  	if ((mtmp = m_at(cc.x,cc.y))			&&  753.  		mtmp->m_ap_type == M_AP_FURNITURE	&&  754.  		(mtmp->mappearance == S_hcdoor || 755. 			mtmp->mappearance == S_vcdoor)	&&  756.  		!Protection_from_shape_changers)	 { 757.  758.  	    stumble_onto_mimic(mtmp); 759. 	    return(1); 760. 	}  761.   762.  	door = &levl[cc.x][cc.y]; 763.  764.  	if(!IS_DOOR(door->typ)) { 765. 		if (is_db_wall(cc.x,cc.y)) { 766. 		    There("is no obvious way to open the drawbridge."); 767. 		    return(0); 768. 		}  769.  		You("%s no door there.",  770.  				Blind ? "feel" : "see"); 771. 		return(0); 772. 	}  773.   774.  	if (!(door->doormask & D_CLOSED)) { 775. 	    const char *mesg; 776.  777.  	    switch (door->doormask) { 778. 	    case D_BROKEN: mesg = " is broken"; break; 779. 	    case D_NODOOR: mesg = "way has no door"; break; 780. 	    case D_ISOPEN: mesg = " is already open"; break; 781. 	    default:	   mesg = " is locked"; break; 782. 	    }  783.  	    pline("This door%s.", mesg); 784. 	    if (Blind) feel_location(cc.x,cc.y); 785. 	    return(0); 786. 	}  787.   788.  	if(verysmall(youmonst.data)) { 789. 	    pline("You're too small to pull the door open."); 790. 	    return(0); 791. 	}  792.   793.  	/* door is known to be CLOSED */ 794. 	if (rnl(20) < (ACURRSTR+ACURR(A_DEX)+ACURR(A_CON))/3) { 795. 	    pline_The("door opens."); 796. 	    if(door->doormask & D_TRAPPED) { 797. 		b_trapped("door", FINGER); 798. 		door->doormask = D_NODOOR; 799. 		if (*in_rooms(cc.x, cc.y, SHOPBASE)) add_damage(cc.x, cc.y, 0L); 800. 	    } else 801. 		door->doormask = D_ISOPEN; 802. 	    if (Blind) 803. 		feel_location(cc.x,cc.y);	/* the hero knows she opened it  */ 804. 	    else 805. 		newsym(cc.x,cc.y); 806. 	    unblock_point(cc.x,cc.y);		/* vision: new see through there */ 807. 	} else { 808. 	    exercise(A_STR, TRUE); 809. 	    pline_The("door resists!"); 810. 	}  811.   812.  	return(1); 813. }  814.   815.  STATIC_OVL 816. boolean 817. obstructed(x,y) 818. register int x, y;  819. { 820.  	register struct monst *mtmp = m_at(x, y); 821.  822.  	if(mtmp && mtmp->m_ap_type != M_AP_FURNITURE) { 823. 		if (mtmp->m_ap_type == M_AP_OBJECT) goto objhere; 824. 		pline("%s stands in the way!", !canspotmon(mtmp) ?  825.  			"Some creature" : Monnam(mtmp)); 826. 		if (!canspotmon(mtmp)) 827. 		    map_invisible(mtmp->mx, mtmp->my); 828. 		return(TRUE); 829. 	}  830.  	if (OBJ_AT(x, y)) { 831. objhere:	pline("%s's in the way.", Something); 832. 		return(TRUE); 833. 	}  834.  	return(FALSE); 835. }  836.   837.  int 838. doclose		/* try to close a door */ 839. {  840.  	register int x, y;  841. register struct rm *door; 842. 	struct monst *mtmp; 843.  844.  	if (nohands(youmonst.data)) { 845. 	    You_cant("close anything -- you have no hands!"); 846. 	    return 0; 847. 	}  848.   849.  	if (u.utrap && u.utraptype == TT_PIT) { 850. 	    You_cant("reach over the edge of the pit."); 851. 	    return 0; 852. 	}  853.   854.  	if(!getdir((char *)0)) return(0); 855.  856.  	x = u.ux + u.dx; 857. 	y = u.uy + u.dy; 858. 	if((x == u.ux) && (y == u.uy)) { 859. 		You("are in the way!"); 860. 		return(1); 861. 	}  862.   863.  	if ((mtmp = m_at(x,y))				&&  864.  		mtmp->m_ap_type == M_AP_FURNITURE	&&  865.  		(mtmp->mappearance == S_hcdoor || 866. 			mtmp->mappearance == S_vcdoor)	&&  867.  		!Protection_from_shape_changers)	 { 868.  869.  	    stumble_onto_mimic(mtmp); 870. 	    return(1); 871. 	}  872.   873.  	door = &levl[x][y]; 874.  875.  	if(!IS_DOOR(door->typ)) { 876. 		if (door->typ == DRAWBRIDGE_DOWN) 877. 		    There("is no obvious way to close the drawbridge."); 878. 		else 879. 		    You("%s no door there.",  880.  				Blind ? "feel" : "see"); 881. 		return(0); 882. 	}  883.   884.  	if(door->doormask == D_NODOOR) { 885. 	    pline("This doorway has no door."); 886. 	    return(0); 887. 	}  888.   889.  	if(obstructed(x, y)) return(0); 890.  891.  	if(door->doormask == D_BROKEN) { 892. 	    pline("This door is broken."); 893. 	    return(0); 894. 	}  895.   896.  	if(door->doormask & (D_CLOSED | D_LOCKED)) { 897. 	    pline("This door is already closed."); 898. 	    return(0); 899. 	}  900.   901.  	if(door->doormask == D_ISOPEN) { 902. 	    if(verysmall(youmonst.data)  903.  #ifdef STEED  904.  		&& !u.usteed  905.  #endif  906.  		) { 907. 		 pline("You're too small to push the door closed."); 908. 		 return(0); 909. 	    }  910.  	    if (  911.  #ifdef STEED  912.  		 u.usteed ||  913.  #endif  914.  		rn2(25) < (ACURRSTR+ACURR(A_DEX)+ACURR(A_CON))/3) { 915. 		pline_The("door closes."); 916. 		door->doormask = D_CLOSED; 917. 		if (Blind) 918. 		    feel_location(x,y);	/* the hero knows she closed it */ 919. 		else 920. 		    newsym(x,y); 921. 		block_point(x,y);	/* vision:  no longer see there */ 922. 	    }  923.  	    else { 924. 	        exercise(A_STR, TRUE); 925. 	        pline_The("door resists!"); 926. 	    }  927.  	}  928.   929.  	return(1); 930. }  931.   932.  boolean			/* box obj was hit with spell effect otmp */ 933. boxlock(obj, otmp)	/* returns true if something happened */ 934. register struct obj *obj, *otmp;	/* obj *is* a box */ 935. {  936.  	register boolean res = 0; 937.  938.  	switch(otmp->otyp) { 939. 	case WAN_LOCKING: 940. 	case SPE_WIZARD_LOCK: 941. 	    if (!obj->olocked) {	/* lock it; fix if broken */ 942. 		pline("Klunk!"); 943. 		obj->olocked = 1; 944. 		obj->obroken = 0; 945. 		res = 1; 946. 	    } /* else already closed and locked */ 947. 	    break; 948. 	case WAN_OPENING: 949. 	case SPE_KNOCK: 950. 	    if (obj->olocked) {		/* unlock; couldn't be broken */ 951. 		pline("Klick!"); 952. 		obj->olocked = 0; 953. 		res = 1; 954. 	    } else			/* silently fix if broken */ 955. 		obj->obroken = 0; 956. 	    break; 957. 	case WAN_POLYMORPH: 958. 	case SPE_POLYMORPH: 959. 	    /* maybe start unlocking chest, get interrupted, then zap it; 960. 	       we must avoid any attempt to resume unlocking it */ 961. 	    if (xlock.box == obj) 962. 		reset_pick; 963. 	    break; 964. 	}  965.  	return res; 966. }  967.   968.  boolean			/* Door/secret door was hit with spell effect otmp */ 969. doorlock(otmp,x,y)	/* returns true if something happened */ 970. struct obj *otmp; 971. int x, y;  972. { 973.  	register struct rm *door = &levl[x][y]; 974. 	boolean res = TRUE; 975. 	int loudness = 0; 976. 	const char *msg = (const char *)0; 977. 	const char *dustcloud = "A cloud of dust"; 978. 	const char *quickly_dissipates = "quickly dissipates"; 979. 	int key = artifact_door(x, y);		/* ALI - Artifact doors */ 980. 	  981.  	if (door->typ == SDOOR) { 982. 	    switch (otmp->otyp) { 983. 	    case WAN_OPENING: 984. 	    case SPE_KNOCK: 985. 	    case WAN_STRIKING: 986. 	    case SPE_FORCE_BOLT: 987. 		if (key)	/* Artifact doors are revealed only */ 988. 		    cvt_sdoor_to_door(door); 989. 		else { 990. 		door->typ = DOOR; 991. 		door->doormask = D_CLOSED | (door->doormask & D_TRAPPED); 992. 		}  993.  		newsym(x,y); 994. 		if (cansee(x,y)) pline("A door appears in the wall!"); 995. 		if (otmp->otyp == WAN_OPENING || otmp->otyp == SPE_KNOCK) 996. 		    return TRUE; 997. 		break;		/* striking: continue door handling below */ 998. 	    case WAN_LOCKING: 999. 	    case SPE_WIZARD_LOCK: 1000. 	   default: 1001. 		return FALSE; 1002. 	   }  1003. 	}  1004.  1005. 	switch(otmp->otyp) { 1006. 	case WAN_LOCKING: 1007. 	case SPE_WIZARD_LOCK: 1008. #ifdef REINCARNATION 1009. 	   if (Is_rogue_level(&u.uz)) { 1010. 	   	boolean vis = cansee(x,y); 1011. 		/* Can't have real locking in Rogue, so just hide doorway */ 1012. 		if (vis) pline("%s springs up in the older, more primitive doorway.", 1013. 			dustcloud); 1014. 		else 1015. 			You_hear("a swoosh."); 1016. 		if (obstructed(x,y)) { 1017. 			if (vis) pline_The("cloud %s.",quickly_dissipates); 1018. 			return FALSE; 1019. 		} 1020. 		block_point(x, y); 1021. 		door->typ = SDOOR; 1022. 		if (vis) pline_The("doorway vanishes!"); 1023. 		newsym(x,y); 1024. 		return TRUE; 1025. 	   }  1026. #endif 1027. 	   if (obstructed(x,y)) return FALSE; 1028. 	   /* Don't allow doors to close over traps. This is for pits */ 1029. 	   /* & trap doors, but is it ever OK for anything else? */ 1030. 	    if (t_at(x,y)) { 1031. 		/* maketrap clears doormask, so it should be NODOOR */ 1032. 		pline( 1033. 		"%s springs up in the doorway, but %s.",  1034. 		dustcloud, quickly_dissipates); 1035. 		return FALSE; 1036. 	   }  1037.  1038. 	    switch (door->doormask & ~D_TRAPPED) { 1039. 	   case D_CLOSED: 1040. 		if (key) 1041. 		   msg = "The door closes!"; 1042. 		else 1043. 		msg = "The door locks!"; 1044. 		break; 1045. 	   case D_ISOPEN: 1046. 		if (key) 1047. 		   msg = "The door swings shut!"; 1048. 		else 1049. 		msg = "The door swings shut, and locks!"; 1050. 		break; 1051. 	   case D_BROKEN: 1052. 		if (key) 1053. 		   msg = "The broken door reassembles!"; 1054. 		else 1055. 		msg = "The broken door reassembles and locks!"; 1056. 		break; 1057. 	   case D_NODOOR: 1058. 		msg = 1059. 		"A cloud of dust springs up and assembles itself into a door!"; 1060. 		break; 1061. 	   default: 1062. 		res = FALSE; 1063. 		break; 1064. 	   }  1065. 	    block_point(x, y); 1066. 	   if (key) 1067. 		door->doormask = D_CLOSED | (door->doormask & D_TRAPPED); 1068. 	   else 1069. 	   door->doormask = D_LOCKED | (door->doormask & D_TRAPPED); 1070. 	   newsym(x,y); 1071. 	   break; 1072. 	case WAN_OPENING: 1073. 	case SPE_KNOCK: 1074. 	   if (!key && door->doormask & D_LOCKED) { 1075. 		msg = "The door unlocks!"; 1076. 		door->doormask = D_CLOSED | (door->doormask & D_TRAPPED); 1077. 	   } else res = FALSE; 1078. 	   break; 1079. 	case WAN_STRIKING: 1080. 	case SPE_FORCE_BOLT: 1081. 	   if (!key && door->doormask & (D_LOCKED | D_CLOSED)) { 1082. 		if (door->doormask & D_TRAPPED) { 1083. 		   if (MON_AT(x, y)) 1084. 			(void) mb_trapped(m_at(x,y)); 1085. 		   else if (flags.verbose) { 1086. 			if (cansee(x,y)) 1087. 			   pline("KABOOM!!  You see a door explode."); 1088. 			else if (flags.soundok) 1089. 			   You_hear("a distant explosion."); 1090. 		   }  1091. 		    door->doormask = D_NODOOR; 1092. 		   unblock_point(x,y); 1093. 		   newsym(x,y); 1094. 		   loudness = 40; 1095. 		   break; 1096. 		} 1097. 		door->doormask = D_BROKEN; 1098. 		if (flags.verbose) { 1099. 		   if (cansee(x,y)) 1100. 			pline_The("door crashes open!"); 1101. 		   else if (flags.soundok) 1102. 			You_hear("a crashing sound."); 1103. 		} 1104. 		unblock_point(x,y); 1105. 		newsym(x,y); 1106. 		/* force vision recalc before printing more messages */ 1107. 		if (vision_full_recalc) vision_recalc(0); 1108. 		loudness = 20; 1109. 	   } else res = FALSE; 1110. 	   break; 1111. 	default: impossible("magic (%d) attempted on door.", otmp->otyp); 1112. 	   break; 1113. 	} 1114. 	if (msg && cansee(x,y)) pline(msg); 1115. 	if (loudness > 0) { 1116. 	   /* door was destroyed */ 1117. 	   wake_nearto(x, y, loudness); 1118. 	   if (*in_rooms(x, y, SHOPBASE)) add_damage(x, y, 0L); 1119. 	} 1120.  1121. 	if (res && picking_at(x, y)) { 1122. 	   /* maybe unseen monster zaps door you're unlocking */ 1123. 	   stop_occupation; 1124. 	   reset_pick; 1125. 	} 1126. 	return res; 1127. } 1128.  1129. STATIC_OVL void 1130. chest_shatter_msg(otmp) 1131. struct obj *otmp; 1132. { 1133. 	const char *disposition; 1134. 	const char *thing; 1135. 	long save_Blinded; 1136. 1137. 	if (otmp->oclass == POTION_CLASS) { 1138. 		You("%s %s shatter!", Blind ? "hear" : "see", an(bottlename)); 1139. 		if (!breathless(youmonst.data) || haseyes(youmonst.data)) 1140. 			potionbreathe(otmp); 1141. 		return; 1142. 	} 1143. 	/* We have functions for distant and singular names, but not one */ 1144. 	/* which does _both_... */ 1145. 	save_Blinded = Blinded; 1146. 	Blinded = 1; 1147. 	thing = singular(otmp, xname); 1148. 	Blinded = save_Blinded; 1149. 	switch (objects[otmp->otyp].oc_material) { 1150. 	case PAPER:	disposition = "is torn to shreds"; 1151. 		break; 1152. 	case WAX:	disposition = "is crushed"; 1153. 		break; 1154. 	case VEGGY:	disposition = "is pulped"; 1155. 		break; 1156. 	case FLESH:	disposition = "is mashed"; 1157. 		break; 1158. 	case GLASS:	disposition = "shatters"; 1159. 		break; 1160. 	case WOOD:	disposition = "splinters to fragments"; 1161. 		break; 1162. 	default:	disposition = "is destroyed"; 1163. 		break; 1164. 	} 1165. 	pline("%s %s!", An(thing), disposition); 1166. } 1167.  1168. /* ALI - Kevin Hugo's artifact doors. 1169. * Return the artifact which unlocks the door at (x, y), or  1170. * zero if it is an ordinary door. 1171. * Note: Not all doors are listed in the doors array (eg., doors  1172.  * dynamically converted from secret doors). Since only trapped 1173. * and artifact doors are needed this isn't a problem. If we ever 1174. * implement trapped secret doors we will have to extend this. 1175. */  1176.  1177. int 1178. artifact_door(x, y) 1179. int x, y; 1180. { 1181.     int i;  1182. 1183.    for(i = 0; i < doorindex; i++) { 1184. 	if (x == doors[i].x && y == doors[i].y) 1185. return doors[i].arti_key; 1186.    }  1187.     return 0; 1188. } 1189.  1190. #endif /* OVLB */ 1191. 1192. /*lock.c*/