]> granicus.if.org Git - nethack/commitdiff
fix #H2428 - cockatrice nests filled with giant ant statues (trunk only)
authornethack.rankin <nethack.rankin>
Wed, 24 Aug 2011 08:17:33 +0000 (08:17 +0000)
committernethack.rankin <nethack.rankin>
Wed, 24 Aug 2011 08:17:33 +0000 (08:17 +0000)
     From a bug report, if the high scores file
is brand new (empty), statues placed in a cockatrice nest (special room)
end up all being giant ant statues.  Statue creation for that room
suppresses object initialization (to prevent the statues from containing
spellbooks), so statue type is left as 0 by mkobj(), then when 'record'
is empty it never gets overridden with a role value as intended.

     This forces obj->corpsenm to be initialized as NON_PM instead of 0
by default, then overrides that for corpses, statues, and figurines even
when mkobj()'s caller requests that initialization be suppressed.  So if
'record' is empty, there will be a sensible fallback statue type.

     obj->corpsenm is overloaded for leashes ('leashmon', mon->m_id),
potions ('fromsink', fountain quaff hack), spellbooks ('spestudied', the
number of times the book has been read), and loadstones (corpsenm hack to
handle singular vs plural for "you can't let go of that/those" message).
If there are any other hidden corpsenm overloads, they may behave
strangely now that corpsenm is defaulting to -1 instead of 0....

doc/fixes35.0
src/mkobj.c

index 657a2cabf6baeecc4b80993c6a5ac2a871eb45b1..2fc5541cb94402dd4ac1333677fe7d815c7bb2e9 100644 (file)
@@ -378,6 +378,7 @@ for hero poly'd into a monster form that lacks a weapon attack but has a claw
        attack, use wielded weapon even when claw attack isn't the very first
 rename the SLEEPING property and Sleeping attribute to SLEEPY and Sleepy, resp.
 give alternate message for "<mon> turns to flee" when mon can't move
+all statues in a cockatrice nest were for giant ant if 'record' was empty
 
 
 Platform- and/or Interface-Specific Fixes
index aaf82ba8415897ac92c3ba02feada8501f5e3eaf..4fba48b591c002791bb39a4d1f8a84ef4cba325e 100644 (file)
@@ -619,6 +619,8 @@ boolean artif;
 #ifdef INVISIBLE_OBJECTS
        otmp->oinvis = !rn2(1250);
 #endif
+       otmp->corpsenm = NON_PM;
+
        if (init) switch (let) {
        case WEAPON_CLASS:
                otmp->quan = is_multigen(otmp) ? (long) rn1(6,6) : 1L;
@@ -683,11 +685,12 @@ boolean artif;
                otmp->quan = (long) rnd(2);
                break;
            }
-           if (otmp->otyp == CORPSE || otmp->otyp == MEAT_RING ||
-               otmp->otyp == KELP_FROND) break;
-           /* fall into next case */
-
+           if (otmp->otyp != CORPSE && otmp->otyp != MEAT_RING &&
+                   otmp->otyp != KELP_FROND && !rn2(6))
+               otmp->quan = 2L;
+           break;
        case GEM_CLASS:
+               otmp->corpsenm = 0;     /* LOADSTONE hack */
                if (otmp->otyp == LOADSTONE) curse(otmp);
                else if (otmp->otyp == ROCK) otmp->quan = (long) rn1(6,6);
                else if (otmp->otyp != LUCKSTONE && !rn2(6)) otmp->quan = 2L;
@@ -722,6 +725,8 @@ boolean artif;
                case OILSKIN_SACK:
                case BAG_OF_HOLDING:    mkbox_cnts(otmp);
                                        break;
+               case LEASH:             otmp->leashmon = 0;
+                                       break;
 #ifdef TOURIST
                case EXPENSIVE_CAMERA:
 #endif
@@ -768,6 +773,7 @@ boolean artif;
        case BALL_CLASS:
                break;
        case POTION_CLASS:
+               otmp->fromsink = 0;
                if (otmp->otyp == POT_OIL)
                    otmp->age = MAX_OIL_IN_FLASK;       /* amount of oil */
                /* fall through */
@@ -778,6 +784,7 @@ boolean artif;
                        blessorcurse(otmp, 4);
                break;
        case SPBOOK_CLASS:
+               otmp->spestudied = 0;
                blessorcurse(otmp, 17);
                break;
        case ARMOR_CLASS:
@@ -851,12 +858,22 @@ boolean artif;
                return (struct obj *)0;
        }
 
-       /* Some things must get done (timers) even if init = 0 */
+       /* some things must get done (corpsenm, timers) even if init = 0 */
        switch (otmp->otyp) {
            case CORPSE:
-           case EGG:
+               if (otmp->corpsenm == NON_PM) {
+                   otmp->corpsenm = undead_to_corpse(rndmonnum());
+                   if (mvitals[otmp->corpsenm].mvflags & (G_NOCORPSE|G_GONE))
+                       otmp->corpsenm = urole.malenum;
+               }
+               /*FALLTHRU*/
+           case STATUE:
            case FIGURINE:
-               set_corpsenm(otmp, otmp->corpsenm);
+               if (otmp->corpsenm == NON_PM) otmp->corpsenm = rndmonnum();
+               /*FALLTHRU*/
+           case EGG:
+        /* case TIN: */
+               set_corpsenm(otmp, otmp->corpsenm);
                break;
        }