1 /* NetHack 3.6 lock.c $NHDT-Date: 1521499715 2018/03/19 22:48:35 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.80 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Robert Patrick Rankin, 2011. */
4 /* NetHack may be freely redistributed. See license for details. */
6 /* JNetHack Copyright */
7 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000 */
8 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2019 */
9 /* JNetHack may be freely redistributed. See license for details. */
13 /* at most one of `door' and `box' should be non-null at any given time */
14 STATIC_VAR NEARDATA struct xlock_s {
17 int picktyp, /* key|pick|card for unlock, sharp vs blunt for #force */
22 /* occupation callbacks */
23 STATIC_PTR int NDECL(picklock);
24 STATIC_PTR int NDECL(forcelock);
26 STATIC_DCL const char *NDECL(lock_action);
27 STATIC_DCL boolean FDECL(obstructed, (int, int, BOOLEAN_P));
28 STATIC_DCL void FDECL(chest_shatter_msg, (struct obj *));
34 if (occupation == picklock) {
48 return (boolean) (occupation == picklock && xlock.door == &levl[x][y]);
51 /* produce an occupation string appropriate for the current activity */
52 STATIC_OVL const char *
55 /* "unlocking"+2 == "locking" */
56 static const char *actions[] = {
58 "unlocking the door", /* [0] */
59 "unlocking the chest", /* [1] */
60 "unlocking the box", /* [2] */
61 "picking the lock" /* [3] */
63 "
\94à
\82Ì
\8c®
\82ð
\82Í
\82¸
\82·",
64 "
\95ó
\94 \82Ì
\8c®
\82ð
\82Í
\82¸
\82·",
65 "
\94 \82Ì
\8c®
\82ð
\82Í
\82¸
\82·",
66 "
\8c®
\82ð
\82Í
\82¸
\82·"
70 /* if the target is currently unlocked, we're trying to lock it now */
71 if (xlock.door && !(xlock.door->doormask & D_LOCKED))
73 return actions[0] + 2; /* "locking the door" */
74 #else /*
\89p
\8cê
\82Í un
\82ð
\8eæ
\82ê
\82Î
\8bt
\82Ì
\88Ó
\96¡
\82É
\82È
\82é
\82ª
\81C
\93ú
\96{
\8cê
\82Í
\82»
\82¤
\82Í
\82¢
\82©
\82È
\82¢
\82Ì
\82Å
\83\8a\83e
\83\89\83\8b\82ð
\8f\91\82 */
75 return "
\94à
\82É
\8c®
\82ð
\82©
\82¯
\82é";
77 else if (xlock.box && !xlock.box->olocked)
79 return xlock.box->otyp == CHEST ? actions[1] + 2 : actions[2] + 2;
81 return xlock.box->otyp == CHEST ? "
\95ó
\94 \82É
\8c®
\82ð
\82©
\82¯
\82é" : "
\94 \82É
\8c®
\82ð
\82©
\82¯
\82é";
83 /* otherwise we're trying to unlock it */
84 else if (xlock.picktyp == LOCK_PICK)
85 return actions[3]; /* "picking the lock" */
86 else if (xlock.picktyp == CREDIT_CARD)
87 return actions[3]; /* same as lock_pick */
89 return actions[0]; /* "unlocking the door" */
91 return xlock.box->otyp == CHEST ? actions[1] : actions[2];
96 /* try to open/close a lock */
101 if (xlock.box->where != OBJ_FLOOR
102 || xlock.box->ox != u.ux || xlock.box->oy != u.uy) {
103 return ((xlock.usedtime = 0)); /* you or it moved */
106 if (xlock.door != &(levl[u.ux + u.dx][u.uy + u.dy])) {
107 return ((xlock.usedtime = 0)); /* you moved */
109 switch (xlock.door->doormask) {
112 pline("This doorway has no door.");
114 pline("
\8fo
\93ü
\8cû
\82É
\82Í
\94à
\82ª
\82È
\82¢
\81D");
115 return ((xlock.usedtime = 0));
118 You("cannot lock an open door.");
120 pline("
\8aJ
\82¢
\82Ä
\82é
\94à
\82É
\8c®
\82ð
\82©
\82¯
\82ç
\82ê
\82È
\82¢
\81D");
121 return ((xlock.usedtime = 0));
124 pline("This door is broken.");
126 pline("
\94à
\82Í
\89ó
\82ê
\82Ä
\82¢
\82é
\81D");
127 return ((xlock.usedtime = 0));
131 if (xlock.usedtime++ >= 50 || nohands(youmonst.data)) {
133 You("give up your attempt at %s.", lock_action());
135 pline("%s
\82Ì
\82ð
\82 \82«
\82ç
\82ß
\82½
\81D", lock_action());
136 exercise(A_DEX, TRUE); /* even if you don't succeed */
137 return ((xlock.usedtime = 0));
140 if (rn2(100) >= xlock.chance)
141 return 1; /* still busy */
143 /* using the Master Key of Thievery finds traps if its bless/curse
144 state is adequate (non-cursed for rogues, blessed for others;
145 checked when setting up 'xlock') */
146 if ((!xlock.door ? (int) xlock.box->otrapped
147 : (xlock.door->doormask & D_TRAPPED) != 0)
148 && xlock.magic_key) {
149 xlock.chance += 20; /* less effort needed next time */
150 /* unfortunately we don't have a 'tknown' flag to record
151 "known to be trapped" so declining to disarm and then
152 retrying lock manipulation will find it all over again */
154 if (yn("You find a trap! Do you want to try to disarm it?") == 'y') {
156 if (yn("ã©
\82ð
\8c©
\82Â
\82¯
\82½
\81I
\8aO
\82µ
\82Ü
\82·
\82©
\81H") == 'y') {
158 boolean alreadyunlocked;
160 /* disarming while using magic key always succeeds */
162 xlock.door->doormask &= ~D_TRAPPED;
167 alreadyunlocked = !(xlock.door->doormask & D_LOCKED);
169 xlock.box->otrapped = 0;
171 what = (xlock.box->otyp == CHEST) ? "chest" : "box";
173 what = (xlock.box->otyp == CHEST) ? "
\95ó
\94 " : "
\94 ";
174 alreadyunlocked = !xlock.box->olocked;
177 You("succeed in disarming the trap. The %s is still %slocked.",
178 what, alreadyunlocked ? "un" : "");
180 You("ã©
\82ð
\8aO
\82µ
\82½
\81D%s
\82Í
\8c®
\82ª%s
\82Ü
\82Ü
\82¾
\81D",
181 what, alreadyunlocked ? "
\8aJ
\82¢
\82½" : "
\82©
\82©
\82Á
\82½");
183 exercise(A_WIS, TRUE);
186 You("stop %s.", lock_action());
188 You("%s
\82Ì
\82ð
\82â
\82ß
\82½
\81D", lock_action());
189 exercise(A_WIS, FALSE);
191 return ((xlock.usedtime = 0));
195 You("succeed in %s.", lock_action());
197 You("%s
\82Ì
\82É
\90¬
\8c÷
\82µ
\82½
\81D", lock_action());
199 if (xlock.door->doormask & D_TRAPPED) {
201 b_trapped("door", FINGER);
203 b_trapped("
\94à", FINGER);
204 xlock.door->doormask = D_NODOOR;
205 unblock_point(u.ux + u.dx, u.uy + u.dy);
206 if (*in_rooms(u.ux + u.dx, u.uy + u.dy, SHOPBASE))
207 add_damage(u.ux + u.dx, u.uy + u.dy, SHOP_DOOR_COST);
208 newsym(u.ux + u.dx, u.uy + u.dy);
209 } else if (xlock.door->doormask & D_LOCKED)
210 xlock.door->doormask = D_CLOSED;
212 xlock.door->doormask = D_LOCKED;
214 xlock.box->olocked = !xlock.box->olocked;
215 xlock.box->lknown = 1;
216 if (xlock.box->otrapped)
217 (void) chest_trap(xlock.box, FINGER, FALSE);
219 exercise(A_DEX, TRUE);
220 return ((xlock.usedtime = 0));
224 breakchestlock(box, destroyit)
228 if (!destroyit) { /* bill for the box but not for its contents */
229 struct obj *hide_contents = box->cobj;
232 costly_alteration(box, COST_BRKLCK);
233 box->cobj = hide_contents;
237 } else { /* #force has destroyed this box (at <u.ux,u.uy>) */
239 struct monst *shkp = (*u.ushops && costly_spot(u.ux, u.uy))
240 ? shop_keeper(*u.ushops)
242 boolean costly = (boolean) (shkp != 0),
243 peaceful_shk = costly && (boolean) shkp->mpeaceful;
247 pline("In fact, you've totally destroyed %s.", the(xname(box)));
249 pline("
\8eÀ
\8dÛ
\82Ì
\82Æ
\82±
\82ë
\81C%s
\82ð
\8a®
\91S
\82É
\89ó
\82µ
\82Ä
\82µ
\82Ü
\82Á
\82½
\81D", xname(xlock.box));
250 /* Put the contents on ground at the hero's feet. */
251 while ((otmp = box->cobj) != 0) {
252 obj_extract_self(otmp);
253 if (!rn2(3) || otmp->oclass == POTION_CLASS) {
254 chest_shatter_msg(otmp);
257 stolen_value(otmp, u.ux, u.uy, peaceful_shk, TRUE);
258 if (otmp->quan == 1L) {
259 obfree(otmp, (struct obj *) 0);
264 if (box->otyp == ICE_BOX && otmp->otyp == CORPSE) {
265 otmp->age = monstermoves - otmp->age; /* actual age */
266 start_corpse_timeout(otmp);
268 place_object(otmp, u.ux, u.uy);
272 loss += stolen_value(box, u.ux, u.uy, peaceful_shk, TRUE);
275 You("owe %ld %s for objects destroyed.", loss, currency(loss));
277 You("
\8aí
\95¨
\94j
\91¹
\82Å%ld%s
\82Ì
\8eØ
\82è
\82ð
\82Â
\82
\82Á
\82½
\81D", loss, currency(loss));
282 /* try to force a locked chest */
286 if ((xlock.box->ox != u.ux) || (xlock.box->oy != u.uy))
287 return ((xlock.usedtime = 0)); /* you or it moved */
289 if (xlock.usedtime++ >= 50 || !uwep || nohands(youmonst.data)) {
291 You("give up your attempt to force the lock.");
293 pline("
\8c®
\82ð
\82±
\82¶
\8aJ
\82¯
\82é
\82Ì
\82ð
\82 \82«
\82ç
\82ß
\82½
\81D");
294 if (xlock.usedtime >= 50) /* you made the effort */
295 exercise((xlock.picktyp) ? A_DEX : A_STR, TRUE);
296 return ((xlock.usedtime = 0));
299 if (xlock.picktyp) { /* blade */
300 if (rn2(1000 - (int) uwep->spe) > (992 - greatest_erosion(uwep) * 10)
301 && !uwep->cursed && !obj_resists(uwep, 0, 99)) {
302 /* for a +0 weapon, probability that it survives an unsuccessful
303 * attempt to force the lock is (.992)^50 = .67
306 pline("%sour %s broke!", (uwep->quan > 1L) ? "One of y" : "Y",
309 pline("%s
\82Í
\89ó
\82ê
\82Ä
\82µ
\82Ü
\82Á
\82½
\81I",xname(uwep));
313 You("give up your attempt to force the lock.");
315 pline("
\8c®
\82ð
\82±
\82¶
\8aJ
\82¯
\82é
\82Ì
\82ð
\82 \82«
\82ç
\82ß
\82½
\81D");
316 exercise(A_DEX, TRUE);
317 return ((xlock.usedtime = 0));
320 wake_nearby(); /* due to hammering on the container */
322 if (rn2(100) >= xlock.chance)
323 return 1; /* still busy */
326 You("succeed in forcing the lock.");
328 pline("
\8c®
\82ð
\82±
\82¶
\8aJ
\82¯
\82½
\81D");
329 breakchestlock(xlock.box, (boolean) (!xlock.picktyp && !rn2(3)));
331 exercise((xlock.picktyp) ? A_DEX : A_STR, TRUE);
332 return ((xlock.usedtime = 0));
338 xlock.usedtime = xlock.chance = xlock.picktyp = 0;
339 xlock.magic_key = FALSE;
344 /* level change; don't reset if hero is carrying xlock.box with him/her */
348 if (!xlock.box || !carried(xlock.box))
352 /* for doapply(); if player gives a direction or resumes an interrupted
353 previous attempt then it costs hero a move even if nothing ultimately
354 happens; when told "can't do that" before being asked for direction
355 or player cancels with ESC while giving direction, it doesn't */
356 #define PICKLOCK_LEARNED_SOMETHING (-1) /* time passes */
357 #define PICKLOCK_DID_NOTHING 0 /* no time passes */
358 #define PICKLOCK_DID_SOMETHING 1
360 /* player is applying a key, lock pick, or credit card */
371 picktyp = pick->otyp;
373 /* check whether we're resuming an interrupted previous attempt */
374 if (xlock.usedtime && picktyp == xlock.picktyp) {
376 static char no_longer[] = "Unfortunately, you can no longer %s %s.";
378 static char no_longer[] = "
\82´
\82ñ
\82Ë
\82ñ
\82È
\82ª
\82ç
\81C
\82 \82È
\82½
\82Í%s%s";
380 if (nohands(youmonst.data)) {
382 const char *what = (picktyp == LOCK_PICK) ? "pick" : "key";
384 const char *what = (picktyp == LOCK_PICK) ? "
\8c®
\8aJ
\82¯
\8aí
\8bï" : "
\8c®";
386 if (picktyp == CREDIT_CARD)
390 what = "
\83J
\81[
\83h";
392 pline(no_longer, "hold the", what);
394 pline(no_longer, what, "
\82ð
\82Â
\82©
\82ß
\82È
\82¢");
396 return PICKLOCK_LEARNED_SOMETHING;
397 } else if (u.uswallow || (xlock.box && !can_reach_floor(TRUE))) {
399 pline(no_longer, "reach the", "lock");
401 pline(no_longer, "
\8c®
\82É", "
\93Í
\82©
\82È
\82¢");
403 return PICKLOCK_LEARNED_SOMETHING;
405 const char *action = lock_action();
408 You("resume your attempt at %s.", action);
410 pline("%s
\82Ì
\82ð
\8dÄ
\8aJ
\82µ
\82½
\81D", action);
411 xlock.magic_key = is_magic_key(&youmonst, pick);
412 set_occupation(picklock, action, 0);
413 return PICKLOCK_DID_SOMETHING;
417 if (nohands(youmonst.data)) {
419 You_cant("hold %s -- you have no hands!", doname(pick));
421 You("%s
\82ð
\82Â
\82©
\82Þ
\82±
\82Æ
\82ª
\82Å
\82«
\82È
\82¢
\81I
\8eè
\82ª
\82È
\82¢
\82ñ
\82¾
\82à
\82Ì
\81I", xname(pick));
422 return PICKLOCK_DID_NOTHING;
423 } else if (u.uswallow) {
425 You_cant("%sunlock %s.", (picktyp == CREDIT_CARD) ? "" : "lock or ",
428 You_cant("%s
\82ð%s
\82È
\82¢
\81D", mon_nam(u.ustuck),
429 (picktyp == CREDIT_CARD) ? "
\8aJ
\82¯
\82ç
\82ê" : "
\8aJ
\82¯
\95Â
\82ß
\82Å
\82«");
431 return PICKLOCK_DID_NOTHING;
434 if (picktyp != LOCK_PICK
435 && picktyp != CREDIT_CARD
436 && picktyp != SKELETON_KEY) {
437 impossible("picking lock with object %d?", picktyp);
438 return PICKLOCK_DID_NOTHING;
440 ch = 0; /* lint suppression */
443 if (!get_adjacent_loc((char *) 0, "Invalid location!", u.ux, u.uy, &cc))
445 if (!get_adjacent_loc((char *) 0, "
\88Ê
\92u
\82ª
\82¨
\82©
\82µ
\82¢
\81I", u.ux, u.uy, &cc))
446 return PICKLOCK_DID_NOTHING;
448 if (cc.x == u.ux && cc.y == u.uy) { /* pick lock on a container */
458 There("isn't any sort of lock up %s.",
459 Levitation ? "here" : "there");
461 pline("%s
\82É
\82Í
\8c®
\82ð
\82©
\82¯
\82é
\82æ
\82¤
\82È
\95¨
\82Í
\82È
\82¢
\81D",
462 Levitation ? "
\82±
\82±" : "
\89º
\95û");
464 return PICKLOCK_LEARNED_SOMETHING;
465 } else if (is_lava(u.ux, u.uy)) {
467 pline("Doing that would probably melt %s.", yname(pick));
469 pline("
\82»
\82ñ
\82È
\82±
\82Æ
\82ð
\82µ
\82½
\82ç%s
\82ª
\97n
\82¯
\82Ä
\82µ
\82Ü
\82¤
\81D", yname(pick));
470 return PICKLOCK_LEARNED_SOMETHING;
471 } else if (is_pool(u.ux, u.uy) && !Underwater) {
473 pline_The("%s has no lock.", hliquid("water"));
475 pline_The("%s
\82É
\8fù
\91O
\82Í
\82È
\82¢
\81D", hliquid("
\90\85"));
476 return PICKLOCK_LEARNED_SOMETHING;
480 c = 'n'; /* in case there are no boxes here */
481 for (otmp = level.objects[cc.x][cc.y]; otmp; otmp = otmp->nexthere)
484 if (!can_reach_floor(TRUE)) {
486 You_cant("reach %s from up here.", the(xname(otmp)));
488 You("
\82±
\82±
\82©
\82ç%s
\82É
\93Í
\82©
\82È
\82¢
\81D", the(xname(otmp)));
489 return PICKLOCK_LEARNED_SOMETHING;
498 verb = "
\8fC
\95\9c\82·
\82é";
499 else if (!otmp->olocked)
501 verb = "lock", it = 1;
503 verb = "
\8c®
\82ð
\82©
\82¯
\82é";
504 else if (picktyp != LOCK_PICK)
506 verb = "unlock", it = 1;
508 verb = "
\8c®
\82ð
\82Í
\82¸
\82·";
513 verb = "
\82±
\82¶
\82 \82¯
\82é";
515 /* "There is <a box> here; <verb> <it|its lock>?" */
517 Sprintf(qsfx, " here; %s %s?", verb, it ? "it" : "its lock");
519 Sprintf(qsfx, "
\82ª
\82 \82é
\81D%s
\81H", verb);
521 (void) safe_qbuf(qbuf, "There is ", qsfx, otmp, doname,
522 ansimpleoname, "a box");
524 (void) safe_qbuf(qbuf, "
\82±
\82±
\82É
\82Í", qsfx, otmp, doname,
525 ansimpleoname, "
\94 ");
537 You_cant("fix its broken lock with %s.", doname(pick));
539 You("
\89ó
\82ê
\82½
\8c®
\82ð%s
\82Å
\8fC
\95\9c\82Å
\82«
\82È
\82¢
\81D", doname(pick));
540 return PICKLOCK_LEARNED_SOMETHING;
541 } else if (picktyp == CREDIT_CARD && !otmp->olocked) {
542 /* credit cards are only good for unlocking */
544 You_cant("do that with %s.",
545 an(simple_typename(picktyp)));
547 pline("%s
\82¶
\82á
\82»
\82ñ
\82È
\82±
\82Æ
\82Í
\82Å
\82«
\82È
\82¢
\81D",
548 simple_typename(picktyp));
550 return PICKLOCK_LEARNED_SOMETHING;
554 ch = ACURR(A_DEX) + 20 * Role_if(PM_ROGUE);
557 ch = 4 * ACURR(A_DEX) + 25 * Role_if(PM_ROGUE);
560 ch = 75 + ACURR(A_DEX);
575 There("doesn't seem to be any sort of lock here.");
577 pline("
\82±
\82±
\82É
\82Í
\8c®
\82ð
\82©
\82¯
\82é
\82æ
\82¤
\82È
\95¨
\82Í
\82È
\82¢
\82æ
\82¤
\82¾
\81D");
578 return PICKLOCK_LEARNED_SOMETHING; /* decided against all boxes */
580 } else { /* pick the lock in a door */
583 if (u.utrap && u.utraptype == TT_PIT) {
585 You_cant("reach over the edge of the pit.");
587 pline("
\97\8e\82µ
\8c\8a\82Ì
\92\86\82©
\82ç
\82Å
\82Í
\93Í
\82©
\82È
\82¢
\81D");
588 return PICKLOCK_LEARNED_SOMETHING;
591 door = &levl[cc.x][cc.y];
592 mtmp = m_at(cc.x, cc.y);
593 if (mtmp && canseemon(mtmp) && mtmp->m_ap_type != M_AP_FURNITURE
594 && mtmp->m_ap_type != M_AP_OBJECT) {
595 if (picktyp == CREDIT_CARD
596 && (mtmp->isshk || mtmp->data == &mons[PM_ORACLE]))
598 verbalize("No checks, no credit, no problem.");
600 verbalize("
\82¢
\82Â
\82à
\83j
\83R
\83j
\83R
\8c»
\8bà
\95¥
\82¢
\81D");
603 pline("I don't think %s would appreciate that.",
606 pline("%s
\82ª
\82»
\82Ì
\89¿
\92l
\82ð
\94F
\82ß
\82é
\82Æ
\82Í
\8ev
\82¦
\82È
\82¢
\81D", mon_nam(mtmp));
608 return PICKLOCK_LEARNED_SOMETHING;
609 } else if (mtmp && is_door_mappear(mtmp)) {
610 /* "The door actually was a <mimic>!" */
611 stumble_onto_mimic(mtmp);
612 /* mimic might keep the key (50% chance, 10% for PYEC or MKoT) */
613 maybe_absorb_item(mtmp, pick, 50, 10);
614 return PICKLOCK_LEARNED_SOMETHING;
616 if (!IS_DOOR(door->typ)) {
617 if (is_drawbridge_wall(cc.x, cc.y) >= 0)
619 You("%s no lock on the drawbridge.", Blind ? "feel" : "see");
621 pline("
\92µ
\82Ë
\8b´
\82É
\82Í
\8c®
\82ª
\82È
\82¢%s
\81D", Blind ? "
\82æ
\82¤
\82¾" : "
\82æ
\82¤
\82É
\8c©
\82¦
\82é");
624 You("%s no door there.", Blind ? "feel" : "see");
626 pline("
\82±
\82±
\82É
\82Í
\94à
\82ª
\82È
\82¢%s
\81D", Blind ? "
\82æ
\82¤
\82¾" : "
\82æ
\82¤
\82É
\8c©
\82¦
\82é");
627 return PICKLOCK_LEARNED_SOMETHING;
629 switch (door->doormask) {
632 pline("This doorway has no door.");
634 pline("
\82±
\82Ì
\8fo
\93ü
\8cû
\82É
\82Í
\94à
\82ª
\82È
\82¢
\81D");
635 return PICKLOCK_LEARNED_SOMETHING;
638 You("cannot lock an open door.");
640 pline("
\8aJ
\82¢
\82Ä
\82é
\94à
\82É
\82Í
\8c®
\82ð
\82©
\82¯
\82ç
\82ê
\82È
\82¢
\81D");
641 return PICKLOCK_LEARNED_SOMETHING;
644 pline("This door is broken.");
646 pline("
\82±
\82Ì
\94à
\82Í
\89ó
\82ê
\82Ä
\82¢
\82é
\81D");
647 return PICKLOCK_LEARNED_SOMETHING;
649 /* credit cards are only good for unlocking */
650 if (picktyp == CREDIT_CARD && !(door->doormask & D_LOCKED)) {
652 You_cant("lock a door with a credit card.");
654 You("
\83N
\83\8c\83W
\83b
\83g
\83J
\81[
\83h
\82Å
\94à
\82É
\8c®
\82ð
\82©
\82¯
\82é
\82±
\82Æ
\82Í
\82Å
\82«
\82È
\82¢
\81D");
655 return PICKLOCK_LEARNED_SOMETHING;
659 Sprintf(qbuf, "%s it?",
660 (door->doormask & D_LOCKED) ? "Unlock" : "Lock");
662 Sprintf(qbuf, "%s
\82Ü
\82·
\82©
\81H",
663 (door->doormask & D_LOCKED) ? "
\82Í
\82¸
\82µ" : "
\82©
\82¯" );
672 ch = 2 * ACURR(A_DEX) + 20 * Role_if(PM_ROGUE);
675 ch = 3 * ACURR(A_DEX) + 30 * Role_if(PM_ROGUE);
678 ch = 70 + ACURR(A_DEX);
689 xlock.picktyp = picktyp;
690 xlock.magic_key = is_magic_key(&youmonst, pick);
692 set_occupation(picklock, lock_action(), 0);
693 return PICKLOCK_DID_SOMETHING;
696 /* try to force a chest with your weapon */
700 register struct obj *otmp;
701 register int c, picktyp;
706 You_cant("force anything from inside here.");
708 You_cant("
\93à
\91¤
\82©
\82ç
\82±
\82¶
\8aJ
\82¯
\82é
\82±
\82Æ
\82Í
\82Å
\82«
\82È
\82¢
\81D");
711 if (!uwep /* proper type test */
712 || ((uwep->oclass == WEAPON_CLASS || is_weptool(uwep))
713 ? (objects[uwep->otyp].oc_skill < P_DAGGER
714 || objects[uwep->otyp].oc_skill == P_FLAIL
715 || objects[uwep->otyp].oc_skill > P_LANCE)
716 : uwep->oclass != ROCK_CLASS)) {
718 You_cant("force anything %s weapon.",
719 !uwep ? "when not wielding a"
720 : (uwep->oclass != WEAPON_CLASS && !is_weptool(uwep))
724 You_cant("%s
\95\90\8aí
\82È
\82µ
\82Å
\8c®
\82ð
\82±
\82¶
\8aJ
\82¯
\82é
\82±
\82Æ
\82Í
\82Å
\82«
\82È
\82¢
\81D",
725 !uwep ? "
\91\95\94õ
\82µ
\82Ä
\82¢
\82é"
726 : (uwep->oclass != WEAPON_CLASS && !is_weptool(uwep))
732 if (!can_reach_floor(TRUE)) {
733 cant_reach_floor(u.ux, u.uy, FALSE, TRUE);
737 picktyp = is_blade(uwep) && !is_pick(uwep);
738 if (xlock.usedtime && xlock.box && picktyp == xlock.picktyp) {
740 You("resume your attempt to force the lock.");
742 pline("
\8c®
\82ð
\82±
\82¶
\82 \82¯
\82é
\82Ì
\82ð
\8dÄ
\8aJ
\82µ
\82½
\81D");
744 set_occupation(forcelock, "forcing the lock", 0);
746 set_occupation(forcelock, "
\8c®
\82ð
\82±
\82¶
\82 \82¯
\82é", 0);
750 /* A lock is made only for the honest man, the thief will break it. */
751 xlock.box = (struct obj *) 0;
752 for (otmp = level.objects[u.ux][u.uy]; otmp; otmp = otmp->nexthere)
754 if (otmp->obroken || !otmp->olocked) {
755 /* force doname() to omit known "broken" or "unlocked"
756 prefix so that the message isn't worded redundantly;
757 since we're about to set lknown, there's no need to
758 remember and then reset its current value */
761 There("is %s here, but its lock is already %s.",
762 doname(otmp), otmp->obroken ? "broken" : "unlocked");
764 pline("
\82±
\82±
\82É
\82Í%s
\82ª
\82 \82é
\81D
\82µ
\82©
\82µ
\82»
\82Ì
\8c®
\82Í
\82à
\82¤%s
\81D",
766 otmp->obroken ? "
\89ó
\82ê
\82Ä
\82¢
\82é" : "
\82Í
\82¸
\82³
\82ê
\82Ä
\82¢
\82é");
772 (void) safe_qbuf(qbuf, "There is ", " here; force its lock?",
773 otmp, doname, ansimpleoname, "a box");
775 (void) safe_qbuf(qbuf, "
\82±
\82±
\82É
\82Í", "
\82ª
\82 \82é
\81D
\8c®
\82ð
\82±
\82¶
\8aJ
\82¯
\82Ü
\82·
\82©
\81H",
776 otmp, doname, ansimpleoname, "
\94 ");
788 You("force %s into a crack and pry.", yname(uwep));
790 You("%s
\82ð
\82·
\82«
\8aÔ
\82É
\8d·
\82µ
\82±
\82ñ
\82Å
\82±
\82¶
\82 \82¯
\82æ
\82¤
\82Æ
\82µ
\82½
\81D",xname(uwep));
793 You("start bashing it with %s.", yname(uwep));
795 pline("%s
\82Å
\89£
\82è
\82Â
\82¯
\82½
\81D", xname(uwep));
797 xlock.chance = objects[uwep->otyp].oc_wldam * 2;
798 xlock.picktyp = picktyp;
799 xlock.magic_key = FALSE;
806 set_occupation(forcelock, "forcing the lock", 0);
808 set_occupation(forcelock, "
\8c®
\82ð
\82±
\82¶
\82 \82¯
\82é", 0);
811 You("decide not to force the issue.");
813 pline("
\82»
\82ê
\82Í
\96³
\88Ó
\96¡
\82È
\8ds
\88×
\82¾
\81D");
818 stumble_on_door_mimic(x, y)
823 if ((mtmp = m_at(x, y)) && is_door_mappear(mtmp)
824 && !Protection_from_shape_changers) {
825 stumble_onto_mimic(mtmp);
831 /* the 'O' command - try to open a door */
835 return doopen_indir(0, 0);
838 /* try to open a door in direction u.dx/u.dy */
844 register struct rm *door;
848 if (nohands(youmonst.data)) {
850 You_cant("open anything -- you have no hands!");
852 You("
\89½
\82à
\8aJ
\82¯
\82é
\82±
\82Æ
\82ª
\82Å
\82«
\82È
\82¢
\81I
\8eè
\82ª
\82È
\82¢
\82ñ
\82¾
\82à
\82Ì
\81I");
856 if (u.utrap && u.utraptype == TT_PIT) {
858 You_cant("reach over the edge of the pit.");
860 pline("
\97\8e\82µ
\8c\8a\82Ì
\92\86\82©
\82ç
\93Í
\82©
\82È
\82¢
\81D");
864 if (x > 0 && y > 0) {
867 } else if (!get_adjacent_loc((char *) 0, (char *) 0, u.ux, u.uy, &cc))
870 /* open at yourself/up/down */
871 if ((cc.x == u.ux) && (cc.y == u.uy))
874 if (stumble_on_door_mimic(cc.x, cc.y))
877 /* when choosing a direction is impaired, use a turn
878 regardless of whether a door is successfully targetted */
879 if (Confusion || Stunned)
882 door = &levl[cc.x][cc.y];
883 portcullis = (is_drawbridge_wall(cc.x, cc.y) >= 0);
885 int oldglyph = door->glyph;
886 schar oldlastseentyp = lastseentyp[cc.x][cc.y];
888 feel_location(cc.x, cc.y);
889 if (door->glyph != oldglyph
890 || lastseentyp[cc.x][cc.y] != oldlastseentyp)
891 res = 1; /* learned something */
894 if (portcullis || !IS_DOOR(door->typ)) {
895 /* closed portcullis or spot that opened bridge would span */
896 if (is_db_wall(cc.x, cc.y) || door->typ == DRAWBRIDGE_UP)
898 There("is no obvious way to open the drawbridge.");
900 pline("
\92µ
\82Ë
\8b´
\82ð
\8d~
\82ë
\82·
\96¾
\94\92\82È
\95û
\96@
\82Í
\82È
\82¢
\81D");
901 else if (portcullis || door->typ == DRAWBRIDGE_DOWN)
903 pline_The("drawbridge is already open.");
905 pline_The("
\92µ
\82Ë
\8b´
\82Í
\82à
\82¤
\8aJ
\82¢
\82Ä
\82¢
\82é
\81D");
906 else if (container_at(cc.x, cc.y, TRUE))
908 pline("%s like something lootable over there.",
909 Blind ? "Feels" : "Seems");
911 pline("
\82±
\82±
\82É
\82Í
\89½
\82©
\93ü
\82ê
\95¨
\82ª
\82 \82é
\82æ
\82¤
\82¾
\81D");
915 You("%s no door there.", Blind ? "feel" : "see");
917 pline("
\82»
\82±
\82É
\82Í
\94à
\82Í
\82È
\82¢
\82æ
\82¤%s
\81D", Blind ? "
\82¾" : "
\82É
\8c©
\82¦
\82é");
921 if (!(door->doormask & D_CLOSED)) {
924 switch (door->doormask) {
929 mesg = "
\94à
\82Í
\89ó
\82ê
\82Ä
\82¢
\82é";
933 mesg = "way has no door";
935 mesg = "
\8fo
\93ü
\8cû
\82É
\82Í
\94à
\82ª
\82È
\82¢";
939 mesg = " is already open";
941 mesg = "
\94à
\82Í
\82à
\82¤
\8aJ
\82¢
\82Ä
\82¢
\82é";
947 mesg = "
\94à
\82É
\82Í
\8c®
\82ª
\8a|
\82©
\82Á
\82Ä
\82¢
\82é";
951 pline("This door%s.", mesg);
953 pline("%s
\81D", mesg);
957 if (verysmall(youmonst.data)) {
959 pline("You're too small to pull the door open.");
961 You("
\94à
\82ð
\89\9f\82·
\82É
\82Í
\8f¬
\82³
\82·
\82¬
\82é
\81D");
965 /* door is known to be CLOSED */
966 if (rnl(20) < (ACURRSTR + ACURR(A_DEX) + ACURR(A_CON)) / 3) {
968 pline_The("door opens.");
970 pline("
\94à
\82Í
\8aJ
\82¢
\82½
\81D");
971 if (door->doormask & D_TRAPPED) {
973 b_trapped("door", FINGER);
975 b_trapped("
\94à", FINGER);
976 door->doormask = D_NODOOR;
977 if (*in_rooms(cc.x, cc.y, SHOPBASE))
978 add_damage(cc.x, cc.y, SHOP_DOOR_COST);
980 door->doormask = D_ISOPEN;
981 feel_newsym(cc.x, cc.y); /* the hero knows she opened it */
982 unblock_point(cc.x, cc.y); /* vision: new see through there */
984 exercise(A_STR, TRUE);
986 pline_The("door resists!");
988 pline("
\82È
\82©
\82È
\82©
\8aJ
\82©
\82È
\82¢
\81I");
995 obstructed(x, y, quietly)
999 register struct monst *mtmp = m_at(x, y);
1001 if (mtmp && mtmp->m_ap_type != M_AP_FURNITURE) {
1002 if (mtmp->m_ap_type == M_AP_OBJECT)
1005 if ((mtmp->mx != x) || (mtmp->my != y)) {
1008 pline("%s%s blocks the way!",
1009 !canspotmon(mtmp) ? Something : s_suffix(Monnam(mtmp)),
1010 !canspotmon(mtmp) ? "" : " tail");
1012 pline("%s%s
\82ª
\97§
\82¿
\82Ó
\82³
\82ª
\82Á
\82Ä
\82¢
\82é
\81I",
1013 !canspotmon(mtmp) ? "
\89½
\82©" : Monnam(mtmp),
1014 !canspotmon(mtmp) ? "" : "
\82Ì
\90K
\94ö");
1018 pline("%s blocks the way!",
1019 !canspotmon(mtmp) ? "Some creature" : Monnam(mtmp));
1021 pline("%s
\82ª
\97§
\82¿
\82Ó
\82³
\82ª
\82Á
\82Ä
\82¢
\82é
\81I",
1022 !canspotmon(mtmp) ? "
\89½
\8eÒ
\82©" : Monnam(mtmp));
1026 if (!canspotmon(mtmp))
1027 map_invisible(x, y);
1034 pline("%s's in the way.", Something);
1036 pline("
\89½
\82©
\82ª
\8fo
\93ü
\8cû
\82É
\82 \82é
\81D");
1042 /* the 'C' command - try to close a door */
1047 register struct rm *door;
1051 if (nohands(youmonst.data)) {
1053 You_cant("close anything -- you have no hands!");
1055 You("
\95Â
\82ß
\82é
\82±
\82Æ
\82ª
\82Å
\82«
\82È
\82¢
\81I
\8eè
\82ª
\82È
\82¢
\82ñ
\82¾
\82à
\82Ì
\81I");
1059 if (u.utrap && u.utraptype == TT_PIT) {
1061 You_cant("reach over the edge of the pit.");
1063 pline("
\97\8e\82µ
\8c\8a\82Ì
\92\86\82©
\82ç
\93Í
\82©
\82È
\82¢
\81D");
1067 if (!getdir((char *) 0))
1072 if ((x == u.ux) && (y == u.uy)) {
1074 You("are in the way!");
1076 pline("
\82 \82È
\82½
\82ª
\8fo
\93ü
\8cû
\82É
\82¢
\82é
\82Ì
\82Å
\95Â
\82Ü
\82ç
\82È
\82¢
\81I");
1083 if (stumble_on_door_mimic(x, y))
1086 /* when choosing a direction is impaired, use a turn
1087 regardless of whether a door is successfully targetted */
1088 if (Confusion || Stunned)
1092 portcullis = (is_drawbridge_wall(x, y) >= 0);
1094 int oldglyph = door->glyph;
1095 schar oldlastseentyp = lastseentyp[x][y];
1097 feel_location(x, y);
1098 if (door->glyph != oldglyph || lastseentyp[x][y] != oldlastseentyp)
1099 res = 1; /* learned something */
1102 if (portcullis || !IS_DOOR(door->typ)) {
1103 /* is_db_wall: closed portcullis */
1104 if (is_db_wall(x, y) || door->typ == DRAWBRIDGE_UP)
1106 pline_The("drawbridge is already closed.");
1108 pline_The("
\92µ
\82Ë
\8b´
\82Í
\82à
\82¤
\95Â
\82¶
\82Ä
\82¢
\82é
\81D");
1109 else if (portcullis || door->typ == DRAWBRIDGE_DOWN)
1111 There("is no obvious way to close the drawbridge.");
1113 pline("
\92µ
\82Ë
\8b´
\82ð
\95Â
\82ß
\82é
\96¾
\94\92\82È
\95û
\96@
\82Í
\82È
\82¢
\81D");
1117 You("%s no door there.", Blind ? "feel" : "see");
1119 pline("
\82»
\82±
\82É
\94à
\82Í
\82È
\82¢
\82æ
\82¤%s
\81D", Blind ? "
\82¾" : "
\82É
\8c©
\82¦
\82é");
1124 if (door->doormask == D_NODOOR) {
1126 pline("This doorway has no door.");
1128 pline("
\8fo
\93ü
\8cû
\82É
\82Í
\94à
\82ª
\82È
\82¢
\81D");
1130 } else if (obstructed(x, y, FALSE)) {
1132 } else if (door->doormask == D_BROKEN) {
1134 pline("This door is broken.");
1136 pline("
\94à
\82Í
\89ó
\82ê
\82Ä
\82¢
\82é
\81D");
1138 } else if (door->doormask & (D_CLOSED | D_LOCKED)) {
1140 pline("This door is already closed.");
1142 pline("
\94à
\82Í
\82à
\82¤
\95Â
\82¶
\82Ä
\82¢
\82é
\81D");
1146 if (door->doormask == D_ISOPEN) {
1147 if (verysmall(youmonst.data) && !u.usteed) {
1149 pline("You're too small to push the door closed.");
1151 You("
\8f¬
\82³
\82·
\82¬
\82Ä
\94à
\82ð
\95Â
\82ß
\82ç
\82ê
\82È
\82¢
\81D");
1155 || rn2(25) < (ACURRSTR + ACURR(A_DEX) + ACURR(A_CON)) / 3) {
1157 pline_The("door closes.");
1159 pline("
\94à
\82Í
\95Â
\82¶
\82½
\81D");
1160 door->doormask = D_CLOSED;
1161 feel_newsym(x, y); /* the hero knows she closed it */
1162 block_point(x, y); /* vision: no longer see there */
1164 exercise(A_STR, TRUE);
1166 pline_The("door resists!");
1168 pline("
\82È
\82©
\82È
\82©
\95Â
\82Ü
\82ç
\82È
\82¢
\81I");
1175 /* box obj was hit with spell or wand effect otmp;
1176 returns true if something happened */
1179 struct obj *obj, *otmp; /* obj *is* a box */
1183 switch (otmp->otyp) {
1185 case SPE_WIZARD_LOCK:
1186 if (!obj->olocked) { /* lock it; fix if broken */
1190 pline("
\83J
\83`
\81I");
1193 if (Role_if(PM_WIZARD))
1198 } /* else already closed and locked */
1202 if (obj->olocked) { /* unlock; couldn't be broken */
1206 pline("
\83R
\83\93\83R
\83\93\81I");
1209 if (Role_if(PM_WIZARD))
1213 } else /* silently fix if broken */
1218 /* maybe start unlocking chest, get interrupted, then zap it;
1219 we must avoid any attempt to resume unlocking it */
1220 if (xlock.box == obj)
1227 /* Door/secret door was hit with spell or wand effect otmp;
1228 returns true if something happened */
1230 doorlock(otmp, x, y)
1234 register struct rm *door = &levl[x][y];
1237 const char *msg = (const char *) 0;
1239 const char *dustcloud = "A cloud of dust";
1241 const char *dustcloud = "
\82Ù
\82±
\82è";
1243 const char *quickly_dissipates = "quickly dissipates";
1245 const char *quickly_dissipates = "
\82 \82Á
\82Æ
\8c¾
\82¤
\82Ü
\82É
\94ò
\82Ñ
\8eU
\82Á
\82½";
1246 boolean mysterywand = (otmp->oclass == WAND_CLASS && !otmp->dknown);
1248 if (door->typ == SDOOR) {
1249 switch (otmp->otyp) {
1253 case SPE_FORCE_BOLT:
1255 door->doormask = D_CLOSED | (door->doormask & D_TRAPPED);
1259 pline("A door appears in the wall!");
1261 pline("
\95Ç
\82©
\82ç
\94à
\82ª
\8c»
\82ê
\82½
\81I");
1262 if (otmp->otyp == WAN_OPENING || otmp->otyp == SPE_KNOCK)
1264 break; /* striking: continue door handling below */
1266 case SPE_WIZARD_LOCK:
1272 switch (otmp->otyp) {
1274 case SPE_WIZARD_LOCK:
1275 if (Is_rogue_level(&u.uz)) {
1276 boolean vis = cansee(x, y);
1277 /* Can't have real locking in Rogue, so just hide doorway */
1280 pline("%s springs up in the older, more primitive doorway.",
1282 pline("
\8cÃ
\82
\82³
\82¢
\81C
\8c´
\8en
\93I
\82È
\8fo
\93ü
\8cû
\82É%s
\82ª
\97§
\82¿
\82±
\82ß
\82½
\81D",
1286 You_hear("a swoosh.");
1288 You_hear("
\83V
\83\85\81[
\83b
\82Æ
\82¢
\82¤
\89¹
\82ð
\95·
\82¢
\82½
\81D");
1289 if (obstructed(x, y, mysterywand)) {
1292 pline_The("cloud %s.", quickly_dissipates);
1294 pline("
\82Ù
\82±
\82è
\82Í%s
\81D",quickly_dissipates);
1301 pline_The("doorway vanishes!");
1303 pline("
\8fo
\93ü
\8cû
\82Í
\8fÁ
\82¦
\82½
\81I");
1307 if (obstructed(x, y, mysterywand))
1309 /* Don't allow doors to close over traps. This is for pits */
1310 /* & trap doors, but is it ever OK for anything else? */
1312 /* maketrap() clears doormask, so it should be NODOOR */
1314 pline("%s springs up in the doorway, but %s.", dustcloud,
1315 quickly_dissipates);
1317 pline("%s
\82ª
\8fo
\93ü
\8cû
\82É
\97§
\82¿
\82±
\82ß
\82½
\81C
\82µ
\82©
\82µ%s", dustcloud,
1318 quickly_dissipates);
1323 switch (door->doormask & ~D_TRAPPED) {
1326 msg = "The door locks!";
1328 msg = "
\94à
\82É
\8c®
\82ª
\82©
\82©
\82Á
\82½
\81I";
1332 msg = "The door swings shut, and locks!";
1334 msg = "
\94à
\82Í
\90¨
\82¢
\82æ
\82
\95Â
\82Ü
\82è
\81C
\8c®
\82ª
\82©
\82©
\82Á
\82½
\81I";
1338 msg = "The broken door reassembles and locks!";
1340 msg = "
\89ó
\82ê
\82½
\94à
\82ª
\8dÄ
\8d\
\90¬
\82³
\82ê
\81C
\8c®
\82ª
\82©
\82©
\82Á
\82½
\81I";
1345 "A cloud of dust springs up and assembles itself into a door!";
1347 "
\82Ù
\82±
\82è
\82ª
\82½
\82¿
\82±
\82ß
\81C
\8fW
\82Ü
\82Á
\82Ä
\94à
\82É
\82È
\82Á
\82½
\81I";
1354 door->doormask = D_LOCKED | (door->doormask & D_TRAPPED);
1359 if (door->doormask & D_LOCKED) {
1361 msg = "The door unlocks!";
1363 msg = "
\94à
\82Ì
\8c®
\82Í
\82Í
\82¸
\82ê
\82½
\81I";
1364 door->doormask = D_CLOSED | (door->doormask & D_TRAPPED);
1369 case SPE_FORCE_BOLT:
1370 if (door->doormask & (D_LOCKED | D_CLOSED)) {
1371 if (door->doormask & D_TRAPPED) {
1373 (void) mb_trapped(m_at(x, y));
1374 else if (flags.verbose) {
1377 pline("KABOOM!! You see a door explode.");
1379 pline("
\82¿
\82ã
\82Ç
\81[
\82ñ
\81I
\94à
\82ª
\94\9a\94
\82µ
\82½
\81D");
1382 You_hear("a distant explosion.");
1384 You_hear("
\89\93\82
\82Ì
\94\9a\94
\89¹
\82ð
\95·
\82¢
\82½
\81D");
1386 door->doormask = D_NODOOR;
1387 unblock_point(x, y);
1392 door->doormask = D_BROKEN;
1393 if (flags.verbose) {
1396 pline_The("door crashes open!");
1398 pline("
\94à
\82Í
\89ó
\82ê
\8aJ
\82¢
\82½
\81I");
1401 You_hear("a crashing sound.");
1403 You_hear("
\89½
\82©
\82ª
\89ó
\82ê
\82é
\89¹
\82ð
\95·
\82¢
\82½
\81D");
1405 unblock_point(x, y);
1407 /* force vision recalc before printing more messages */
1408 if (vision_full_recalc)
1415 impossible("magic (%d) attempted on door.", otmp->otyp);
1418 if (msg && cansee(x, y))
1421 /* door was destroyed */
1422 wake_nearto(x, y, loudness);
1423 if (*in_rooms(x, y, SHOPBASE))
1424 add_damage(x, y, 0L);
1427 if (res && picking_at(x, y)) {
1428 /* maybe unseen monster zaps door you're unlocking */
1436 chest_shatter_msg(otmp)
1439 const char *disposition;
1443 if (otmp->oclass == POTION_CLASS) {
1445 You("%s %s shatter!", Blind ? "hear" : "see", an(bottlename()));
1448 You_hear("%s
\82ª
\8a\84\82ê
\82é
\89¹
\82ð
\95·
\82¢
\82½
\81I", bottlename());
1450 pline("%s
\82ª
\8a\84\82ê
\82½
\81I", bottlename());
1452 if (!breathless(youmonst.data) || haseyes(youmonst.data))
1453 potionbreathe(otmp);
1456 /* We have functions for distant and singular names, but not one */
1457 /* which does _both_... */
1458 save_Blinded = Blinded;
1460 thing = singular(otmp, xname);
1461 Blinded = save_Blinded;
1462 switch (objects[otmp->otyp].oc_material) {
1465 disposition = "is torn to shreds";
1467 disposition = "
\82Í
\90¡
\92f
\82³
\82ê
\82½";
1471 disposition = "is crushed";
1473 disposition = "
\82ð
\8f°
\82É
\82Ô
\82¿
\82Ü
\82¯
\82½";
1477 disposition = "is pulped";
1479 disposition = "
\82Í
\82Ç
\82ë
\82Ç
\82ë
\82É
\82È
\82Á
\82½";
1483 disposition = "is mashed";
1485 disposition = "
\82Í
\82Ç
\82ë
\82Ç
\82ë
\82É
\82È
\82Á
\82½";
1489 disposition = "shatters";
1491 disposition = "
\82Í
\8a\84\82ê
\82½";
1495 disposition = "splinters to fragments";
1497 disposition = "
\82Í
\82©
\82¯
\82ç
\82É
\82È
\82Á
\82½";
1501 disposition = "is destroyed";
1503 disposition = "
\82Í
\89ó
\82ê
\82½";
1507 pline("%s %s!", An(thing), disposition);
1509 pline("%s%s
\81I", thing, disposition);