diff --git a/include/extern.h b/include/extern.h index e2e6740a0..1fc00a2fa 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1154,6 +1154,7 @@ E boolean FDECL(can_track, (struct permonst *)); E boolean FDECL(breakarm, (struct permonst *)); E boolean FDECL(sliparm, (struct permonst *)); E boolean FDECL(sticks, (struct permonst *)); +E int FDECL(num_horns, (struct permonst *)); /* E boolean FDECL(canseemon, (struct monst *)); */ E struct attack *FDECL(dmgtype_fromattack, (struct permonst *,int,int)); E boolean FDECL(dmgtype, (struct permonst *,int)); diff --git a/include/mondata.h b/include/mondata.h index 20d5da88c..6cf6ea9ee 100644 --- a/include/mondata.h +++ b/include/mondata.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)mondata.h 3.4 2001/02/14 */ +/* SCCS Id: @(#)mondata.h 3.4 2003/01/08 */ /* Copyright (c) 1989 Mike Threepoint */ /* NetHack may be freely redistributed. See license for details. */ @@ -45,7 +45,7 @@ #define nolimbs(ptr) (((ptr)->mflags1 & M1_NOLIMBS) == M1_NOLIMBS) #define notake(ptr) (((ptr)->mflags1 & M1_NOTAKE) != 0L) #define has_head(ptr) (((ptr)->mflags1 & M1_NOHEAD) == 0L) -#define has_horns(ptr) ((ptr) == &mons[PM_MINOTAUR]) +#define has_horns(ptr) (num_horns(ptr) > 0) #define is_whirly(ptr) ((ptr)->mlet == S_VORTEX || \ (ptr) == &mons[PM_AIR_ELEMENTAL]) #define is_silent(ptr) ((ptr)->msound == MS_SILENT) diff --git a/src/do_wear.c b/src/do_wear.c index baeed4dcc..df352fc2a 100644 --- a/src/do_wear.c +++ b/src/do_wear.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)do_wear.c 3.4 2002/11/29 */ +/* SCCS Id: @(#)do_wear.c 3.4 2003/01/08 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1202,6 +1202,12 @@ boolean noisy; if (uarmh) { if (noisy) already_wearing(an(c_helmet)); err++; + } else if (Upolyd && has_horns(youmonst.data) && !is_flimsy(otmp)) { + /* (flimsy exception matches polyself handling) */ + if (noisy) + pline_The("%s won't fit over your horn%s.", + c_helmet, plur(num_horns(youmonst.data))); + err++; } else *mask = W_ARMH; } else if (is_shield(otmp)) { diff --git a/src/mondata.c b/src/mondata.c index fd15557a2..887612275 100644 --- a/src/mondata.c +++ b/src/mondata.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)mondata.c 3.4 2002/12/09 */ +/* SCCS Id: @(#)mondata.c 3.4 2003/01/08 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -301,6 +301,26 @@ sticks(ptr) /* creature sticks other creatures it hits */ attacktype(ptr,AT_HUGS))); } +/* number of horns this type of monster has on its head */ +int +num_horns(ptr) +struct permonst *ptr; +{ + switch (monsndx(ptr)) { + case PM_HORNED_DEVIL: /* ? "more than one" */ + case PM_MINOTAUR: + return 2; + case PM_WHITE_UNICORN: + case PM_GRAY_UNICORN: + case PM_BLACK_UNICORN: + case PM_KI_RIN: + return 1; + default: + break; + } + return 0; +} + struct attack * dmgtype_fromattack(ptr, dtyp, atyp) struct permonst *ptr; @@ -365,7 +385,7 @@ monsndx(ptr) /* return an index into the mons array */ /* ought to switch this to use `fmt_ptr' */ panic("monsndx - could not index monster (%lx)", (unsigned long)ptr); - return FALSE; /* will not get here */ + return NON_PM; /* will not get here */ } return(i); diff --git a/src/polyself.c b/src/polyself.c index b591136d0..7b7848f74 100644 --- a/src/polyself.c +++ b/src/polyself.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)polyself.c 3.4 2002/07/11 */ +/* SCCS Id: @(#)polyself.c 3.4 2003/01/08 */ /* Copyright (C) 1987, 1988, 1989 by Ken Arromdee */ /* NetHack may be freely redistributed. See license for details. */ @@ -617,18 +617,20 @@ break_armor() #endif } if (has_horns(youmonst.data)) { - if ((otmp = uarmh) != 0) { - if (is_flimsy(otmp) && !donning(otmp)) { - char yourbuf[BUFSZ]; - /* Future possiblities: This could damage/destroy helmet*/ - Your("horns pierce through %s %s.", shk_your(yourbuf, otmp), - xname(otmp)); - } else { - if (donning(otmp)) cancel_don(); - Your("helmet falls to the %s!", surface(u.ux, u.uy)); - (void) Helmet_off(); - dropx(otmp); - } + if ((otmp = uarmh) != 0) { + if (is_flimsy(otmp) && !donning(otmp)) { + char hornbuf[BUFSZ], yourbuf[BUFSZ]; + + /* Future possiblities: This could damage/destroy helmet */ + Sprintf(hornbuf, "horn%s", plur(num_horns(youmonst.data))); + Your("%s %s through %s %s.", vtense(hornbuf, "pierce"), + shk_your(yourbuf, otmp), xname(otmp)); + } else { + if (donning(otmp)) cancel_don(); + Your("helmet falls to the %s!", surface(u.ux, u.uy)); + (void) Helmet_off(); + dropx(otmp); + } } } if (nohands(youmonst.data) || verysmall(youmonst.data)) { diff --git a/src/worn.c b/src/worn.c index 738088ddd..0720c3d44 100644 --- a/src/worn.c +++ b/src/worn.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)worn.c 3.4 2002/11/07 */ +/* SCCS Id: @(#)worn.c 3.4 2003/01/08 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -436,6 +436,8 @@ boolean racialexception; break; case W_ARMH: if (!is_helmet(obj)) continue; + /* (flimsy exception matches polyself handling) */ + if (has_horns(mon->data) && !is_flimsy(obj)) continue; break; case W_ARMS: if (!is_shield(obj)) continue; @@ -596,6 +598,7 @@ boolean polyspot; register struct obj *otmp; struct permonst *mdat = mon->data; boolean vis = cansee(mon->mx, mon->my); + boolean handless_or_tiny = (nohands(mdat) || verysmall(mdat)); const char *pronoun = mhim(mon), *ppronoun = mhis(mon); @@ -675,7 +678,7 @@ boolean polyspot; } #endif } - if (nohands(mdat) || verysmall(mdat)) { + if (handless_or_tiny) { /* [caller needs to handle weapon checks] */ if ((otmp = which_armor(mon, W_ARMG)) != 0) { if (vis) @@ -693,7 +696,11 @@ boolean polyspot; if (polyspot) bypass_obj(otmp); m_lose_armor(mon, otmp); } - if ((otmp = which_armor(mon, W_ARMH)) != 0) { + } + if (handless_or_tiny || has_horns(mdat)) { + if ((otmp = which_armor(mon, W_ARMH)) != 0 && + /* flimsy test for horns matches polyself handling */ + (handless_or_tiny || !is_flimsy(otmp))) { if (vis) pline("%s helmet falls to the %s!", s_suffix(Monnam(mon)), surface(mon->mx, mon->my)); @@ -703,8 +710,7 @@ boolean polyspot; m_lose_armor(mon, otmp); } } - if (nohands(mdat) || verysmall(mdat) || slithy(mdat) || - mdat->mlet == S_CENTAUR) { + if (handless_or_tiny || slithy(mdat) || mdat->mlet == S_CENTAUR) { if ((otmp = which_armor(mon, W_ARMF)) != 0) { if (vis) { if (is_whirly(mon->data))