iterating gi.invent (github issue #1315)
GitHub issue #1315 points out that it is possible for a downstream function to change an object's nobj field to point to a completely different chain. The cited example by @vultur-cadens was: for (obj = gi.invent; obj; obj = obj->nobj) if (obj->oclass != COIN_CLASS && !obj->cursed && !rn2(5)) { curse(obj); ++buc_changed; } curse() drops the weapon with drop_uswapwep(), which calls dropx(), which calls dropy(), which calls dropz(), which calls place_object(). place_object alters the nobj pointer, to point to the floor chain: otmp->nobj = fobj; fobj = otmp; The result was that the next loop iteration was then using floor objects from the floor chain. This alters several for-loops to use a more consistent approach, particularly when the obj is being handed off to a function, where a downstream function might, or might not, alter the nobj field. References: https://github.com/NetHack/NetHack/issues/1315 https://www.reddit.com/r/nethack/comments/1gkc9ub/even_if_you_drop_an_item_before_drinking_from_the/
This commit is contained in:
@@ -315,18 +315,20 @@ drinkfountain(void)
|
||||
dowaterdemon();
|
||||
break;
|
||||
case 24: { /* Maybe curse some items */
|
||||
struct obj *obj;
|
||||
struct obj *obj, *nextobj;
|
||||
int buc_changed = 0;
|
||||
|
||||
pline("This water's no good!");
|
||||
morehungry(rn1(20, 11));
|
||||
exercise(A_CON, FALSE);
|
||||
/* this is more severe than rndcurse() */
|
||||
for (obj = gi.invent; obj; obj = obj->nobj)
|
||||
for (obj = gi.invent; obj; obj = nextobj) {
|
||||
nextobj = obj->nobj;
|
||||
if (obj->oclass != COIN_CLASS && !obj->cursed && !rn2(5)) {
|
||||
curse(obj);
|
||||
++buc_changed;
|
||||
}
|
||||
}
|
||||
if (buc_changed)
|
||||
update_inventory();
|
||||
break;
|
||||
@@ -498,13 +500,14 @@ dipfountain(struct obj *obj)
|
||||
pline("An urge to take a bath overwhelms you.");
|
||||
{
|
||||
long money = money_cnt(gi.invent);
|
||||
struct obj *otmp;
|
||||
struct obj *otmp, *nextobj;
|
||||
|
||||
if (money > 10) {
|
||||
/* Amount to lose. Might get rounded up as fountains don't
|
||||
* pay change... */
|
||||
money = somegold(money) / 10;
|
||||
for (otmp = gi.invent; otmp && money > 0; otmp = otmp->nobj)
|
||||
for (otmp = gi.invent; otmp && money > 0; otmp = nextobj) {
|
||||
nextobj = otmp->nobj;
|
||||
if (otmp->oclass == COIN_CLASS) {
|
||||
int denomination = objects[otmp->otyp].oc_cost;
|
||||
long coin_loss =
|
||||
@@ -515,6 +518,7 @@ dipfountain(struct obj *obj)
|
||||
if (!otmp->quan)
|
||||
delobj(otmp);
|
||||
}
|
||||
}
|
||||
You("lost some of your gold in the fountain!");
|
||||
CLEAR_FOUNTAIN_LOOTED(u.ux, u.uy);
|
||||
exercise(A_WIS, FALSE);
|
||||
|
||||
Reference in New Issue
Block a user