Purple worm changes

Shriekers only spawn purple worms when they're appropriate difficulty.
Non-tame Purple worms eat corpses off the ground.
Baby purple worms attack shriekers.
Hero polyed into baby purple worm is warned against shriekers.

Original changes by copperwater <aosdict@gmail.com>, added with some
formatting adjustments and consolidation.
This commit is contained in:
Pasi Kallinen
2020-04-05 12:43:54 +03:00
parent 8119c52d84
commit cf1c725148
6 changed files with 87 additions and 4 deletions

View File

@@ -103,6 +103,10 @@ for farlook, describe water in the castle moat and in Juiblex's swamp as moat
make hezrous emit poison clouds when they move
stepping from one type of terrain to another was triggering an unnecessary
status update
make shriekers summon baby purple worms if purple worms would be too tough
make non-tame (baby) purple worms eat corpses off the ground
make baby purple worms attack shriekers
make hero polymorphed into baby purple worm warned against shriekers
Fixes to 3.7.0-x Problems that Were Exposed Via git Repository

View File

@@ -1458,6 +1458,7 @@ E int FDECL(minliquid, (struct monst *));
E int NDECL(movemon);
E int FDECL(meatmetal, (struct monst *));
E int FDECL(meatobj, (struct monst *));
E int FDECL(meatcorpse, (struct monst *));
E void FDECL(mpickgold, (struct monst *));
E boolean FDECL(mpickstuff, (struct monst *, const char *));
E int FDECL(curr_mon_load, (struct monst *));

View File

@@ -205,6 +205,7 @@ struct monst {
given the current level difficulty and the hero's level. */
#define monmax_difficulty(levdif) (((levdif) + u.ulevel) / 2)
#define monmin_difficulty(levdif) ((levdif) / 6)
#define monmax_difficulty_lev() (monmax_difficulty(level_difficulty()))
/* Macros for whether a type of monster is too strong for a specific level. */
#define montoostrong(monindx, lev) (mons[monindx].difficulty > lev)

View File

@@ -1143,6 +1143,69 @@ struct monst *mtmp;
return (count > 0 || ecount > 0) ? 1 : 0;
}
/* Monster eats a corpse off the ground.
* Return value is 0 = nothing eaten, 1 = ate a corpse, 2 = died */
int
meatcorpse(mtmp) /* for purple worms and other voracious monsters */
struct monst* mtmp;
{
struct obj *otmp;
struct permonst *ptr, *original_ptr = mtmp->data, *corpsepm;
boolean poly, grow, heal, eyes = FALSE;
int x = mtmp->mx, y = mtmp->my;
/* if a pet, eating is handled separately, in dog.c */
if (mtmp->mtame)
return 0;
for (otmp = g.level.objects[x][y]; otmp; otmp = otmp->nexthere) {
if (otmp->otyp != CORPSE)
continue;
corpsepm = &mons[otmp->corpsenm];
if (is_rider(corpsepm)) {
revive_corpse(otmp);
continue;
}
/* don't eat harmful corpses */
if (touch_petrifies(corpsepm) && !resists_ston(mtmp))
continue;
if (cansee(x, y) && canseemon(mtmp)) {
if (flags.verbose)
pline("%s eats %s!", Monnam(mtmp), distant_name(otmp, doname));
} else if (flags.verbose)
You_hear("a masticating sound.");
poly = polyfodder(otmp);
grow = mlevelgain(otmp);
heal = mhealup(otmp);
eyes = (otmp->otyp == CARROT);
delobj(otmp);
if (poly) {
if (newcham(mtmp, NULL, FALSE, FALSE))
ptr = mtmp->data;
} else if (grow) {
ptr = grow_up(mtmp, (struct monst *) 0);
} else if (heal) {
mtmp->mhp = mtmp->mhpmax;
}
if ((eyes || heal) && !mtmp->mcansee)
mcureblindness(mtmp, canseemon(mtmp));
/* in case it polymorphed or died */
if (ptr != original_ptr)
return !ptr ? 2 : 1;
/* Engulf & devour is instant, so don't set meating */
if (mtmp->minvis)
newsym(x, y);
return 1;
}
return 0;
}
void
mpickgold(mtmp)
register struct monst *mtmp;
@@ -1602,9 +1665,11 @@ mm_aggression(magr, mdef)
struct monst *magr, /* monster that is currently deciding where to move */
*mdef; /* another monster which is next to it */
{
int mndx = monsndx(magr->data);
/* supposedly purple worms are attracted to shrieking because they
like to eat shriekers, so attack the latter when feasible */
if (magr->data == &mons[PM_PURPLE_WORM]
if ((mndx == PM_PURPLE_WORM || mndx == PM_BABY_PURPLE_WORM)
&& mdef->data == &mons[PM_SHRIEKER])
return ALLOW_M | ALLOW_TM;
/* Various other combinations such as dog vs cat, cat vs rat, and
@@ -2930,9 +2995,13 @@ struct monst *mtmp;
stop_occupation();
}
if (!rn2(10)) {
if (!rn2(13))
(void) makemon(&mons[PM_PURPLE_WORM], 0, 0, NO_MM_FLAGS);
else
if (!rn2(13)) {
/* don't generate purple worms if they would be too difficult */
int pm = montoostrong(PM_PURPLE_WORM, monmax_difficulty_lev())
? PM_BABY_PURPLE_WORM : PM_PURPLE_WORM;
(void) makemon(&mons[pm], 0, 0, NO_MM_FLAGS);
} else
(void) makemon((struct permonst *) 0, 0, 0, NO_MM_FLAGS);
}
aggravate();

View File

@@ -1534,6 +1534,13 @@ register int after;
return 2; /* it died */
}
/* Maybe a purple worm ate a corpse */
if (ptr == &mons[PM_PURPLE_WORM]
|| ptr == &mons[PM_BABY_PURPLE_WORM]) {
if (meatcorpse(mtmp) == 2)
return 2; /* it died */
}
if (!*in_rooms(mtmp->mx, mtmp->my, SHOPBASE) || !rn2(25)) {
boolean picked = FALSE;

View File

@@ -1908,6 +1908,7 @@ polysense()
switch (u.umonnum) {
case PM_PURPLE_WORM:
case PM_BABY_PURPLE_WORM:
warnidx = PM_SHRIEKER;
break;
case PM_VAMPIRE: