Source:NetHack 3.1.0/lock.c

From NetHackWiki
Revision as of 06:37, 4 March 2008 by Kernigh bot (talk | contribs) (NetHack 3.1.0/lock.c moved to Source:NetHack 3.1.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.1.0. To link to a particular line, write [[NetHack 3.1.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.1	92/09/02
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.    #define CONTAINER_BITS 0	/* box options not [yet?] implemented */
8.    
9.    STATIC_PTR int NDECL(picklock);
10.   STATIC_PTR int NDECL(forcelock);
11.   
12.   STATIC_VAR struct xlock_s {
13.   	int	door_or_box, picktyp;
14.   	struct rm  *door;
15.   	struct obj *box;
16.   	int chance, usedtime;
17.   } NEARDATA xlock;
18.   
19.   #ifdef OVLB
20.   
21.   static boolean FDECL(obstructed,(int,int));
22.   static void FDECL(chest_shatter_msg, (struct obj *));
23.   
24.   boolean
25.   picking_at(x, y)
26.   int x, y;
27.   {
28.   	return((occupation == picklock) && 
29.   	       xlock.door_or_box && (xlock.door == &levl[x][y])); 
30.   }
31.   
32.   STATIC_PTR
33.   int
34.   picklock()	/* try to open/close a lock */
35.   {
36.   
37.   	if(!xlock.door_or_box) {	/* box */
38.   
39.   	    if((xlock.box->ox != u.ux) || (xlock.box->oy != u.uy)) {
40.   		return((xlock.usedtime = 0));		/* you or it moved */
41.   	    }
42.   	} else {		/* door */
43.   	    if(xlock.door != &(levl[u.ux+u.dx][u.uy+u.dy])) {
44.   		return((xlock.usedtime = 0));		/* you moved */
45.   	    }
46.   	    switch (xlock.door->doormask) {
47.   		case D_NODOOR:
48.   		    pline("This doorway has no door.");
49.   		    return((xlock.usedtime = 0));
50.   		case D_ISOPEN:
51.   		    pline("Picking the lock of an open door is pointless.");
52.   		    return((xlock.usedtime = 0));
53.   		case D_BROKEN:
54.   		    pline("This door is broken.");
55.   		    return((xlock.usedtime = 0));
56.   	    }
57.   	}
58.   
59.   	if(xlock.usedtime++ >= 50
60.   #ifdef POLYSELF
61.   	   || nohands(uasmon)
62.   #endif
63.   	   ) {
64.   	    You("give up your attempt to %s the lock.",
65.   		  (xlock.door_or_box ? !(xlock.door->doormask & D_LOCKED) :
66.   		   !xlock.box->olocked) ? "lock" :
67.   		  ((xlock.picktyp == LOCK_PICK) ? "pick" : "open" ));
68.   
69.   	    exercise(A_DEX, TRUE);	/* even if you don't succeed */
70.   	    return((xlock.usedtime = 0));
71.   	}
72.   
73.   	if(rn2(100) > xlock.chance) return(1);		/* still busy */
74.   
75.   	if(xlock.door_or_box) {
76.   	    You("succeed in %sing the lock.",
77.   		  !(xlock.door->doormask & D_LOCKED) ? "lock" :
78.   		  ((xlock.picktyp == LOCK_PICK) ? "pick" : "open" ));
79.   	    if(xlock.door->doormask & D_TRAPPED) {
80.   		    b_trapped("door");
81.   		    xlock.door->doormask = D_NODOOR;
82.   		    unblock_point(u.ux+u.dx, u.uy+u.dy);
83.   		    newsym(u.ux+u.dx, u.uy+u.dy);
84.   	    } else if(xlock.door->doormask == D_LOCKED)
85.   		xlock.door->doormask = D_CLOSED;
86.   	    else xlock.door->doormask = D_LOCKED;
87.   	} else {
88.   	    You("succeed in %sing the lock.",
89.   		  (!xlock.box->olocked) ? "lock" :
90.   		  (xlock.picktyp == LOCK_PICK) ? "pick" : "open" );
91.   	    xlock.box->olocked = !xlock.box->olocked;
92.   	    if(xlock.box->otrapped)	
93.   		(void) chest_trap(xlock.box, FINGER, FALSE);
94.   	}
95.   	exercise(A_DEX, TRUE);
96.   	return((xlock.usedtime = 0));
97.   }
98.   
99.   STATIC_PTR
100.  int
101.  forcelock()	/* try to force a locked chest */
102.  {
103.  
104.  	register struct obj *otmp, *otmp2;
105.  
106.  	if((xlock.box->ox != u.ux) || (xlock.box->oy != u.uy))
107.  		return((xlock.usedtime = 0));		/* you or it moved */
108.  
109.  	if(xlock.usedtime++ >= 50 || !uwep
110.  #ifdef POLYSELF
111.  	   || nohands(uasmon)
112.  #endif
113.  	   ) {
114.  	    You("give up your attempt to force the lock.");
115.  	    if(xlock.usedtime >= 50)		/* you made the effort */
116.  	      exercise((xlock.picktyp) ? A_DEX : A_STR, TRUE);
117.  	    return((xlock.usedtime = 0));
118.  	}
119.  
120.  	if(xlock.picktyp) {	/* blade */
121.  
122.  	    if(rn2(1000-(int)uwep->spe) > (992-(int)uwep->oeroded*10) && 
123.  	       !uwep->cursed) {
124.  		/* for a +0 weapon, probability that it survives an unsuccessful
125.  		 * attempt to force the lock is (.992)^50 = .67
126.  		 */
127.  		pline("%sour %s broke!",
128.  		      (uwep->quan > 1L) ? "One of y" : "Y", xname(uwep));
129.  		useup(uwep);
130.  		You("give up your attempt to force the lock.");
131.  		exercise(A_DEX, TRUE);
132.  		return((xlock.usedtime = 0));
133.  	    }
134.  	} else			/* blunt */
135.  	    wake_nearby();	/* due to hammering on the container */
136.  
137.  	if(rn2(100) > xlock.chance) return(1);		/* still busy */
138.  
139.  	You("succeed in forcing the lock.");
140.  	xlock.box->olocked = 0;
141.  	xlock.box->obroken = 1;
142.  	if(!xlock.picktyp && !rn2(3)) {
143.  	    register struct monst *shkp;
144.  	    long loss = 0L;
145.  
146.  #ifdef GCC_WARN
147.  	    shkp = (struct monst *) 0;
148.  #endif
149.  
150.  	    if(*u.ushops) shkp = shop_keeper(*u.ushops);
151.  
152.  	    pline("In fact, you've totally destroyed %s.",
153.  		  the(xname(xlock.box)));
154.  
155.  	    /* Put the contents on ground at the hero's feet. */
156.  	    for (otmp = xlock.box->cobj; otmp; otmp = otmp2) {
157.  		otmp2 = otmp->nobj;
158.  		if(!rn2(3) || otmp->oclass == POTION_CLASS) {
159.  		    chest_shatter_msg(otmp);
160.  		    if(*u.ushops && costly_spot(u.ux, u.uy))
161.  		        loss += stolen_value(otmp, u.ux, u.uy,
162.  					     (boolean)shkp->mpeaceful, TRUE);
163.  		    if (otmp->quan == 1L) {
164.  			obfree(otmp, (struct obj *) 0);
165.  			continue;
166.  		    }
167.  		    useup(otmp);
168.  		}
169.  		place_object(otmp,u.ux,u.uy);
170.  		otmp->nobj = fobj;
171.  		fobj = otmp;
172.  		stackobj(otmp);
173.  	    }
174.  	    xlock.box->cobj = (struct obj *) 0;	/* no contents */
175.  	    if(*u.ushops && costly_spot(u.ux, u.uy))
176.  		loss += stolen_value(otmp, u.ux, u.uy,
177.  					     (boolean)shkp->mpeaceful, TRUE);
178.  	    if(loss) You("owe %ld zorkmids for objects destroyed.", loss);
179.  	    delobj(xlock.box);
180.  	}
181.  	exercise((xlock.picktyp) ? A_DEX : A_STR, TRUE);
182.  	return((xlock.usedtime = 0));
183.  }
184.  
185.  #endif /* OVLB */
186.  #ifdef OVL0
187.  
188.  void
189.  reset_pick() { xlock.usedtime = 0; }
190.  
191.  #endif /* OVL0 */
192.  #ifdef OVLB
193.  
194.  int
195.  pick_lock(pick) /* pick a lock with a given object */
196.  	register struct	obj	*pick;
197.  {
198.  	register int x, y, picktyp, c, ch;
199.  	register struct rm	*door;
200.  	register struct obj	*otmp;
201.  	char qbuf[QBUFSZ];
202.  
203.  #ifdef GCC_WARN
204.  	ch = 0;		/* GCC myopia */
205.  #endif
206.  	picktyp = pick->otyp;
207.  	if(xlock.usedtime && picktyp == xlock.picktyp) {
208.  
209.  	    You("resume your attempt to %s the lock.",
210.  		  (xlock.door_or_box ? !(xlock.door->doormask & D_LOCKED) :
211.  		   !xlock.box->olocked) ? "lock" :
212.  		  ((xlock.picktyp == LOCK_PICK) ? "pick" : "open" ));
213.  
214.  	    set_occupation(picklock,
215.  			   (picktyp == LOCK_PICK) ? "picking the lock" :
216.  						    "opening the lock",  0);
217.  	    return(1);
218.  	}
219.  
220.  #ifdef POLYSELF
221.  	if(nohands(uasmon)) {
222.  		You("can't hold a %s - you have no hands!", xname(pick));
223.  		return(0);
224.  	}
225.  #endif
226.  	if((picktyp != LOCK_PICK &&
227.  #ifdef TOURIST
228.  	    picktyp != CREDIT_CARD &&
229.  #endif
230.  	    picktyp != SKELETON_KEY)) {
231.  		impossible("picking lock with object %d?", picktyp);
232.  		return(0);
233.  	}
234.  	if(!getdir(NULL)) return(0);
235.  
236.  	x = u.ux + u.dx;
237.  	y = u.uy + u.dy;
238.  	if((x == u.ux) && (y == u.uy)) { /* pick the lock on a container */
239.  	    c = 'n';			/* in case there are no boxes here */
240.  	    for(otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
241.  		if (Is_box(otmp)) {
242.  		    const char *verb;
243.  		    boolean it = 0;
244.  #if CONTAINER_BITS
245.  		    if (!otmp->oclosed) {	/* it's open */
246.  			pline("There is %s here.", doname(otmp));
247.  			continue;
248.  		    }
249.  		    if (!otmp->lknown) verb = "work";
250.  		    else
251.  #endif
252.  			 if (otmp->obroken) verb = "fix";
253.  		    else if (!otmp->olocked) verb = "lock", it = 1;
254.  		    else if (picktyp != LOCK_PICK) verb = "unlock", it = 1;
255.  		    else verb = "pick";
256.  		    Sprintf(qbuf, "There is %s here, %s %s?",
257.  			    doname(otmp), verb, it ? "it" : "its lock");
258.  
259.  		    c = ynq(qbuf);
260.  		    if(c == 'q') return(0);
261.  		    if(c == 'n') continue;
262.  
263.  #if CONTAINER_BITS
264.  		    otmp->lknown = 1;
265.  #endif
266.  		    if (otmp->obroken) {
267.  			You("can't fix its broken lock with %s.", doname(pick));
268.  			return 0;
269.  		    }
270.  #ifdef TOURIST
271.  		    else if (picktyp == CREDIT_CARD && !otmp->olocked) {
272.  			/* credit cards are only good for unlocking */
273.  			You("can't do that with %s.", doname(pick));
274.  			return 0;
275.  		    }
276.  #endif
277.  		    switch(picktyp) {
278.  #ifdef TOURIST
279.  			case CREDIT_CARD:
280.  			    ch = ACURR(A_DEX)+(20*(pl_character[0] == 'R'));
281.  			    break;
282.  #endif
283.  			case LOCK_PICK:
284.  			    ch = 4*ACURR(A_DEX)+(25*(pl_character[0] == 'R'));
285.  			    break;
286.  			case SKELETON_KEY:
287.  			    ch = 75 + ACURR(A_DEX);
288.  			    break;
289.  			default:	ch = 0;
290.  		    }
291.  		    if(otmp->cursed) ch /= 2;
292.  
293.  		    xlock.door_or_box = 0;
294.  		    xlock.picktyp = picktyp;
295.  		    xlock.box = otmp;
296.  		    break;
297.  		}
298.  	    if(c != 'y')
299.  		return(0);		/* decided against all boxes */
300.  	} else {			/* pick the lock in a door */
301.  	    struct monst *mtmp;
302.  
303.  	    door = &levl[x][y];
304.  	    if ((mtmp = m_at(x, y)) && canseemon(mtmp)
305.  			&& mtmp->m_ap_type != M_AP_FURNITURE
306.  			&& mtmp->m_ap_type != M_AP_OBJECT) {
307.  #ifdef TOURIST
308.  		if (picktyp == CREDIT_CARD &&
309.  		    (mtmp->isshk || mtmp->data == &mons[PM_ORACLE]))
310.  		    verbalize("No checks, no credit, no problem.");
311.  		else
312.  #endif
313.  		    pline("I don't think %s would appreciate that.", mon_nam(mtmp));
314.  		return(0);
315.  	    }
316.  	    if(!IS_DOOR(door->typ)) {
317.  		if (is_drawbridge_wall(x,y) >= 0)
318.  		    You("%s no lock on the drawbridge.",
319.  				Blind ? "feel" : "see");
320.  		else
321.  		    You("%s no door there.",
322.  				Blind ? "feel" : "see");
323.  		return(0);
324.  	    }
325.  	    switch (door->doormask) {
326.  		case D_NODOOR:
327.  		    pline("This doorway has no door.");
328.  		    return(0);
329.  		case D_ISOPEN:
330.  		    pline("Picking the lock of an open door is pointless.");
331.  		    return(0);
332.  		case D_BROKEN:
333.  		    pline("This door is broken.");
334.  		    return(0);
335.  		default:
336.  #ifdef TOURIST
337.  		    /* credit cards are only good for unlocking */
338.  		    if(picktyp == CREDIT_CARD && !(door->doormask & D_LOCKED)) {
339.  			You("can't lock a door with a credit card.");
340.  			return(0);
341.  		    }
342.  #endif
343.  
344.  		    Sprintf(qbuf,"%sock it?",
345.  			(door->doormask & D_LOCKED) ? "Unl" : "L" );
346.  
347.  		    c = yn(qbuf);
348.  		    if(c == 'n') return(0);
349.  
350.  		    switch(picktyp) {
351.  #ifdef TOURIST
352.  			case CREDIT_CARD:
353.  			    ch = 2*ACURR(A_DEX)+(20*(pl_character[0] == 'R'));
354.  			    break;
355.  #endif
356.  			case LOCK_PICK:
357.  			    ch = 3*ACURR(A_DEX)+(30*(pl_character[0] == 'R'));
358.  			    break;
359.  			case SKELETON_KEY:
360.  			    ch = 70 + ACURR(A_DEX);
361.  			    break;
362.  			default:    ch = 0;
363.  		    }
364.  		    xlock.door_or_box = 1;
365.  		    xlock.door = door;
366.  	    }
367.  	}
368.  	flags.move = 0;
369.  	xlock.chance = ch;
370.  	xlock.picktyp = picktyp;
371.  	xlock.usedtime = 0;
372.  	set_occupation(picklock,
373.  		       (picktyp == LOCK_PICK) ? "picking the lock" :
374.  						"opening the lock",  0);
375.  	return(1);
376.  }
377.  
378.  int
379.  doforce()		/* try to force a chest with your weapon */
380.  {
381.  	register struct obj *otmp;
382.  	register int c, picktyp;
383.  	char qbuf[QBUFSZ];
384.  
385.  	if(!uwep ||	/* proper type test */
386.  	   (uwep->oclass != WEAPON_CLASS && uwep->oclass != ROCK_CLASS &&
387.  						uwep->otyp != PICK_AXE) ||
388.  	   (uwep->otyp < BOOMERANG) ||
389.  	   (uwep->otyp > AKLYS && uwep->oclass != ROCK_CLASS &&
390.  						uwep->otyp != PICK_AXE)
391.  #ifdef KOPS
392.  	   || uwep->otyp == RUBBER_HOSE
393.  #endif
394.  	  ) {
395.  	    You("can't force anything without a %sweapon.",
396.  		  (uwep) ? "proper " : "");
397.  	    return(0);
398.  	}
399.  
400.  	picktyp = is_blade(uwep);
401.  	if(xlock.usedtime && xlock.box && picktyp == xlock.picktyp) {
402.  	    You("resume your attempt to force the lock.");
403.  	    set_occupation(forcelock, "forcing the lock", 0);
404.  	    return(1);
405.  	}
406.  
407.  	/* A lock is made only for the honest man, the thief will break it. */
408.  	xlock.box = (struct obj *)0;
409.  	for(otmp = level.objects[u.ux][u.uy]; otmp; otmp = otmp->nexthere)
410.  	    if(Is_box(otmp)) {
411.  #if CONTAINER_BITS
412.  		if (!otmp->oclosed) {	/* it's open */
413.  		    pline("There is %s here.", doname(otmp));
414.  		    continue;
415.  		}
416.  		if (otmp->obroken || (otmp->lknown && !otmp->olocked)) {
417.  #else
418.  		if (otmp->obroken || !otmp->olocked) {
419.  #endif
420.  		    pline("There is %s here, but its lock is already %s.",
421.  			  doname(otmp), otmp->obroken ? "broken" : "unlocked");
422.  		    continue;
423.  		}
424.  		Sprintf(qbuf,"There is %s here, force its lock?", doname(otmp));
425.  
426.  		c = ynq(qbuf);
427.  		if(c == 'q') return(0);
428.  		if(c == 'n') continue;
429.  
430.  #if CONTAINER_BITS
431.  		if (!otmp->olocked) {	/* lock-status wasn't known */
432.  		    pline("Well what'd'ya know?  It's already unlocked.");
433.  		    otmp->lknown = 1;
434.  		    return 0;
435.  		}
436.  #endif
437.  		if(picktyp)
438.  		    You("force your %s into a crack and pry.", xname(uwep));
439.  		else
440.  		    You("start bashing it with your %s.", xname(uwep));
441.  		xlock.box = otmp;
442.  		xlock.chance = objects[otmp->otyp].oc_wldam * 2;
443.  		xlock.picktyp = picktyp;
444.  		xlock.usedtime = 0;
445.  		break;
446.  	    }
447.  
448.  	if(xlock.box)	set_occupation(forcelock, "forcing the lock", 0);
449.  	else		You("decide not to force the issue.");
450.  	return(1);
451.  }
452.  
453.  int
454.  doopen()		/* try to open a door */
455.  {
456.  	register int x, y;
457.  	register struct rm *door;
458.  	struct monst *mtmp;
459.  
460.  	if (u.utrap && u.utraptype == TT_PIT) {
461.  	    You("can't reach over the edge of the pit.");
462.  	    return 0;
463.  	}
464.  
465.  	if(!getdir(NULL)) return(0);
466.  
467.  	x = u.ux + u.dx;
468.  	y = u.uy + u.dy;
469.  	if((x == u.ux) && (y == u.uy)) return(0);
470.  
471.  	if ((mtmp = m_at(x,y))				&&
472.  		mtmp->m_ap_type == M_AP_FURNITURE	&&
473.  		(mtmp->mappearance == S_hcdoor ||
474.  			mtmp->mappearance == S_vcdoor)	&&
475.  		!Protection_from_shape_changers)	 {
476.  
477.  	    stumble_onto_mimic(mtmp);
478.  	    return(1);
479.  	}
480.  
481.  	door = &levl[x][y];
482.  
483.  	if(!IS_DOOR(door->typ)) {
484.  		if (is_db_wall(x,y)) {
485.  		    pline("There is no obvious way to open the drawbridge.");
486.  		    return(0);
487.  		}
488.  		You("%s no door there.",
489.  				Blind ? "feel" : "see");
490.  		return(0);
491.  	}
492.  
493.  	if(!(door->doormask & D_CLOSED)) {
494.  	  switch(door->doormask) {
495.  	     case D_BROKEN: pline("This door is broken."); break;
496.  	     case D_NODOOR: pline("This doorway has no door."); break;
497.  	     case D_ISOPEN: pline("This door is already open."); break;
498.  	     default:	    pline("This door is locked."); break;
499.  	  }
500.  	  return(0);
501.  	}
502.  
503.  #ifdef POLYSELF
504.  	if(verysmall(uasmon)) {
505.  	    pline("You're too small to pull the door open.");
506.  	    return(0);
507.  	}
508.  #endif
509.  	/* door is known to be CLOSED */
510.  	if (rnl(20) < (ACURRSTR+ACURR(A_DEX)+ACURR(A_CON))/3) {
511.  	    pline("The door opens.");
512.  	    if(door->doormask & D_TRAPPED) {
513.  		b_trapped("door");
514.  		door->doormask = D_NODOOR;
515.  	    } else
516.  		door->doormask = D_ISOPEN;
517.  	    if (Blind)
518.  		feel_location(x,y);	/* the hero knows she opened it  */
519.  	    else
520.  		newsym(x,y);
521.  	    unblock_point(x,y);		/* vision: new see through there */
522.  	} else {
523.  	    exercise(A_STR, TRUE);
524.  	    pline("The door resists!");
525.  	}
526.  
527.  	return(1);
528.  }
529.  
530.  static
531.  boolean
532.  obstructed(x,y)
533.  register int x, y;
534.  {
535.  	register struct monst *mtmp = m_at(x, y);
536.  
537.  	if(mtmp && mtmp->m_ap_type != M_AP_FURNITURE) {
538.  		if (mtmp->m_ap_type == M_AP_OBJECT) goto objhere;
539.  		pline("%s stands in the way!", Blind ?
540.  			"Some creature" : Monnam(mtmp));
541.  		return(TRUE);
542.  	}
543.  	if (OBJ_AT(x, y)) {
544.  objhere:	pline("Something's in the way.");
545.  		return(TRUE);
546.  	}
547.  	return(FALSE);
548.  }
549.  
550.  int
551.  doclose()		/* try to close a door */
552.  {
553.  	register int x, y;
554.  	register struct rm *door;
555.  	struct monst *mtmp;
556.  
557.  	if (u.utrap && u.utraptype == TT_PIT) {
558.  	    You("can't reach over the edge of the pit.");
559.  	    return 0;
560.  	}
561.  
562.  	if(!getdir(NULL)) return(0);
563.  
564.  	x = u.ux + u.dx;
565.  	y = u.uy + u.dy;
566.  	if((x == u.ux) && (y == u.uy)) {
567.  		You("are in the way!");
568.  		return(1);
569.  	}
570.  
571.  	if ((mtmp = m_at(x,y))				&&
572.  		mtmp->m_ap_type == M_AP_FURNITURE	&& 
573.  		(mtmp->mappearance == S_hcdoor ||
574.  			mtmp->mappearance == S_vcdoor)	&&
575.  		!Protection_from_shape_changers)	 {
576.  
577.  	    stumble_onto_mimic(mtmp);
578.  	    return(1);
579.  	}
580.  
581.  	door = &levl[x][y];
582.  
583.  	if(!IS_DOOR(door->typ)) {
584.  		if (door->typ == DRAWBRIDGE_DOWN)
585.  		    pline("There is no obvious way to close the drawbridge.");
586.  		else
587.  		    You("%s no door there.",
588.  				Blind ? "feel" : "see");
589.  		return(0);
590.  	}
591.  
592.  	if(door->doormask == D_NODOOR) {
593.  	    pline("This doorway has no door.");
594.  	    return(0);
595.  	}
596.  
597.  	if(obstructed(x, y)) return(0);
598.  
599.  	if(door->doormask == D_BROKEN) {
600.  	    pline("This door is broken.");
601.  	    return(0);
602.  	}
603.  
604.  	if(door->doormask & (D_CLOSED | D_LOCKED)) {
605.  	    pline("This door is already closed.");
606.  	    return(0);
607.  	}
608.  
609.  	if(door->doormask == D_ISOPEN) {
610.  #ifdef POLYSELF
611.  	    if(verysmall(uasmon)) {
612.  		 pline("You're too small to push the door closed.");
613.  		 return(0);
614.   	    }
615.  #endif
616.  	    if (rn2(25) < (ACURRSTR+ACURR(A_DEX)+ACURR(A_CON))/3) {
617.  		pline("The door closes.");
618.  		door->doormask = D_CLOSED;
619.  		if (Blind)
620.  		    feel_location(x,y);	/* the hero knows she closed it */
621.  		else
622.  		    newsym(x,y);
623.  		block_point(x,y);	/* vision:  no longer see there */
624.  	    }
625.  	    else {
626.  	        exercise(A_STR, TRUE);
627.  	        pline("The door resists!");
628.  	    }
629.  	}
630.  
631.  	return(1);
632.  }
633.  
634.  boolean			/* box obj was hit with spell effect otmp */
635.  boxlock(obj, otmp)	/* returns true if something happened */
636.  register struct obj *obj, *otmp;	/* obj *is* a box */
637.  {
638.  	register boolean res = 0;
639.  
640.  	switch(otmp->otyp) {
641.  	case WAN_LOCKING:
642.  	case SPE_WIZARD_LOCK:
643.  	    if (!obj->olocked) {	/* lock it; fix if broken */
644.  		pline("Klunk!");
645.  #if CONTAINER_BITS
646.  		obj->lknown = 0;
647.  		obj->oclosed = 1;
648.  #endif
649.  		obj->olocked = 1;
650.  		obj->obroken = 0;
651.  		res = 1;
652.  	    } /* else already closed and locked */
653.  	    break;
654.  	case WAN_OPENING:
655.  	case SPE_KNOCK:
656.  	    if (obj->olocked) {		/* unlock; couldn't be broken */
657.  		pline("Klick!");
658.  #if CONTAINER_BITS
659.  		obj->lknown = 0;
660.  #endif
661.  		obj->olocked = 0;
662.  		res = 1;
663.  	    } else			/* silently fix if broken */
664.  		obj->obroken = 0;
665.  #if CONTAINER_BITS
666.  	    obj->oclosed = 0;		/* now open, unconditionally */
667.  #endif
668.  	    break;
669.  	}
670.  	return res;
671.  }
672.  
673.  boolean			/* Door/secret door was hit with spell effect otmp */
674.  doorlock(otmp,x,y)	/* returns true if something happened */
675.  register struct obj *otmp;
676.  int x, y;
677.  {
678.  	register struct rm *door = &levl[x][y];
679.  	boolean res = 1;
680.  	const char *msg = NULL;
681.  
682.  	if (door->typ == SDOOR) {
683.  	    if (otmp->otyp == WAN_OPENING || otmp->otyp == SPE_KNOCK) {
684.  		door->typ = DOOR;
685.  		door->doormask = D_CLOSED | (door->doormask & D_TRAPPED);
686.  		if (cansee(x,y)) pline("A section of the wall opens up!");
687.  		newsym(x,y);
688.  		return(1);
689.  	    } else
690.  		return(0);
691.  	}
692.  
693.  	switch(otmp->otyp) {
694.  	case WAN_LOCKING:
695.  	case SPE_WIZARD_LOCK:
696.  	    if (obstructed(x,y)) return 0;
697.  	    switch (door->doormask & ~D_TRAPPED) {
698.  	    case D_CLOSED:
699.  		msg = "The door locks!";
700.  		break;
701.  	    case D_ISOPEN:
702.  		msg = "The door swings shut, and locks!";
703.  		break;
704.  	    case D_BROKEN:
705.  		msg = "The broken door reassembles and locks!";
706.  		break;
707.  	    case D_NODOOR:
708.  		msg =
709.  		"A cloud of dust springs up and assembles itself into a door!";
710.  		break;
711.  	    default:
712.  		res = 0;
713.  		break;
714.  	    }
715.  	    block_point(x, y);
716.  	    door->doormask = D_LOCKED | (door->doormask & D_TRAPPED);
717.  	    newsym(x,y);
718.  	    break;
719.  	case WAN_OPENING:
720.  	case SPE_KNOCK:
721.  	    if (door->doormask & D_LOCKED) {
722.  		msg = "The door unlocks!";
723.  		door->doormask = D_CLOSED | (door->doormask & D_TRAPPED);
724.  	    } else res = 0;
725.  	    break;
726.  	case WAN_STRIKING:
727.  	case SPE_FORCE_BOLT:
728.  	    if (door->doormask & (D_LOCKED | D_CLOSED)) {
729.  		if (door->doormask & D_TRAPPED) {
730.  		    if (MON_AT(x, y))
731.  			(void) mb_trapped(m_at(x,y));
732.  		    else if (flags.verbose) {
733.  			if (cansee(x,y))
734.  			    pline("KABOOM!!  You see a door explode.");
735.  			else if (flags.soundok)
736.  			    You("hear a distant explosion.");
737.  		    }
738.  		    door->doormask = D_NODOOR;
739.  		    unblock_point(x,y);
740.  		    newsym(x,y);
741.  		    break;
742.  		}
743.  		door->doormask = D_BROKEN;
744.  		if (flags.verbose) {
745.  		    if (cansee(x,y))
746.  			pline("The door crashes open!");
747.  		    else if (flags.soundok)
748.  			You("hear a crashing sound.");
749.  		}
750.  		unblock_point(x,y);
751.  		newsym(x,y);
752.  	    } else res = 0;
753.  	    break;
754.  	default: impossible("magic (%d) attempted on door.", otmp->otyp);
755.  	    break;
756.  	}
757.  	if (msg && cansee(x,y)) pline(msg);
758.  	return res;
759.  }
760.  
761.  static void
762.  chest_shatter_msg(otmp)
763.  struct obj *otmp;
764.  {
765.  	const char *disposition, *article = (otmp->quan > 1L) ? "A" : "The";
766.  	char *thing;
767.  	long save_Blinded;
768.  
769.  	if (otmp->oclass == POTION_CLASS) {
770.  		You("%s a flask shatter!", Blind ? "hear" : "see");
771.  		potionbreathe(otmp);
772.  		return;
773.  	}
774.  	/* We have functions for distant and singular names, but not one */
775.  	/* which does _both_... */
776.  	save_Blinded = Blinded;
777.  	Blinded = 1;
778.  	thing = singular(otmp, xname);
779.  	Blinded = save_Blinded;
780.  	switch (objects[otmp->otyp].oc_material) {
781.  	case PAPER:	disposition = "is torn to shreds";
782.  		break;
783.  	case WAX:	disposition = "is crushed";
784.  		break;
785.  	case VEGGY:	disposition = "is pulped";
786.  		break;
787.  	case FLESH:	disposition = "is mashed";
788.  		break;
789.  	case GLASS:	disposition = "shatters";
790.  		break;
791.  	case WOOD:	disposition = "splinters to fragments";
792.  		break;
793.  	default:	disposition = "is destroyed";
794.  		break;
795.  	}
796.  	pline("%s %s %s!", article, thing, disposition);
797.  }
798.  
799.  #endif /* OVLB */
800.  
801.  /*lock.c*/