]> granicus.if.org Git - nethack/commitdiff
revisit #H4083 - glob ID and merging
authorPatR <rankin@nethack.org>
Fri, 29 Jan 2016 02:13:25 +0000 (18:13 -0800)
committerPatR <rankin@nethack.org>
Fri, 29 Jan 2016 02:13:25 +0000 (18:13 -0800)
Globs on the floor used different criteria (anything goes) than globs
in inventory (mostly requiring same ownership when in shops and same
curse/bless state--other stuff generally isn't applicable) when
deciding whether two globs should merge.  That was okay as long as
the globs on the floor were from being left behind when a pudding or
ooze was killed, but not if the player had picked some up, dipped
them in holy or unholy water, and dropped them again.  This changes
things so that globs on the floor use the same criteria as globs in
inventory when deciding whether to coallesce.

Also, my earlier fix was modifying globs in the mergeable() test (to
make bknown and rknown match) rather than during actual merge, which
would be a problem if the merger didn't take place for some reason.

include/extern.h
src/do.c
src/invent.c
src/mkobj.c

index 2e9f0250ecaee6150de042d6a9b16716d81e394e..3c0abfaab3c6e540f1bcf16fbc3778b92a3fcf08 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 extern.h        $NHDT-Date: 1453514592 2016/01/23 02:03:12 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.542 $ */
+/* NetHack 3.6 extern.h        $NHDT-Date: 1454033598 2016/01/29 02:13:18 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.543 $ */
 /* Copyright (c) Steve Creps, 1988.                              */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -943,6 +943,7 @@ E int NDECL(dolook);
 E boolean FDECL(will_feel_cockatrice, (struct obj *, BOOLEAN_P));
 E void FDECL(feel_cockatrice, (struct obj *, BOOLEAN_P));
 E void FDECL(stackobj, (struct obj *));
+E boolean FDECL(mergable, (struct obj *, struct obj *));
 E int NDECL(doprgold);
 E int NDECL(doprwep);
 E int NDECL(doprarm);
@@ -1275,7 +1276,7 @@ E long FDECL(peek_at_iced_corpse_age, (struct obj *));
 E int FDECL(hornoplenty, (struct obj *, BOOLEAN_P));
 E void NDECL(obj_sanity_check);
 E struct obj *FDECL(obj_nexto, (struct obj *));
-E struct obj *FDECL(obj_nexto_xy, (int, int, int, unsigned));
+E struct obj *FDECL(obj_nexto_xy, (struct obj *, int, int, BOOLEAN_P));
 E struct obj *FDECL(obj_absorb, (struct obj **, struct obj **));
 E struct obj *FDECL(obj_meld, (struct obj **, struct obj **));
 
index 4b2ac50716126b1440b35ef1aace5fa64f6dffd6..f6058eabd1b2ab7e1512f9f7dde38148dd773932 100644 (file)
--- a/src/do.c
+++ b/src/do.c
@@ -1,4 +1,4 @@
-/* NetHack 3.6 do.c    $NHDT-Date: 1446975464 2015/11/08 09:37:44 $  $NHDT-Branch: master $:$NHDT-Revision: 1.149 $ */
+/* NetHack 3.6 do.c    $NHDT-Date: 1454033599 2016/01/29 02:13:19 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.153 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -215,15 +215,13 @@ const char *verb;
                   otense(obj, "tumble"), the_your[t->madeby_u]);
     } else if (obj->globby) {
         /* Globby things like puddings might stick together */
-        while (obj
-               && (otmp = obj_nexto_xy(obj->otyp, x, y, obj->o_id))
-                      != (struct obj *) 0) {
+        while (obj && (otmp = obj_nexto_xy(obj, x, y, TRUE)) != 0) {
             pudding_merge_message(obj, otmp);
             /* intentionally not getting the melded object; obj_meld may set
              * obj to null. */
             (void) obj_meld(&obj, &otmp);
         }
-        return (boolean) (obj == NULL);
+        return (boolean) !obj;
     }
     return FALSE;
 }
index 504f027225d9222fc15de9ee8ced47b7ff173d99..3d46f692b1729e387e319e1b29758dd8b956e992 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 invent.c        $NHDT-Date: 1452650438 2016/01/13 02:00:38 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.188 $ */
+/* NetHack 3.6 invent.c        $NHDT-Date: 1454033599 2016/01/29 02:13:19 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.192 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -9,7 +9,6 @@
 
 STATIC_DCL int FDECL(CFDECLSPEC sortloot_cmp, (struct obj *, struct obj *));
 STATIC_DCL void NDECL(reorder_invent);
-STATIC_DCL boolean FDECL(mergable, (struct obj *, struct obj *));
 STATIC_DCL void FDECL(noarmor, (BOOLEAN_P));
 STATIC_DCL void FDECL(invdisp_nothing, (const char *, const char *));
 STATIC_DCL boolean FDECL(worn_wield_only, (struct obj *));
@@ -335,7 +334,7 @@ struct obj **potmp, **pobj;
         /* handle puddings a bit differently; absorption will
          * free the other object automatically so we can just
          * return out from here.  */
-        if (Is_pudding(obj)) {
+        if (obj->globby) {
             pudding_merge_message(otmp, obj);
             obj_absorb(potmp, pobj);
             return 1;
@@ -2889,8 +2888,8 @@ struct obj *obj;
     return;
 }
 
-/* returns TRUE if obj  & otmp can be merged */
-STATIC_OVL boolean
+/* returns TRUE if obj & otmp can be merged; used in invent.c and mkobj.c */
+boolean
 mergable(otmp, obj)
 register struct obj *otmp, *obj;
 {
@@ -2908,31 +2907,24 @@ register struct obj *otmp, *obj;
         return TRUE;
 
     if (obj->unpaid != otmp->unpaid || obj->spe != otmp->spe
-        || obj->dknown != otmp->dknown
         || obj->cursed != otmp->cursed || obj->blessed != otmp->blessed
         || obj->no_charge != otmp->no_charge || obj->obroken != otmp->obroken
         || obj->otrapped != otmp->otrapped || obj->lamplit != otmp->lamplit
         || obj->bypass != otmp->bypass)
         return FALSE;
 
+    if (obj->globby)
+        return TRUE;
+    /* Checks beyond this point either aren't applicable to globs
+     * or don't inhibit their merger.
+     */
+
     if (obj->oclass == FOOD_CLASS
         && (obj->oeaten != otmp->oeaten || obj->orotten != otmp->orotten))
         return FALSE;
 
-    if (obj->globby) {
-        /* globs won't merge if they have different bless/curse
-           state, but will merge non-bknown with bknown */
-        if (obj->bknown != otmp->bknown)
-            obj->bknown = otmp->bknown = 0;
-        if (obj->rknown != otmp->rknown)
-            obj->rknown = otmp->rknown = 0;
-        if (obj->greased != otmp->greased)
-            obj->greased = otmp->greased = 0;
-        /* checks beyond this point aren't applicable to globs */
-        return TRUE;
-    }
-
-    if ((obj->bknown != otmp->bknown && !Role_if(PM_PRIEST))
+    if (obj->dknown != otmp->dknown
+        || (obj->bknown != otmp->bknown && !Role_if(PM_PRIEST))
         || obj->oeroded != otmp->oeroded || obj->oeroded2 != otmp->oeroded2
         || obj->greased != otmp->greased)
         return FALSE;
index a6f8bfd295fa56b51bfa4a474f81d2a25b9ca608..1c664127daf3856b46084f8dfc00b77e3d195d58 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 mkobj.c $NHDT-Date: 1447475943 2015/11/14 04:39:03 $  $NHDT-Branch: master $:$NHDT-Revision: 1.113 $ */
+/* NetHack 3.6 mkobj.c $NHDT-Date: 1454033600 2016/01/29 02:13:20 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.116 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -2578,15 +2578,10 @@ struct obj *
 obj_nexto(otmp)
 struct obj *otmp;
 {
-    struct obj *otmp2 = (struct obj *) 0;
-
-    if (otmp) {
-        otmp2 = obj_nexto_xy(otmp->otyp, otmp->ox, otmp->oy, otmp->o_id);
-    } else {
+    if (!otmp)
         impossible("obj_nexto: wasn't given an object to check");
-    }
 
-    return otmp2;
+    return obj_nexto_xy(otmp, otmp->ox, otmp->oy, TRUE);
 }
 
 /*
@@ -2598,24 +2593,27 @@ struct obj *otmp;
  * reliably predict which one we want to 'find' first
  */
 struct obj *
-obj_nexto_xy(otyp, x, y, oid)
-int otyp, x, y;
-unsigned oid;
+obj_nexto_xy(obj, x, y, recurs)
+struct obj *obj;
+int x, y;
+boolean recurs;
 {
     struct obj *otmp;
-    int fx, fy, ex, ey;
+    int fx, fy, ex, ey, otyp = obj->otyp;
     short dx, dy;
 
     /* check under our "feet" first */
     otmp = sobj_at(otyp, x, y);
     while (otmp) {
         /* don't be clever and find ourselves */
-        if (otmp->o_id != oid) {
+        if (otmp != obj && mergable(otmp, obj))
             return otmp;
-        }
         otmp = nxtobj(otmp, otyp, TRUE);
     }
 
+    if (!recurs)
+        return (struct obj *) 0;
+
     /* search in a random order */
     dx = (rn2(2) ? -1 : 1);
     dy = (rn2(2) ? -1 : 1);
@@ -2626,9 +2624,8 @@ unsigned oid;
         for (fy = ey; abs(fy - ey) < 3; fy += dy) {
             /* 0, 0 was checked above */
             if (isok(fx, fy) && (fx != x || fy != y)) {
-                if ((otmp = sobj_at(otyp, fx, fy)) != 0) {
+                if ((otmp = obj_nexto_xy(obj, fx, fy, FALSE)) != 0)
                     return otmp;
-                }
             }
         }
     }
@@ -2644,14 +2641,22 @@ struct obj *
 obj_absorb(obj1, obj2)
 struct obj **obj1, **obj2;
 {
-    struct obj *otmp1 = (struct obj *) 0, *otmp2 = (struct obj *) 0;
-    int extrawt = 0;
+    struct obj *otmp1, *otmp2;
+    int extrawt;
 
     /* don't let people dumb it up */
     if (obj1 && obj2) {
         otmp1 = *obj1;
         otmp2 = *obj2;
-        if (otmp1 && otmp2) {
+        if (otmp1 && otmp2 && otmp1 != otmp2) {
+            if (otmp1->bknown != otmp2->bknown)
+                otmp1->bknown = otmp2->bknown = 0;
+            if (otmp1->rknown != otmp2->rknown)
+                otmp1->rknown = otmp2->rknown = 0;
+            if (otmp1->greased != otmp2->greased)
+                otmp1->greased = otmp2->greased = 0;
+            if (otmp1->orotten || otmp2->orotten)
+                otmp1->orotten = otmp2->orotten = 1;
             extrawt = otmp2->oeaten ? otmp2->oeaten : otmp2->owt;
             otmp1->owt += extrawt;
             otmp1->oeaten += otmp1->oeaten ? extrawt : 0;
@@ -2677,13 +2682,14 @@ struct obj *
 obj_meld(obj1, obj2)
 struct obj **obj1, **obj2;
 {
-    struct obj *otmp1 = (struct obj *) 0, *otmp2 = (struct obj *) 0;
+    struct obj *otmp1, *otmp2;
 
     if (obj1 && obj2) {
         otmp1 = *obj1;
         otmp2 = *obj2;
-        if (otmp1 && otmp2) {
-            if (otmp1->owt > otmp2->owt || rn2(2)) {
+        if (otmp1 && otmp2 && otmp1 != otmp2) {
+            if (otmp1->owt > otmp2->owt
+                || (otmp1->owt == otmp2->owt && rn2(2))) {
                 return obj_absorb(obj1, obj2);
             }
             return obj_absorb(obj2, obj1);