From: PatR Date: Fri, 11 Oct 2019 00:43:31 +0000 (-0700) Subject: mksobj failure X-Git-Tag: v3.6.3.757eca7~35 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ad302fb8a99a5795c4d206870ea6573349b2d92a;p=nethack mksobj failure 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. --- diff --git a/src/mkobj.c b/src/mkobj.c index 24124f706..a92deceb6 100644 --- a/src/mkobj.c +++ b/src/mkobj.c @@ -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)