fix #H6942 - dropx vs hold_another_object

Dropping an existing fragile item while levitating will usually
break it.  Getting a new wished-for fragile item and dropping it
because of fumbling or overfull inventory never would.

Some callers of hold_another_object() held on to its return value,
others discarded that.  That return value was unsafe if the item
was dropped and fell down a hole (or broke [after this change]).
Return Null if we can't be sure of the value, and make sure all
callers are prepared to deal with Null.
This commit is contained in:
PatR
2018-12-23 12:37:26 -08:00
parent df5dc6050d
commit 7bc36ddef4
11 changed files with 68 additions and 47 deletions

View File

@@ -303,6 +303,7 @@ training riding skill had an off-by-one bug when counting turns riding
message sequencing when vampire shifts to fog cloud to pass under closed door: message sequencing when vampire shifts to fog cloud to pass under closed door:
when in sight, give form change message before moving to door spot when in sight, give form change message before moving to door spot
limit carrying heavy loads from water to land limit carrying heavy loads from water to land
failing to carry a wished-for item behaved differenctly from dropping one
Fixes to Post-3.6.1 Problems that Were Exposed Via git Repository Fixes to Post-3.6.1 Problems that Were Exposed Via git Repository

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 extern.h $NHDT-Date: 1545383614 2018/12/21 09:13:34 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.675 $ */ /* NetHack 3.6 extern.h $NHDT-Date: 1545597403 2018/12/23 20:36:43 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.676 $ */
/* Copyright (c) Steve Creps, 1988. */ /* Copyright (c) Steve Creps, 1988. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -536,7 +536,7 @@ E void FDECL(impact_drop, (struct obj *, XCHAR_P, XCHAR_P, XCHAR_P));
E int NDECL(dothrow); E int NDECL(dothrow);
E int NDECL(dofire); E int NDECL(dofire);
E void FDECL(endmultishot, (BOOLEAN_P)); E void FDECL(endmultishot, (BOOLEAN_P));
E void FDECL(hitfloor, (struct obj *)); E void FDECL(hitfloor, (struct obj *, BOOLEAN_P));
E void FDECL(hurtle, (int, int, int, BOOLEAN_P)); E void FDECL(hurtle, (int, int, int, BOOLEAN_P));
E void FDECL(mhurtle, (struct monst *, int, int, int)); E void FDECL(mhurtle, (struct monst *, int, int, int));
E boolean FDECL(throwing_weapon, (struct obj *)); E boolean FDECL(throwing_weapon, (struct obj *));

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 artifact.c $NHDT-Date: 1543745353 2018/12/02 10:09:13 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.127 $ */ /* NetHack 3.6 artifact.c $NHDT-Date: 1545597414 2018/12/23 20:36:54 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.128 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2013. */ /*-Copyright (c) Robert Patrick Rankin, 2013. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -1479,6 +1479,7 @@ struct obj *obj;
} }
case ENERGY_BOOST: { case ENERGY_BOOST: {
int epboost = (u.uenmax + 1 - u.uen) / 2; int epboost = (u.uenmax + 1 - u.uen) / 2;
if (epboost > 120) if (epboost > 120)
epboost = 120; /* arbitrary */ epboost = 120; /* arbitrary */
else if (epboost < 12) else if (epboost < 12)
@@ -1598,6 +1599,7 @@ struct obj *obj;
otmp->owt = weight(otmp); otmp->owt = weight(otmp);
otmp = hold_another_object(otmp, "Suddenly %s out.", otmp = hold_another_object(otmp, "Suddenly %s out.",
aobjnam(otmp, "fall"), (char *) 0); aobjnam(otmp, "fall"), (char *) 0);
nhUse(otmp);
break; break;
} }
} }
@@ -1621,7 +1623,7 @@ struct obj *obj;
} }
if ((eprop & ~W_ARTI) || iprop) { if ((eprop & ~W_ARTI) || iprop) {
nothing_special: nothing_special:
/* you had the property from some other source too */ /* you had the property from some other source too */
if (carried(obj)) if (carried(obj))
You_feel("a surge of power, but nothing seems to happen."); You_feel("a surge of power, but nothing seems to happen.");
@@ -1975,7 +1977,7 @@ boolean loseit; /* whether to drop it if hero can longer touch it */
if (loseit && obj) { if (loseit && obj) {
if (Levitation) { if (Levitation) {
freeinv(obj); freeinv(obj);
hitfloor(obj); hitfloor(obj, TRUE);
} else { } else {
/* dropx gives a message iff item lands on an altar */ /* dropx gives a message iff item lands on an altar */
if (!IS_ALTAR(levl[u.ux][u.uy].typ)) if (!IS_ALTAR(levl[u.ux][u.uy].typ))

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 do.c $NHDT-Date: 1545043771 2018/12/17 10:49:31 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.181 $ */ /* NetHack 3.6 do.c $NHDT-Date: 1545597418 2018/12/23 20:36:58 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.182 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Derek S. Ray, 2015. */ /*-Copyright (c) Derek S. Ray, 2015. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -612,7 +612,7 @@ register struct obj *obj;
if (obj->oclass == COIN_CLASS) if (obj->oclass == COIN_CLASS)
context.botl = 1; context.botl = 1;
freeinv(obj); freeinv(obj);
hitfloor(obj); hitfloor(obj, TRUE);
if (levhack) if (levhack)
float_down(I_SPECIAL | TIMEOUT, W_ARTI | W_ART); float_down(I_SPECIAL | TIMEOUT, W_ARTI | W_ART);
return 1; return 1;

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 dothrow.c $NHDT-Date: 1545044705 2018/12/17 11:05:05 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.154 $ */ /* NetHack 3.6 dothrow.c $NHDT-Date: 1545597420 2018/12/23 20:37:00 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.155 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2013. */ /*-Copyright (c) Robert Patrick Rankin, 2013. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -415,21 +415,21 @@ boolean verbose;
} }
} }
/* /* Object hits floor at hero's feet.
* Object hits floor at hero's feet. Called from drop() and throwit(). Called from drop(), throwit(), hold_another_object(). */
*/
void void
hitfloor(obj) hitfloor(obj, verbosely)
register struct obj *obj; struct obj *obj;
boolean verbosely; /* usually True; False if caller has given drop message */
{ {
if (IS_SOFT(levl[u.ux][u.uy].typ) || u.uinwater) { if (IS_SOFT(levl[u.ux][u.uy].typ) || u.uinwater || u.uswallow) {
dropy(obj); dropy(obj);
return; return;
} }
if (IS_ALTAR(levl[u.ux][u.uy].typ)) if (IS_ALTAR(levl[u.ux][u.uy].typ))
doaltarobj(obj); doaltarobj(obj);
else else if (verbosely)
pline("%s hit%s the %s.", Doname2(obj), (obj->quan == 1L) ? "s" : "", pline("%s %s the %s.", Doname2(obj), otense(obj, "hit"),
surface(u.ux, u.uy)); surface(u.ux, u.uy));
if (hero_breaks(obj, u.ux, u.uy, TRUE)) if (hero_breaks(obj, u.ux, u.uy, TRUE))
@@ -1047,7 +1047,7 @@ boolean hitsroof;
done(STONING); done(STONING);
return obj ? TRUE : FALSE; return obj ? TRUE : FALSE;
} }
hitfloor(obj); hitfloor(obj, TRUE);
thrownobj = 0; thrownobj = 0;
losehp(Maybe_Half_Phys(dmg), "falling object", KILLED_BY_AN); losehp(Maybe_Half_Phys(dmg), "falling object", KILLED_BY_AN);
} }
@@ -1168,7 +1168,7 @@ boolean twoweap; /* used to restore twoweapon mode if wielded weapon returns */
for dealing with cursed saddle: throw holy water > */ for dealing with cursed saddle: throw holy water > */
potionhit(u.usteed, obj, POTHIT_HERO_THROW); potionhit(u.usteed, obj, POTHIT_HERO_THROW);
} else { } else {
hitfloor(obj); hitfloor(obj, TRUE);
} }
thrownobj = (struct obj *) 0; thrownobj = (struct obj *) 0;
return; return;

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 invent.c $NHDT-Date: 1545043772 2018/12/17 10:49:32 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.244 $ */ /* NetHack 3.6 invent.c $NHDT-Date: 1545597422 2018/12/23 20:37:02 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.245 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Derek S. Ray, 2015. */ /*-Copyright (c) Derek S. Ray, 2015. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -975,9 +975,9 @@ const char *drop_fmt, *drop_arg, *hold_msg;
} }
} }
if (Fumbling) { if (Fumbling) {
if (drop_fmt) obj->nomerge = 1;
pline(drop_fmt, drop_arg); obj = addinv(obj); /* dropping expects obj to be in invent */
dropy(obj); goto drop_it;
} else { } else {
long oquan = obj->quan; long oquan = obj->quan;
int prev_encumbr = near_capacity(); /* before addinv() */ int prev_encumbr = near_capacity(); /* before addinv() */
@@ -994,12 +994,10 @@ const char *drop_fmt, *drop_arg, *hold_msg;
obj = addinv(obj); obj = addinv(obj);
if (inv_cnt(FALSE) > 52 || ((obj->otyp != LOADSTONE || !obj->cursed) if (inv_cnt(FALSE) > 52 || ((obj->otyp != LOADSTONE || !obj->cursed)
&& near_capacity() > prev_encumbr)) { && near_capacity() > prev_encumbr)) {
if (drop_fmt)
pline(drop_fmt, drop_arg);
/* undo any merge which took place */ /* undo any merge which took place */
if (obj->quan > oquan) if (obj->quan > oquan)
obj = splitobj(obj, oquan); obj = splitobj(obj, oquan);
dropx(obj); goto drop_it;
} else { } else {
if (flags.autoquiver && !uquiver && !obj->owornmask if (flags.autoquiver && !uquiver && !obj->owornmask
&& (is_missile(obj) || ammo_and_launcher(obj, uwep) && (is_missile(obj) || ammo_and_launcher(obj, uwep)
@@ -1010,6 +1008,18 @@ const char *drop_fmt, *drop_arg, *hold_msg;
} }
} }
return obj; return obj;
drop_it:
if (drop_fmt)
pline(drop_fmt, drop_arg);
obj->nomerge = 0;
if (can_reach_floor(TRUE)) {
dropx(obj);
} else {
freeinv(obj);
hitfloor(obj, FALSE);
}
return (struct obj *) 0; /* might be gone */
} }
/* useup() all of an item regardless of its quantity */ /* useup() all of an item regardless of its quantity */

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 mail.c $NHDT-Date: 1542765359 2018/11/21 01:55:59 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.37 $ */ /* NetHack 3.6 mail.c $NHDT-Date: 1545597424 2018/12/23 20:37:04 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.39 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Pasi Kallinen, 2018. */ /*-Copyright (c) Pasi Kallinen, 2018. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -186,7 +186,7 @@ coord *startp;
*/ */
lax = 0; /* be picky */ lax = 0; /* be picky */
max_distance = -1; max_distance = -1;
retry: retry:
for (row = 0; row < ROWNO; row++) { for (row = 0; row < ROWNO; row++) {
if (viz_rmin[row] < viz_rmax[row]) { if (viz_rmin[row] < viz_rmax[row]) {
/* There are valid positions on this row. */ /* There are valid positions on this row. */
@@ -418,15 +418,17 @@ struct mail_info *info;
display_nhwindow(WIN_MESSAGE, FALSE); display_nhwindow(WIN_MESSAGE, FALSE);
obj = hold_another_object(obj, "Oops!", (const char *) 0, obj = hold_another_object(obj, "Oops!", (const char *) 0,
(const char *) 0); (const char *) 0);
nhUse(obj);
} }
/* zip back to starting location */ go_back:
go_back: /* zip back to starting location */
if (!md_rush(md, start.x, start.y)) if (!md_rush(md, start.x, start.y))
md->mx = md->my = 0; /* for mongone, md is not on map */ md->mx = md->my = 0; /* for mongone, md is not on map */
mongone(md); mongone(md);
/* deliver some classes of messages even if no daemon ever shows up */
give_up: give_up:
/* deliver some classes of messages even if no daemon ever shows up */
if (!message_seen && info->message_typ == MSG_OTHER) if (!message_seen && info->message_typ == MSG_OTHER)
pline("Hark! \"%s.\"", info->display_txt); pline("Hark! \"%s.\"", info->display_txt);
} }
@@ -609,7 +611,7 @@ boolean adminmsg;
else else
unlink(mailbox); unlink(mailbox);
return; return;
bail: bail:
/* bail out _professionally_ */ /* bail out _professionally_ */
if (!adminmsg) if (!adminmsg)
pline("It appears to be all gibberish."); pline("It appears to be all gibberish.");

View File

@@ -1,4 +1,4 @@
/* 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 $ */ /* NetHack 3.6 mkobj.c $NHDT-Date: 1545597425 2018/12/23 20:37:05 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.137 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Derek S. Ray, 2015. */ /*-Copyright (c) Derek S. Ray, 2015. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -2168,18 +2168,21 @@ boolean tipping; /* caller emptying entire contents; affects shop handling */
being included in its formatted name during next message */ being included in its formatted name during next message */
iflags.suppress_price++; iflags.suppress_price++;
if (!tipping) { if (!tipping) {
obj = hold_another_object( obj = hold_another_object(obj,
obj, u.uswallow ? "Oops! %s out of your reach!" u.uswallow
: (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz) ? "Oops! %s out of your reach!"
|| levl[u.ux][u.uy].typ < IRONBARS : (Is_airlevel(&u.uz)
|| levl[u.ux][u.uy].typ >= ICE) || Is_waterlevel(&u.uz)
? "Oops! %s away from you!" || levl[u.ux][u.uy].typ < IRONBARS
: "Oops! %s to the floor!", || levl[u.ux][u.uy].typ >= ICE)
The(aobjnam(obj, "slip")), (const char *) 0); ? "Oops! %s away from you!"
: "Oops! %s to the floor!",
The(aobjnam(obj, "slip")), (char *) 0);
nhUse(obj);
} else { } else {
/* assumes this is taking place at hero's location */ /* assumes this is taking place at hero's location */
if (!can_reach_floor(TRUE)) { if (!can_reach_floor(TRUE)) {
hitfloor(obj); /* does altar check, message, drop */ hitfloor(obj, TRUE); /* does altar check, message, drop */
} else { } else {
if (IS_ALTAR(levl[u.ux][u.uy].typ)) if (IS_ALTAR(levl[u.ux][u.uy].typ))
doaltarobj(obj); /* does its own drop message */ doaltarobj(obj); /* does its own drop message */

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 pickup.c $NHDT-Date: 1543188989 2018/11/25 23:36:29 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.220 $ */ /* NetHack 3.6 pickup.c $NHDT-Date: 1545597427 2018/12/23 20:37:07 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.221 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2012. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -2023,6 +2023,7 @@ boolean *prev_loot;
} }
otmp = hold_another_object(otmp, "You drop %s!", doname(otmp), otmp = hold_another_object(otmp, "You drop %s!", doname(otmp),
(const char *) 0); (const char *) 0);
nhUse(otmp);
timepassed = rnd(3); timepassed = rnd(3);
if (prev_loot) if (prev_loot)
*prev_loot = TRUE; *prev_loot = TRUE;
@@ -3188,7 +3189,7 @@ struct obj *box; /* or bag */
if (highdrop) { if (highdrop) {
/* might break or fall down stairs; handles altars itself */ /* might break or fall down stairs; handles altars itself */
hitfloor(otmp); hitfloor(otmp, TRUE);
} else { } else {
if (altarizing) { if (altarizing) {
doaltarobj(otmp); doaltarobj(otmp);

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 potion.c $NHDT-Date: 1545182147 2018/12/19 01:15:47 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.156 $ */ /* NetHack 3.6 potion.c $NHDT-Date: 1545597429 2018/12/23 20:37:09 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.157 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2013. */ /*-Copyright (c) Robert Patrick Rankin, 2013. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -2237,6 +2237,7 @@ more_dips:
singlepotion = singlepotion =
hold_another_object(singlepotion, "You juggle and drop %s!", hold_another_object(singlepotion, "You juggle and drop %s!",
doname(singlepotion), (const char *) 0); doname(singlepotion), (const char *) 0);
nhUse(singlepotion);
update_inventory(); update_inventory();
return 1; return 1;
} }

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 uhitm.c $NHDT-Date: 1544840256 2018/12/15 02:17:36 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.196 $ */ /* NetHack 3.6 uhitm.c $NHDT-Date: 1545597432 2018/12/23 20:37:12 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.197 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2012. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -1546,7 +1546,8 @@ struct attack *mattk;
/* give the object to the character */ /* give the object to the character */
otmp = hold_another_object(otmp, "You snatched but dropped %s.", otmp = hold_another_object(otmp, "You snatched but dropped %s.",
doname(otmp), "You steal: "); doname(otmp), "You steal: ");
if (otmp->where != OBJ_INVENT) /* might have dropped otmp, and it might have broken or left level */
if (!otmp || otmp->where != OBJ_INVENT)
continue; continue;
if (theft_petrifies(otmp)) if (theft_petrifies(otmp))
break; /* stop thieving even though hero survived */ break; /* stop thieving even though hero survived */