]> granicus.if.org Git - nethack/commitdiff
hats vs horns
authornethack.rankin <nethack.rankin>
Thu, 9 Jan 2003 01:20:49 +0000 (01:20 +0000)
committernethack.rankin <nethack.rankin>
Thu, 9 Jan 2003 01:20:49 +0000 (01:20 +0000)
     Some recent newsgroup discussion claiming that a pet ki-rin was
wearing a helmet (I think poster was hallucinating) caused me to look
at some of the hat handling code.  There were a couple of noticeable
problems and one latent one in code added for 3.4.1.  Polymorphing
into a minotaur pushes hard helmets off hero's head, but nothing
prevented you from putting one right back on.  Helmet wearing monsters
who polymorphed into minotaurs weren't affected at all.  And message
handling always assumed multiple horns even though we have some singled
horned monsters, but since all those have no hands they can't wear any
armor and that potential pluralization issue wasn't noticeable.

include/extern.h
include/mondata.h
src/do_wear.c
src/mondata.c
src/polyself.c
src/worn.c

index e2e6740a089bd65a7219e0d69f363776315d386a..1fc00a2fa6c27c6b8e4ee06c5c953fd9cfc7f0fe 100644 (file)
@@ -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));
index 20d5da88c79956d7d0c683cc5c431ea34593e896..6cf6ea9eeaf9415df08e0126e899d7ecb5a38b19 100644 (file)
@@ -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)
index baeed4dcc43a83487bbeba4ca7b59a15b429dd47..df352fc2a965b5bbe52700cc43a57e7dbd8f41d9 100644 (file)
@@ -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)) {
index fd15557a2d49f7537d394842c8bee669368497e1..887612275509be98b4b97121fea4518d4ec6ab24 100644 (file)
@@ -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);
index b591136d00318e791bab78a5d63e3df2ee1bae16..7b7848f74e9ff66705dcaca369fe74ceea499051 100644 (file)
@@ -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)) {
index 738088ddd3c7a9321b4f44672d23e643c2a39ba8..0720c3d44d21ff422581fd76c842e8458d05f20f 100644 (file)
@@ -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))