Skip to content

Commit

Permalink
fix #332 - strangulation affects headless monsters (trunk only)
Browse files Browse the repository at this point in the history
     From a bug report:  amulet of strangulation
continues to kill hero if he polymorphs into a creature which doesn't
need to breathe or doesn't have a head or even a circulatory system.
Currently, the messages are different when the hero doesn't need to
breathe, but that doesn't seem good enough.  This makes strangulation
stop when you polymorph into something which shouldn't be vulnerable and
restart if you poly into something vulnerable while still wearing the
bad amulet.

     can_be_strangled() is doing more checks that necessary, in case the
strangulation property ever gets conferred by something other than an
amulet.  Its criteria for protection from strangling might need tweaking.
  • Loading branch information
nethack.rankin committed May 18, 2007
1 parent 78d9a41 commit 4be4323
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 6 deletions.
1 change: 1 addition & 0 deletions doc/fixes35.0
Expand Up @@ -229,6 +229,7 @@ eliminate case-sensitivity when converting words from singular to plural and
breath attack directed at self by poly'd hero always hits
override non-silver vs shades for artifacts which deal extra damage to undead
assorted mirror fixes--mainly visibility issues
some monsters can't be strangled; self-polymorph can stop/restart strangulation


Platform- and/or Interface-Specific Fixes
Expand Down
1 change: 1 addition & 0 deletions include/extern.h
Expand Up @@ -1329,6 +1329,7 @@ E boolean FDECL(hates_silver, (struct permonst *));
E boolean FDECL(mon_hates_silver, (struct monst *));
E boolean FDECL(passes_bars, (struct permonst *));
E boolean FDECL(can_blow, (struct monst *));
E boolean FDECL(can_be_strangled, (struct monst *));
E boolean FDECL(can_track, (struct permonst *));
E boolean FDECL(breakarm, (struct permonst *));
E boolean FDECL(sliparm, (struct permonst *));
Expand Down
15 changes: 10 additions & 5 deletions src/do_wear.c
@@ -1,4 +1,4 @@
/* SCCS Id: @(#)do_wear.c 3.5 2007/03/19 */
/* SCCS Id: @(#)do_wear.c 3.5 2007/05/16 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */

Expand Down Expand Up @@ -626,9 +626,11 @@ Amulet_on()
break;
}
case AMULET_OF_STRANGULATION:
makeknown(AMULET_OF_STRANGULATION);
pline("It constricts your throat!");
Strangled = 6;
if (can_be_strangled(&youmonst)) {
makeknown(AMULET_OF_STRANGULATION);
pline("It constricts your throat!");
Strangled = 6L;
}
break;
case AMULET_OF_RESTFUL_SLEEP:
HSleeping = rnd(100);
Expand Down Expand Up @@ -671,8 +673,11 @@ Amulet_off()
break;
case AMULET_OF_STRANGULATION:
if (Strangled) {
if (Breathless)
Your("%s is no longer constricted!", body_part(NECK));
else
You("can breathe more easily!");
Strangled = 0;
Strangled = 0L;
}
break;
case AMULET_OF_RESTFUL_SLEEP:
Expand Down
33 changes: 32 additions & 1 deletion src/mondata.c
@@ -1,4 +1,4 @@
/* SCCS Id: @(#)mondata.c 3.5 2007/03/02 */
/* SCCS Id: @(#)mondata.c 3.5 2007/05/16 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */

Expand Down Expand Up @@ -299,6 +299,37 @@ register struct monst *mtmp;
return TRUE;
}

boolean
can_be_strangled(mon) /* TRUE if mon is vulnerable to strangulation */
struct monst *mon;
{
struct obj *mamul;
boolean nonbreathing, nobrainer;

/* For amulet of strangulation support: here we're considering
strangulation to be loss of blood flow to the brain due to
constriction of the arteries in the neck, so all headless
creatures are immune (no neck) as are mindless creatures
who don't need to breathe (brain, if any, doesn't care).
Mindless creatures who do need to breath are vulnerable, as
are non-breathing creatures which have higher brain function. */
if (!has_head(mon->data)) return FALSE;
if (mon == &youmonst) {
/* hero can't be mindless but poly'ing into mindless form can
confer strangulation protection */
nobrainer = mindless(youmonst.data);
nonbreathing = Breathless;
} else {
nobrainer = mindless(mon->data);
/* monsters don't wear amulets of magical breathing,
so second part doesn't achieve anything useful... */
nonbreathing = (breathless(mon->data) ||
((mamul = which_armor(mon, W_AMUL)) != 0 &&
(mamul->otyp == AMULET_OF_MAGICAL_BREATHING)));
}
return (boolean)(!nobrainer || !nonbreathing);
}

boolean
can_track(ptr) /* returns TRUE if monster can track well */
register struct permonst *ptr;
Expand Down
28 changes: 28 additions & 0 deletions src/polyself.c
Expand Up @@ -21,6 +21,7 @@

#include "hack.h"

STATIC_DCL void FDECL(check_strangling, (BOOLEAN_P));
STATIC_DCL void FDECL(polyman, (const char *,const char *));
STATIC_DCL void NDECL(break_armor);
STATIC_DCL void FDECL(drop_weapon,(int));
Expand All @@ -46,6 +47,30 @@ set_uasmon()
#endif
}

/* for changing into form that's immune to strangulation */
STATIC_OVL void
check_strangling(on)
boolean on;
{
if (on) { /* on -- maybe resume strangling */
/* when Strangled is already set, polymorphing from one
vulnerable form into another causes the counter to be reset */
if (uamul && uamul->otyp == AMULET_OF_STRANGULATION &&
can_be_strangled(&youmonst)) {
Your("%s %s your %s!", simpleonames(uamul),
Strangled ? "still constricts" : "begins constricting",
body_part(NECK)); /* "throat" */
Strangled = 6L;
makeknown(AMULET_OF_STRANGULATION);
}
} else { /* off -- maybe block strangling */
if (Strangled && !can_be_strangled(&youmonst)) {
Strangled = 0L;
You("are no longer being strangled.");
}
}
}

/* make a (new) human out of the player */
STATIC_OVL void
polyman(fmt, arg)
Expand Down Expand Up @@ -109,6 +134,7 @@ const char *fmt, *arg;
Blinded = 1L;
make_blinded(0L, TRUE); /* remove blindness */
}
check_strangling(TRUE);

if(!Levitation && !u.ustuck &&
(is_pool(u.ux,u.uy) || is_lava(u.ux,u.uy)))
Expand Down Expand Up @@ -491,6 +517,7 @@ int mntmp;
make_slimed(0L, (char*) 0);
}
}
check_strangling(FALSE); /* maybe stop strangling */
if (nohands(youmonst.data)) Glib = 0;

/*
Expand Down Expand Up @@ -631,6 +658,7 @@ int mntmp;
You("orient yourself on the web.");
u.utrap = 0;
}
check_strangling(TRUE); /* maybe start strangling */
(void) polysense(youmonst.data);

context.botl = 1;
Expand Down
6 changes: 6 additions & 0 deletions src/timeout.c
Expand Up @@ -354,6 +354,12 @@ nh_timeout()
Strcpy(killer.name,
(u.uburied) ? "suffocation" : "strangulation");
done(DIED);
/* must be declining to die in explore|wizard mode;
treat like being cured of strangulation by prayer */
if (uamul && uamul->otyp == AMULET_OF_STRANGULATION) {
Your("amulet vanishes!");
useup(uamul);
}
break;
case FUMBLING:
/* call this only when a move took place. */
Expand Down

0 comments on commit 4be4323

Please sign in to comment.