github issue #1299 - sleeping mimics

Issue reported by elunna:  sleeping mimics can grab the hero, and
zapping a concealed mimic with a wand of sleep describes the target
as a mimic but doesn't bring it out of concealment.

The grab-when-asleep case is reasonable.  It's a reflexive counter-
attack by a magical creature.  And the mimic wakes up in the process.
But the mimic wasn't being brought out of concealment.  Do that.

Unconceal mimics hit by wand of sleep unless already sleeping.

Fixes #1299
This commit is contained in:
PatR
2024-11-29 23:30:04 -08:00
parent 689f6c4c82
commit 149cb96020
5 changed files with 77 additions and 26 deletions

View File

@@ -1,4 +1,4 @@
/* NetHack 3.7 zap.c $NHDT-Date: 1723946858 2024/08/18 02:07:38 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.542 $ */
/* NetHack 3.7 zap.c $NHDT-Date: 1732979463 2024/11/30 07:11:03 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.551 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2013. */
/* NetHack may be freely redistributed. See license for details. */
@@ -148,7 +148,11 @@ learnwand(struct obj *obj)
}
}
/* Routines for IMMEDIATE wands and spells. */
/*
* Routines for IMMEDIATE wands and spells.
* Also RAY or NODIR for wands that are being broken rather than zapped.
*/
/* bhitm: monster mtmp was hit by the effect of wand or spell otmp */
int
bhitm(struct monst *mtmp, struct obj *otmp)
@@ -350,6 +354,10 @@ bhitm(struct monst *mtmp, struct obj *otmp)
}
case WAN_LOCKING:
case SPE_WIZARD_LOCK:
/* can't use Is_box() here */
if (disguised_mimic && (is_obj_mappear(mtmp, CHEST)
|| is_obj_mappear(mtmp, LARGE_BOX)))
seemimic(mtmp);
wake = closeholdingtrap(mtmp, &learn_it);
break;
case WAN_PROBING:
@@ -360,6 +368,9 @@ bhitm(struct monst *mtmp, struct obj *otmp)
break;
case WAN_OPENING:
case SPE_KNOCK:
if (disguised_mimic && (is_obj_mappear(mtmp, CHEST)
|| is_obj_mappear(mtmp, LARGE_BOX)))
seemimic(mtmp);
wake = FALSE; /* don't want immediate counterattack */
if (mtmp == u.ustuck) {
/* zapping either holder/holdee or self [zapyourself()] will
@@ -450,7 +461,8 @@ bhitm(struct monst *mtmp, struct obj *otmp)
break;
case WAN_SLEEP: /* (broken wand) */
/* [wakeup() doesn't rouse victims of temporary sleep,
so it's okay to leave `wake' set to TRUE here] */
so it's okay to leave `wake' set to TRUE here;
revealing concealed mimic is handled by sleep_monst()] */
reveal_invis = TRUE;
if (sleep_monst(mtmp, d(1 + otmp->spe, 12), WAND_CLASS))
slept_monst(mtmp);
@@ -458,6 +470,8 @@ bhitm(struct monst *mtmp, struct obj *otmp)
learn_it = TRUE;
break;
case SPE_STONE_TO_FLESH:
/* FIXME: mimics disguished as stone furniture or stone object
should be taken out of concealment. */
if (monsndx(mtmp->data) == PM_STONE_GOLEM) {
char *name = Monnam(mtmp);
@@ -3491,7 +3505,8 @@ exclam(int force)
}
void
hit(const char *str, /* zap text or missile name */
hit(
const char *str, /* zap text or missile name */
struct monst *mtmp, /* target; for missile, might be hero */
const char *force) /* usually either "." or "!" via exclam() */
{
@@ -3500,11 +3515,8 @@ hit(const char *str, /* zap text or missile name */
&& (cansee(gb.bhitpos.x, gb.bhitpos.y)
|| canspotmon(mtmp) || engulfing_u(mtmp))));
if (!verbosely)
pline("%s %s it.", The(str), vtense(str, "hit"));
else
pline("%s %s %s%s", The(str), vtense(str, "hit"),
mon_nam(mtmp), force);
pline("%s %s %s%s", The(str), vtense(str, "hit"),
verbosely ? mon_nam(mtmp) : "it", force);
}
void
@@ -4209,7 +4221,8 @@ zhitm(
tmp += destroy_items(mon, AD_COLD, orig_dmg);
break;
case ZT_SLEEP:
/* possibly resistance and shield effect handled by sleep_monst() */
/* resistance and shield effect and revealing concealed mimic are
handled by sleep_monst() */
tmp = 0;
(void) sleep_monst(mon, d(nd, 25),
type == ZT_WAND(ZT_SLEEP) ? WAND_CLASS : '\0');
@@ -4576,8 +4589,9 @@ burn_floor_objects(
/* will zap/spell/breath attack score a hit against armor class `ac'? */
staticfn int
zap_hit(int ac,
int type) /* either hero cast spell type or 0 */
zap_hit(
int ac,
int type) /* either hero cast spell type or 0 */
{
int chance = rn2(20);
int spell_bonus = type ? spell_hit_bonus(type) : 0;