1 /* NetHack 3.6 lock.c $NHDT-Date: 1446955300 2015/11/08 04:01:40 $ $NHDT-Branch: master $:$NHDT-Revision: 1.67 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
7 STATIC_PTR
int NDECL(picklock
);
8 STATIC_PTR
int NDECL(forcelock
);
10 /* at most one of `door' and `box' should be non-null at any given time */
11 STATIC_VAR NEARDATA
struct xlock_s
{
14 int picktyp
, /* key|pick|card for unlock, sharp vs blunt for #force */
18 STATIC_DCL
const char *NDECL(lock_action
);
19 STATIC_DCL boolean
FDECL(obstructed
, (int, int, BOOLEAN_P
));
20 STATIC_DCL
void FDECL(chest_shatter_msg
, (struct obj
*));
26 if (occupation
== picklock
) {
40 return (boolean
) (occupation
== picklock
&& xlock
.door
== &levl
[x
][y
]);
43 /* produce an occupation string appropriate for the current activity */
44 STATIC_OVL
const char *
47 /* "unlocking"+2 == "locking" */
48 static const char *actions
[] = {
49 "unlocking the door", /* [0] */
50 "unlocking the chest", /* [1] */
51 "unlocking the box", /* [2] */
52 "picking the lock" /* [3] */
55 /* if the target is currently unlocked, we're trying to lock it now */
56 if (xlock
.door
&& !(xlock
.door
->doormask
& D_LOCKED
))
57 return actions
[0] + 2; /* "locking the door" */
58 else if (xlock
.box
&& !xlock
.box
->olocked
)
59 return xlock
.box
->otyp
== CHEST
? actions
[1] + 2 : actions
[2] + 2;
60 /* otherwise we're trying to unlock it */
61 else if (xlock
.picktyp
== LOCK_PICK
)
62 return actions
[3]; /* "picking the lock" */
63 else if (xlock
.picktyp
== CREDIT_CARD
)
64 return actions
[3]; /* same as lock_pick */
66 return actions
[0]; /* "unlocking the door" */
68 return xlock
.box
->otyp
== CHEST
? actions
[1] : actions
[2];
73 /* try to open/close a lock */
78 if (xlock
.box
->where
!= OBJ_FLOOR
79 || xlock
.box
->ox
!= u
.ux
|| xlock
.box
->oy
!= u
.uy
) {
80 return ((xlock
.usedtime
= 0)); /* you or it moved */
83 if (xlock
.door
!= &(levl
[u
.ux
+ u
.dx
][u
.uy
+ u
.dy
])) {
84 return ((xlock
.usedtime
= 0)); /* you moved */
86 switch (xlock
.door
->doormask
) {
88 pline("This doorway has no door.");
89 return ((xlock
.usedtime
= 0));
91 You("cannot lock an open door.");
92 return ((xlock
.usedtime
= 0));
94 pline("This door is broken.");
95 return ((xlock
.usedtime
= 0));
99 if (xlock
.usedtime
++ >= 50 || nohands(youmonst
.data
)) {
100 You("give up your attempt at %s.", lock_action());
101 exercise(A_DEX
, TRUE
); /* even if you don't succeed */
102 return ((xlock
.usedtime
= 0));
105 if (rn2(100) >= xlock
.chance
)
106 return 1; /* still busy */
108 You("succeed in %s.", lock_action());
110 if (xlock
.door
->doormask
& D_TRAPPED
) {
111 b_trapped("door", FINGER
);
112 xlock
.door
->doormask
= D_NODOOR
;
113 unblock_point(u
.ux
+ u
.dx
, u
.uy
+ u
.dy
);
114 if (*in_rooms(u
.ux
+ u
.dx
, u
.uy
+ u
.dy
, SHOPBASE
))
115 add_damage(u
.ux
+ u
.dx
, u
.uy
+ u
.dy
, 0L);
116 newsym(u
.ux
+ u
.dx
, u
.uy
+ u
.dy
);
117 } else if (xlock
.door
->doormask
& D_LOCKED
)
118 xlock
.door
->doormask
= D_CLOSED
;
120 xlock
.door
->doormask
= D_LOCKED
;
122 xlock
.box
->olocked
= !xlock
.box
->olocked
;
123 xlock
.box
->lknown
= 1;
124 if (xlock
.box
->otrapped
)
125 (void) chest_trap(xlock
.box
, FINGER
, FALSE
);
127 exercise(A_DEX
, TRUE
);
128 return ((xlock
.usedtime
= 0));
132 breakchestlock(box
, destroyit
)
136 if (!destroyit
) { /* bill for the box but not for its contents */
137 struct obj
*hide_contents
= box
->cobj
;
140 costly_alteration(box
, COST_BRKLCK
);
141 box
->cobj
= hide_contents
;
145 } else { /* #force has destroyed this box (at <u.ux,u.uy>) */
147 struct monst
*shkp
= (*u
.ushops
&& costly_spot(u
.ux
, u
.uy
))
148 ? shop_keeper(*u
.ushops
)
150 boolean costly
= (boolean
) (shkp
!= 0),
151 peaceful_shk
= costly
&& (boolean
) shkp
->mpeaceful
;
154 pline("In fact, you've totally destroyed %s.", the(xname(box
)));
155 /* Put the contents on ground at the hero's feet. */
156 while ((otmp
= box
->cobj
) != 0) {
157 obj_extract_self(otmp
);
158 if (!rn2(3) || otmp
->oclass
== POTION_CLASS
) {
159 chest_shatter_msg(otmp
);
162 stolen_value(otmp
, u
.ux
, u
.uy
, peaceful_shk
, TRUE
);
163 if (otmp
->quan
== 1L) {
164 obfree(otmp
, (struct obj
*) 0);
169 if (box
->otyp
== ICE_BOX
&& otmp
->otyp
== CORPSE
) {
170 otmp
->age
= monstermoves
- otmp
->age
; /* actual age */
171 start_corpse_timeout(otmp
);
173 place_object(otmp
, u
.ux
, u
.uy
);
177 loss
+= stolen_value(box
, u
.ux
, u
.uy
, peaceful_shk
, TRUE
);
179 You("owe %ld %s for objects destroyed.", loss
, currency(loss
));
184 /* try to force a locked chest */
188 if ((xlock
.box
->ox
!= u
.ux
) || (xlock
.box
->oy
!= u
.uy
))
189 return ((xlock
.usedtime
= 0)); /* you or it moved */
191 if (xlock
.usedtime
++ >= 50 || !uwep
|| nohands(youmonst
.data
)) {
192 You("give up your attempt to force the lock.");
193 if (xlock
.usedtime
>= 50) /* you made the effort */
194 exercise((xlock
.picktyp
) ? A_DEX
: A_STR
, TRUE
);
195 return ((xlock
.usedtime
= 0));
198 if (xlock
.picktyp
) { /* blade */
199 if (rn2(1000 - (int) uwep
->spe
) > (992 - greatest_erosion(uwep
) * 10)
200 && !uwep
->cursed
&& !obj_resists(uwep
, 0, 99)) {
201 /* for a +0 weapon, probability that it survives an unsuccessful
202 * attempt to force the lock is (.992)^50 = .67
204 pline("%sour %s broke!", (uwep
->quan
> 1L) ? "One of y" : "Y",
207 You("give up your attempt to force the lock.");
208 exercise(A_DEX
, TRUE
);
209 return ((xlock
.usedtime
= 0));
212 wake_nearby(); /* due to hammering on the container */
214 if (rn2(100) >= xlock
.chance
)
215 return 1; /* still busy */
217 You("succeed in forcing the lock.");
218 breakchestlock(xlock
.box
, (boolean
) (!xlock
.picktyp
&& !rn2(3)));
220 exercise((xlock
.picktyp
) ? A_DEX
: A_STR
, TRUE
);
221 return ((xlock
.usedtime
= 0));
227 xlock
.usedtime
= xlock
.chance
= xlock
.picktyp
= 0;
232 /* level change; don't reset if hero is carrying xlock.box with him/her */
236 if (!xlock
.box
|| !carried(xlock
.box
))
240 /* for doapply(); if player gives a direction or resumes an interrupted
241 previous attempt then it costs hero a move even if nothing ultimately
242 happens; when told "can't do that" before being asked for direction
243 or player cancels with ESC while giving direction, it doesn't */
244 #define PICKLOCK_LEARNED_SOMETHING (-1) /* time passes */
245 #define PICKLOCK_DID_NOTHING 0 /* no time passes */
246 #define PICKLOCK_DID_SOMETHING 1
248 /* player is applying a key, lock pick, or credit card */
259 picktyp
= pick
->otyp
;
261 /* check whether we're resuming an interrupted previous attempt */
262 if (xlock
.usedtime
&& picktyp
== xlock
.picktyp
) {
263 static char no_longer
[] = "Unfortunately, you can no longer %s %s.";
265 if (nohands(youmonst
.data
)) {
266 const char *what
= (picktyp
== LOCK_PICK
) ? "pick" : "key";
267 if (picktyp
== CREDIT_CARD
)
269 pline(no_longer
, "hold the", what
);
271 return PICKLOCK_LEARNED_SOMETHING
;
272 } else if (u
.uswallow
|| (xlock
.box
&& !can_reach_floor(TRUE
))) {
273 pline(no_longer
, "reach the", "lock");
275 return PICKLOCK_LEARNED_SOMETHING
;
277 const char *action
= lock_action();
279 You("resume your attempt at %s.", action
);
280 set_occupation(picklock
, action
, 0);
281 return PICKLOCK_DID_SOMETHING
;
285 if (nohands(youmonst
.data
)) {
286 You_cant("hold %s -- you have no hands!", doname(pick
));
287 return PICKLOCK_DID_NOTHING
;
288 } else if (u
.uswallow
) {
289 You_cant("%sunlock %s.", (picktyp
== CREDIT_CARD
) ? "" : "lock or ",
291 return PICKLOCK_DID_NOTHING
;
294 if ((picktyp
!= LOCK_PICK
&& picktyp
!= CREDIT_CARD
295 && picktyp
!= SKELETON_KEY
)) {
296 impossible("picking lock with object %d?", picktyp
);
297 return PICKLOCK_DID_NOTHING
;
299 ch
= 0; /* lint suppression */
301 if (!get_adjacent_loc((char *) 0, "Invalid location!", u
.ux
, u
.uy
, &cc
))
302 return PICKLOCK_DID_NOTHING
;
304 if (cc
.x
== u
.ux
&& cc
.y
== u
.uy
) { /* pick lock on a container */
311 There("isn't any sort of lock up %s.",
312 Levitation
? "here" : "there");
313 return PICKLOCK_LEARNED_SOMETHING
;
314 } else if (is_lava(u
.ux
, u
.uy
)) {
315 pline("Doing that would probably melt %s.", yname(pick
));
316 return PICKLOCK_LEARNED_SOMETHING
;
317 } else if (is_pool(u
.ux
, u
.uy
) && !Underwater
) {
318 pline_The("water has no lock.");
319 return PICKLOCK_LEARNED_SOMETHING
;
323 c
= 'n'; /* in case there are no boxes here */
324 for (otmp
= level
.objects
[cc
.x
][cc
.y
]; otmp
; otmp
= otmp
->nexthere
)
327 if (!can_reach_floor(TRUE
)) {
328 You_cant("reach %s from up here.", the(xname(otmp
)));
329 return PICKLOCK_LEARNED_SOMETHING
;
334 else if (!otmp
->olocked
)
335 verb
= "lock", it
= 1;
336 else if (picktyp
!= LOCK_PICK
)
337 verb
= "unlock", it
= 1;
341 /* "There is <a box> here; <verb> <it|its lock>?" */
342 Sprintf(qsfx
, " here; %s %s?", verb
, it
? "it" : "its lock");
343 (void) safe_qbuf(qbuf
, "There is ", qsfx
, otmp
, doname
,
344 ansimpleoname
, "a box");
354 You_cant("fix its broken lock with %s.", doname(pick
));
355 return PICKLOCK_LEARNED_SOMETHING
;
356 } else if (picktyp
== CREDIT_CARD
&& !otmp
->olocked
) {
357 /* credit cards are only good for unlocking */
358 You_cant("do that with %s.",
359 an(simple_typename(picktyp
)));
360 return PICKLOCK_LEARNED_SOMETHING
;
364 ch
= ACURR(A_DEX
) + 20 * Role_if(PM_ROGUE
);
367 ch
= 4 * ACURR(A_DEX
) + 25 * Role_if(PM_ROGUE
);
370 ch
= 75 + ACURR(A_DEX
);
378 xlock
.picktyp
= picktyp
;
385 There("doesn't seem to be any sort of lock here.");
386 return PICKLOCK_LEARNED_SOMETHING
; /* decided against all boxes */
388 } else { /* pick the lock in a door */
391 if (u
.utrap
&& u
.utraptype
== TT_PIT
) {
392 You_cant("reach over the edge of the pit.");
393 return PICKLOCK_LEARNED_SOMETHING
;
396 door
= &levl
[cc
.x
][cc
.y
];
397 mtmp
= m_at(cc
.x
, cc
.y
);
398 if (mtmp
&& canseemon(mtmp
) && mtmp
->m_ap_type
!= M_AP_FURNITURE
399 && mtmp
->m_ap_type
!= M_AP_OBJECT
) {
400 if (picktyp
== CREDIT_CARD
401 && (mtmp
->isshk
|| mtmp
->data
== &mons
[PM_ORACLE
]))
402 verbalize("No checks, no credit, no problem.");
404 pline("I don't think %s would appreciate that.",
406 return PICKLOCK_LEARNED_SOMETHING
;
407 } else if (mtmp
&& is_door_mappear(mtmp
)) {
408 /* "The door actually was a <mimic>!" */
409 stumble_onto_mimic(mtmp
);
410 /* mimic might keep the key (50% chance, 10% for PYEC) */
411 maybe_absorb_item(mtmp
, pick
, 50, 10);
412 return PICKLOCK_LEARNED_SOMETHING
;
414 if (!IS_DOOR(door
->typ
)) {
415 if (is_drawbridge_wall(cc
.x
, cc
.y
) >= 0)
416 You("%s no lock on the drawbridge.", Blind
? "feel" : "see");
418 You("%s no door there.", Blind
? "feel" : "see");
419 return PICKLOCK_LEARNED_SOMETHING
;
421 switch (door
->doormask
) {
423 pline("This doorway has no door.");
424 return PICKLOCK_LEARNED_SOMETHING
;
426 You("cannot lock an open door.");
427 return PICKLOCK_LEARNED_SOMETHING
;
429 pline("This door is broken.");
430 return PICKLOCK_LEARNED_SOMETHING
;
432 /* credit cards are only good for unlocking */
433 if (picktyp
== CREDIT_CARD
&& !(door
->doormask
& D_LOCKED
)) {
434 You_cant("lock a door with a credit card.");
435 return PICKLOCK_LEARNED_SOMETHING
;
438 Sprintf(qbuf
, "%s it?",
439 (door
->doormask
& D_LOCKED
) ? "Unlock" : "Lock");
447 ch
= 2 * ACURR(A_DEX
) + 20 * Role_if(PM_ROGUE
);
450 ch
= 3 * ACURR(A_DEX
) + 30 * Role_if(PM_ROGUE
);
453 ch
= 70 + ACURR(A_DEX
);
464 xlock
.picktyp
= picktyp
;
466 set_occupation(picklock
, lock_action(), 0);
467 return PICKLOCK_DID_SOMETHING
;
470 /* try to force a chest with your weapon */
474 register struct obj
*otmp
;
475 register int c
, picktyp
;
479 You_cant("force anything from inside here.");
482 if (!uwep
/* proper type test */
483 || ((uwep
->oclass
== WEAPON_CLASS
|| is_weptool(uwep
))
484 ? (objects
[uwep
->otyp
].oc_skill
< P_DAGGER
485 || objects
[uwep
->otyp
].oc_skill
== P_FLAIL
486 || objects
[uwep
->otyp
].oc_skill
> P_LANCE
)
487 : uwep
->oclass
!= ROCK_CLASS
)) {
488 You_cant("force anything %s weapon.",
489 !uwep
? "when not wielding a"
490 : (uwep
->oclass
!= WEAPON_CLASS
&& !is_weptool(uwep
))
495 if (!can_reach_floor(TRUE
)) {
496 cant_reach_floor(u
.ux
, u
.uy
, FALSE
, TRUE
);
500 picktyp
= is_blade(uwep
) && !is_pick(uwep
);
501 if (xlock
.usedtime
&& xlock
.box
&& picktyp
== xlock
.picktyp
) {
502 You("resume your attempt to force the lock.");
503 set_occupation(forcelock
, "forcing the lock", 0);
507 /* A lock is made only for the honest man, the thief will break it. */
508 xlock
.box
= (struct obj
*) 0;
509 for (otmp
= level
.objects
[u
.ux
][u
.uy
]; otmp
; otmp
= otmp
->nexthere
)
511 if (otmp
->obroken
|| !otmp
->olocked
) {
512 There("is %s here, but its lock is already %s.", doname(otmp
),
513 otmp
->obroken
? "broken" : "unlocked");
517 (void) safe_qbuf(qbuf
, "There is ", " here; force its lock?",
518 otmp
, doname
, ansimpleoname
, "a box");
528 You("force %s into a crack and pry.", yname(uwep
));
530 You("start bashing it with %s.", yname(uwep
));
532 xlock
.chance
= objects
[uwep
->otyp
].oc_wldam
* 2;
533 xlock
.picktyp
= picktyp
;
539 set_occupation(forcelock
, "forcing the lock", 0);
541 You("decide not to force the issue.");
546 stumble_on_door_mimic(x
, y
)
551 if ((mtmp
= m_at(x
, y
)) && is_door_mappear(mtmp
)
552 && !Protection_from_shape_changers
) {
553 stumble_onto_mimic(mtmp
);
559 /* the 'O' command - try to open a door */
563 return doopen_indir(0, 0);
566 /* try to open a door in direction u.dx/u.dy */
572 register struct rm
*door
;
576 if (nohands(youmonst
.data
)) {
577 You_cant("open anything -- you have no hands!");
581 if (u
.utrap
&& u
.utraptype
== TT_PIT
) {
582 You_cant("reach over the edge of the pit.");
586 if (x
> 0 && y
> 0) {
589 } else if (!get_adjacent_loc((char *) 0, (char *) 0, u
.ux
, u
.uy
, &cc
))
592 if ((cc
.x
== u
.ux
) && (cc
.y
== u
.uy
))
595 if (stumble_on_door_mimic(cc
.x
, cc
.y
))
598 /* when choosing a direction is impaired, use a turn
599 regardless of whether a door is successfully targetted */
600 if (Confusion
|| Stunned
)
603 door
= &levl
[cc
.x
][cc
.y
];
604 portcullis
= (is_drawbridge_wall(cc
.x
, cc
.y
) >= 0);
606 int oldglyph
= door
->glyph
;
607 schar oldlastseentyp
= lastseentyp
[cc
.x
][cc
.y
];
609 feel_location(cc
.x
, cc
.y
);
610 if (door
->glyph
!= oldglyph
611 || lastseentyp
[cc
.x
][cc
.y
] != oldlastseentyp
)
612 res
= 1; /* learned something */
615 if (portcullis
|| !IS_DOOR(door
->typ
)) {
616 /* closed portcullis or spot that opened bridge would span */
617 if (is_db_wall(cc
.x
, cc
.y
) || door
->typ
== DRAWBRIDGE_UP
)
618 There("is no obvious way to open the drawbridge.");
619 else if (portcullis
|| door
->typ
== DRAWBRIDGE_DOWN
)
620 pline_The("drawbridge is already open.");
622 You("%s no door there.", Blind
? "feel" : "see");
626 if (!(door
->doormask
& D_CLOSED
)) {
629 switch (door
->doormask
) {
634 mesg
= "way has no door";
637 mesg
= " is already open";
643 pline("This door%s.", mesg
);
647 if (verysmall(youmonst
.data
)) {
648 pline("You're too small to pull the door open.");
652 /* door is known to be CLOSED */
653 if (rnl(20) < (ACURRSTR
+ ACURR(A_DEX
) + ACURR(A_CON
)) / 3) {
654 pline_The("door opens.");
655 if (door
->doormask
& D_TRAPPED
) {
656 b_trapped("door", FINGER
);
657 door
->doormask
= D_NODOOR
;
658 if (*in_rooms(cc
.x
, cc
.y
, SHOPBASE
))
659 add_damage(cc
.x
, cc
.y
, 0L);
661 door
->doormask
= D_ISOPEN
;
662 feel_newsym(cc
.x
, cc
.y
); /* the hero knows she opened it */
663 unblock_point(cc
.x
, cc
.y
); /* vision: new see through there */
665 exercise(A_STR
, TRUE
);
666 pline_The("door resists!");
673 obstructed(x
, y
, quietly
)
677 register struct monst
*mtmp
= m_at(x
, y
);
679 if (mtmp
&& mtmp
->m_ap_type
!= M_AP_FURNITURE
) {
680 if (mtmp
->m_ap_type
== M_AP_OBJECT
)
683 if ((mtmp
->mx
!= x
) || (mtmp
->my
!= y
)) {
685 pline("%s%s blocks the way!",
686 !canspotmon(mtmp
) ? Something
: s_suffix(Monnam(mtmp
)),
687 !canspotmon(mtmp
) ? "" : " tail");
689 pline("%s blocks the way!",
690 !canspotmon(mtmp
) ? "Some creature" : Monnam(mtmp
));
693 if (!canspotmon(mtmp
))
700 pline("%s's in the way.", Something
);
706 /* the 'C' command - try to close a door */
711 register struct rm
*door
;
715 if (nohands(youmonst
.data
)) {
716 You_cant("close anything -- you have no hands!");
720 if (u
.utrap
&& u
.utraptype
== TT_PIT
) {
721 You_cant("reach over the edge of the pit.");
725 if (!getdir((char *) 0))
730 if ((x
== u
.ux
) && (y
== u
.uy
)) {
731 You("are in the way!");
738 if (stumble_on_door_mimic(x
, y
))
741 /* when choosing a direction is impaired, use a turn
742 regardless of whether a door is successfully targetted */
743 if (Confusion
|| Stunned
)
747 portcullis
= (is_drawbridge_wall(x
, y
) >= 0);
749 int oldglyph
= door
->glyph
;
750 schar oldlastseentyp
= lastseentyp
[x
][y
];
753 if (door
->glyph
!= oldglyph
|| lastseentyp
[x
][y
] != oldlastseentyp
)
754 res
= 1; /* learned something */
757 if (portcullis
|| !IS_DOOR(door
->typ
)) {
758 /* is_db_wall: closed portcullis */
759 if (is_db_wall(x
, y
) || door
->typ
== DRAWBRIDGE_UP
)
760 pline_The("drawbridge is already closed.");
761 else if (portcullis
|| door
->typ
== DRAWBRIDGE_DOWN
)
762 There("is no obvious way to close the drawbridge.");
765 You("%s no door there.", Blind
? "feel" : "see");
770 if (door
->doormask
== D_NODOOR
) {
771 pline("This doorway has no door.");
773 } else if (obstructed(x
, y
, FALSE
)) {
775 } else if (door
->doormask
== D_BROKEN
) {
776 pline("This door is broken.");
778 } else if (door
->doormask
& (D_CLOSED
| D_LOCKED
)) {
779 pline("This door is already closed.");
783 if (door
->doormask
== D_ISOPEN
) {
784 if (verysmall(youmonst
.data
) && !u
.usteed
) {
785 pline("You're too small to push the door closed.");
789 || rn2(25) < (ACURRSTR
+ ACURR(A_DEX
) + ACURR(A_CON
)) / 3) {
790 pline_The("door closes.");
791 door
->doormask
= D_CLOSED
;
792 feel_newsym(x
, y
); /* the hero knows she closed it */
793 block_point(x
, y
); /* vision: no longer see there */
795 exercise(A_STR
, TRUE
);
796 pline_The("door resists!");
803 /* box obj was hit with spell or wand effect otmp;
804 returns true if something happened */
807 struct obj
*obj
, *otmp
; /* obj *is* a box */
811 switch (otmp
->otyp
) {
813 case SPE_WIZARD_LOCK
:
814 if (!obj
->olocked
) { /* lock it; fix if broken */
818 if (Role_if(PM_WIZARD
))
823 } /* else already closed and locked */
827 if (obj
->olocked
) { /* unlock; couldn't be broken */
831 if (Role_if(PM_WIZARD
))
835 } else /* silently fix if broken */
840 /* maybe start unlocking chest, get interrupted, then zap it;
841 we must avoid any attempt to resume unlocking it */
842 if (xlock
.box
== obj
)
849 /* Door/secret door was hit with spell or wand effect otmp;
850 returns true if something happened */
856 register struct rm
*door
= &levl
[x
][y
];
859 const char *msg
= (const char *) 0;
860 const char *dustcloud
= "A cloud of dust";
861 const char *quickly_dissipates
= "quickly dissipates";
862 boolean mysterywand
= (otmp
->oclass
== WAND_CLASS
&& !otmp
->dknown
);
864 if (door
->typ
== SDOOR
) {
865 switch (otmp
->otyp
) {
871 door
->doormask
= D_CLOSED
| (door
->doormask
& D_TRAPPED
);
874 pline("A door appears in the wall!");
875 if (otmp
->otyp
== WAN_OPENING
|| otmp
->otyp
== SPE_KNOCK
)
877 break; /* striking: continue door handling below */
879 case SPE_WIZARD_LOCK
:
885 switch (otmp
->otyp
) {
887 case SPE_WIZARD_LOCK
:
888 if (Is_rogue_level(&u
.uz
)) {
889 boolean vis
= cansee(x
, y
);
890 /* Can't have real locking in Rogue, so just hide doorway */
892 pline("%s springs up in the older, more primitive doorway.",
895 You_hear("a swoosh.");
896 if (obstructed(x
, y
, mysterywand
)) {
898 pline_The("cloud %s.", quickly_dissipates
);
904 pline_The("doorway vanishes!");
908 if (obstructed(x
, y
, mysterywand
))
910 /* Don't allow doors to close over traps. This is for pits */
911 /* & trap doors, but is it ever OK for anything else? */
913 /* maketrap() clears doormask, so it should be NODOOR */
914 pline("%s springs up in the doorway, but %s.", dustcloud
,
919 switch (door
->doormask
& ~D_TRAPPED
) {
921 msg
= "The door locks!";
924 msg
= "The door swings shut, and locks!";
927 msg
= "The broken door reassembles and locks!";
931 "A cloud of dust springs up and assembles itself into a door!";
938 door
->doormask
= D_LOCKED
| (door
->doormask
& D_TRAPPED
);
943 if (door
->doormask
& D_LOCKED
) {
944 msg
= "The door unlocks!";
945 door
->doormask
= D_CLOSED
| (door
->doormask
& D_TRAPPED
);
951 if (door
->doormask
& (D_LOCKED
| D_CLOSED
)) {
952 if (door
->doormask
& D_TRAPPED
) {
954 (void) mb_trapped(m_at(x
, y
));
955 else if (flags
.verbose
) {
957 pline("KABOOM!! You see a door explode.");
959 You_hear("a distant explosion.");
961 door
->doormask
= D_NODOOR
;
967 door
->doormask
= D_BROKEN
;
970 pline_The("door crashes open!");
972 You_hear("a crashing sound.");
976 /* force vision recalc before printing more messages */
977 if (vision_full_recalc
)
984 impossible("magic (%d) attempted on door.", otmp
->otyp
);
987 if (msg
&& cansee(x
, y
))
990 /* door was destroyed */
991 wake_nearto(x
, y
, loudness
);
992 if (*in_rooms(x
, y
, SHOPBASE
))
993 add_damage(x
, y
, 0L);
996 if (res
&& picking_at(x
, y
)) {
997 /* maybe unseen monster zaps door you're unlocking */
1005 chest_shatter_msg(otmp
)
1008 const char *disposition
;
1012 if (otmp
->oclass
== POTION_CLASS
) {
1013 You("%s %s shatter!", Blind
? "hear" : "see", an(bottlename()));
1014 if (!breathless(youmonst
.data
) || haseyes(youmonst
.data
))
1015 potionbreathe(otmp
);
1018 /* We have functions for distant and singular names, but not one */
1019 /* which does _both_... */
1020 save_Blinded
= Blinded
;
1022 thing
= singular(otmp
, xname
);
1023 Blinded
= save_Blinded
;
1024 switch (objects
[otmp
->otyp
].oc_material
) {
1026 disposition
= "is torn to shreds";
1029 disposition
= "is crushed";
1032 disposition
= "is pulped";
1035 disposition
= "is mashed";
1038 disposition
= "shatters";
1041 disposition
= "splinters to fragments";
1044 disposition
= "is destroyed";
1047 pline("%s %s!", An(thing
), disposition
);