OSDN Git Service

upgrade to 3.6.2
[jnethack/source.git] / src / worn.c
index 0d9e935..0cb7948 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 worn.c  $NHDT-Date: 1496959481 2017/06/08 22:04:41 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.49 $ */
+/* NetHack 3.6 worn.c  $NHDT-Date: 1550524569 2019/02/18 21:16:09 $  $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.56 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /*-Copyright (c) Robert Patrick Rankin, 2013. */
 /* NetHack may be freely redistributed.  See license for details. */
@@ -34,7 +34,8 @@ const struct worn {
              { W_TOOL, &ublindf },
              { W_BALL, &uball },
              { W_CHAIN, &uchain },
-             { 0, 0 } };
+             { 0, 0 }
+};
 
 /* This only allows for one blocking item per property */
 #define w_blocks(o, m) \
@@ -144,6 +145,19 @@ register struct obj *obj;
     update_inventory();
 }
 
+/* return item worn in slot indiciated by wornmask; needed by poly_obj() */
+struct obj *
+wearmask_to_obj(wornmask)
+long wornmask;
+{
+    const struct worn *wp;
+
+    for (wp = worn; wp->w_mask; wp++)
+        if (wp->w_mask & wornmask)
+            return *wp->w_obj;
+    return (struct obj *) 0;
+}
+
 /* return a bitmask of the equipment slot(s) a given item might be worn in */
 long
 wearslot(obj)
@@ -320,7 +334,8 @@ struct obj *obj; /* item to make known if effect can be seen */
     }
 }
 
-/* armor put on or taken off; might be magical variety */
+/* armor put on or taken off; might be magical variety
+   [TODO: rename to 'update_mon_extrinsics()' and change all callers...] */
 void
 update_mon_intrinsics(mon, obj, on, silently)
 struct monst *mon;
@@ -372,7 +387,7 @@ boolean on, silently;
             if (which <= 8) { /* 1 thru 8 correspond to MR_xxx mask values */
                 /* FIRE,COLD,SLEEP,DISINT,SHOCK,POISON,ACID,STONE */
                 mask = (uchar) (1 << (which - 1));
-                mon->mintrinsics |= (unsigned short) mask;
+                mon->mextrinsics |= (unsigned short) mask;
             }
             break;
         }
@@ -398,25 +413,22 @@ boolean on, silently;
         case ACID_RES:
         case STONE_RES:
             mask = (uchar) (1 << (which - 1));
-            /* If the monster doesn't have this resistance intrinsically,
-               check whether any other worn item confers it.  Note that
-               we don't currently check for anything conferred via simply
-               carrying an object. */
-            if (!(mon->data->mresists & mask)) {
-                for (otmp = mon->minvent; otmp; otmp = otmp->nobj)
-                    if (otmp->owornmask
-                        && (int) objects[otmp->otyp].oc_oprop == which)
-                        break;
-                if (!otmp)
-                    mon->mintrinsics &= ~((unsigned short) mask);
-            }
+            /* update monster's extrinsics (for worn objects only;
+               'obj' itself might still be worn or already unworn) */
+            for (otmp = mon->minvent; otmp; otmp = otmp->nobj)
+                if (otmp != obj
+                    && otmp->owornmask
+                    && (int) objects[otmp->otyp].oc_oprop == which)
+                    break;
+            if (!otmp)
+                mon->mextrinsics &= ~((unsigned short) mask);
             break;
         default:
             break;
         }
     }
 
-maybe_blocks:
+ maybe_blocks:
     /* obj->owornmask has been cleared by this point, so we can't use it.
        However, since monsters don't wield armor, we don't have to guard
        against that and can get away with a blanket worn-mask value. */
@@ -730,6 +742,13 @@ clear_bypasses()
     struct obj *otmp, *nobj;
     struct monst *mtmp;
 
+    /*
+     * 'Object' bypass is also used for one monster function:
+     * polymorph control of long worms.  Activated via setting
+     * context.bypasses even if no specific object has been
+     * bypassed.
+     */
+
     for (otmp = fobj; otmp; otmp = nobj) {
         nobj = otmp->nobj;
         if (otmp->bypass) {
@@ -761,10 +780,19 @@ clear_bypasses()
             continue;
         for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
             otmp->bypass = 0;
+        /* long worm created by polymorph has mon->mextra->mcorpsenm set
+           to PM_LONG_WORM to flag it as not being subject to further
+           polymorph (so polymorph zap won't hit monster to transform it
+           into a long worm, then hit that worm's tail and transform it
+           again on same zap); clearing mcorpsenm reverts worm to normal */
+        if (mtmp->data == &mons[PM_LONG_WORM] && has_mcorpsenm(mtmp))
+            MCORPSENM(mtmp) = NON_PM;
     }
     for (mtmp = migrating_mons; mtmp; mtmp = mtmp->nmon) {
         for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
             otmp->bypass = 0;
+        /* no MCORPSENM(mtmp)==PM_LONG_WORM check here; long worms can't
+           be just created by polymorph and migrating at the same time */
     }
     /* billobjs and mydogs chains don't matter here */
     context.bypasses = FALSE;
@@ -808,6 +836,30 @@ struct obj *objchain;
     return objchain;
 }
 
+/* like nxt_unbypassed_obj() but operates on sortloot_item array rather
+   than an object linked list; the array contains obj==Null terminator;
+   there's an added complication that the array may have stale pointers
+   for deleted objects (see Multiple-Drop case in askchain(invent.c)) */
+struct obj *
+nxt_unbypassed_loot(lootarray, listhead)
+Loot *lootarray;
+struct obj *listhead;
+{
+    struct obj *o, *obj;
+
+    while ((obj = lootarray->obj) != 0) {
+        for (o = listhead; o; o = o->nobj)
+            if (o == obj)
+                break;
+        if (o && !obj->bypass) {
+            bypass_obj(obj);
+            break;
+        }
+        ++lootarray;
+    }
+    return obj;
+}
+
 void
 mon_break_armor(mon, polyspot)
 struct monst *mon;