Source:NetHack 3.0.0/lock.c

Below is the full text to lock.c from the source code of NetHack 3.0.0. To link to a particular line, write [[NetHack 3.0.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.0	88/10/22 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 struct { 8.   	int	door_or_box, picktyp; 9.   	struct rm  *door; 10.  	struct obj *box; 11.  	int chance, usedtime; 12.  } xlock; 13.   14.   static 15.  int 16.  picklock {	/* try to open/close a lock */ 17.   18.   	if(!xlock.door_or_box) {	/* box */ 19.   20.   	    if((xlock.box->ox != u.ux) || (xlock.box->oy != u.uy)) { 21.  		return((xlock.usedtime = 0));		/* you or it moved */ 22.  	    }  23.   	} else {		/* door */ 24.  	    if(xlock.door != &(levl[u.ux+u.dx][u.uy+u.dy])) { 25.  		return((xlock.usedtime = 0));		/* you moved */ 26.  	    }  27.   	    switch (xlock.door->doormask) { 28.  		case D_NODOOR: 29.  		    pline("This doorway has no door."); 30.  		    return((xlock.usedtime = 0)); 31.  		case D_ISOPEN: 32.  		    pline("Picking the lock of an open door is pointless."); 33.  		    return((xlock.usedtime = 0)); 34.  		case D_BROKEN: 35.  		    pline("This door is broken."); 36.  		    return((xlock.usedtime = 0)); 37.  	    }  38.   	}  39.    40.   	if(xlock.usedtime++ >= 50  41.   #ifdef POLYSELF  42.   	   || nohands(uasmon)  43.   #endif  44.   	   ) { 45.  	    You("give up your attempt to %s the lock.",  46.   		  (xlock.door_or_box ? !(xlock.door->doormask & D_LOCKED) : 47.  		   !xlock.box->olocked) ? "lock" :  48.   		  ((xlock.picktyp == LOCK_PICK) ? "pick" : "open" )); 49.   50.   	    return((xlock.usedtime = 0)); 51.  	}  52.    53.   	if(rn2(100) > xlock.chance) return(1);		/* still busy */ 54.   55.   	if(xlock.door_or_box) { 56.  	    You("succeed in %sing the lock.",  57.   		  !(xlock.door->doormask & D_LOCKED) ? "lock" :  58.   		  ((xlock.picktyp == LOCK_PICK) ? "pick" : "open" )); 59.  	    if(xlock.door->doormask & D_TRAPPED) { 60.  		    b_trapped("door"); 61.  		    xlock.door->doormask = D_NODOOR; 62.  	    } else if(xlock.door->doormask == D_LOCKED) 63.  		xlock.door->doormask = D_CLOSED; 64.  	    else xlock.door->doormask = D_LOCKED; 65.  	} else { 66.  	    You("succeed in %sing the lock.",  67.   		  (!xlock.box->olocked) ? "lock" :  68.   		  (xlock.picktyp == LOCK_PICK) ? "pick" : "open" ); 69.  	    xlock.box->olocked = !xlock.box->olocked; 70.  	    if(xlock.box->otrapped)	chest_trap(xlock.box, FINGER); 71.  	}  72.   	return((xlock.usedtime = 0)); 73.  }  74.    75.   static 76.  int 77.  forcelock {	/* try to force a locked chest */ 78.   79.   	register struct obj *otmp, *otmp2; 80.  	register struct obj *probj = fcobj;  /* initialize to make lint happy */ 81.   82.   	if((xlock.box->ox != u.ux) || (xlock.box->oy != u.uy)) 83.  		return((xlock.usedtime = 0));		/* you or it moved */ 84.   85.   	if(xlock.usedtime++ >= 50 || !uwep  86.   #ifdef POLYSELF  87.   	   || nohands(uasmon)  88.   #endif  89.   	   ) { 90.  	    You("give up your attempt to force the lock."); 91.   92.   	    return((xlock.usedtime = 0)); 93.  	}  94.    95.   	if(xlock.picktyp) {	/* blade */ 96.   97.   	    if(rn2(1000-uwep->spe) > 992 && !uwep->cursed) { 98.  		/* for a +0 weapon, probability that it survives an unsuccessful 99.  		 * attempt to force the lock is (.992)^50 = .67 100. 		 */  101.  		pline("%sour %s broke!",  102.  		      (uwep->quan > 1) ? "One of y" : "Y", xname(uwep)); 103. 		useup(uwep); 104. 		You("give up your attempt to force the lock."); 105. 		return((xlock.usedtime = 0)); 106. 	    }  107.  	} else			/* blunt */ 108. 	    wake_nearby;	/* due to hammering on the container */ 109.  110.  	if(rn2(100) > xlock.chance) return(1);		/* still busy */ 111.  112.  	You("succeed in forcing the lock."); 113. 	xlock.box->olocked = !xlock.box->olocked; 114. 	if(!xlock.picktyp && !rn2(3)) { 115.  116.  	    pline("In fact, you've totally destroyed the %s.",  117.  		  xname(xlock.box)); 118. 	    for(otmp = fcobj; otmp; otmp = otmp2) { 119.  120.  		otmp2 = otmp->nobj; 121. 		if(otmp->cobj == xlock.box) { 122.  123.  		    /* unlink it from the "contained" list */ 124. 		    if(otmp == fcobj) fcobj = otmp2; 125. 		    else	      probj->nobj = otmp2; 126.  127.  		    if(!rn2(3) || otmp->olet == POTION_SYM) 128. 			free((genericptr_t) otmp); 129. 		    else { /* spill it onto the floor */ 130. 			otmp->nobj = xlock.box->nobj; 131. 			xlock.box->nobj = otmp; 132. 			otmp->cobj = (struct obj *)0; 133. 			otmp->ox = u.ux; 134. 			otmp->oy = u.uy; 135. 			levl[u.ux][u.uy].omask = 1; 136. 			stackobj(otmp); 137. 		    }  138.  		} else probj = otmp; 139. 	    }  140.  	    delobj(xlock.box); 141. 	}  142.  	return((xlock.usedtime = 0)); 143. }  144.   145.  int 146. pick_lock(pick) /* pick a lock with a given object */ 147. 	register struct	obj	*pick; 148. {  149.  	register int x, y, picktyp, c, ch; 150. 	register struct rm	*door; 151. 	register struct obj	*otmp; 152.  153.  	picktyp = pick->otyp; 154. 	if(xlock.usedtime && picktyp == xlock.picktyp) { 155.  156.  	    You("resume your attempt to %s the lock.",  157.  		  (xlock.door_or_box ? !(xlock.door->doormask & D_LOCKED) : 158. 		   !xlock.box->olocked) ? "lock" :  159.  		  ((xlock.picktyp == LOCK_PICK) ? "pick" : "open" )); 160.  161.  	    set_occupation(picklock,  162.  			   (picktyp == LOCK_PICK) ? "picking the lock" :  163.  						    "opening the lock",  0); 164. 	    return(1); 165. 	}  166.   167.  #ifdef POLYSELF 168. 	if(nohands(uasmon)) { 169. 		You("can't hold a %s - you have no hands!"); 170. 		return(0); 171. 	}  172.  #endif 173. 	if((picktyp != LOCK_PICK && picktyp != CREDIT_CARD && 174. 	    picktyp != SKELETON_KEY && picktyp != KEY)) { 175. 		impossible("picking lock with object %d?", picktyp); 176. 		return(0); 177. 	}  178.  	if(!getdir(1)) return(0); 179.  180.  	x = u.ux + u.dx; 181. 	y = u.uy + u.dy; 182. 	if((x == u.ux) && (y == u.uy)) { /* pick the lock on a container */ 183. 	    c = 'n';			/* in case there are no boxes here */ 184. 	    if(levl[x][y].omask) 185. 	    for(otmp = fobj; otmp; otmp = otmp->nobj) 186. 		if((otmp->ox == x) && (otmp->oy == y)) 187. 		    if(Is_box(otmp)) { 188. 			pline("There is %s here, %s the lock? ",  189.  			doname(otmp), (!otmp->olocked) ? "close" :  190.  			((picktyp == LOCK_PICK) ? "pick" : "open" )); 191.  192.  			c = ynq; 193. 			if(c == 'q') return(0); 194. 			if(c == 'n') continue; 195.  196.  			if(picktyp == KEY && otmp->spe != pick->spe) { 197. 				pline("The %s won't fit the lock.",xname(pick)); 198. 				return(1); 199. 			}  200.  			switch(picktyp) { 201. 			    case CREDIT_CARD: 202. 				ch = ACURR(A_DEX)+(20*(pl_character[0] == 'R')); 203. 				break; 204. 			    case LOCK_PICK: 205. 				ch = 4*ACURR(A_DEX)+(25*(pl_character[0] == 'R')); 206. 				break; 207. 			    case SKELETON_KEY: 208. 				ch = 75 + ACURR(A_DEX); 209. 				break; 210. 			    case KEY: 211. 				ch = 1000; 212. 				break; 213. 			    default:	ch = 0; 214. 			}  215.  			if(otmp->cursed) ch /= 2; 216.  217.  			xlock.door_or_box = 0; 218. 			xlock.picktyp = picktyp; 219. 			xlock.box = otmp; 220. 			break; 221. 		    }  222.  	    if(c != 'y') 223. 		return(0);		/* decided against all boxes */ 224. 	} else {			/* pick the lock in a door */ 225. 	    struct monst *mtmp; 226.  227.  	    door = &levl[x][y]; 228. 	    if (door->mmask && canseemon(mtmp = m_at(x,y)) && !mtmp->mimic) { 229. 		if (picktyp == CREDIT_CARD &&  230.  #ifdef ORACLE  231.  		    (mtmp->isshk || mtmp->data == &mons[PM_ORACLE])) 232. #else 233. 		    mtmp->isshk)  234.  #endif  235.  		    pline("\"No checks, no credit, no problem.\"");  236.  		else  237.  		    kludge("I don't think %s would appreciate that.", mon_nam(mtmp));  238.  		return(0);  239.  	    }  240.  	    if(!IS_DOOR(door->typ)) {  241.  #ifdef STRONGHOLD  242.  		if (is_drawbridge_wall(x,y) >= 0)  243.  		    You("%s no lock on the drawbridge.", 244. 				Blind ? "feel" : "see"); 245.  		else  246.  #endif  247.  		You("%s no door there.", 248. 				Blind ? "feel" : "see"); 249.  		return(0);  250.  	    }  251.  	    switch (door->doormask) {  252.  		case D_NODOOR:  253.  		    pline("This doorway has no door.");  254.  		    return(0);  255.  		case D_ISOPEN:  256.  		    pline("Picking the lock of an open door is pointless.");  257.  		    return(0);  258.  		case D_BROKEN:  259.  		    pline("This door is broken.");  260.  		    return(0);  261.  		default:  262.  		    pline("%sock it? ", (door->doormask & D_LOCKED) ? "Unl" : "L" ); 263.   264.  		    c = yn;  265.  		    if(c == 'n') return(0);  266.   267.  		    switch(picktyp) {  268.  			case CREDIT_CARD:  269.  			    ch = 2*ACURR(A_DEX)+(20*(pl_character[0] == 'R'));  270.  			    break;  271.  			case LOCK_PICK:  272.  			    ch = 3*ACURR(A_DEX)+(30*(pl_character[0] == 'R'));  273.  			    break;  274.  			case SKELETON_KEY:  275.  			    ch = 70 + ACURR(A_DEX);  276.  			    break;  277.  			case KEY:  278.  			    pline("The %s won't fit the door.", xname(pick));  279.  			    return(1);  280.  			default:    ch = 0;  281.  		    }  282.  		    xlock.door_or_box = 1;  283.  		    xlock.door = door;  284.  	    }  285.  	}  286.  	flags.move = 0;  287.  	xlock.chance = ch;  288.  	xlock.picktyp = picktyp;  289.  	xlock.usedtime = 0;  290.  	set_occupation(picklock, 291. 		       (picktyp == LOCK_PICK) ? "picking the lock" : 292. 						"opening the lock",  0);  293.  	return(1);  294.  }  295.   296.  int  297.  doforce {		/* try to force a chest with your weapon */  298.   299.  	register struct obj *otmp;  300.  	register int c, picktyp;  301.   302.  	if(!uwep ||	/* proper type test */ 303. 	   (uwep->olet != WEAPON_SYM && uwep->olet != ROCK_SYM &&  304.  						uwep->otyp != PICK_AXE) || 305. 	   (uwep->otyp < DAGGER) || 306. 	   (uwep->otyp > VOULGE && uwep->olet != ROCK_SYM &&  307.  						uwep->otyp != PICK_AXE) 308. 	  ) {  309.  	    You("can't force anything without a %sweapon.", 310. 		  (uwep) ? "proper " : ""); 311.  	    return(0);  312.  	}  313.   314.  	picktyp = (uwep->otyp >= DAGGER && uwep->otyp <= KATANA);  315.  	if(xlock.usedtime && xlock.box && picktyp == xlock.picktyp) {  316.  	    You("resume your attempt to force the lock.");  317.  	    set_occupation(forcelock, "forcing the lock", 0);  318.  	    return(1);  319.  	}  320.   321.  	/* A lock is made only for the honest man, the thief will break it. */  322.  	xlock.box = (struct obj *)0;  323.  	if(levl[u.ux][u.uy].omask)  324.  	for(otmp = fobj; otmp; otmp = otmp->nobj)  325.  	    if((otmp->ox == u.ux) && (otmp->oy == u.uy))  326.  		if(Is_box(otmp)) {  327.  		  if(otmp->olocked)  328.  		    pline("There is %s here, force the lock? ", doname(otmp));  329.  		  else {  330.  		    pline("There is a %s here, but it's already unlocked.", 331. 			  xname(otmp));  332.  		    continue;  333.  		  }  334.   335.  		  c = ynq;  336.  		  if(c == 'q') return(0);  337.  		  if(c == 'n') continue;  338.   339.  		  if(picktyp)  340.  		    You("force your %s into a crack and pry.", xname(uwep));  341.  		  else  342.  		    You("start bashing it with your %s.", xname(uwep));  343.  		  xlock.box = otmp;  344.  		  xlock.chance = objects[otmp->otyp].wldam * 2;  345.  		  xlock.picktyp = picktyp;  346.  		  xlock.usedtime = 0;  347.  		  break;  348.  		}  349.   350.  	if(xlock.box)	set_occupation(forcelock, "forcing the lock", 0);  351.  	else		You("decide not to force the issue.");  352.  	return(1);  353.  }  354.   355.  int  356.  doopen {		/* try to open a door */  357.  	register int x, y;  358.  	register struct rm *door;  359.   360.  	if(!getdir(1)) return(0);  361.   362.  	x = u.ux + u.dx;  363.  	y = u.uy + u.dy; 364. 	if((x == u.ux) && (y == u.uy)) return(0); 365.  366.  	door = &levl[x][y]; 367.  368.  	if(!IS_DOOR(door->typ)) { 369. #ifdef STRONGHOLD 370. 		if (is_drawbridge_wall(x,y) >= 0) { 371. 		    pline("There is no obvious way to open the drawbridge."); 372. 		    return(0); 373. 		}  374.  #endif 375. 		You("%s no door there.",  376.  				Blind ? "feel" : "see"); 377. 		return(0); 378. 	}  379.   380.  	if(!(door->doormask & D_CLOSED)) { 381. 	  switch(door->doormask) { 382. 	     case D_BROKEN: pline("This door is broken."); break; 383. 	     case D_NODOOR: pline("This doorway has no door."); break; 384. 	     case D_ISOPEN: pline("This door is already open."); break; 385. 	     default:	    pline("This door is locked."); break; 386. 	  }  387.  	  return(0); 388. 	}  389.   390.  #ifdef POLYSELF 391. 	if(verysmall(uasmon)) { 392. 	    pline("You're too small to pull the door open."); 393. 	    return(0); 394. 	}  395.  #endif 396. 	/* door is known to be CLOSED */ 397. 	if (rnl(20) < (ACURR(A_STR)+ACURR(A_DEX)+ACURR(A_CON))/3) { 398. 	    pline("The door opens."); 399. 	    if(door->doormask & D_TRAPPED) { 400. 		b_trapped("door"); 401. 		door->doormask = D_NODOOR; 402. 	    } else 403. 		door->doormask = D_ISOPEN; 404. 	} else { 405. 	    pline("The door resists!"); 406. 	}  407.   408.  	return(1); 409. }  410.   411.  static 412. boolean 413. obstructed(x,y) 414. register int x, y;  415. { 416.  	if(levl[x][y].mmask) { 417. 		if (m_at(x,y)->mimic) goto obj; 418. 		pline("%s stands in the way!", Blind ?  419.  			"Some creature" : Monnam(m_at(x,y))); 420. 		return(TRUE); 421. 	}  422.  	if (levl[x][y].omask || levl[x][y].gmask) { 423. obj: 424. 		pline("Something's in the way."); 425. 		return(TRUE); 426. 	}  427.  	return(FALSE); 428. }  429.   430.  int 431. doclose {		/* try to close a door */ 432. 	register int x, y;  433. register struct rm *door; 434.  435.  	if(!getdir(1)) return(0); 436.  437.  	x = u.ux + u.dx; 438. 	y = u.uy + u.dy; 439. 	if((x == u.ux) && (y == u.uy)) { 440. 		You("are in the way!"); 441. 		return(1); 442. 	}  443.  	door = &levl[x][y]; 444.  445.  	if(!IS_DOOR(door->typ)) { 446. #ifdef STRONGHOLD 447. 		if (door->typ == DRAWBRIDGE_DOWN) 448. 		    pline("There is no obvious way to close the drawbridge."); 449. 		else 450. #endif 451. 		You("%s no door there.",  452.  				Blind ? "feel" : "see"); 453. 		return(0); 454. 	}  455.   456.  	if(door->doormask == D_NODOOR) { 457. 	    pline("This doorway has no door."); 458. 	    return(0); 459. 	}  460.   461.  	if(obstructed(x, y)) return(0); 462.  463.  	if(door->doormask == D_BROKEN) { 464. 	    pline("This door is broken."); 465. 	    return(0); 466. 	}  467.   468.  	if(door->doormask & (D_CLOSED | D_LOCKED)) { 469. 	    pline("This door is already closed."); 470. 	    return(0); 471. 	}  472.   473.  	if(door->doormask == D_ISOPEN) { 474. #ifdef POLYSELF 475. 	    if(verysmall(uasmon)) { 476. 		 pline("You're too small to push the door closed."); 477. 		 return(0); 478.  	    }  479.  #endif 480. 	    if (rn2(25) < (ACURR(A_STR)+ACURR(A_DEX)+ACURR(A_CON))/3) { 481. 		pline("The door closes."); 482. 		door->doormask = D_CLOSED; 483. 	    }  484.  	    else pline("The door resists!"); 485. 	}  486.   487.  	return(1); 488. }  489.   490.  int 491. boxlock(obj, otmp)	/* box obj was hit with spell effect otmp */ 492. 			/* returns 1 if something happened */ 493. 	register struct obj *obj, *otmp;	/* obj *is* a box */ 494. {  495.  	register boolean res; 496.  497.  	switch(otmp->otyp) { 498. 	    case WAN_LOCKING: 499. #ifdef SPELLS 500. 	    case SPE_WIZARD_LOCK: 501. #endif 502. 			if(!obj->olocked) { 503. 				pline("Klunk!"); 504. 				obj->olocked = !(obj->olocked); 505. 				res = 1; 506. 			} else	res = 0; 507. 			break; 508. 	    case WAN_OPENING: 509. #ifdef SPELLS 510. 	    case SPE_KNOCK: 511. #endif 512. 			if(obj->olocked) { 513. 				pline("Klick!"); 514. 				obj->olocked = !(obj->olocked); 515. 				res = 1; 516. 			} else	res = 0; 517. 			break; 518. 	}  519.  	return(res); 520. }  521.   522.  int 523. doorlock(otmp,x,y)	/* door was hit with spell effect otmp */ 524. 	register struct obj *otmp; 525. 	int x, y;  526. { 527.  	register struct rm *door = &levl[x][y]; 528. 	boolean res = 1; 529.  530.  	if(obstructed(x,y)) 531. 		return 0; 532.  533.  	if(door->typ == SDOOR) { 534. 	    if(otmp->otyp == WAN_OPENING  535.  #ifdef SPELLS  536.  	       || otmp->otyp == SPE_KNOCK  537.  #endif /* SPELLS /**/  538.  	      ) { 539. 		door->typ = DOOR; 540. 		door->doormask = D_CLOSED | (door->doormask & D_TRAPPED); 541. 		if(cansee(x,y)) { 542. 		    pline("A section of the wall opens up!"); 543. 		    newsym(x,y); 544. 		}  545.  		return(1); 546. 	    } else 547. 		return(0); 548. 	}  549.   550.  #ifdef STRONGHOLD 551. 	/* make sure it isn't an open drawbridge */ 552. 	if (is_maze_lev && find_drawbridge(&x,&y)) { 553. 	    if(otmp->otyp == WAN_OPENING  554.  #ifdef SPELLS  555.  	       || otmp->otyp == SPE_KNOCK  556.  #endif /* SPELLS /**/  557.  	      ) 558. 		    (void) open_drawbridge(x,y); 559. 	    else 560. 		    (void) close_drawbridge(x,y); 561. 	    return 1; 562. 	}  563.  #endif 564.  565.  	switch(otmp->otyp) { 566. 	    case WAN_LOCKING: 567. #ifdef SPELLS 568. 	    case SPE_WIZARD_LOCK: 569. #endif 570. 		if (cansee(x,y)) 571. 		switch (door->doormask & ~D_TRAPPED) { 572. 			case D_CLOSED: 573. 				pline("The door locks!"); 574. 				break; 575. 			case D_ISOPEN: 576. 				pline("The door swings shut, and locks!"); 577. 				break; 578. 			case D_BROKEN: 579. 				pline("The broken door reassembles and locks!"); 580. 				break; 581. 			case D_NODOOR: 582. 	pline("A cloud of dust springs up and assembles itself into a door!"); 583. 				break; 584. 			default: res = 0; 585. 		}  586.  		door->doormask = D_LOCKED | (door->doormask & D_TRAPPED); 587. 		break; 588. 	    case WAN_OPENING: 589. #ifdef SPELLS 590. 	    case SPE_KNOCK: 591. #endif 592. 		if(door->doormask & D_LOCKED) { 593. 		    door->doormask = D_CLOSED | (door->doormask & D_TRAPPED); 594. 		    if(cansee(x,y)) pline("The door unlocks!"); 595. 		} else res = 0; 596. 		break; 597. 	    default:	impossible("magic (%d) attempted on door.", otmp->otyp); 598. 	}  599.  	return res; 600. }  601.   602.  #ifdef STUPID_CPP	/* otherwise these functions are macros in obj.h */ 603. int 604. Is_container(otmp) struct obj * otmp; { 605. 	return(otmp->otyp >= ICE_BOX && otmp->otyp <= BAG_OF_TRICKS); 606. }  607.   608.  int 609. Is_box(otmp) struct obj * otmp; { 610. 	return(otmp->otyp == LARGE_BOX || otmp->otyp == CHEST); 611. }  612.   613.  int 614. Is_mbag(otmp) struct obj * otmp; { 615. 	return(otmp->otyp == BAG_OF_HOLDING || otmp->otyp == BAG_OF_TRICKS); 616. }  617.   618.  int 619. is_sword(otmp) struct obj * otmp; { 620. 	return(otmp->otyp >= SHORT_SWORD && otmp->otyp <= KATANA); 621. }  622.   623.  int 624. bimanual(otmp) struct obj * otmp; { 625. 	return(otmp->olet == WEAPON_SYM && objects[otmp->otyp].oc_bimanual); 626. }  627.  #endif /* STUPID_CPP */