Source:NetHack 3.0.0/lock.c

From NetHackWiki
Revision as of 04:48, 4 March 2008 by Kernigh bot (talk | contribs) (NetHack 3.0.0/lock.c moved to Source:NetHack 3.0.0/lock.c: Robot: moved page)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

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

The NetHack General Public License applies to screenshots, source code and other content from NetHack.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

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 */