pull request #1175 - obj->corpsenm fixes
Pull request by mkuoppal: some objects which use the corpsenm field to access the mons[] array can have a corpsenm value of NON_PM (-1) and weren't avoiding array access in those cases. In addition to a fixes entry for it, this makes some revisions to the commited code, handling a few of the cases differently. Closes #1175
This commit is contained in:
@@ -1348,6 +1348,7 @@ if polymorphing a potion turned it into oil, dipping potions produced oil
|
|||||||
into non-oil kept its relative age (no noticeable effect though)
|
into non-oil kept its relative age (no noticeable effect though)
|
||||||
an engulfer capable of passing through iron bars could do so even when hero
|
an engulfer capable of passing through iron bars could do so even when hero
|
||||||
was engulfed
|
was engulfed
|
||||||
|
some uses of mons[obj->corpsenm] weren't excluding obj->corpsenm==NON_PM (-1)
|
||||||
|
|
||||||
|
|
||||||
Fixes to 3.7.0-x General Problems Exposed Via git Repository
|
Fixes to 3.7.0-x General Problems Exposed Via git Repository
|
||||||
|
|||||||
@@ -199,6 +199,8 @@
|
|||||||
|
|
||||||
#define touch_petrifies(ptr) \
|
#define touch_petrifies(ptr) \
|
||||||
((ptr) == &mons[PM_COCKATRICE] || (ptr) == &mons[PM_CHICKATRICE])
|
((ptr) == &mons[PM_COCKATRICE] || (ptr) == &mons[PM_CHICKATRICE])
|
||||||
|
/* Medusa doesn't pass touch_petrifies() but does petrify if eaten */
|
||||||
|
#define flesh_petrifies(pm) (touch_petrifies(pm) || (pm) == &mons[PM_MEDUSA])
|
||||||
|
|
||||||
/* missiles made of rocks don't harm these: xorns and earth elementals
|
/* missiles made of rocks don't harm these: xorns and earth elementals
|
||||||
(but not ghosts and shades because that would impact all missile use
|
(but not ghosts and shades because that would impact all missile use
|
||||||
|
|||||||
@@ -929,17 +929,16 @@ dogfood(struct monst *mon, struct obj *obj)
|
|||||||
switch (obj->oclass) {
|
switch (obj->oclass) {
|
||||||
case FOOD_CLASS:
|
case FOOD_CLASS:
|
||||||
fx = (obj->otyp == CORPSE || obj->otyp == TIN || obj->otyp == EGG)
|
fx = (obj->otyp == CORPSE || obj->otyp == TIN || obj->otyp == EGG)
|
||||||
|
/* corpsenm might be NON_PM (special tin, unhatachable egg) */
|
||||||
? obj->corpsenm
|
? obj->corpsenm
|
||||||
: NUMMONS; /* valid mons[mndx] to pacify static analyzer */
|
: NON_PM;
|
||||||
|
/* mons[NUMMONS] is valid; predicate tests against it will fail */
|
||||||
fptr = fx >= LOW_PM ? &mons[fx] : NULL;
|
fptr = &mons[(fx >= LOW_PM) ? fx : NUMMONS];
|
||||||
|
|
||||||
if (obj->otyp == CORPSE && is_rider(fptr))
|
if (obj->otyp == CORPSE && is_rider(fptr))
|
||||||
return TABU;
|
return TABU;
|
||||||
if ((obj->otyp == CORPSE || obj->otyp == EGG)
|
if ((obj->otyp == CORPSE || obj->otyp == EGG)
|
||||||
/* Medusa's corpse doesn't pass the touch_petrifies() test
|
&& flesh_petrifies(fptr) /* c*ckatrice or Medusa */
|
||||||
but does cause petrification if eaten */
|
|
||||||
&& ((fptr && touch_petrifies(fptr)) || obj->corpsenm == PM_MEDUSA)
|
|
||||||
&& !resists_ston(mon))
|
&& !resists_ston(mon))
|
||||||
return POISON;
|
return POISON;
|
||||||
if (obj->otyp == LUMP_OF_ROYAL_JELLY
|
if (obj->otyp == LUMP_OF_ROYAL_JELLY
|
||||||
|
|||||||
@@ -48,9 +48,6 @@ static int tin_ok(struct obj *);
|
|||||||
/* also used to see if you're allowed to eat cats and dogs */
|
/* also used to see if you're allowed to eat cats and dogs */
|
||||||
#define CANNIBAL_ALLOWED() (Role_if(PM_CAVE_DWELLER) || Race_if(PM_ORC))
|
#define CANNIBAL_ALLOWED() (Role_if(PM_CAVE_DWELLER) || Race_if(PM_ORC))
|
||||||
|
|
||||||
/* monster types that cause hero to be turned into stone if eaten */
|
|
||||||
#define flesh_petrifies(pm) (touch_petrifies(pm) || (pm) == &mons[PM_MEDUSA])
|
|
||||||
|
|
||||||
/* Rider corpses are treated as non-rotting so that attempting to eat one
|
/* Rider corpses are treated as non-rotting so that attempting to eat one
|
||||||
will be sure to reach the stage of eating where that meal is fatal;
|
will be sure to reach the stage of eating where that meal is fatal;
|
||||||
acid blob corpses eventually rot away to nothing but before that happens
|
acid blob corpses eventually rot away to nothing but before that happens
|
||||||
@@ -58,7 +55,7 @@ static int tin_ok(struct obj *);
|
|||||||
become rotten */
|
become rotten */
|
||||||
#define nonrotting_corpse(mnum) \
|
#define nonrotting_corpse(mnum) \
|
||||||
((mnum) == PM_LIZARD || (mnum) == PM_LICHEN \
|
((mnum) == PM_LIZARD || (mnum) == PM_LICHEN \
|
||||||
|| ((mnum) >= LOW_PM && is_rider(&mons[mnum])) \
|
|| is_rider(&mons[mnum]) \
|
||||||
|| (mnum) == PM_ACID_BLOB)
|
|| (mnum) == PM_ACID_BLOB)
|
||||||
|
|
||||||
/* non-rotting non-corpses; unlike lizard corpses, these items will behave
|
/* non-rotting non-corpses; unlike lizard corpses, these items will behave
|
||||||
@@ -1415,12 +1412,12 @@ tin_details(struct obj *obj, int mnum, char *buf)
|
|||||||
void
|
void
|
||||||
set_tin_variety(struct obj *obj, int forcetype)
|
set_tin_variety(struct obj *obj, int forcetype)
|
||||||
{
|
{
|
||||||
register int r;
|
int r, mnum = obj->corpsenm;
|
||||||
|
|
||||||
if (forcetype == SPINACH_TIN
|
if (forcetype == SPINACH_TIN
|
||||||
|| (forcetype == HEALTHY_TIN
|
|| (forcetype == HEALTHY_TIN
|
||||||
&& (obj->corpsenm == NON_PM /* empty or already spinach */
|
&& (mnum == NON_PM /* empty or already spinach */
|
||||||
|| !vegetarian(&mons[obj->corpsenm])))) { /* replace meat */
|
|| !vegetarian(&mons[mnum])))) { /* replace meat */
|
||||||
obj->corpsenm = NON_PM; /* not based on any monster */
|
obj->corpsenm = NON_PM; /* not based on any monster */
|
||||||
obj->spe = 1; /* spinach */
|
obj->spe = 1; /* spinach */
|
||||||
return;
|
return;
|
||||||
@@ -1434,17 +1431,18 @@ set_tin_variety(struct obj *obj, int forcetype)
|
|||||||
r = forcetype;
|
r = forcetype;
|
||||||
} else { /* RANDOM_TIN */
|
} else { /* RANDOM_TIN */
|
||||||
r = rn2(TTSZ - 1); /* take your pick */
|
r = rn2(TTSZ - 1); /* take your pick */
|
||||||
if (r == ROTTEN_TIN && nonrotting_corpse(obj->corpsenm))
|
if (r == ROTTEN_TIN && (mnum >= LOW_PM && nonrotting_corpse(mnum)))
|
||||||
r = HOMEMADE_TIN; /* lizards don't rot */
|
r = HOMEMADE_TIN; /* lizards don't rot */
|
||||||
}
|
}
|
||||||
obj->spe = -(r + 1); /* offset by 1 to allow index 0 */
|
obj->spe = -(r + 1); /* offset by 1 to allow index 0 */
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
tin_variety(struct obj *obj,
|
tin_variety(
|
||||||
boolean displ) /* we're just displaying so leave things alone */
|
struct obj *obj,
|
||||||
|
boolean displ) /* we're just displaying so leave things alone */
|
||||||
{
|
{
|
||||||
register int r;
|
int r, mnum = obj->corpsenm;
|
||||||
|
|
||||||
if (obj->spe == 1) {
|
if (obj->spe == 1) {
|
||||||
r = SPINACH_TIN;
|
r = SPINACH_TIN;
|
||||||
@@ -1453,13 +1451,14 @@ tin_variety(struct obj *obj,
|
|||||||
} else if (obj->spe < 0) {
|
} else if (obj->spe < 0) {
|
||||||
r = -(obj->spe);
|
r = -(obj->spe);
|
||||||
--r; /* get rid of the offset */
|
--r; /* get rid of the offset */
|
||||||
} else
|
} else {
|
||||||
r = rn2(TTSZ - 1);
|
r = rn2(TTSZ - 1);
|
||||||
|
}
|
||||||
|
|
||||||
if (!displ && r == HOMEMADE_TIN && !obj->blessed && !rn2(7))
|
if (!displ && r == HOMEMADE_TIN && !obj->blessed && !rn2(7))
|
||||||
r = ROTTEN_TIN; /* some homemade tins go bad */
|
r = ROTTEN_TIN; /* some homemade tins go bad */
|
||||||
|
|
||||||
if (r == ROTTEN_TIN && nonrotting_corpse(obj->corpsenm))
|
if (r == ROTTEN_TIN && (mnum >= LOW_PM && nonrotting_corpse(mnum)))
|
||||||
r = HOMEMADE_TIN; /* lizards don't rot */
|
r = HOMEMADE_TIN; /* lizards don't rot */
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@@ -1762,12 +1761,15 @@ eatcorpse(struct obj *otmp)
|
|||||||
int retcode = 0, tp = 0, mnum = otmp->corpsenm;
|
int retcode = 0, tp = 0, mnum = otmp->corpsenm;
|
||||||
long rotted = 0L;
|
long rotted = 0L;
|
||||||
int ll_conduct = 0;
|
int ll_conduct = 0;
|
||||||
boolean stoneable = (flesh_petrifies(&mons[mnum]) && !Stone_resistance
|
boolean stoneable,
|
||||||
&& !poly_when_stoned(gy.youmonst.data)),
|
|
||||||
slimeable = (mnum == PM_GREEN_SLIME && !Slimed && !Unchanging
|
slimeable = (mnum == PM_GREEN_SLIME && !Slimed && !Unchanging
|
||||||
&& !slimeproof(gy.youmonst.data)),
|
&& !slimeproof(gy.youmonst.data)),
|
||||||
glob = otmp->globby ? TRUE : FALSE;
|
glob = otmp->globby ? TRUE : FALSE;
|
||||||
|
|
||||||
|
assert(mnum >= LOW_PM);
|
||||||
|
stoneable = (flesh_petrifies(&mons[mnum]) && !Stone_resistance
|
||||||
|
&& !poly_when_stoned(gy.youmonst.data));
|
||||||
|
|
||||||
/* KMH, conduct */
|
/* KMH, conduct */
|
||||||
if (!vegan(&mons[mnum]))
|
if (!vegan(&mons[mnum]))
|
||||||
if (!u.uconduct.unvegan++) {
|
if (!u.uconduct.unvegan++) {
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ static void sanity_check_single_mon(struct monst *, boolean, const char *);
|
|||||||
static struct obj *make_corpse(struct monst *, unsigned);
|
static struct obj *make_corpse(struct monst *, unsigned);
|
||||||
static int minliquid_core(struct monst *);
|
static int minliquid_core(struct monst *);
|
||||||
static void m_calcdistress(struct monst *);
|
static void m_calcdistress(struct monst *);
|
||||||
static boolean mstoning(const struct obj *obj);
|
|
||||||
static boolean monlineu(struct monst *, int, int);
|
static boolean monlineu(struct monst *, int, int);
|
||||||
static long mm_2way_aggression(struct monst *, struct monst *);
|
static long mm_2way_aggression(struct monst *, struct monst *);
|
||||||
static long mm_aggression(struct monst *, struct monst *);
|
static long mm_aggression(struct monst *, struct monst *);
|
||||||
@@ -1157,24 +1156,13 @@ meatbox(struct monst *mon, struct obj *otmp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean
|
#define mstoning(obj) \
|
||||||
mstoning(const struct obj *obj)
|
(ofood(obj) && obj->corpsenm >= LOW_PM \
|
||||||
{
|
&& flesh_petrifies(&mons[obj->corpsenm]))
|
||||||
const int nm = obj->corpsenm;
|
|
||||||
|
|
||||||
if (nm < LOW_PM)
|
/* Monster mtmp consumes an object.
|
||||||
return FALSE;
|
Monster may die, polymorph, grow up, heal, etc; meating is not changed.
|
||||||
|
Object is extracted from any linked list and freed. */
|
||||||
if (nm == PM_MEDUSA)
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
return ofood(obj) && touch_petrifies(&mons[nm]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* monster consumes an object.
|
|
||||||
|
|
||||||
monster may die, polymorph, grow up, heal, etc; meating is not changed.
|
|
||||||
object is extracted from any linked list and freed. */
|
|
||||||
void
|
void
|
||||||
m_consume_obj(struct monst *mtmp, struct obj *otmp)
|
m_consume_obj(struct monst *mtmp, struct obj *otmp)
|
||||||
{
|
{
|
||||||
@@ -1429,8 +1417,10 @@ meatobj(struct monst* mtmp) /* for gelatinous cubes */
|
|||||||
return (count > 0 || ecount > 0) ? 1 : 0;
|
return (count > 0 || ecount > 0) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef mstoning
|
||||||
|
|
||||||
/* Monster eats a corpse off the ground.
|
/* Monster eats a corpse off the ground.
|
||||||
* Return value is 0 = nothing eaten, 1 = ate a corpse, 2 = died */
|
Return value is 0 = nothing eaten, 1 = ate a corpse, 2 = died. */
|
||||||
int
|
int
|
||||||
meatcorpse(
|
meatcorpse(
|
||||||
struct monst *mtmp) /* for purple worms and other voracious monsters */
|
struct monst *mtmp) /* for purple worms and other voracious monsters */
|
||||||
|
|||||||
Reference in New Issue
Block a user