diff --git a/doc/fixes35.0 b/doc/fixes35.0 index ceef4dc77..d566d4e85 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -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 diff --git a/include/extern.h b/include/extern.h index efb311413..274dc1be6 100644 --- a/include/extern.h +++ b/include/extern.h @@ -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 *)); diff --git a/src/do_name.c b/src/do_name.c index 1989f9c23..93c0b379a 100644 --- a/src/do_name.c +++ b/src/do_name.c @@ -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 diff --git a/src/priest.c b/src/priest.c index 0a44222eb..cb9021c28 100644 --- a/src/priest.c +++ b/src/priest.c @@ -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 ");