OSDN Git Service

upgrade to 3.6.1
[jnethack/source.git] / src / steal.c
index b48dd9a..2483734 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 steal.c $NHDT-Date: 1446713643 2015/11/05 08:54:03 $  $NHDT-Branch: master $:$NHDT-Revision: 1.65 $ */
+/* NetHack 3.6 steal.c $NHDT-Date: 1496614914 2017/06/04 22:21:54 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.69 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2012. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -579,53 +580,86 @@ register struct obj *otmp;
     return freed_otmp;
 }
 
+/* called for AD_SAMU (the Wizard and quest nemeses) */
 void
 stealamulet(mtmp)
 struct monst *mtmp;
 {
-    struct obj *otmp = (struct obj *) 0;
-    int real = 0, fake = 0;
-
-    /* select the artifact to steal */
-    if (u.uhave.amulet) {
-        real = AMULET_OF_YENDOR;
-        fake = FAKE_AMULET_OF_YENDOR;
-    } else if (u.uhave.questart) {
+    char buf[BUFSZ];
+    struct obj *otmp = 0, *obj = 0;
+    int real = 0, fake = 0, n;
+
+    /* target every quest artifact, not just current role's;
+       if hero has more than one, choose randomly so that player
+       can't use inventory ordering to influence the theft */
+    for (n = 0, obj = invent; obj; obj = obj->nobj)
+        if (any_quest_artifact(obj))
+            ++n, otmp = obj;
+    if (n > 1) {
+        n = rnd(n);
         for (otmp = invent; otmp; otmp = otmp->nobj)
-            if (is_quest_artifact(otmp))
+            if (any_quest_artifact(otmp) && !--n)
                 break;
-        if (!otmp)
-            return; /* should we panic instead? */
-    } else if (u.uhave.bell) {
-        real = BELL_OF_OPENING;
-        fake = BELL;
-    } else if (u.uhave.book) {
-        real = SPE_BOOK_OF_THE_DEAD;
-    } else if (u.uhave.menorah) {
-        real = CANDELABRUM_OF_INVOCATION;
-    } else
-        return; /* you have nothing of special interest */
+    }
 
     if (!otmp) {
+        /* if we didn't find any quest arifact, find another valuable item */
+        if (u.uhave.amulet) {
+            real = AMULET_OF_YENDOR;
+            fake = FAKE_AMULET_OF_YENDOR;
+        } else if (u.uhave.bell) {
+            real = BELL_OF_OPENING;
+            fake = BELL;
+        } else if (u.uhave.book) {
+            real = SPE_BOOK_OF_THE_DEAD;
+        } else if (u.uhave.menorah) {
+            real = CANDELABRUM_OF_INVOCATION;
+        } else
+            return; /* you have nothing of special interest */
+
         /* If we get here, real and fake have been set up. */
-        for (otmp = invent; otmp; otmp = otmp->nobj)
-            if (otmp->otyp == real || (otmp->otyp == fake && !mtmp->iswiz))
-                break;
+        for (n = 0, obj = invent; obj; obj = obj->nobj)
+            if (obj->otyp == real || (obj->otyp == fake && !mtmp->iswiz))
+                ++n, otmp = obj;
+        if (n > 1) {
+            n = rnd(n);
+            for (otmp = invent; otmp; otmp = otmp->nobj)
+                if ((otmp->otyp == real
+                     || (otmp->otyp == fake && !mtmp->iswiz)) && !--n)
+                    break;
+        }
     }
 
     if (otmp) { /* we have something to snatch */
+        /* take off outer gear if we're targetting [hypothetical]
+           quest artifact suit, shirt, gloves, or rings */
+        if ((otmp == uarm || otmp == uarmu) && uarmc)
+            remove_worn_item(uarmc, FALSE);
+        if (otmp == uarmu && uarm)
+            remove_worn_item(uarm, FALSE);
+        if ((otmp == uarmg || ((otmp == uright || otmp == uleft) && uarmg))
+            && uwep) {
+            /* gloves are about to be unworn; unwield weapon(s) first */
+            if (u.twoweap)    /* remove_worn_item(uswapwep) indirectly */
+                remove_worn_item(uswapwep, FALSE); /* clears u.twoweap */
+            remove_worn_item(uwep, FALSE);
+        }
+        if ((otmp == uright || otmp == uleft) && uarmg)
+            /* calls Gloves_off() to handle wielded cockatrice corpse */
+            remove_worn_item(uarmg, FALSE);
+
+        /* finally, steal the target item */
         if (otmp->owornmask)
             remove_worn_item(otmp, TRUE);
         if (otmp->unpaid)
             subfrombill(otmp, shop_keeper(*u.ushops));
         freeinv(otmp);
-        /* mpickobj wont merge otmp because none of the above things
-           to steal are mergable */
-        (void) mpickobj(mtmp, otmp); /* may merge and free otmp */
+        Strcpy(buf, doname(otmp));
+        (void) mpickobj(mtmp, otmp); /* could merge and free otmp but won't */
 /*JP
-        pline("%s stole %s!", Monnam(mtmp), doname(otmp));
+        pline("%s steals %s!", Monnam(mtmp), buf);
 */
-        pline("%s\82Í%s\82ð\93\90\82ñ\82¾\81I", Monnam(mtmp), doname(otmp));
+        pline("%s\82Í%s\82ð\93\90\82ñ\82¾\81I", Monnam(mtmp), buf);
         if (can_teleport(mtmp->data) && !tele_restrict(mtmp))
             (void) rloc(mtmp, TRUE);
     }
@@ -705,10 +739,11 @@ boolean verbosely;
         if (mon->mhp > 0) {
             mon->misc_worn_check &= ~obj->owornmask;
             update_mon = TRUE;
-            /* don't charge for an owned saddle on dead steed (provided
-               that the hero is within the same shop at the time) */
-        } else if (mon->mtame && (obj->owornmask & W_SADDLE) && !obj->unpaid
-                   && costly_spot(omx, omy)
+
+        /* don't charge for an owned saddle on dead steed (provided
+           that the hero is within the same shop at the time) */
+        } else if (mon->mtame && (obj->owornmask & W_SADDLE) != 0L
+                   && !obj->unpaid && costly_spot(omx, omy)
                    /* being at costly_spot guarantees lev->roomno is not 0 */
                    && index(in_rooms(u.ux, u.uy, SHOPBASE),
                             levl[omx][omy].roomno)) {
@@ -740,7 +775,7 @@ boolean verbosely;
 
 /* some monsters bypass the normal rules for moving between levels or
    even leaving the game entirely; when that happens, prevent them from
-   taking the Amulet or invocation tools with them */
+   taking the Amulet, invocation items, or quest artifact with them */
 void
 mdrop_special_objs(mon)
 struct monst *mon;
@@ -750,8 +785,10 @@ struct monst *mon;
     for (obj = mon->minvent; obj; obj = otmp) {
         otmp = obj->nobj;
         /* the Amulet, invocation tools, and Rider corpses resist even when
-           artifacts and ordinary objects are given 0% resistance chance */
-        if (obj_resists(obj, 0, 0)) {
+           artifacts and ordinary objects are given 0% resistance chance;
+           current role's quest artifact is rescued too--quest artifacts
+           for the other roles are not */
+        if (obj_resists(obj, 0, 0) || is_quest_artifact(obj)) {
             obj_extract_self(obj);
             mdrop_obj(mon, obj, FALSE);
         }