fix bz130 - muse: sliming and fire horns

There was no check for being capable of using items when an attempt
to cure being turned into green slime picked scroll, wand, or horn
of fire.

Also, implement a 'TODO' in the same section of code.  Monsters
can enter fire traps to cure themselves from slime.  I made that
be for monsters smart enough to use items too, even though there's
no actual item involved.
This commit is contained in:
PatR
2016-03-05 19:57:25 -08:00
parent 83c58f009e
commit d3ac3b3bd6
2 changed files with 88 additions and 21 deletions

View File

@@ -175,6 +175,8 @@ prevent a hostile renegade Angel of <lawful god> from delivering taunt
a few types of monster (barrow wight, Nazgul, erinys) have weapon attacks that
don't deal physical damage, so special damage like stoning via wielded
cockatrice corpse wouldn't be inflicted
non-item-using monsters who happened to be carrying scroll or wand of fire or
a fire horn could use it to cure themselves of being turned into slime
Platform- and/or Interface-Specific Fixes
@@ -239,6 +241,8 @@ when choosing an inventory item and '-' for bare-hands/fingers/no-ammo is a
choice, include that in the inventory menu if player types '?' or '*'
feedback from probing of long worm now includes number of segments it has
monk starts with 'shuriken' pre-discovered (despite language issue...)
item-using monster on or next to a fire trap can use it to be cured of
turning into slime
Platform- and/or Interface-Specific New Features

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 muse.c $NHDT-Date: 1449799863 2015/12/11 02:11:03 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.69 $ */
/* NetHack 3.6 muse.c $NHDT-Date: 1457236628 2016/03/06 03:57:08 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.71 $ */
/* Copyright (C) 1990 by Ken Arromdee */
/* NetHack may be freely redistributed. See license for details. */
@@ -34,7 +34,7 @@ STATIC_DCL boolean FDECL(cures_stoning, (struct monst *, struct obj *,
BOOLEAN_P));
STATIC_DCL boolean FDECL(mcould_eat_tin, (struct monst *));
STATIC_DCL boolean FDECL(muse_unslime, (struct monst *, struct obj *,
BOOLEAN_P));
struct trap *, BOOLEAN_P));
STATIC_DCL int FDECL(cures_sliming, (struct monst *, struct obj *));
STATIC_DCL boolean FDECL(green_mon, (struct monst *));
@@ -605,7 +605,7 @@ struct monst *mtmp;
int i, fleetim, how = 0;
struct obj *otmp = m.defensive;
boolean vis, vismon, oseen;
const char *mcsa = "%s can see again.";
const char *Mnam, *mcsa = "%s can see again.";
if ((i = precheck(mtmp, otmp)) != 0)
return i;
@@ -824,9 +824,10 @@ struct monst *mtmp;
if (vis) {
struct trap *t = t_at(trapx, trapy);
pline("%s %s into a %s!", Monnam(mtmp),
makeplural(locomotion(mtmp->data, "jump")),
t->ttyp == TRAPDOOR ? "trap door" : "hole");
Mnam = Monnam(mtmp);
pline("%s %s into a %s!", Mnam,
vtense(Mnam, locomotion(mtmp->data, "jump")),
(t->ttyp == TRAPDOOR) ? "trap door" : "hole");
if (levl[trapx][trapy].typ == SCORR) {
levl[trapx][trapy].typ = CORR;
unblock_point(trapx, trapy);
@@ -920,8 +921,9 @@ struct monst *mtmp;
case MUSE_TELEPORT_TRAP:
m_flee(mtmp);
if (vis) {
pline("%s %s onto a teleport trap!", Monnam(mtmp),
makeplural(locomotion(mtmp->data, "jump")));
Mnam = Monnam(mtmp);
pline("%s %s onto a teleport trap!", Mnam,
vtense(Mnam, locomotion(mtmp->data, "jump")));
seetrap(t_at(trapx, trapy));
}
/* don't use rloc_to() because worm tails must "move" */
@@ -1862,9 +1864,12 @@ struct monst *mtmp;
m_useup(mtmp, otmp);
return 2;
case MUSE_POLY_TRAP:
if (vismon)
pline("%s deliberately %s onto a polymorph trap!", Monnam(mtmp),
makeplural(locomotion(mtmp->data, "jump")));
if (vismon) {
const char *Mnam = Monnam(mtmp);
pline("%s deliberately %s onto a polymorph trap!", Mnam,
vtense(Mnam, locomotion(mtmp->data, "jump")));
}
if (vis)
seetrap(t_at(trapx, trapy));
@@ -2322,6 +2327,7 @@ struct monst *mon;
boolean by_you;
{
struct obj *obj, odummy;
struct permonst *mptr = mon->data;
/*
* muse_unslime() gives "mon starts turning green", "mon zaps
@@ -2330,7 +2336,7 @@ boolean by_you;
* (via our caller) newcham()'s "mon turns into slime" feedback.
*/
if (slimeproof(mon->data))
if (slimeproof(mptr))
return FALSE;
if (mon->meating || !mon->mcanmove || mon->msleeping)
return FALSE;
@@ -2342,27 +2348,61 @@ boolean by_you;
[possible extension: monst capable of casting high level clerical
spells could toss pillar of fire at self--probably too suicidal] */
if (!mon->mcan && !mon->mspec_used
&& attacktype_fordmg(mon->data, AT_BREA, AD_FIRE)) {
&& attacktype_fordmg(mptr, AT_BREA, AD_FIRE)) {
odummy = zeroobj; /* otyp == STRANGE_OBJECT */
return muse_unslime(mon, &odummy, by_you);
return muse_unslime(mon, &odummy, (struct trap *) 0, by_you);
}
for (obj = mon->minvent; obj; obj = obj->nobj)
if (cures_sliming(mon, obj))
return muse_unslime(mon, obj, by_you);
/* same MUSE criteria as use_defensive() */
if (!is_animal(mptr) && !mindless(mptr)) {
struct trap *t;
/* TODO: check for and move onto an adjacent fire trap */
for (obj = mon->minvent; obj; obj = obj->nobj)
if (cures_sliming(mon, obj))
return muse_unslime(mon, obj, (struct trap *) 0, by_you);
if (((t = t_at(mon->mx, mon->my)) == 0 || t->ttyp != FIRE_TRAP)
&& !mon->mtrapped && !mptr->mmove == 0) {
int xy[2][8], x, y, idx, ridx, nxy = 0;
for (x = mon->mx - 1; x <= mon->mx + 1; ++x)
for (y = mon->my - 1; y <= mon->my + 1; ++y)
if (isok(x, y) && accessible(x, y)
&& !m_at(x, y) && (x != u.ux || y != u.uy)) {
xy[0][nxy] = x, xy[1][nxy] = y;
++nxy;
}
for (idx = 0; idx < nxy; ++idx) {
ridx = rn1(nxy - idx, idx);
if (ridx != idx) {
x = xy[0][idx];
xy[0][idx] = xy[0][ridx];
xy[0][ridx] = x;
y = xy[1][idx];
xy[1][idx] = xy[1][ridx];
xy[1][ridx] = y;
}
if ((t = t_at(xy[0][idx], xy[1][idx])) != 0
&& t->ttyp == FIRE_TRAP)
break;
}
}
if (t && t->ttyp == FIRE_TRAP)
return muse_unslime(mon, &zeroobj, t, by_you);
} /* MUSE */
return FALSE;
}
/* mon uses an item--selected by caller--to burn away incipient slime */
STATIC_OVL boolean
muse_unslime(mon, obj, by_you)
muse_unslime(mon, obj, trap, by_you)
struct monst *mon;
struct obj *obj;
struct trap *trap;
boolean by_you; /* true: if mon kills itself, hero gets credit/blame */
{
{ /* [by_you not honored if 'mon' triggers fire trap]. */
struct obj *odummyp;
int otyp = obj->otyp, dmg;
boolean vis = canseemon(mon), res = TRUE;
@@ -2373,7 +2413,30 @@ boolean by_you; /* true: if mon kills itself, hero gets credit/blame */
/* -4 => sliming, causes quiet loss of enhanced speed */
mon_adjust_speed(mon, -4, (struct obj *) 0);
if (otyp == STRANGE_OBJECT) {
if (trap) {
const char *Mnam = vis ? Monnam(mon) : 0;
if (mon->mx == trap->tx && mon->my == trap->ty) {
if (vis)
pline("%s triggers %s fire trap!", Mnam,
trap->tseen ? "the" : "a");
} else {
remove_monster(mon->mx, mon->my);
newsym(mon->mx, mon->my);
place_monster(mon, trap->tx, trap->ty);
if (mon->wormno) /* won't happen; worms don't MUSE to unslime */
worm_move(mon);
newsym(mon->mx, mon->my);
if (vis)
pline("%s %s %s %s fire trap!", Mnam,
vtense(Mnam, locomotion(mon->data, "move")),
is_floater(mon->data) ? "over" : "onto",
trap->tseen ? "the" : "a");
}
/* hack to avoid mintrap()'s chance of avoiding known trap */
mon->mtrapseen &= ~(1 << (FIRE_TRAP - 1));
mintrap(mon);
} else if (otyp == STRANGE_OBJECT) {
/* monster is using fire breath on self */
if (vis)
pline("%s breathes fire on %sself.", Monnam(mon), mhim(mon));