OSDN Git Service

upgrade to 3.6.1
[jnethack/source.git] / src / lock.c
index 7527dcd..17c8112 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 lock.c  $NHDT-Date: 1446955300 2015/11/08 04:01:40 $  $NHDT-Branch: master $:$NHDT-Revision: 1.67 $ */
+/* NetHack 3.6 lock.c  $NHDT-Date: 1521499715 2018/03/19 22:48:35 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.80 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2011. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
 
 #include "hack.h"
 
-STATIC_PTR int NDECL(picklock);
-STATIC_PTR int NDECL(forcelock);
-
 /* at most one of `door' and `box' should be non-null at any given time */
 STATIC_VAR NEARDATA struct xlock_s {
     struct rm *door;
     struct obj *box;
     int picktyp, /* key|pick|card for unlock, sharp vs blunt for #force */
         chance, usedtime;
+    boolean magic_key;
 } xlock;
 
+/* occupation callbacks */
+STATIC_PTR int NDECL(picklock);
+STATIC_PTR int NDECL(forcelock);
+
 STATIC_DCL const char *NDECL(lock_action);
 STATIC_DCL boolean FDECL(obstructed, (int, int, BOOLEAN_P));
 STATIC_DCL void FDECL(chest_shatter_msg, (struct obj *));
@@ -95,7 +98,8 @@ STATIC_PTR int
 picklock(VOID_ARGS)
 {
     if (xlock.box) {
-        if ((xlock.box->ox != u.ux) || (xlock.box->oy != u.uy)) {
+        if (xlock.box->where != OBJ_FLOOR
+            || xlock.box->ox != u.ux || xlock.box->oy != u.uy) {
             return ((xlock.usedtime = 0)); /* you or it moved */
         }
     } else { /* door */
@@ -136,6 +140,40 @@ picklock(VOID_ARGS)
     if (rn2(100) >= xlock.chance)
         return 1; /* still busy */
 
+    /* using the Master Key of Thievery finds traps if its bless/curse
+       state is adequate (non-cursed for rogues, blessed for others;
+       checked when setting up 'xlock') */
+    if ((!xlock.door ? (int) xlock.box->otrapped
+                     : (xlock.door->doormask & D_TRAPPED) != 0)
+        && xlock.magic_key) {
+        xlock.chance += 20; /* less effort needed next time */
+        /* unfortunately we don't have a 'tknown' flag to record
+           "known to be trapped" so declining to disarm and then
+           retrying lock manipulation will find it all over again */
+        if (yn("You find a trap!  Do you want to try to disarm it?") == 'y') {
+            const char *what;
+            boolean alreadyunlocked;
+
+            /* disarming while using magic key always succeeds */
+            if (xlock.door) {
+                xlock.door->doormask &= ~D_TRAPPED;
+                what = "door";
+                alreadyunlocked = !(xlock.door->doormask & D_LOCKED);
+            } else {
+                xlock.box->otrapped = 0;
+                what = (xlock.box->otyp == CHEST) ? "chest" : "box";
+                alreadyunlocked = !xlock.box->olocked;
+            }
+            You("succeed in disarming the trap.  The %s is still %slocked.",
+                what, alreadyunlocked ? "un" : "");
+            exercise(A_WIS, TRUE);
+        } else {
+            You("stop %s.", lock_action());
+            exercise(A_WIS, FALSE);
+        }
+        return ((xlock.usedtime = 0));
+    }
+
 /*JP
     You("succeed in %s.", lock_action());
 */
@@ -149,7 +187,7 @@ picklock(VOID_ARGS)
             xlock.door->doormask = D_NODOOR;
             unblock_point(u.ux + u.dx, u.uy + u.dy);
             if (*in_rooms(u.ux + u.dx, u.uy + u.dy, SHOPBASE))
-                add_damage(u.ux + u.dx, u.uy + u.dy, 0L);
+                add_damage(u.ux + u.dx, u.uy + u.dy, SHOP_DOOR_COST);
             newsym(u.ux + u.dx, u.uy + u.dy);
         } else if (xlock.door->doormask & D_LOCKED)
             xlock.door->doormask = D_CLOSED;
@@ -281,10 +319,19 @@ void
 reset_pick()
 {
     xlock.usedtime = xlock.chance = xlock.picktyp = 0;
+    xlock.magic_key = FALSE;
     xlock.door = 0;
     xlock.box = 0;
 }
 
+/* level change; don't reset if hero is carrying xlock.box with him/her */
+void
+maybe_reset_pick()
+{
+    if (!xlock.box || !carried(xlock.box))
+        reset_pick();
+}
+
 /* for doapply(); if player gives a direction or resumes an interrupted
    previous attempt then it costs hero a move even if nothing ultimately
    happens; when told "can't do that" before being asked for direction
@@ -318,6 +365,7 @@ struct obj *pick;
             const char *what = (picktyp == LOCK_PICK) ? "pick" : "key";
 */
             const char *what = (picktyp == LOCK_PICK) ? "\8c®\8aJ\82¯\8aí\8bï" : "\8c®";
+
             if (picktyp == CREDIT_CARD)
 /*JP
                 what = "card";
@@ -343,6 +391,7 @@ struct obj *pick;
             You("resume your attempt at %s.", action);
 */
             pline("%s\82Ì\82ð\8dÄ\8aJ\82µ\82½\81D", action);
+            xlock.magic_key = is_magic_key(&youmonst, pick);
             set_occupation(picklock, action, 0);
             return PICKLOCK_DID_SOMETHING;
         }
@@ -365,8 +414,9 @@ struct obj *pick;
         return PICKLOCK_DID_NOTHING;
     }
 
-    if ((picktyp != LOCK_PICK && picktyp != CREDIT_CARD
-         && picktyp != SKELETON_KEY)) {
+    if (picktyp != LOCK_PICK
+        && picktyp != CREDIT_CARD
+        && picktyp != SKELETON_KEY) {
         impossible("picking lock with object %d?", picktyp);
         return PICKLOCK_DID_NOTHING;
     }
@@ -401,9 +451,9 @@ struct obj *pick;
             return PICKLOCK_LEARNED_SOMETHING;
         } else if (is_pool(u.ux, u.uy) && !Underwater) {
 /*JP
-            pline_The("water has no lock.");
+            pline_The("%s has no lock.", hliquid("water"));
 */
-            pline("\90\85\82É\8fù\91O\82Í\82È\82¢\81D");
+            pline_The("%s\82É\8fù\91O\82Í\82È\82¢\81D", hliquid("\90\85"));
             return PICKLOCK_LEARNED_SOMETHING;
         }
 
@@ -494,7 +544,6 @@ struct obj *pick;
                 if (otmp->cursed)
                     ch /= 2;
 
-                xlock.picktyp = picktyp;
                 xlock.box = otmp;
                 xlock.door = 0;
                 break;
@@ -539,7 +588,7 @@ struct obj *pick;
         } else if (mtmp && is_door_mappear(mtmp)) {
             /* "The door actually was a <mimic>!" */
             stumble_onto_mimic(mtmp);
-            /* mimic might keep the key (50% chance, 10% for PYEC) */
+            /* mimic might keep the key (50% chance, 10% for PYEC or MKoT) */
             maybe_absorb_item(mtmp, pick, 50, 10);
             return PICKLOCK_LEARNED_SOMETHING;
         }
@@ -617,6 +666,7 @@ struct obj *pick;
     context.move = 0;
     xlock.chance = ch;
     xlock.picktyp = picktyp;
+    xlock.magic_key = is_magic_key(&youmonst, pick);
     xlock.usedtime = 0;
     set_occupation(picklock, lock_action(), 0);
     return PICKLOCK_DID_SOMETHING;
@@ -681,11 +731,17 @@ doforce()
     for (otmp = level.objects[u.ux][u.uy]; otmp; otmp = otmp->nexthere)
         if (Is_box(otmp)) {
             if (otmp->obroken || !otmp->olocked) {
+                /* force doname() to omit known "broken" or "unlocked"
+                   prefix so that the message isn't worded redundantly;
+                   since we're about to set lknown, there's no need to
+                   remember and then reset its current value */
+                otmp->lknown = 0;
 #if 0 /*JP*/
-                There("is %s here, but its lock is already %s.", doname(otmp),
-                      otmp->obroken ? "broken" : "unlocked");
+                There("is %s here, but its lock is already %s.",
+                      doname(otmp), otmp->obroken ? "broken" : "unlocked");
 #else
-                pline("\82±\82±\82É\82Í%s\82ª\82 \82é\81C\82µ\82©\82µ\82»\82Ì\8c®\82Í\82à\82¤%s\81D", doname(otmp),
+                pline("\82±\82±\82É\82Í%s\82ª\82 \82é\81D\82µ\82©\82µ\82»\82Ì\8c®\82Í\82à\82¤%s\81D",
+                      doname(otmp),
                       otmp->obroken ? "\89ó\82ê\82Ä\82¢\82é" : "\82Í\82¸\82³\82ê\82Ä\82¢\82é");
 #endif
                 otmp->lknown = 1;
@@ -695,7 +751,7 @@ doforce()
             (void) safe_qbuf(qbuf, "There is ", " here; force its lock?",
                              otmp, doname, ansimpleoname, "a box");
 #else
-            (void) safe_qbuf(qbuf, "\82±\82±\82É\82Í", "\82ª\82 \82é\81C\8c®\82ð\82±\82\8aJ\82¯\82Ü\82·\82©\81H",
+            (void) safe_qbuf(qbuf, "\82±\82±\82É\82Í", "\82ª\82 \82é\81D\8c®\82ð\82±\82\8aJ\82¯\82Ü\82·\82©\81H",
                              otmp, doname, ansimpleoname, "\94 ");
 #endif
             otmp->lknown = 1;
@@ -719,6 +775,7 @@ doforce()
             xlock.box = otmp;
             xlock.chance = objects[uwep->otyp].oc_wldam * 2;
             xlock.picktyp = picktyp;
+            xlock.magic_key = FALSE;
             xlock.usedtime = 0;
             break;
         }
@@ -789,8 +846,9 @@ int x, y;
     } else if (!get_adjacent_loc((char *) 0, (char *) 0, u.ux, u.uy, &cc))
         return 0;
 
+    /* open at yourself/up/down */
     if ((cc.x == u.ux) && (cc.y == u.uy))
-        return 0;
+        return doloot();
 
     if (stumble_on_door_mimic(cc.x, cc.y))
         return 1;
@@ -824,6 +882,9 @@ int x, y;
             pline_The("drawbridge is already open.");
 */
             pline_The("\92µ\82Ë\8b´\82Í\82à\82¤\8aJ\82¢\82Ä\82¢\82é\81D");
+        else if (container_at(cc.x, cc.y, TRUE))
+            pline("%s like something lootable over there.",
+                  Blind ? "Feels" : "Seems");
         else
 /*JP
             You("%s no door there.", Blind ? "feel" : "see");
@@ -889,7 +950,7 @@ int x, y;
             b_trapped("\94à", FINGER);
             door->doormask = D_NODOOR;
             if (*in_rooms(cc.x, cc.y, SHOPBASE))
-                add_damage(cc.x, cc.y, 0L);
+                add_damage(cc.x, cc.y, SHOP_DOOR_COST);
         } else
             door->doormask = D_ISOPEN;
         feel_newsym(cc.x, cc.y); /* the hero knows she opened it */