diff --git a/doc/fixes35.0 b/doc/fixes35.0 index d7ad63329..2e49b4fba 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -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 diff --git a/include/extern.h b/include/extern.h index 1b75c11a1..d15118c6d 100644 --- a/include/extern.h +++ b/include/extern.h @@ -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 *)); diff --git a/src/do_wear.c b/src/do_wear.c index 9044f7930..8ce78939b 100644 --- a/src/do_wear.c +++ b/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. */ @@ -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); @@ -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: diff --git a/src/mondata.c b/src/mondata.c index f3e319fea..cd8010b5d 100644 --- a/src/mondata.c +++ b/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. */ @@ -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; diff --git a/src/polyself.c b/src/polyself.c index fe7989023..20d1ff147 100644 --- a/src/polyself.c +++ b/src/polyself.c @@ -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)); @@ -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) @@ -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))) @@ -491,6 +517,7 @@ int mntmp; make_slimed(0L, (char*) 0); } } + check_strangling(FALSE); /* maybe stop strangling */ if (nohands(youmonst.data)) Glib = 0; /* @@ -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; diff --git a/src/timeout.c b/src/timeout.c index a3898ce4b..b0f7793bc 100644 --- a/src/timeout.c +++ b/src/timeout.c @@ -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. */