]> granicus.if.org Git - nethack/commitdiff
partial fix for #H38 - hallucination of personal names (trunk only)
authornethack.rankin <nethack.rankin>
Thu, 9 Feb 2006 06:12:00 +0000 (06:12 +0000)
committernethack.rankin <nethack.rankin>
Thu, 9 Feb 2006 06:12:00 +0000 (06:12 +0000)
     This fixes the monnam() family of functions so that hallucinated
personal names, such as Barney, won't be prefixed by "the".  It uses the
same hack as is used for shopkeeper names:  single character prefix on
names which warrant some handling other than the default.  rndmonnam()
strips that off, so unmodified callers (which is almost all of them...)
retain the same behavior has before.

     There are several capitalized names that I have no idea whether need
to be treated as personal names:
  Evil Iggy - name, or type of monster named after someone?
  Totoro    - no clue
  Invid     - ditto
  Vorlon    - just guessing that it's a species rather than an individual.
I couldn't remember whether Godzilla was baby Godzilla's mother or father,
so I went with female there.  So far, no callers of rndmonnam() care about
gender so it doesn't make any difference.  Because of that, I didn't look
though the non-capitalized names to see whether any should be all male or
all female and need one of the other prefix codes.

     I've added "were-rabbit" from the Wallace & Gromit movie.  The recent
ads for its DVD release reminded me that I was going to add that back when
the movie first came out.  I haven't seen it but the creature name fits.

     I also fixed Smokey Bear.  Smokey the Bear is a common misspelling;
I thought we had fixed that ages ago, back when people still had some clue
as to who in the world he was.

doc/fixes35.0
include/extern.h
src/do_name.c
src/priest.c

index ceef4dc77b1f0205a18181207e9eb31ad8ef2ab1..d566d4e852238eeac61afe5d3eb6f3c68e480261 100644 (file)
@@ -120,6 +120,8 @@ avoid inappropriate message when using a cursed lamp while blind
 player polymorphed as a guardian naga spit the wrong kind of venom
 put #define for potion occupant chance and cursed wand zap chance in one place
 candles should not be fireproof
+recognize most instances where hallucinatory monster name should be treated
+       as a personal name (to avoid "the Barney") instead of a description
 
 
 Platform- and/or Interface-Specific Fixes
index efb3114133339a328869f34b30b82e471df9aa4b..274dc1be66ebd838cb27e592499c659114f0dfdd 100644 (file)
@@ -1102,6 +1102,7 @@ E struct obj *FDECL(mkobj_at, (CHAR_P,int,int,BOOLEAN_P));
 E struct obj *FDECL(mksobj_at, (int,int,int,BOOLEAN_P,BOOLEAN_P));
 E struct obj *FDECL(mkobj, (CHAR_P,BOOLEAN_P));
 E int NDECL(rndmonnum);
+E boolean FDECL(bogon_is_pname, (const char *));
 E struct obj *FDECL(splitobj, (struct obj *,long));
 E void FDECL(replace_object, (struct obj *,struct obj *));
 E void FDECL(bill_dummy_object, (struct obj *));
index 1989f9c23f91d78e9b0d83ec4689d9154c1f676f..93c0b379a70264ce905a1ce353c21d0106c2e2e5 100644 (file)
@@ -1,4 +1,4 @@
-/*     SCCS Id: @(#)do_name.c  3.5     2005/11/19      */
+/*     SCCS Id: @(#)do_name.c  3.5     2006/02/08      */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -718,8 +718,10 @@ boolean called;
        /* Put the actual monster name or type into the buffer now */
        /* Be sure to remember whether the buffer starts with a name */
        if (do_hallu) {
-           Strcat(buf, rndmonnam());
-           name_at_start = FALSE;
+           const char *rname = rndmonnam();
+
+           Strcat(buf, rname);
+           name_at_start = bogon_is_pname(rname);
        } else if (has_name(mtmp)) {
            char *name = MNAME(mtmp);
 
@@ -915,6 +917,15 @@ char *outbuf;
     return outbuf;
 }
 
+/*
+ *  Name prefix codes (same as shknam.c):
+ *     dash          _  female, personal name
+ *     underscore    _  female, general name
+ *     plus          +  male, personal name
+ *     vertical bar  |  male, general name (implied for most of shktools)
+ *     equals        =  gender not specified, personal name
+ */
+
 static const char * const bogusmons[] = {
        "jumbo shrimp", "giant pigmy", "gnu", "killer penguin",
        "giant cockroach", "giant slug", "maggot", "pterodactyl",
@@ -934,7 +945,8 @@ static const char * const bogusmons[] = {
        "hydra", "siren",                       /* Greek legend */
        "killer bunny",                         /* Monty Python */
        "rodent of unusual size",               /* The Princess Bride */
-       "Smokey the bear",      /* "Only you can prevent forest fires!" */
+       "were-rabbit",                          /* Wallace & Gromit */
+       "+Smokey Bear",         /* "Only you can prevent forest fires!" */
        "Luggage",                              /* Discworld */
        "Ent",                                  /* Lord of the Rings */
        "tangle tree", "nickelpede", "wiggle",  /* Xanth */
@@ -947,7 +959,7 @@ static const char * const bogusmons[] = {
        "ohmu",                                 /* Nausicaa */
        "youma",                                /* Sailor Moon */
        "nyaasu",                               /* Pokemon (Meowth) */
-       "Godzilla", "King Kong",                /* monster movies */
+       "-Godzilla", "+King Kong",              /* monster movies */
        "earthquake beast",                     /* old L of SH */
        "Invid",                                /* Robotech */
        "Terminator",                           /* The Terminator */
@@ -958,26 +970,23 @@ static const char * const bogusmons[] = {
        "teenage mutant ninja turtle",          /* TMNT */
        "samurai rabbit",                       /* Usagi Yojimbo */
        "aardvark",                             /* Cerebus */
-       "Audrey II",                            /* Little Shop of Horrors */
+       "=Audrey II",                           /* Little Shop of Horrors */
        "witch doctor", "one-eyed one-horned flying purple people eater",
                                                /* 50's rock 'n' roll */
-       "Barney the dinosaur",                  /* saccharine kiddy TV */
-       "Morgoth",                              /* Angband */
+       "+Barney the dinosaur",                 /* saccharine kiddy TV */
+       "+Morgoth",                             /* Angband */
        "Vorlon",                               /* Babylon 5 */
-       "questing beast",               /* King Arthur */
+       "questing beast",                       /* King Arthur */
        "Predator",                             /* Movie */
        "mother-in-law"                         /* common pest */
 };
 
 
-/* Return a random monster name, for hallucination.
- * KNOWN BUG: May be a proper name (Godzilla, Barney), may not
- * (the Terminator, a Dalek).  There's no elegant way to deal
- * with this without radically modifying the calling functions.
- */
+/* return a random monster name, for hallucination */
 const char *
 rndmonnam()
 {
+       const char *mname;
        int name;
 
        do {
@@ -985,8 +994,36 @@ rndmonnam()
        } while (name < SPECIAL_PM &&
            (type_is_pname(&mons[name]) || (mons[name].geno & G_NOGEN)));
 
-       if (name >= SPECIAL_PM) return bogusmons[name - SPECIAL_PM];
-       return mons[name].mname;
+       if (name >= SPECIAL_PM) {
+           mname = bogusmons[name - SPECIAL_PM];
+           /* strip prefix if present */
+           if (!letter(*mname)) ++mname;
+       } else {
+           mname = mons[name].mname;
+       }
+       return mname;
+}
+
+/* scan bogusmons to check whether this name is in the list and has a prefix */
+boolean
+bogon_is_pname(mname)
+const char *mname;
+{
+       const char *bname;
+       int name;
+
+       if (!mname || !*mname) return FALSE;
+       if (!strncmpi(mname, "the ", 4)) mname += 4;
+       /* scan the bogusmons[] list; case sensitive here */
+       for (name = 0; name < SIZE(bogusmons); name++) {
+           bname = bogusmons[name];
+           /* we can skip all ordinary entries */
+           if (letter(*bname)) continue;
+           /* starts with a classification code; does rest of name match? */
+           if (!strcmp(mname, bname + 1))
+               return index("-+=", *bname) ? TRUE : FALSE;
+       }
+       return FALSE;
 }
 
 #ifdef REINCARNATION
index 0a44222ebcd06735c291a9ed38d866c18146a9c7..cb9021c2836c55bcd65a6d63f77a48d9ff10148c 100644 (file)
@@ -260,7 +260,7 @@ struct monst *mon;
  *     - aligned priests with ispriest and high priests have shrines
  *             they retain ispriest and epri when polymorphed
  *     - aligned priests without ispriest are roamers
- *             they have isminion set and access epri as emin
+ *             they have isminion set and use emin rather than epri
  *     - minions do not have ispriest but have isminion and emin
  *     - caller needs to inhibit Hallucination if it wants to force
  *             the true name even when under that influence
@@ -270,14 +270,16 @@ priestname(mon, pname)
 register struct monst *mon;
 char *pname;           /* caller-supplied output buffer */
 {
-    boolean aligned_priest = mon->data == &mons[PM_ALIGNED_PRIEST],
+    boolean do_hallu = Hallucination,
+           aligned_priest = mon->data == &mons[PM_ALIGNED_PRIEST],
            high_priest = mon->data == &mons[PM_HIGH_PRIEST];
-    const char *what = Hallucination ? rndmonnam() : mon->data->mname;
+    const char *what = do_hallu ? rndmonnam() : mon->data->mname;
 
     if (!mon->ispriest && !mon->isminion)      /* should never happen...  */
        return strcpy(pname, what);             /* caller must be confused */
 
-    Strcpy(pname, "the ");
+    *pname = '\0';
+    if (!do_hallu || !bogon_is_pname(what)) Strcat(pname, "the ");
     if (mon->minvis) Strcat(pname, "invisible ");
     if (mon->isminion && EMIN(mon)->renegade)
        Strcat(pname, "renegade ");