]> granicus.if.org Git - nethack/commitdiff
mksobj failure
authorPatR <rankin@nethack.org>
Fri, 11 Oct 2019 00:43:31 +0000 (17:43 -0700)
committerPatR <rankin@nethack.org>
Fri, 11 Oct 2019 00:43:31 +0000 (17:43 -0700)
If mksobj() was told to initialize the object it's creating and the
object class was something it didn't understand, it would issue a
warning and return Null.  But an unknown object class is a severe
internal error and very few callers were prepared to deal with a
Null result, so change mksobj() to panic instead.  Also eliminate the
few attempts to deal with Null result that are present in mkobj.c;
I didn't go looking elsewhere.

src/mkobj.c

index 24124f706a7daf1e21dfbf3e1f9282ad3813fbeb..a92deceb67817505f074e8503ae860710297f123 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 mkobj.c $NHDT-Date: 1570569798 2019/10/08 21:23:18 $  $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.153 $ */
+/* NetHack 3.6 mkobj.c $NHDT-Date: 1570754586 2019/10/11 00:43:06 $  $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.154 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /*-Copyright (c) Derek S. Ray, 2015. */
 /* NetHack may be freely redistributed.  See license for details. */
@@ -235,15 +235,14 @@ boolean init, artif;
     struct obj *otmp;
 
     otmp = mksobj(otyp, init, artif);
-    if (otmp) {
-        add_to_migration(otmp);
-        otmp->owornmask = (long) MIGR_TO_SPECIES;
-        otmp->corpsenm = mflags2;
-    }
+    add_to_migration(otmp);
+    otmp->owornmask = (long) MIGR_TO_SPECIES;
+    otmp->corpsenm = mflags2;
     return otmp;
 }
 
-/* mkobj(): select a type of item from a class, use mksobj() to create it */
+/* mkobj(): select a type of item from a class, use mksobj() to create it;
+   result is always non-Null */
 struct obj *
 mkobj(oclass, artif)
 char oclass;
@@ -309,8 +308,7 @@ struct obj *box;
 
     for (n = rn2(n + 1); n > 0; n--) {
         if (box->otyp == ICE_BOX) {
-            if (!(otmp = mksobj(CORPSE, TRUE, TRUE)))
-                continue;
+            otmp = mksobj(CORPSE, TRUE, TRUE);
             /* Note: setting age to 0 is correct.  Age has a different
              * from usual meaning for objects stored in ice boxes. -KAA
              */
@@ -768,7 +766,7 @@ static const char dknowns[] = { WAND_CLASS,   RING_CLASS, POTION_CLASS,
                                 SCROLL_CLASS, GEM_CLASS,  SPBOOK_CLASS,
                                 WEAPON_CLASS, TOOL_CLASS, 0 };
 
-/* mksobj(): create a specific type of object */
+/* mksobj(): create a specific type of object; result it always non-Null */
 struct obj *
 mksobj(otyp, init, artif)
 int otyp;
@@ -1062,10 +1060,12 @@ boolean artif;
         case COIN_CLASS:
             break; /* do nothing */
         default:
-            impossible("impossible mkobj %d, sym '%c'.", otmp->otyp,
-                       objects[otmp->otyp].oc_class);
-            dealloc_obj(otmp); /* free() would suffice here */
-            return (struct obj *) 0;
+            /* 3.6.3: this used to be impossible() followed by return 0
+               but most callers aren't prepared to deal with Null result
+               and cluttering them up to do so is pointless */
+            panic("mksobj tried to make type %d, class %d.",
+                  (int) otmp->otyp, (int) objects[otmp->otyp].oc_class);
+            /*NOTREACHED*/
         }
     }
 
@@ -1473,6 +1473,7 @@ register struct obj *obj;
 
 static int treefruits[] = { APPLE, ORANGE, PEAR, BANANA, EUCALYPTUS_LEAF };
 
+/* called when a tree is kicked; never returns Null */
 struct obj *
 rnd_treefruit_at(x, y)
 int x, y;
@@ -1480,15 +1481,17 @@ int x, y;
     return mksobj_at(treefruits[rn2(SIZE(treefruits))], x, y, TRUE, FALSE);
 }
 
+/* create a stack of N gold pieces; never returns Null */
 struct obj *
 mkgold(amount, x, y)
 long amount;
 int x, y;
 {
-    register struct obj *gold = g_at(x, y);
+    struct obj *gold = g_at(x, y);
 
     if (amount <= 0L) {
         long mul = rnd(30 / max(12-depth(&u.uz), 2));
+
         amount = (long) (1 + rnd(level_difficulty() + 2) * mul);
     }
     if (gold) {
@@ -1501,12 +1504,14 @@ int x, y;
     return gold;
 }
 
-/* return TRUE if the corpse has special timing */
-#define special_corpse(num)                                                 \
-    (((num) == PM_LIZARD) || ((num) == PM_LICHEN) || (is_rider(&mons[num])) \
-     || (mons[num].mlet == S_TROLL))
+/* return TRUE if the corpse has special timing;
+   lizards and lichen don't rot, trolls and Riders auto-revive */
+#define special_corpse(num) \
+    (((num) == PM_LIZARD || (num) == PM_LICHEN)                 \
+     || (mons[num].mlet == S_TROLL || is_rider(&mons[num])))
 
-/*
+/* mkcorpstat: make a corpse or statue; never returns Null.
+ *
  * OEXTRA note: Passing mtmp causes mtraits to be saved
  * even if ptr passed as well, but ptr is always used for
  * the corpse type (corpsenm). That allows the corpse type
@@ -1523,40 +1528,37 @@ struct permonst *ptr;
 int x, y;
 unsigned corpstatflags;
 {
-    register struct obj *otmp;
+    struct obj *otmp;
     boolean init = ((corpstatflags & CORPSTAT_INIT) != 0);
 
     if (objtype != CORPSE && objtype != STATUE)
         impossible("making corpstat type %d", objtype);
     if (x == 0 && y == 0) { /* special case - random placement */
         otmp = mksobj(objtype, init, FALSE);
-        if (otmp)
-            (void) rloco(otmp);
-    } else
+        (void) rloco(otmp);
+    } else {
         otmp = mksobj_at(objtype, x, y, init, FALSE);
-    if (otmp) {
-        if (mtmp) {
-            struct obj *otmp2;
-
-            if (!ptr)
-                ptr = mtmp->data;
-            /* save_mtraits frees original data pointed to by otmp */
-            otmp2 = save_mtraits(otmp, mtmp);
-            if (otmp2)
-                otmp = otmp2;
-        }
-        /* use the corpse or statue produced by mksobj() as-is
-           unless `ptr' is non-null */
-        if (ptr) {
-            int old_corpsenm = otmp->corpsenm;
-
-            otmp->corpsenm = monsndx(ptr);
-            otmp->owt = weight(otmp);
-            if (otmp->otyp == CORPSE && (special_corpse(old_corpsenm)
-                                         || special_corpse(otmp->corpsenm))) {
-                obj_stop_timers(otmp);
-                start_corpse_timeout(otmp);
-            }
+    }
+
+    /* when 'mtmp' is non-null make a corpse or statue of that monster,
+       otherwise keep the random type chosen by mksobj() */
+    if (mtmp) {
+        int old_corpsenm = otmp->corpsenm;
+
+        /* save_mtraits updates otmp->oextra->omonst in place */
+        (void) save_mtraits(otmp, mtmp);
+
+        /* when 'ptr' is non-null use the type specified by our caller,
+           otherwise use the monster's species for the corpse */
+        if (!ptr)
+            ptr = mtmp->data;
+
+        otmp->corpsenm = monsndx(ptr);
+        otmp->owt = weight(otmp);
+        if (otmp->otyp == CORPSE && (special_corpse(old_corpsenm)
+                                     || special_corpse(otmp->corpsenm))) {
+            obj_stop_timers(otmp);
+            start_corpse_timeout(otmp);
         }
     }
     return otmp;
@@ -1574,15 +1576,14 @@ int
 corpse_revive_type(obj)
 struct obj *obj;
 {
-    int revivetype;
+    int revivetype = obj->corpsenm;
     struct monst *mtmp;
-    if (has_omonst(obj)
-        && ((mtmp = get_mtraits(obj, FALSE)) != (struct monst *) 0)) {
+
+    if (has_omonst(obj) && ((mtmp = get_mtraits(obj, FALSE)) != 0)) {
         /* mtmp is a temporary pointer to a monster's stored
         attributes, not a real monster */
         revivetype = mtmp->mnum;
-    } else
-        revivetype = obj->corpsenm;
+    }
     return revivetype;
 }
 
@@ -1658,26 +1659,29 @@ boolean copyof;
     return mnew;
 }
 
-/* make an object named after someone listed in the scoreboard file */
+/* make an object named after someone listed in the scoreboard file;
+   never returns Null */
 struct obj *
 mk_tt_object(objtype, x, y)
 int objtype; /* CORPSE or STATUE */
-register int x, y;
+int x, y;
 {
-    register struct obj *otmp, *otmp2;
+    struct obj *otmp;
     boolean initialize_it;
 
     /* player statues never contain books */
     initialize_it = (objtype != STATUE);
-    if ((otmp = mksobj_at(objtype, x, y, initialize_it, FALSE)) != 0) {
-        /* tt_oname will return null if the scoreboard is empty */
-        if ((otmp2 = tt_oname(otmp)) != 0)
-            otmp = otmp2;
-    }
+    otmp = mksobj_at(objtype, x, y, initialize_it, FALSE);
+    /* tt_oname() will return null if the scoreboard is empty;
+       assigning an object name used to allocate a new obj but
+       doesn't any more so we can safely ignore the return value */
+    (void) tt_oname(otmp);
+
     return otmp;
 }
 
-/* make a new corpse or statue, uninitialized if a statue (i.e. no books) */
+/* make a new corpse or statue, uninitialized if a statue (i.e. no books);
+   never returns Null */
 struct obj *
 mk_named_object(objtype, ptr, x, y, nm)
 int objtype; /* CORPSE or STATUE */
@@ -1686,8 +1690,8 @@ int x, y;
 const char *nm;
 {
     struct obj *otmp;
-    unsigned corpstatflags =
-        (objtype != STATUE) ? CORPSTAT_INIT : CORPSTAT_NONE;
+    unsigned corpstatflags = (objtype != STATUE) ? CORPSTAT_INIT
+                                                 : CORPSTAT_NONE;
 
     otmp = mkcorpstat(objtype, (struct monst *) 0, ptr, x, y, corpstatflags);
     if (nm)