]> granicus.if.org Git - nethack/commitdiff
Schroedinger's Cat
authorPatR <rankin@nethack.org>
Wed, 21 Nov 2018 11:10:49 +0000 (03:10 -0800)
committerPatR <rankin@nethack.org>
Wed, 21 Nov 2018 11:10:49 +0000 (03:10 -0800)
If hero was carrying Schroedinger's Box at end of game, disclosing
inventory converted it into an ordinary box.  That interferred with
subsequent disclosure when writing DUMPLOG, which saw an empty box
if inventory had been shown or the special box with newly-determined
contents if not.  I tried a couple of ways to fix it and decided
that redoing it was better in the long run.

Schroedinger's box is still flagged with box->spe = 1, but instead
of having that affect the box's weight, now there is always a cat
corpse in the box.  When opened, that will already be in place for
a dead cat or be discarded for a live one, but the weight will be
standard for container+contents and when box->cknown is set it will
always be "containing 1 item" (which might turn out to be a monster).

Some temporary code fixes up old save/bones files to stay compatible.

TODO:  food detection used to skip Schroedinger's Box; now it will
always find a corpse, so some fixup like the ridiculous probing code
is needed.

doc/fixes36.2
include/extern.h
src/end.c
src/makemon.c
src/mkobj.c
src/pickup.c
src/restore.c
src/zap.c

index 183b012c08286f622b566d0af5c6d7cdf1e6282a..3f6bc996f92c2d9aa0a647be67616fe568e4afc7 100644 (file)
@@ -205,6 +205,8 @@ successfully paying for shop damage with shop credit would be followed by
 if a migrating monster was killed off because there was no room on the
        destination level, it would leave a corpse even if it was a type
        which should never leave one (demon, golem, blob, &c)
+end of game while carrying Schroedinger's Box would reveal cat-or-corpse
+       for inventory disclosure or put that info into dumplog, but not both
 
 
 Fixes to Post-3.6.1 Problems that Were Exposed Via git Repository
index ff0976e185d8d0c0a8058f6768d3067d1368cdcf..89910b0bba91889ff9ffa71c67dbdce7456ff5f3 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 extern.h        $NHDT-Date: 1541719965 2018/11/08 23:32:45 $  $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.647 $ */
+/* NetHack 3.6 extern.h        $NHDT-Date: 1542798602 2018/11/21 11:10:02 $  $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.650 $ */
 /* Copyright (c) Steve Creps, 1988.                              */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -1848,6 +1848,7 @@ E struct obj *FDECL(pick_obj, (struct obj *));
 E int NDECL(encumber_msg);
 E int FDECL(container_at, (int, int, BOOLEAN_P));
 E int NDECL(doloot);
+E void FDECL(observe_quantum_cat, (struct obj *, BOOLEAN_P, BOOLEAN_P));
 E boolean FDECL(container_gone, (int (*)(OBJ_P)));
 E boolean NDECL(u_handsy);
 E int FDECL(use_container, (struct obj **, int, BOOLEAN_P));
index 7d89bd03a6c3f671b398efb086491a77a078f166..a433acc072ba6281f8058adaf1abff42882c4e5d 100644 (file)
--- a/src/end.c
+++ b/src/end.c
@@ -1,4 +1,4 @@
-/* NetHack 3.6 end.c   $NHDT-Date: 1541902951 2018/11/11 02:22:31 $  $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.150 $ */
+/* NetHack 3.6 end.c   $NHDT-Date: 1542798619 2018/11/21 11:10:19 $  $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.152 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /*-Copyright (c) Robert Patrick Rankin, 2012. */
 /* NetHack may be freely redistributed.  See license for details. */
@@ -49,7 +49,6 @@ STATIC_DCL void FDECL(get_valuables, (struct obj *));
 STATIC_DCL void FDECL(sort_valuables, (struct valuable_data *, int));
 STATIC_DCL void FDECL(artifact_score, (struct obj *, BOOLEAN_P, winid));
 STATIC_DCL void FDECL(really_done, (int)) NORETURN;
-STATIC_DCL boolean FDECL(odds_and_ends, (struct obj *, int));
 STATIC_DCL void FDECL(savelife, (int));
 STATIC_PTR int FDECL(CFDECLSPEC vanqsort_cmp, (const genericptr,
                                                const genericptr));
@@ -954,6 +953,13 @@ int size; /* max value is less than 20 */
     return;
 }
 
+#if 0
+/*
+ * odds_and_ends() was used for 3.6.0 and 3.6.1.
+ * Schroedinger's Cat is handled differently starting with 3.6.2.
+ */
+STATIC_DCL boolean FDECL(odds_and_ends, (struct obj *, int));
+
 #define CAT_CHECK 2
 
 STATIC_OVL boolean
@@ -962,6 +968,7 @@ struct obj *list;
 int what;
 {
     struct obj *otmp;
+
     for (otmp = list; otmp; otmp = otmp->nobj) {
         switch (what) {
         case CAT_CHECK: /* Schroedinger's Cat */
@@ -975,6 +982,7 @@ int what;
     }
     return FALSE;
 }
+#endif
 
 /* called twice; first to calculate total, then to list relevant items */
 STATIC_OVL void
@@ -1218,6 +1226,20 @@ int how;
             obj->known = obj->bknown = obj->dknown = obj->rknown = 1;
             if (Is_container(obj) || obj->otyp == STATUE)
                 obj->cknown = obj->lknown = 1;
+            /* we resolve Schroedinger's cat now in case of both
+               disclosure and dumplog, where the 50:50 chance for
+               live cat has to be the same both times */
+            if (SchroedingersBox(obj)) {
+                if (!Schroedingers_cat) {
+                    /* tell observe_quantum_cat() not to create a cat; if it
+                       chooses live cat in this situation, it will leave the
+                       SchroedingersBox flag set (for container_contents()) */
+                    observe_quantum_cat(obj, FALSE, FALSE);
+                    if (SchroedingersBox(obj))
+                        Schroedingers_cat = TRUE;
+                } else
+                    obj->spe = 0; /* ordinary box with cat corpse in it */
+            }
         }
 
         if (strcmp(flags.end_disclose, "none"))
@@ -1228,7 +1250,7 @@ int how;
 
     /* if pets will contribute to score, populate mydogs list now
        (bones creation isn't a factor, but pline() messaging is; used to
-       be done ever sooner, but we need it to come after dump_everything()
+       be done even sooner, but we need it to come after dump_everything()
        so that any accompanying pets are still on the map during dump) */
     if (how == ESCAPED || how == ASCENDED)
         keepdogs(TRUE);
@@ -1389,22 +1411,22 @@ int how;
         viz_array[0][0] |= IN_SIGHT; /* need visibility for naming */
         mtmp = mydogs;
         Strcpy(pbuf, "You");
-        if (!Schroedingers_cat) /* check here in case disclosure was off */
-            Schroedingers_cat = odds_and_ends(invent, CAT_CHECK);
-        if (Schroedingers_cat) {
-            int mhp, m_lev = adj_lev(&mons[PM_HOUSECAT]);
-
-            mhp = d(m_lev, 8);
-            nowrap_add(u.urexp, mhp);
-            Strcat(eos(pbuf), " and Schroedinger's cat");
-        }
-        if (mtmp) {
+        if (mtmp || Schroedingers_cat) {
             while (mtmp) {
                 Sprintf(eos(pbuf), " and %s", mon_nam(mtmp));
                 if (mtmp->mtame)
                     nowrap_add(u.urexp, mtmp->mhp);
                 mtmp = mtmp->nmon;
             }
+            /* [it might be more robust to create a housecat and add it to
+               mydogs; it doesn't have to be placed on the map for that] */
+            if (Schroedingers_cat) {
+                int mhp, m_lev = adj_lev(&mons[PM_HOUSECAT]);
+
+                mhp = d(m_lev, 8);
+                nowrap_add(u.urexp, mhp);
+                Strcat(eos(pbuf), " and Schroedinger's cat");
+            }
             dump_forward_putstr(endwin, 0, pbuf, done_stopprint);
             pbuf[0] = '\0';
         } else {
@@ -1513,23 +1535,18 @@ boolean identified, all_containers, reportempty;
 {
     register struct obj *box, *obj;
     char buf[BUFSZ];
-    boolean cat, deadcat;
+    boolean cat,
+            dumping =
+#ifdef DUMPLOG
+                     iflags.in_dumplog ? TRUE :
+#endif
+                     FALSE;
 
     for (box = list; box; box = box->nobj) {
         if (Is_container(box) || box->otyp == STATUE) {
             box->cknown = 1; /* we're looking at the contents now */
             if (identified)
                 box->lknown = 1;
-            cat = deadcat = FALSE;
-            if (SchroedingersBox(box) && !Schroedingers_cat) {
-                /* Schroedinger's Cat? */
-                cat = odds_and_ends(box, CAT_CHECK);
-                if (cat)
-                    Schroedingers_cat = TRUE;
-                else
-                    deadcat = TRUE;
-                box->spe = 0;
-            }
             if (box->otyp == BAG_OF_TRICKS) {
                 continue; /* wrong type of container */
             } else if (box->cobj) {
@@ -1537,38 +1554,49 @@ boolean identified, all_containers, reportempty;
                 Loot *sortedcobj, *srtc;
                 unsigned sortflags;
 
+                /* at this stage, the SchroedingerBox() flag is only set
+                   if the cat inside the box is alive; the box actually
+                   contains a cat corpse that we'll pretend is not there;
+                   for dead cat, the flag will be clear and there'll be
+                   a cat corpse inside the box; either way, inventory
+                   reports the box as containing "1 item" */
+                cat = SchroedingersBox(box);
+
                 Sprintf(buf, "Contents of %s:", the(xname(box)));
                 putstr(tmpwin, 0, buf);
-                putstr(tmpwin, 0, "");
-                sortflags = (((flags.sortloot == 'l' || flags.sortloot == 'f')
-                              ? SORTLOOT_LOOT : 0)
-                             | (flags.sortpack ? SORTLOOT_PACK : 0));
-                sortedcobj = sortloot(&box->cobj, sortflags, FALSE,
-                                      (boolean FDECL((*), (OBJ_P))) 0);
-                for (srtc = sortedcobj; ((obj = srtc->obj) != 0); ++srtc) {
-                    if (identified) {
-                        discover_object(obj->otyp, TRUE, FALSE);
-                        obj->known = obj->bknown = obj->dknown
-                            = obj->rknown = 1;
-                        if (Is_container(obj) || obj->otyp == STATUE)
-                            obj->cknown = obj->lknown = 1;
+                if (!dumping)
+                    putstr(tmpwin, 0, "");
+                buf[0] = buf[1] = ' '; /* two leading spaces */
+                if (box->cobj && !cat) {
+                    sortflags = (((flags.sortloot == 'l'
+                                   || flags.sortloot == 'f')
+                                     ? SORTLOOT_LOOT : 0)
+                                 | (flags.sortpack ? SORTLOOT_PACK : 0));
+                    sortedcobj = sortloot(&box->cobj, sortflags, FALSE,
+                                          (boolean FDECL((*), (OBJ_P))) 0);
+                    for (srtc = sortedcobj; ((obj = srtc->obj) != 0); ++srtc) {
+                        if (identified) {
+                            discover_object(obj->otyp, TRUE, FALSE);
+                            obj->known = obj->bknown = obj->dknown
+                                = obj->rknown = 1;
+                            if (Is_container(obj) || obj->otyp == STATUE)
+                                obj->cknown = obj->lknown = 1;
+                        }
+                        Strcpy(&buf[2], doname(obj));
+                        putstr(tmpwin, 0, buf);
                     }
-                    putstr(tmpwin, 0, doname(obj));
+                    unsortloot(&sortedcobj);
+                } else if (cat) {
+                    Strcpy(&buf[2], "Schroedinger's cat!");
+                    putstr(tmpwin, 0, buf);
                 }
-                unsortloot(&sortedcobj);
-                if (cat)
-                    putstr(tmpwin, 0, "Schroedinger's cat");
-                else if (deadcat)
-                    putstr(tmpwin, 0, "Schroedinger's dead cat");
+                if (dumping)
+                    putstr(0, 0, "");
                 display_nhwindow(tmpwin, TRUE);
                 destroy_nhwindow(tmpwin);
                 if (all_containers)
                     container_contents(box->cobj, identified, TRUE,
                                        reportempty);
-            } else if (cat || deadcat) {
-                pline("%s Schroedinger's %scat!", Tobjnam(box, "contain"),
-                      deadcat ? "dead " : "");
-                display_nhwindow(WIN_MESSAGE, FALSE);
             } else if (reportempty) {
                 pline("%s is empty.", upstart(thesimpleoname(box)));
                 display_nhwindow(WIN_MESSAGE, FALSE);
index 30630fb16e0f2c18ab501f52e760b19a620d79cd..33cc7709cf23e3bbb05affe53bf654d347237a8f 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 makemon.c       $NHDT-Date: 1539804904 2018/10/17 19:35:04 $  $NHDT-Branch: keni-makedefsm $:$NHDT-Revision: 1.127 $ */
+/* NetHack 3.6 makemon.c       $NHDT-Date: 1542798623 2018/11/21 11:10:23 $  $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.128 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /*-Copyright (c) Robert Patrick Rankin, 2012. */
 /* NetHack may be freely redistributed.  See license for details. */
@@ -280,7 +280,8 @@ register struct monst *mtmp;
                 if (rn2(2))
                     (void) mongets(mtmp, rn2(3) ? DAGGER : KNIFE);
                 if (rn2(5))
-                    (void) mongets(mtmp, rn2(3) ? LEATHER_JACKET : LEATHER_CLOAK);
+                    (void) mongets(mtmp, rn2(3) ? LEATHER_JACKET
+                                                : LEATHER_CLOAK);
                 if (rn2(3))
                     (void) mongets(mtmp, rn2(3) ? LOW_BOOTS : HIGH_BOOTS);
                 if (rn2(3))
@@ -304,7 +305,8 @@ register struct monst *mtmp;
             case PM_HUNTER:
                 (void) mongets(mtmp, rn2(3) ? SHORT_SWORD : DAGGER);
                 if (rn2(2))
-                    (void) mongets(mtmp, rn2(2) ? LEATHER_JACKET : LEATHER_ARMOR);
+                    (void) mongets(mtmp, rn2(2) ? LEATHER_JACKET
+                                                : LEATHER_ARMOR);
                 (void) mongets(mtmp, BOW);
                 m_initthrow(mtmp, ARROW, 12);
                 break;
@@ -744,9 +746,21 @@ register struct monst *mtmp;
         break;
     case S_QUANTMECH:
         if (!rn2(20)) {
+            struct obj *catcorpse;
+
             otmp = mksobj(LARGE_BOX, FALSE, FALSE);
-            otmp->spe = 1; /* flag for special box */
-            otmp->owt = weight(otmp);
+            /* we used to just set the flag, which resulted in weight()
+               treating the box as being heavier by the weight of a cat;
+               now we include a cat corpse that won't rot; when opening or
+               disclosing the box's contents, the corpse might be revived,
+               otherwise it's given a rot timer; weight is now ordinary */
+            if ((catcorpse = mksobj(CORPSE, TRUE, FALSE)) != 0) {
+                otmp->spe = 1; /* flag for special SchroedingersBox */
+                set_corpsenm(catcorpse, PM_HOUSECAT);
+                (void) stop_timer(ROT_CORPSE, obj_to_any(catcorpse));
+                add_to_container(otmp, catcorpse);
+                otmp->owt = weight(otmp);
+            }
             (void) mpickobj(mtmp, otmp);
         }
         break;
index 8442f680cff0f41f53d71da9a1b42b46c2fe52ed..9a0ec48f2a99a81752a6bdc48dccc7ede62df16d 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 mkobj.c $NHDT-Date: 1518053380 2018/02/08 01:29:40 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.130 $ */
+/* NetHack 3.6 mkobj.c $NHDT-Date: 1542798624 2018/11/21 11:10:24 $  $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.136 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /*-Copyright (c) Derek S. Ray, 2015. */
 /* NetHack may be freely redistributed.  See license for details. */
@@ -1388,8 +1388,6 @@ register struct obj *obj;
        when we assume this is a brand new glob so use objects[].oc_weight */
     if (obj->globby && obj->owt > 0)
         wt = obj->owt;
-    if (SchroedingersBox(obj))
-        wt += mons[PM_HOUSECAT].cwt;
     if (Is_container(obj) || obj->otyp == STATUE) {
         struct obj *contents;
         register int cwt = 0;
index 319f1f031490d43d42c5eb91c8e802db9c992c3d..d68def38d7026a56e3e08f30954f060a2605b285 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 pickup.c        $NHDT-Date: 1541312259 2018/11/04 06:17:39 $  $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.201 $ */
+/* NetHack 3.6 pickup.c        $NHDT-Date: 1542798625 2018/11/21 11:10:25 $  $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.202 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /*-Copyright (c) Robert Patrick Rankin, 2012. */
 /* NetHack may be freely redistributed.  See license for details. */
@@ -34,7 +34,6 @@ STATIC_PTR int FDECL(in_container, (struct obj *));
 STATIC_PTR int FDECL(out_container, (struct obj *));
 STATIC_DCL void FDECL(removed_from_icebox, (struct obj *));
 STATIC_DCL long FDECL(mbag_item_gone, (int, struct obj *));
-STATIC_DCL void FDECL(observe_quantum_cat, (struct obj *));
 STATIC_DCL void FDECL(explain_container_prompt, (BOOLEAN_P));
 STATIC_DCL int FDECL(traditional_loot, (BOOLEAN_P));
 STATIC_DCL int FDECL(menu_loot, (int, BOOLEAN_P));
@@ -2321,45 +2320,66 @@ struct obj *item;
     return loss;
 }
 
-STATIC_OVL void
-observe_quantum_cat(box)
+/* used for #loot/apply, #tip, and final disclosure */
+void
+observe_quantum_cat(box, makecat, givemsg)
 struct obj *box;
+boolean makecat, givemsg;
 {
     static NEARDATA const char sc[] = "Schroedinger's Cat";
     struct obj *deadcat;
-    struct monst *livecat;
+    struct monst *livecat = 0;
     xchar ox, oy;
+    boolean itsalive = !rn2(2);
 
-    box->spe = 0; /* box->owt will be updated below */
     if (get_obj_location(box, &ox, &oy, 0))
         box->ox = ox, box->oy = oy; /* in case it's being carried */
 
     /* this isn't really right, since any form of observation
        (telepathic or monster/object/food detection) ought to
-       force the determination of alive vs dead state; but basing
-       it just on opening the box is much simpler to cope with */
-    livecat = rn2(2)
-                  ? makemon(&mons[PM_HOUSECAT], box->ox, box->oy, NO_MINVENT)
-                  : 0;
-    if (livecat) {
-        livecat->mpeaceful = 1;
-        set_malign(livecat);
-        if (!canspotmon(livecat))
-            You("think %s brushed your %s.", something, body_part(FOOT));
-        else
-            pline("%s inside the box is still alive!", Monnam(livecat));
-        (void) christen_monst(livecat, sc);
+       force the determination of alive vs dead state; but basing it
+       just on opening or disclosing the box is much simpler to cope with */
+
+    /* SchroedingersBox already has a cat corpse in it */
+    deadcat = box->cobj;
+    if (itsalive) {
+        if (makecat)
+            livecat = makemon(&mons[PM_HOUSECAT], box->ox, box->oy,
+                              NO_MINVENT | MM_ADJACENTOK);
+        if (livecat) {
+            livecat->mpeaceful = 1;
+            set_malign(livecat);
+            if (givemsg) {
+                if (!canspotmon(livecat))
+                    You("think %s brushed your %s.", something,
+                        body_part(FOOT));
+                else
+                    pline("%s inside the box is still alive!",
+                          Monnam(livecat));
+            }
+            (void) christen_monst(livecat, sc);
+            if (deadcat) {
+                obj_extract_self(deadcat);
+                obfree(deadcat, (struct obj *) 0), deadcat = 0;
+            }
+            box->owt = weight(box);
+            box->spe = 0;
+        }
     } else {
-        deadcat = mk_named_object(CORPSE, &mons[PM_HOUSECAT],
-                                  box->ox, box->oy, sc);
+        box->spe = 0; /* now an ordinary box (with a cat corpse inside) */
         if (deadcat) {
-            obj_extract_self(deadcat);
-            (void) add_to_container(box, deadcat);
+            /* set_corpsenm() will start the rot timer that was removed
+               when makemon() created SchroedingersBox; start it from
+               now rather than from when this special corpse got created */
+            deadcat->age = monstermoves;
+            set_corpsenm(deadcat, PM_HOUSECAT);
+            deadcat = oname(deadcat, sc);
         }
-        pline_The("%s inside the box is dead!",
-                  Hallucination ? rndmonnam((char *) 0) : "housecat");
+        if (givemsg)
+            pline_The("%s inside the box is dead!",
+                      Hallucination ? rndmonnam((char *) 0) : "housecat");
     }
-    box->owt = weight(box);
+    nhUse(deadcat);
     return;
 }
 
@@ -2472,7 +2492,7 @@ boolean more_containers; /* True iff #loot multiple and this isn't last one */
     /* check for Schroedinger's Cat */
     quantum_cat = SchroedingersBox(current_container);
     if (quantum_cat) {
-        observe_quantum_cat(current_container);
+        observe_quantum_cat(current_container, TRUE, TRUE);
         used = 1;
     }
 
@@ -3096,7 +3116,7 @@ struct obj *box; /* or bag */
     } else if (SchroedingersBox(box)) {
         char yourbuf[BUFSZ];
 
-        observe_quantum_cat(box);
+        observe_quantum_cat(box, TRUE, TRUE);
         if (!Has_contents(box)) /* evidently a live cat came out */
             /* container type of "large box" is inferred */
             pline("%sbox is now empty.", Shk_Your(yourbuf, box));
index f7a1e6a26a4e8af0788001d3ae1c14bcc174cd26..f26379967f1383e686a0b90b5d25f97bc892a9fa 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 restore.c       $NHDT-Date: 1451082255 2015/12/25 22:24:15 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.103 $ */
+/* NetHack 3.6 restore.c       $NHDT-Date: 1542798626 2018/11/21 11:10:26 $  $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.109 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /*-Copyright (c) Michael Allison, 2009. */
 /* NetHack may be freely redistributed.  See license for details. */
@@ -298,10 +298,32 @@ boolean ghostly, frozen;
         /* get contents of a container or statue */
         if (Has_contents(otmp)) {
             struct obj *otmp3;
+
             otmp->cobj = restobjchn(fd, ghostly, Is_IceBox(otmp));
             /* restore container back pointers */
             for (otmp3 = otmp->cobj; otmp3; otmp3 = otmp3->nobj)
                 otmp3->ocontainer = otmp;
+        } else if (SchroedingersBox(otmp)) {
+            struct obj *catcorpse;
+
+            /*
+             * TODO:  Remove this after 3.6.x save compatibility is dropped.
+             *
+             * For 3.6.2, SchroedingersBox() always has a cat corpse in it.
+             * For 3.6.[01], it was empty and its weight was falsified
+             * to have the value it would have had if there was one inside.
+             * Put a non-rotting cat corpse in this box to convert to 3.6.2.
+             *
+             * [Note: after this fix up, future save/restore of this object
+             * will take the Has_contents() code path above.]
+             */
+            if ((catcorpse = mksobj(CORPSE, TRUE, FALSE)) != 0) {
+                otmp->spe = 1; /* flag for special SchroedingersBox */
+                set_corpsenm(catcorpse, PM_HOUSECAT);
+                (void) stop_timer(ROT_CORPSE, obj_to_any(catcorpse));
+                add_to_container(otmp, catcorpse);
+                otmp->owt = weight(otmp);
+            }
         }
         if (otmp->bypass)
             otmp->bypass = 0;
index 5781d87898b646d2cd3a6314c4d603b2cd0029df..d53468fe38d2658d685d30647a4efe5a7ec541ae 100644 (file)
--- a/src/zap.c
+++ b/src/zap.c
@@ -1,4 +1,4 @@
-/* NetHack 3.6 zap.c   $NHDT-Date: 1537234123 2018/09/18 01:28:43 $  $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.287 $ */
+/* NetHack 3.6 zap.c   $NHDT-Date: 1542798627 2018/11/21 11:10:27 $  $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.289 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /*-Copyright (c) Robert Patrick Rankin, 2013. */
 /* NetHack may be freely redistributed.  See license for details. */
@@ -1916,14 +1916,17 @@ struct obj *obj, *otmp;
             if (Is_container(obj) || obj->otyp == STATUE) {
                 obj->cknown = obj->lknown = 1;
                 if (!obj->cobj) {
-                    boolean catbox = SchroedingersBox(obj);
-
+                    pline("%s empty.", Tobjnam(obj, "are"));
+                } else if (SchroedingersBox(obj)) {
                     /* we don't want to force alive vs dead
                        determination for Schroedinger's Cat here,
                        so just make probing be inconclusive for it */
-                    if (catbox)
-                        obj->cknown = 0;
-                    pline("%s empty.", Tobjnam(obj, catbox ? "seem" : "are"));
+                    You("aren't sure whether %s has %s or its corpse inside.",
+                        the(xname(obj)),
+                        /* unfortunately, we can't tell whether rndmonnam()
+                           picks a form which can't leave a corpse */
+                        an(Hallucination ? rndmonnam((char *) 0) : "cat"));
+                    obj->cknown = 0;
                 } else {
                     struct obj *o;
                     /* view contents (not recursively) */