1 /* NetHack 3.7 do_name.c $NHDT-Date: 1737013431 2025/01/15 23:43:51 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.326 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Pasi Kallinen, 2018. */
4 /* NetHack may be freely redistributed. See license for details. */
8 staticfn
char *nextmbuf(void);
9 staticfn
char *name_from_player(char *, const char *, const char *);
10 staticfn
void do_mgivenname(void);
11 staticfn boolean
alreadynamed(struct monst
*, char *, char *) NONNULLPTRS
;
12 staticfn
void do_oname(struct obj
*) NONNULLARG1
;
13 staticfn
char *docall_xname(struct obj
*) NONNULLARG1
;
14 staticfn
void namefloorobj(void);
18 /* manage a pool of BUFSZ buffers, so callers don't have to */
22 static char NEARDATA bufs
[NUMMBUF
][BUFSZ
];
23 static int bufidx
= 0;
25 bufidx
= (bufidx
+ 1) % NUMMBUF
;
29 /* allocate space for a monster's name; removes old name if there is one */
33 int lth
) /* desired length (caller handles adding 1 for terminator) */
36 /* allocate mextra if necessary; otherwise get rid of old name */
38 mon
->mextra
= newmextra();
40 free_mgivenname(mon
); /* has mextra, might also have name */
41 MGIVENNAME(mon
) = (char *) alloc((unsigned) lth
);
43 /* zero length: the new name is empty; get rid of the old name */
44 if (has_mgivenname(mon
))
49 /* release a monster's name; retains mextra even if all fields are now null */
51 free_mgivenname(struct monst
*mon
)
53 if (has_mgivenname(mon
)) {
54 free((genericptr_t
) MGIVENNAME(mon
));
55 MGIVENNAME(mon
) = (char *) 0;
59 /* allocate space for an object's name; removes old name if there is one */
63 int lth
) /* desired length (caller handles adding 1 for terminator) */
66 /* allocate oextra if necessary; otherwise get rid of old name */
68 obj
->oextra
= newoextra();
70 free_oname(obj
); /* already has oextra, might also have name */
71 ONAME(obj
) = (char *) alloc((unsigned) lth
);
73 /* zero length: the new name is empty; get rid of the old name */
79 /* release an object's name; retains oextra even if all fields are now null */
81 free_oname(struct obj
*obj
)
84 free((genericptr_t
) ONAME(obj
));
85 ONAME(obj
) = (char *) 0;
89 /* safe_oname() always returns a valid pointer to
90 * a string, either the pointer to an object's name
91 * if it has one, or a pointer to an empty string
95 safe_oname(struct obj
*obj
)
102 /* get a name for a monster or an object from player;
103 truncate if longer than PL_PSIZ, then return it */
106 char *outbuf
, /* output buffer, assumed to be at least BUFSZ long;
107 * anything longer than PL_PSIZ will be truncated */
109 const char *defres
) /* only used if EDIT_GETLIN is enabled; only useful
110 * if windowport xxx's xxx_getlin() supports that */
114 if (defres
&& *defres
)
115 Strcpy(outbuf
, defres
); /* default response from getlin() */
119 getlin(prompt
, outbuf
);
120 if (!*outbuf
|| *outbuf
== '\033')
123 /* strip leading and trailing spaces, condense internal sequences */
124 (void) mungspaces(outbuf
);
125 if (strlen(outbuf
) >= PL_PSIZ
)
126 outbuf
[PL_PSIZ
- 1] = '\0';
130 /* historical note: this returns a monster pointer because it used to
131 allocate a new bigger block of memory to hold the monster and its name */
133 christen_monst(struct monst
*mtmp
, const char *name
)
138 /* dogname & catname are PL_PSIZ arrays; object names have same limit */
139 lth
= (name
&& *name
) ? ((int) strlen(name
) + 1) : 0;
142 name
= strncpy(buf
, name
, PL_PSIZ
- 1);
143 buf
[PL_PSIZ
- 1] = '\0';
145 new_mgivenname(mtmp
, lth
); /* removes old name if one is present */
147 Strcpy(MGIVENNAME(mtmp
), name
);
148 /* if 'mtmp' is leashed, persistent inventory window needs updating */
150 update_inventory(); /* x - leash (attached to Fido) */
154 /* check whether user-supplied name matches or nearly matches an unnameable
155 monster's name, or is an attempt to delete the monster's name; if so, give
156 alternate reject message for do_mgivenname() */
158 alreadynamed(struct monst
*mtmp
, char *monnambuf
, char *usrbuf
)
160 char pronounbuf
[10], *p
;
162 if (!*usrbuf
) { /* attempt to erase existing name */
163 boolean name_not_title
= (has_mgivenname(mtmp
)
164 || type_is_pname(mtmp
->data
)
166 pline("%s would rather keep %s existing %s.", upstart(monnambuf
),
167 is_rider(mtmp
->data
) ? "its" : mhis(mtmp
),
168 name_not_title
? "name" : "title");
170 } else if (fuzzymatch(usrbuf
, monnambuf
, " -_", TRUE
)
171 /* catch trying to name "the Oracle" as "Oracle" */
172 || (!strncmpi(monnambuf
, "the ", 4)
173 && fuzzymatch(usrbuf
, monnambuf
+ 4, " -_", TRUE
))
174 /* catch trying to name "invisible Orcus" as "Orcus" */
175 || ((p
= strstri(monnambuf
, "invisible ")) != 0
176 && fuzzymatch(usrbuf
, p
+ 10, " -_", TRUE
))
177 /* catch trying to name "the priest of Crom" as "Crom" */
178 || ((p
= strstri(monnambuf
, " of ")) != 0
179 && fuzzymatch(usrbuf
, p
+ 4, " -_", TRUE
))) {
180 if (is_rider(mtmp
->data
)) {
181 /* avoid gendered pronoun for riders */
182 pline("%s is already called that.", upstart(monnambuf
));
184 pline("%s is already called %s.",
185 upstart(strcpy(pronounbuf
, mhe(mtmp
))), monnambuf
);
188 } else if (mtmp
->data
== &mons
[PM_JUIBLEX
]
189 && strstri(monnambuf
, "Juiblex")
190 && !strcmpi(usrbuf
, "Jubilex")) {
191 pline("%s doesn't like being called %s.", upstart(monnambuf
), usrbuf
);
197 /* allow player to assign a name to some chosen monster */
201 char buf
[BUFSZ
], monnambuf
[BUFSZ
], qbuf
[QBUFSZ
];
204 struct monst
*mtmp
= 0;
205 boolean do_swallow
= FALSE
;
208 You("would never recognize it anyway.");
213 if (getpos(&cc
, FALSE
, "the monster you want to name") < 0
214 || !isok(cc
.x
, cc
.y
))
216 cx
= cc
.x
, cy
= cc
.y
;
219 if (u
.usteed
&& canspotmon(u
.usteed
)) {
222 pline("This %s creature is called %s and cannot be renamed.",
223 beautiful(), svp
.plname
);
229 /* Allow you to name the monster that has swallowed you */
230 if (!mtmp
&& u
.uswallow
) {
231 int glyph
= glyph_at(cx
, cy
);
233 if (glyph_is_swallow(glyph
)) {
239 if (!do_swallow
&& (!mtmp
241 && (!(cansee(cx
, cy
) || see_with_infrared(mtmp
))
242 || mtmp
->mundetected
|| M_AP_TYPE(mtmp
) == M_AP_FURNITURE
243 || M_AP_TYPE(mtmp
) == M_AP_OBJECT
244 || (mtmp
->minvis
&& !See_invisible
))))) {
246 pline("I see no monster there.");
249 /* special case similar to the one in lookat() */
250 Sprintf(qbuf
, "What do you want to call %s?",
251 distant_monnam(mtmp
, ARTICLE_THE
, monnambuf
));
252 /* use getlin() to get a name string from the player */
253 if (!name_from_player(buf
, qbuf
,
254 has_mgivenname(mtmp
) ? MGIVENNAME(mtmp
) : NULL
))
257 /* Unique monsters have their own specific names or titles.
258 * Shopkeepers, temple priests and other minions use alternate
259 * name formatting routines which ignore any user-supplied name.
261 * Don't say a new name is being rejected if it happens to match
262 * the existing name, or if the player is trying to remove the
263 * monster's existing name without assigning a new one.
265 if ((mtmp
->data
->geno
& G_UNIQ
) && !mtmp
->ispriest
) {
266 if (!alreadynamed(mtmp
, monnambuf
, buf
))
267 pline("%s doesn't like being called names!", upstart(monnambuf
));
268 } else if (mtmp
->isshk
269 && !(Deaf
|| helpless(mtmp
)
270 || mtmp
->data
->msound
<= MS_ANIMAL
)) {
271 if (!alreadynamed(mtmp
, monnambuf
, buf
)) {
272 SetVoice(mtmp
, 0, 80, 0);
273 verbalize("I'm %s, not %s.", shkname(mtmp
), buf
);
275 } else if (mtmp
->ispriest
|| mtmp
->isminion
|| mtmp
->isshk
276 || mtmp
->data
== &mons
[PM_GHOST
] || has_ebones(mtmp
)) {
277 if (!alreadynamed(mtmp
, monnambuf
, buf
))
278 pline("%s will not accept the name %s.", upstart(monnambuf
), buf
);
280 (void) christen_monst(mtmp
, buf
);
285 * This routine used to change the address of 'obj' so be unsafe if not
286 * used with extreme care. Applying a name to an object no longer
287 * allocates a replacement object, so that old risk is gone.
290 do_oname(struct obj
*obj
)
292 char *bufp
, buf
[BUFSZ
], bufcpy
[BUFSZ
], qbuf
[QBUFSZ
];
294 short objtyp
= STRANGE_OBJECT
;
296 /* Do this now because there's no point in even asking for a name */
297 if (obj
->otyp
== SPE_NOVEL
) {
298 pline("%s already has a published name.", Ysimple_name2(obj
));
302 Sprintf(qbuf
, "What do you want to name %s ",
303 is_plural(obj
) ? "these" : "this");
304 (void) safe_qbuf(qbuf
, qbuf
, "?", obj
, xname
, simpleonames
, "item");
305 /* use getlin() to get a name string from the player */
306 if (!name_from_player(buf
, qbuf
, safe_oname(obj
)))
310 * We don't violate illiteracy conduct here, although it is
311 * arguable that we should for anything other than "X". Doing so
312 * would make attaching player's notes to hero's inventory have an
313 * in-game effect, which may or may not be the correct thing to do.
315 * We do violate illiteracy in oname() if player creates Sting or
316 * Orcrist, clearly being literate (no pun intended...).
319 if (obj
->oartifact
) {
320 /* this used to give "The artifact seems to resist the attempt."
321 but resisting is definite, no "seems to" about it */
322 pline("%s resists the attempt.",
323 /* any artifact should always pass the has_oname() test
324 but be careful just in case */
325 has_oname(obj
) ? ONAME(obj
) : "The artifact");
329 /* relax restrictions over proper capitalization for artifacts */
330 if ((aname
= artifact_name(buf
, &objtyp
, TRUE
)) != 0
331 && (restrict_name(obj
, aname
) || exist_artifact(obj
->otyp
, aname
))) {
332 /* substitute canonical spelling before slippage */
334 /* this used to change one letter, substituting a value
335 of 'a' through 'y' (due to an off by one error, 'z'
336 would never be selected) and then force that to
337 upper case if such was the case of the input;
338 now, the hand slip scuffs one or two letters as if
339 the text had been trodden upon, sometimes picking
340 punctuation instead of an arbitrary letter;
341 unfortunately, we have to cover the possibility of
342 it targeting spaces so failing to make any change
343 (we know that it must eventually target a nonspace
344 because buf[] matches a valid artifact name) */
346 /* for "the Foo of Bar", only scuff "Foo of Bar" part */
347 bufp
= !strncmpi(buf
, "the ", 4) ? (buf
+ 4) : buf
;
349 wipeout_text(bufp
, rnd_on_display_rng(2), (unsigned) 0);
350 } while (!strcmp(buf
, bufcpy
));
351 pline("While engraving, your %s slips.", body_part(HAND
));
352 display_nhwindow(WIN_MESSAGE
, FALSE
);
353 You("engrave: \"%s\".", buf
);
354 /* violate illiteracy conduct since hero attempted to write
355 a valid artifact name */
356 u
.uconduct
.literate
++;
357 } else if (obj
->otyp
== objtyp
) {
358 /* artifact_name() always returns non-Null when it sets objtyp */
361 /* artifact_name() found a match and restrict_name() didn't reject
362 it; since 'obj' is the right type, naming will change it into an
363 artifact so use canonical capitalization (Sting or Orcrist) */
367 obj
= oname(obj
, buf
, ONAME_VIA_NAMING
| ONAME_KNOW_ARTI
);
373 struct obj
*obj
, /* item to assign name to */
374 const char *name
, /* name to assign */
375 unsigned oflgs
) /* flags, mostly for artifact creation */
379 boolean via_naming
= (oflgs
& ONAME_VIA_NAMING
) != 0,
380 skip_inv_update
= (oflgs
& ONAME_SKIP_INVUPD
) != 0;
382 lth
= *name
? (int) (strlen(name
) + 1) : 0;
385 name
= strncpy(buf
, name
, PL_PSIZ
- 1);
386 buf
[PL_PSIZ
- 1] = '\0';
388 /* If named artifact exists in the game, do not create another.
389 Also trying to create an artifact shouldn't de-artifact
390 it (e.g. Excalibur from prayer). In this case the object
391 will retain its current name. */
392 if (obj
->oartifact
|| (lth
&& exist_artifact(obj
->otyp
, name
)))
395 new_oname(obj
, lth
); /* removes old name if one is present */
397 Strcpy(ONAME(obj
), name
);
400 artifact_exists(obj
, name
, TRUE
, oflgs
);
401 if (obj
->oartifact
) {
402 /* can't dual-wield with artifact as secondary weapon */
405 /* activate warning if you've just named your weapon "Sting" */
407 set_artifact_intrinsic(obj
, TRUE
, W_WEP
);
408 /* if obj is owned by a shop, increase your bill */
412 /* violate illiteracy conduct since successfully wrote arti-name */
413 if (!u
.uconduct
.literate
++)
414 livelog_printf(LL_CONDUCT
| LL_ARTIFACT
,
415 "became literate by naming %s",
416 bare_artifactname(obj
));
418 livelog_printf(LL_ARTIFACT
,
419 "chose %s to be named \"%s\"",
420 ansimpleoname(obj
), bare_artifactname(obj
));
423 if (carried(obj
) && !skip_inv_update
)
429 objtyp_is_callable(int i
)
431 if (objects
[i
].oc_uname
)
434 switch(objects
[i
].oc_class
) {
436 /* 3.7: calling these used to be allowed but that enabled the
437 player to tell whether two unID'd amulets of yendor were both
438 fake or one was real by calling them distinct names and then
439 checking discoveries to see whether first name was replaced
440 by second or both names stuck; with more than two available
441 to work with, if they weren't all fake it was possible to
442 determine which one was the real one */
443 if (i
== AMULET_OF_YENDOR
|| i
== FAKE_AMULET_OF_YENDOR
)
444 break; /* return FALSE */
456 if (OBJ_DESCR(objects
[i
]))
465 /* getobj callback for object to name (specific item) - anything but gold */
467 name_ok(struct obj
*obj
)
469 if (!obj
|| obj
->oclass
== COIN_CLASS
)
470 return GETOBJ_EXCLUDE
;
472 if (!obj
->dknown
|| obj
->oartifact
|| obj
->otyp
== SPE_NOVEL
)
473 return GETOBJ_DOWNPLAY
;
475 return GETOBJ_SUGGEST
;
478 /* getobj callback for object to call (name its type) */
480 call_ok(struct obj
*obj
)
482 if (!obj
|| !objtyp_is_callable(obj
->otyp
))
483 return GETOBJ_EXCLUDE
;
485 /* not a likely candidate if not seen yet since naming will fail,
486 or if it has been discovered and doesn't already have a name;
487 when something has been named and then becomes discovered, it
488 remains a likely candidate until player renames it to <space>
489 to remove that no longer needed name */
490 if (!obj
->dknown
|| (objects
[obj
->otyp
].oc_name_known
491 && !objects
[obj
->otyp
].oc_uname
))
492 return GETOBJ_DOWNPLAY
;
494 return GETOBJ_SUGGEST
;
497 /* #call / #name command - player can name monster or object or type of obj */
504 menu_item
*pick_list
= 0;
505 struct _cmd_queue cq
, *cmdq
;
507 /* if player wants a,b,c instead of i,o when looting, do that here too */
508 boolean abc
= flags
.lootabc
;
511 if ((cmdq
= cmdq_pop()) != 0) {
513 free((genericptr_t
) cmdq
);
514 if (cq
.typ
== CMDQ_KEY
)
517 cmdq_clear(CQ_CANNED
);
520 win
= create_nhwindow(NHW_MENU
);
521 start_menu(win
, MENU_BEHAVE_STANDARD
);
523 any
.a_char
= 'm'; /* group accelerator 'C' */
524 add_menu(win
, &nul_glyphinfo
, &any
, abc
? 0 : any
.a_char
, 'C',
525 ATR_NONE
, clr
, "a monster", MENU_ITEMFLAGS_NONE
);
527 /* we use y and n as accelerators so that we can accept user's
528 response keyed to old "name an individual object?" prompt */
529 any
.a_char
= 'i'; /* group accelerator 'y' */
530 add_menu(win
, &nul_glyphinfo
, &any
, abc
? 0 : any
.a_char
, 'y',
531 ATR_NONE
, clr
, "a particular object in inventory",
532 MENU_ITEMFLAGS_NONE
);
533 any
.a_char
= 'o'; /* group accelerator 'n' */
534 add_menu(win
, &nul_glyphinfo
, &any
, abc
? 0 : any
.a_char
, 'n',
535 ATR_NONE
, clr
, "the type of an object in inventory",
536 MENU_ITEMFLAGS_NONE
);
538 any
.a_char
= 'f'; /* group accelerator ',' (or ':' instead?) */
539 add_menu(win
, &nul_glyphinfo
, &any
, abc
? 0 : any
.a_char
, ',',
540 ATR_NONE
, clr
, "the type of an object upon the floor",
541 MENU_ITEMFLAGS_NONE
);
542 any
.a_char
= 'd'; /* group accelerator '\' */
543 add_menu(win
, &nul_glyphinfo
, &any
, abc
? 0 : any
.a_char
, '\\',
544 ATR_NONE
, clr
, "the type of an object on discoveries list",
545 MENU_ITEMFLAGS_NONE
);
546 any
.a_char
= 'a'; /* group accelerator 'l' */
547 add_menu(win
, &nul_glyphinfo
, &any
, abc
? 0 : any
.a_char
, 'l',
548 ATR_NONE
, clr
, "record an annotation for the current level",
549 MENU_ITEMFLAGS_NONE
);
550 end_menu(win
, "What do you want to name?");
551 if (select_menu(win
, PICK_ONE
, &pick_list
) > 0) {
552 ch
= pick_list
[0].item
.a_char
;
553 free((genericptr_t
) pick_list
);
556 destroy_nhwindow(win
);
563 case 'm': /* name a visible monster */
566 case 'i': /* name an individual object in inventory */
567 obj
= getobj("name", name_ok
, GETOBJ_PROMPT
);
571 case 'o': /* name a type of object in inventory */
572 obj
= getobj("call", call_ok
, GETOBJ_NOFLAGS
);
574 /* behave as if examining it in inventory;
575 this might set dknown if it was picked up
576 while blind and the hero can now see */
580 You("would never recognize another one.");
582 } else if (call_ok(obj
) == GETOBJ_EXCLUDE
) {
583 You("know those as well as you ever will.");
590 case 'f': /* name a type of object visible on the floor */
593 case 'd': /* name a type of object on the discoveries list */
596 case 'a': /* annotate level */
603 /* for use by safe_qbuf() */
605 docall_xname(struct obj
*obj
)
610 otemp
.oextra
= (struct oextra
*) 0;
612 /* in case water is already known, convert "[un]holy water" to "water" */
613 otemp
.blessed
= otemp
.cursed
= 0;
614 /* remove attributes that are doname() caliber but get formatted
615 by xname(); most of these fixups aren't really needed because the
616 relevant type of object isn't callable so won't reach this far */
617 if (otemp
.oclass
== WEAPON_CLASS
)
618 otemp
.opoisoned
= 0; /* not poisoned */
619 else if (otemp
.oclass
== POTION_CLASS
)
620 otemp
.odiluted
= 0; /* not diluted */
621 else if (otemp
.otyp
== TOWEL
|| otemp
.otyp
== STATUE
)
622 otemp
.spe
= 0; /* not wet or historic */
623 else if (otemp
.otyp
== TIN
)
624 otemp
.known
= 0; /* suppress tin type (homemade, &c) and mon type */
625 else if (otemp
.otyp
== FIGURINE
)
626 otemp
.corpsenm
= NON_PM
; /* suppress mon type */
627 else if (otemp
.otyp
== HEAVY_IRON_BALL
)
628 otemp
.owt
= objects
[HEAVY_IRON_BALL
].oc_weight
; /* not "very heavy" */
629 else if (otemp
.oclass
== FOOD_CLASS
&& otemp
.globby
)
630 otemp
.owt
= 120; /* 6*20, neither a small glob nor a large one */
632 return an(xname(&otemp
));
636 docall(struct obj
*obj
)
638 char buf
[BUFSZ
], qbuf
[QBUFSZ
];
640 boolean had_name
= FALSE
;
643 return; /* probably blind; Blind || Hallucination for 'fromsink' */
644 flush_screen(1); /* buffered updates might matter to player's response */
646 if (obj
->oclass
== POTION_CLASS
&& obj
->fromsink
)
647 /* fromsink: kludge, meaning it's sink water */
648 Sprintf(qbuf
, "Call a stream of %s fluid:",
649 OBJ_DESCR(objects
[obj
->otyp
]));
651 (void) safe_qbuf(qbuf
, "Call ", ":", obj
,
652 docall_xname
, simpleonames
, "thing");
653 /* pointer to old name */
654 uname_p
= &(objects
[obj
->otyp
].oc_uname
);
655 /* use getlin() to get a name string from the player */
656 if (!name_from_player(buf
, qbuf
, *uname_p
))
662 free((genericptr_t
) *uname_p
), *uname_p
= NULL
; /* clear oc_uname */
665 /* strip leading and trailing spaces; uncalls item if all spaces */
666 (void) mungspaces(buf
);
668 if (had_name
) /* possibly remove from disco[]; old *uname_p is gone */
669 undiscover_object(obj
->otyp
);
671 *uname_p
= dupstr(buf
);
672 discover_object(obj
->otyp
, FALSE
, TRUE
); /* possibly add to disco[] */
683 boolean fakeobj
= FALSE
, use_plural
;
685 cc
.x
= u
.ux
, cc
.y
= u
.uy
;
686 /* "dot for under/over you" only makes sense when the cursor hasn't
687 been moved off the hero's '@' yet, but there's no way to adjust
688 the help text once getpos() has started */
689 Sprintf(buf
, "object on map (or '.' for one %s you)",
690 (u
.uundetected
&& hides_under(gy
.youmonst
.data
))
692 if (getpos(&cc
, FALSE
, buf
) < 0 || cc
.x
<= 0)
694 if (u_at(cc
.x
, cc
.y
)) {
695 obj
= vobj_at(u
.ux
, u
.uy
);
697 glyph
= glyph_at(cc
.x
, cc
.y
);
698 if (glyph_is_object(glyph
))
699 fakeobj
= object_from_map(glyph
, cc
.x
, cc
.y
, &obj
);
700 /* else 'obj' stays null */
703 /* "under you" is safe here since there's no object to hide under */
704 There("doesn't seem to be any object %s.",
705 u_at(cc
.x
, cc
.y
) ? "under you" : "there");
708 /* note well: 'obj' might be an instance of STRANGE_OBJECT if target
709 is a mimic; passing that to xname (directly or via simpleonames)
710 would yield "glorkum" so we need to handle it explicitly; it will
711 always fail the Hallucination test and pass the !callable test,
712 resulting in the "can't be assigned a type name" message */
713 Strcpy(buf
, (obj
->otyp
!= STRANGE_OBJECT
)
715 : obj_descr
[STRANGE_OBJECT
].oc_name
);
716 use_plural
= (obj
->quan
> 1L);
718 const char *unames
[6];
721 /* straight role name */
722 unames
[0] = ((Upolyd
? u
.mfemale
: flags
.female
) && gu
.urole
.name
.f
)
725 /* random rank title for hero's role
727 note: the 30 is hardcoded in xlev_to_rank, so should be
728 hardcoded here too */
729 unames
[1] = rank_of(rn2_on_display_rng(30) + 1,
730 Role_switch
, flags
.female
);
731 /* random fake monster */
732 unames
[2] = bogusmon(tmpbuf
, (char *) 0);
733 /* increased chance for fake monster */
734 unames
[3] = unames
[2];
736 unames
[4] = roguename();
738 unames
[5] = "Wibbly Wobbly";
739 pline("%s %s to call you \"%s.\"",
740 The(buf
), use_plural
? "decide" : "decides",
741 unames
[rn2_on_display_rng(SIZE(unames
))]);
742 } else if (call_ok(obj
) == GETOBJ_EXCLUDE
) {
743 pline("%s %s can't be assigned a type name.",
744 use_plural
? "Those" : "That", buf
);
745 } else if (!obj
->dknown
) {
746 You("don't know %s %s well enough to name %s.",
747 use_plural
? "those" : "that", buf
, use_plural
? "them" : "it");
752 obj
->where
= OBJ_FREE
; /* object_from_map() sets it to OBJ_FLOOR */
753 dealloc_obj(obj
); /* has no contents */
757 static const char *const ghostnames
[] = {
758 /* these names should have length < PL_NSIZ */
759 /* Capitalize the names for aesthetics -dgk */
760 "Adri", "Andries", "Andreas", "Bert", "David", "Dirk",
761 "Emile", "Frans", "Fred", "Greg", "Hether", "Jay",
762 "John", "Jon", "Karnov", "Kay", "Kenny", "Kevin",
763 "Maud", "Michiel", "Mike", "Peter", "Robert", "Ron",
764 "Tom", "Wilmar", "Nick Danger", "Phoenix", "Jiro", "Mizue",
765 "Stephan", "Lance Braccus", "Shadowhawk"
768 /* ghost names formerly set by x_monnam(), now by makemon() instead */
772 return rn2(7) ? ROLL_FROM(ghostnames
)
773 : (const char *) svp
.plname
;
777 * Monster naming functions:
778 * x_monnam is the generic monster-naming function.
779 * seen unseen detected named
780 * mon_nam: the newt it the invisible orc Fido
781 * noit_mon_nam:your newt (as if detected) your invisible orc Fido
782 * some_mon_nam:the newt someone the invisible orc Fido
784 * l_monnam: newt it invisible orc dog called Fido
785 * Monnam: The newt It The invisible orc Fido
786 * noit_Monnam: Your newt (as if detected) Your invisible orc Fido
787 * Some_Monnam: The newt Someone The invisible orc Fido
789 * Adjmonnam: The poor newt It The poor invisible orc The poor Fido
790 * Amonnam: A newt It An invisible orc Fido
791 * a_monnam: a newt it an invisible orc Fido
792 * m_monnam: newt xan orc Fido
793 * y_monnam: your newt your xan your invisible orc Fido
794 * YMonnam: Your newt Your xan Your invisible orc Fido
795 * noname_monnam(mon,article):
796 * article newt art xan art invisible orc art dog
802 * ARTICLE_NONE, ARTICLE_THE, ARTICLE_A: obvious
803 * ARTICLE_YOUR: "your" on pets, "the" on everything else
805 * If the monster would be referred to as "it" or if the monster has a name
806 * _and_ there is no adjective, "invisible", "saddled", etc., override this
807 * and always use no article.
811 * SUPPRESS_IT, SUPPRESS_INVISIBLE, SUPPRESS_HALLUCINATION, SUPPRESS_SADDLE.
812 * SUPPRESS_MAPPEARANCE: if monster is mimicking another monster (cloned
813 * Wizard or quickmimic pet), describe the real monster rather
814 * than its current form;
815 * EXACT_NAME: combination of all the above
816 * SUPPRESS_NAME: omit monster's assigned name (unless uniq w/ pname).
817 * AUGMENT_IT: not suppression but shares suppression bitmask; if result
818 * would have been "it", return "someone" if humanoid or
819 * "something" otherwise.
821 * Bug: if the monster is a priest or shopkeeper, not every one of these
822 * options works, since those are special cases.
828 const char *adjective
,
832 char *buf
= nextmbuf();
833 struct permonst
*mdat
= mtmp
->data
;
835 boolean do_hallu
, do_invis
, do_it
, do_saddle
, do_mappear
,
836 do_exact
, do_name
, augment_it
;
837 boolean name_at_start
, has_adjectives
, insertbuf2
,
838 mappear_as_mon
= (M_AP_TYPE(mtmp
) == M_AP_MONSTER
);
839 char *bp
, buf2
[BUFSZ
];
841 if (mtmp
== &gy
.youmonst
)
842 return strcpy(buf
, "you"); /* ignore article, "invisible", &c */
844 if (program_state
.gameover
)
845 suppress
|= SUPPRESS_HALLUCINATION
;
846 if (article
== ARTICLE_YOUR
&& !mtmp
->mtame
)
847 article
= ARTICLE_THE
;
849 if (u
.uswallow
&& mtmp
== u
.ustuck
) {
851 * This monster has become important, for the moment anyway.
852 * As the hero's consumer, it is worthy of ARTICLE_THE.
853 * Also, suppress invisible as that particular characteristic
854 * is unimportant now and you can see its interior anyway.
856 article
= ARTICLE_THE
;
857 suppress
|= SUPPRESS_INVISIBLE
;
859 do_hallu
= Hallucination
&& !(suppress
& SUPPRESS_HALLUCINATION
);
860 do_invis
= mtmp
->minvis
&& !(suppress
& SUPPRESS_INVISIBLE
);
861 do_it
= !canspotmon(mtmp
) && article
!= ARTICLE_YOUR
862 && !program_state
.gameover
&& mtmp
!= u
.usteed
863 && !engulfing_u(mtmp
) && !(suppress
& SUPPRESS_IT
);
864 do_saddle
= !(suppress
& SUPPRESS_SADDLE
);
865 do_mappear
= mappear_as_mon
&& !(suppress
& SUPPRESS_MAPPEARANCE
);
866 do_exact
= (suppress
& EXACT_NAME
) == EXACT_NAME
;
867 do_name
= !(suppress
& SUPPRESS_NAME
) || type_is_pname(mdat
);
868 augment_it
= (suppress
& AUGMENT_IT
) != 0;
872 /* unseen monsters, etc.; usually "it" but sometimes more specific;
873 when hallucinating, the more specific values might be inverted */
875 /* !is_animal excludes all Y; !mindless excludes Z, M, \' */
876 boolean s_one
= humanoid(mdat
) && !is_animal(mdat
) && !mindless(mdat
);
878 Strcpy(buf
, !augment_it
? "it"
879 : (!do_hallu
? s_one
: !rn2(2)) ? "someone"
884 /* priests and minions: don't even use this function */
885 if ((mtmp
->ispriest
|| mtmp
->isminion
) && !do_mappear
) {
887 long save_prop
= EHalluc_resistance
;
888 unsigned save_invis
= mtmp
->minvis
;
890 /* when true name is wanted, explicitly block Hallucination */
892 EHalluc_resistance
= 1L;
895 /* EXACT_NAME will force "of <deity>" on the Astral Plane */
896 name
= priestname(mtmp
, article
, do_exact
, buf2
);
897 EHalluc_resistance
= save_prop
;
898 mtmp
->minvis
= save_invis
;
899 if (article
== ARTICLE_NONE
&& !strncmp(name
, "the ", 4))
901 return strcpy(buf
, name
);
904 /* 'pm_name' is the base part of most names */
906 /*assert(ismnum(mtmp->mappearance));*/
907 pm_name
= pmname(&mons
[mtmp
->mappearance
], Mgender(mtmp
));
909 pm_name
= mon_pmname(mtmp
);
912 /* Shopkeepers: use shopkeeper name. For normal shopkeepers, just
913 * "Asidonhopo"; for unusual ones, "Asidonhopo the invisible
914 * shopkeeper" or "Asidonhopo the blue dragon". If hallucinating,
915 * none of this applies.
917 if (mtmp
->isshk
&& !do_hallu
&& !do_mappear
) {
918 if (adjective
&& article
== ARTICLE_THE
) {
919 /* pathological case: "the angry Asidonhopo the blue dragon"
922 Strcat(strcat(buf
, adjective
), " ");
923 Strcat(buf
, shkname(mtmp
));
925 Strcat(buf
, shkname(mtmp
));
926 if (mdat
!= &mons
[PM_SHOPKEEPER
] || do_invis
){
927 Strcat(buf
, " the ");
929 Strcat(buf
, "invisible ");
930 Strcat(buf
, pm_name
);
936 /* Put the adjectives in the buffer */
938 Strcat(strcat(buf
, adjective
), " ");
940 Strcat(buf
, "invisible ");
941 if (do_saddle
&& (mtmp
->misc_worn_check
& W_SADDLE
) && !Blind
943 Strcat(buf
, "saddled ");
944 has_adjectives
= (buf
[0] != '\0');
946 /* Put the actual monster name or type into the buffer now.
947 Remember whether the buffer starts with a personal name. */
950 char *rname
= rndmonnam(&rnamecode
);
953 name_at_start
= bogon_is_pname(rnamecode
);
954 } else if (do_name
&& has_mgivenname(mtmp
)) {
955 char *name
= MGIVENNAME(mtmp
);
959 if (has_ebones(mtmp
)) {
961 if (mdat
== &mons
[PM_GHOST
]) {
962 Sprintf(eos(buf
), "%s ghost", s_suffix(name
));
963 name_at_start
= TRUE
;
965 Sprintf(eos(buf
), "%s called %s", pm_name
, name
);
966 name_at_start
= (boolean
) type_is_pname(mdat
);
967 } else if (is_mplayer(mdat
) && (bp
= strstri(name
, " the ")) != 0) {
968 /* <name> the <adjective> <invisible> <saddled> <rank> */
972 pbuf
[bp
- name
+ 5] = '\0'; /* adjectives right after " the " */
975 Strcat(pbuf
, bp
+ 5); /* append the rest of the name */
977 article
= ARTICLE_NONE
;
978 name_at_start
= TRUE
;
981 name_at_start
= TRUE
;
983 #if 0 /* hardfought */
986 } else if (is_mplayer(mdat
) && !In_endgame(&u
.uz
)) {
989 Strcpy(pbuf
, rank_of((int) mtmp
->m_lev
, monsndx(mdat
),
990 (boolean
) mtmp
->female
));
991 Strcat(buf
, lcase(pbuf
));
992 name_at_start
= FALSE
;
994 Strcat(buf
, pm_name
);
995 name_at_start
= (boolean
) type_is_pname(mdat
);
998 if (name_at_start
&& (article
== ARTICLE_YOUR
|| !has_adjectives
)) {
999 if (mdat
== &mons
[PM_WIZARD_OF_YENDOR
])
1000 article
= ARTICLE_THE
;
1002 article
= ARTICLE_NONE
;
1003 } else if ((mdat
->geno
& G_UNIQ
) != 0 && article
== ARTICLE_A
) {
1004 article
= ARTICLE_THE
;
1008 buf2
[0] = '\0'; /* lint suppression */
1011 Strcpy(buf2
, "your ");
1014 Strcpy(buf2
, "the ");
1017 /* avoid an() here */
1018 (void) just_an(buf2
, buf
); /* copy "a " or "an " into buf2[] */
1026 Strcat(buf2
, buf
); /* buf2[] isn't viable to return, */
1027 Strcpy(buf
, buf2
); /* so transfer the result to buf[] */
1033 l_monnam(struct monst
*mtmp
)
1035 return x_monnam(mtmp
, ARTICLE_NONE
, (char *) 0,
1036 (has_mgivenname(mtmp
)) ? SUPPRESS_SADDLE
: 0, TRUE
);
1040 mon_nam(struct monst
*mtmp
)
1042 return x_monnam(mtmp
, ARTICLE_THE
, (char *) 0,
1043 (has_mgivenname(mtmp
)) ? SUPPRESS_SADDLE
: 0, FALSE
);
1046 /* print the name as if mon_nam() (y_monnam() if tame) was called, but
1047 assume that the player can always see the monster--used for probing and
1048 for monsters aggravating the player with a cursed potion of invisibility;
1049 also used for pet moving "reluctantly" onto cursed object when that pet
1050 can be seen either before or after it moves */
1052 noit_mon_nam(struct monst
*mtmp
)
1054 return x_monnam(mtmp
, ARTICLE_YOUR
, (char *) 0,
1055 (has_mgivenname(mtmp
) ? (SUPPRESS_SADDLE
| SUPPRESS_IT
)
1060 /* in between noit_mon_nam() and mon_nam(); if the latter would pick "it",
1061 use "someone" (for humanoids) or "something" (for others) instead */
1063 some_mon_nam(struct monst
*mtmp
)
1065 return x_monnam(mtmp
, ARTICLE_THE
, (char *) 0,
1066 (has_mgivenname(mtmp
) ? (SUPPRESS_SADDLE
| AUGMENT_IT
)
1072 Monnam(struct monst
*mtmp
)
1074 char *bp
= mon_nam(mtmp
);
1081 noit_Monnam(struct monst
*mtmp
)
1083 char *bp
= noit_mon_nam(mtmp
);
1090 Some_Monnam(struct monst
*mtmp
)
1092 char *bp
= some_mon_nam(mtmp
);
1098 /* return "a dog" rather than "Fido", honoring hallucination and visibility */
1100 noname_monnam(struct monst
*mtmp
, int article
)
1102 return x_monnam(mtmp
, article
, (char *) 0, SUPPRESS_NAME
, FALSE
);
1105 /* monster's own name -- overrides hallucination and [in]visibility
1106 so shouldn't be used in ordinary messages (mainly for disclosure) */
1108 m_monnam(struct monst
*mtmp
)
1110 return x_monnam(mtmp
, ARTICLE_NONE
, (char *) 0, EXACT_NAME
, FALSE
);
1113 /* pet name: "your little dog" */
1115 y_monnam(struct monst
*mtmp
)
1117 int prefix
, suppression_flag
;
1119 prefix
= mtmp
->mtame
? ARTICLE_YOUR
: ARTICLE_THE
;
1120 suppression_flag
= (has_mgivenname(mtmp
)
1121 /* "saddled" is redundant when mounted */
1122 || mtmp
== u
.usteed
)
1126 return x_monnam(mtmp
, prefix
, (char *) 0, suppression_flag
, FALSE
);
1129 /* y_monnam() for start of sentence */
1131 YMonnam(struct monst
*mtmp
)
1133 char *bp
= y_monnam(mtmp
);
1140 Adjmonnam(struct monst
*mtmp
, const char *adj
)
1142 char *bp
= x_monnam(mtmp
, ARTICLE_THE
, adj
,
1143 has_mgivenname(mtmp
) ? SUPPRESS_SADDLE
: 0, FALSE
);
1150 a_monnam(struct monst
*mtmp
)
1152 return x_monnam(mtmp
, ARTICLE_A
, (char *) 0,
1153 has_mgivenname(mtmp
) ? SUPPRESS_SADDLE
: 0, FALSE
);
1157 Amonnam(struct monst
*mtmp
)
1159 char *bp
= a_monnam(mtmp
);
1165 /* used for monster ID by the '/', ';', and 'C' commands to block remote
1166 identification of the endgame altars via their attending priests */
1170 int article
, /* only ARTICLE_NONE and ARTICLE_THE are handled here */
1173 /* high priest(ess)'s identity is concealed on the Astral Plane,
1174 unless you're adjacent (overridden for hallucination which does
1175 its own obfuscation) */
1176 if (mon
->data
== &mons
[PM_HIGH_CLERIC
] && !Hallucination
1177 && Is_astralevel(&u
.uz
) && !m_next2u(mon
)) {
1178 Strcpy(outbuf
, article
== ARTICLE_THE
? "the " : "");
1179 Strcat(outbuf
, mon
->female
? "high priestess" : "high priest");
1181 Strcpy(outbuf
, x_monnam(mon
, article
, (char *) 0, 0, TRUE
));
1186 /* returns mon_nam(mon) relative to other_mon; normal name unless they're
1187 the same, in which case the reference is to {him|her|it} self */
1189 mon_nam_too(struct monst
*mon
, struct monst
*other_mon
)
1193 if (mon
!= other_mon
) {
1194 outbuf
= mon_nam(mon
);
1196 outbuf
= nextmbuf();
1197 switch (pronoun_gender(mon
, PRONOUN_HALLU
)) {
1199 Strcpy(outbuf
, "himself");
1202 Strcpy(outbuf
, "herself");
1206 Strcpy(outbuf
, "itself");
1208 case 3: /* could happen when hallucinating */
1209 Strcpy(outbuf
, "themselves");
1216 /* construct "<monnamtext> <verb> <othertext> {him|her|it}self" which might
1217 be distorted by Hallu; if that's plural, adjust monnamtext and verb */
1221 char *monnamtext
, /* modifiable 'mbuf' with adequate room at end */
1223 const char *othertext
)
1225 char *verbs
, selfbuf
[40]; /* sizeof "themselves" suffices */
1227 /* "himself"/"herself"/"itself", maybe "themselves" if hallucinating */
1228 Strcpy(selfbuf
, mon_nam_too(mon
, mon
));
1229 /* verb starts plural; this will yield singular except for "themselves" */
1230 verbs
= vtense(selfbuf
, verb
);
1231 if (!strcmp(verb
, verbs
)) { /* a match indicates that it stayed plural */
1232 monnamtext
= makeplural(monnamtext
);
1233 /* for "it", makeplural() produces "them" but we want "they" */
1234 if (!strcmpi(monnamtext
, genders
[3].he
)) {
1235 boolean capitaliz
= (monnamtext
[0] == highc(monnamtext
[0]));
1237 Strcpy(monnamtext
, genders
[3].him
);
1239 monnamtext
[0] = highc(monnamtext
[0]);
1242 Strcat(strcat(monnamtext
, " "), verbs
);
1243 if (othertext
&& *othertext
)
1244 Strcat(strcat(monnamtext
, " "), othertext
);
1245 Strcat(strcat(monnamtext
, " "), selfbuf
);
1249 /* for debugging messages, where data might be suspect and we aren't
1250 taking what the hero does or doesn't know into consideration */
1252 minimal_monnam(struct monst
*mon
, boolean ckloc
)
1254 struct permonst
*ptr
;
1255 char *outbuf
= nextmbuf();
1258 Strcpy(outbuf
, "[Null monster]");
1259 } else if ((ptr
= mon
->data
) == 0) {
1260 Strcpy(outbuf
, "[Null mon->data]");
1261 } else if (ptr
< &mons
[0]) {
1262 Sprintf(outbuf
, "[Invalid mon->data %s < %s]",
1263 fmt_ptr((genericptr_t
) mon
->data
),
1264 fmt_ptr((genericptr_t
) &mons
[0]));
1265 } else if (ptr
>= &mons
[NUMMONS
]) {
1266 Sprintf(outbuf
, "[Invalid mon->data %s >= %s]",
1267 fmt_ptr((genericptr_t
) mon
->data
),
1268 fmt_ptr((genericptr_t
) &mons
[NUMMONS
]));
1269 } else if (ckloc
&& ptr
== &mons
[PM_LONG_WORM
] && mon
->mx
1270 && svl
.level
.monsters
[mon
->mx
][mon
->my
] != mon
) {
1271 Sprintf(outbuf
, "%s <%d,%d>",
1272 pmname(&mons
[PM_LONG_WORM_TAIL
], Mgender(mon
)),
1275 Sprintf(outbuf
, "%s%s <%d,%d>",
1276 mon
->mtame
? "tame " : mon
->mpeaceful
? "peaceful " : "",
1277 mon_pmname(mon
), mon
->mx
, mon
->my
);
1278 if (mon
->cham
!= NON_PM
)
1279 Sprintf(eos(outbuf
), "{%s}",
1280 pmname(&mons
[mon
->cham
], Mgender(mon
)));
1285 #ifndef PMNAME_MACROS
1287 Mgender(struct monst
*mtmp
)
1291 if (mtmp
== &gy
.youmonst
) {
1292 if (Upolyd
? u
.mfemale
: flags
.female
)
1294 } else if (mtmp
->female
) {
1301 pmname(struct permonst
*pm
, int mgender
)
1303 if (mgender
< MALE
|| mgender
>= NUM_MGENDERS
|| !pm
->pmnames
[mgender
])
1305 return pm
->pmnames
[mgender
];
1307 #endif /* PMNAME_MACROS */
1309 /* mons[]->pmname for a monster */
1311 mon_pmname(struct monst
*mon
)
1313 /* for neuter, mon->data->pmnames[MALE] will be Null and use [NEUTRAL] */
1314 return pmname(mon
->data
, Mgender(mon
));
1317 /* mons[]->pmname for a corpse or statue or figurine */
1319 obj_pmname(struct obj
*obj
)
1321 #if 0 /* ignore saved montraits even when they're available; they determine
1322 * what a corpse would revive as if resurrected (human corpse from
1323 * slain vampire revives as vampire rather than as human, for example)
1324 * and don't necessarily reflect the state of the corpse itself */
1325 if (has_omonst(obj
)) {
1326 struct monst
*m
= OMONST(obj
);
1328 /* obj->oextra->omonst->data is Null but ...->mnum is set */
1329 if (ismnum(m
->mnum
))
1330 return pmname(&mons
[m
->mnum
], Mgender(m
));
1333 if ((obj
->otyp
== CORPSE
|| obj
->otyp
== STATUE
|| obj
->otyp
== FIGURINE
)
1334 && ismnum(obj
->corpsenm
)) {
1335 int cgend
= (obj
->spe
& CORPSTAT_GENDER
),
1336 mgend
= ((cgend
== CORPSTAT_MALE
) ? MALE
1337 : (cgend
== CORPSTAT_FEMALE
) ? FEMALE
1339 mndx
= obj
->corpsenm
;
1341 /* mons[].pmnames[] for monster cleric uses "priest" or "priestess"
1342 or "aligned cleric"; we want to avoid "aligned cleric [corpse]"
1343 unless it has been explicitly flagged as neuter rather than
1344 defaulting to random (which fails male or female check above);
1345 role monster cleric uses "priest" or "priestess" or "cleric"
1346 without "aligned" prefix so we switch to that; [can't force
1347 random gender to be chosen here because splitting a stack of
1348 corpses could cause the split-off portion to change gender, so
1349 settle for avoiding "aligned"] */
1350 if (mndx
== PM_ALIGNED_CLERIC
&& cgend
== CORPSTAT_RANDOM
)
1353 return pmname(&mons
[mndx
], mgend
);
1355 impossible("obj_pmname otyp:%i,corpsenm:%i", obj
->otyp
, obj
->corpsenm
);
1356 return "two-legged glorkum-seeker";
1359 /* used by bogusmon(next) and also by init_CapMons(rumors.c);
1360 bogon_is_pname(below) checks a hard-coded subset of these rather than
1362 Also used in rumors.c */
1363 const char bogon_codes
[] = "-_+|="; /* see dat/bonusmon.txt */
1365 /* fake monsters used to be in a hard-coded array, now in a data file */
1367 bogusmon(char *buf
, char *code
)
1373 /* might fail (return empty buf[]) if the file isn't available */
1374 get_rnd_text(BOGUSMONFILE
, buf
, rn2_on_display_rng
, MD_PAD_BOGONS
);
1376 Strcpy(buf
, "bogon");
1377 } else if (strchr(bogon_codes
, *mnam
)) { /* strip prefix if present */
1385 /* return a random monster name, for hallucination */
1387 rndmonnam(char *code
)
1389 static char buf
[BUFSZ
];
1392 #define BOGUSMONSIZE 100 /* arbitrary */
1398 name
= rn2_on_display_rng(SPECIAL_PM
+ BOGUSMONSIZE
- LOW_PM
) + LOW_PM
;
1399 } while (name
< SPECIAL_PM
1400 && (type_is_pname(&mons
[name
]) || (mons
[name
].geno
& G_NOGEN
)));
1402 if (name
>= SPECIAL_PM
) {
1403 mnam
= bogusmon(buf
, code
);
1405 mnam
= strcpy(buf
, pmname(&mons
[name
], rn2_on_display_rng(2)));
1411 /* check bogusmon prefix to decide whether it's a personal name */
1413 bogon_is_pname(char code
)
1417 return strchr("-+=", code
) ? TRUE
: FALSE
;
1420 /* name of a Rogue player */
1426 if ((opts
= nh_getenv("ROGUEOPTS")) != 0) {
1427 for (i
= opts
; *i
; i
++)
1428 if (!strncmp("name=", i
, 5)) {
1430 if ((j
= strchr(i
+ 5, ',')) != 0)
1435 return rn2(3) ? (rn2(2) ? "Michael Toy" : "Kenneth Arnold")
1439 static NEARDATA
const char *const hcolors
[] = {
1440 "ultraviolet", "infrared", "bluish-orange", "reddish-green", "dark white",
1441 "light black", "sky blue-pink", "pinkish-cyan", "indigo-chartreuse",
1442 "salty", "sweet", "sour", "bitter", "umami", /* basic tastes */
1443 "striped", "spiral", "swirly", "plaid", "checkered", "argyle", "paisley",
1444 "blotchy", "guernsey-spotted", "polka-dotted", "square", "round",
1445 "triangular", "cabernet", "sangria", "fuchsia", "wisteria", "lemon-lime",
1446 "strawberry-banana", "peppermint", "romantic", "incandescent",
1447 "octarine", /* Discworld: the Colour of Magic */
1448 "excitingly dull", "mauve", "electric",
1449 "neon", "fluorescent", "phosphorescent", "translucent", "opaque",
1450 "psychedelic", "iridescent", "rainbow-colored", "polychromatic",
1451 "colorless", "colorless green",
1452 "dancing", "singing", "loving", "loudy", "noisy", "clattery", "silent",
1453 "apocyan", "infra-pink", "opalescent", "violant", "tuneless",
1454 "viridian", "aureolin", "cinnabar", "purpurin", "gamboge", "madder",
1455 "bistre", "ecru", "fulvous", "tekhelet", "selective yellow",
1459 hcolor(const char *colorpref
)
1461 return (Hallucination
|| !colorpref
)
1462 ? hcolors
[rn2_on_display_rng(SIZE(hcolors
))]
1466 /* return a random real color unless hallucinating */
1470 int k
= rn2(CLR_MAX
);
1472 return Hallucination
? hcolor((char *) 0)
1473 : (k
== NO_COLOR
) ? "colorless"
1477 static NEARDATA
const char *const hliquids
[] = {
1478 "yoghurt", "oobleck", "clotted blood", "diluted water", "purified water",
1479 "instant coffee", "tea", "herbal infusion", "liquid rainbow",
1480 "creamy foam", "mulled wine", "bouillon", "nectar", "grog", "flubber",
1481 "ketchup", "slow light", "oil", "vinaigrette", "liquid crystal", "honey",
1482 "caramel sauce", "ink", "aqueous humour", "milk substitute",
1483 "fruit juice", "glowing lava", "gastric acid", "mineral water",
1484 "cough syrup", "quicksilver", "sweet vitriol", "grey goo", "pink slime",
1486 /* "new coke (tm)", --better not */
1489 /* if hallucinating, return a random liquid instead of 'liquidpref' */
1492 const char *liquidpref
) /* use as-is when not hallucintg (unless empty) */
1494 boolean hallucinate
= Hallucination
&& !program_state
.gameover
;
1496 if (hallucinate
|| !liquidpref
|| !*liquidpref
) {
1497 int indx
, count
= SIZE(hliquids
);
1499 /* if we have a non-hallucinatory default value, include it
1500 among the choices */
1501 if (liquidpref
&& *liquidpref
)
1503 indx
= rn2_on_display_rng(count
);
1504 if (IndexOk(indx
, hliquids
))
1505 return hliquids
[indx
];
1510 /* Aliases for road-runner nemesis
1512 static const char *const coynames
[] = {
1513 "Carnivorous Vulgaris", "Road-Runnerus Digestus", "Eatibus Anythingus",
1514 "Famishus-Famishus", "Eatibus Almost Anythingus", "Eatius Birdius",
1515 "Famishius Fantasticus", "Eternalii Famishiis", "Famishus Vulgarus",
1516 "Famishius Vulgaris Ingeniusi", "Eatius-Slobbius", "Hardheadipus Oedipus",
1517 "Carnivorous Slobbius", "Hard-Headipus Ravenus", "Evereadii Eatibus",
1518 "Apetitius Giganticus", "Hungrii Flea-Bagius", "Overconfidentii Vulgaris",
1519 "Caninus Nervous Rex", "Grotesques Appetitus", "Nemesis Ridiculii",
1524 coyotename(struct monst
*mtmp
, char *buf
)
1527 Sprintf(buf
, "%s - %s",
1528 x_monnam(mtmp
, ARTICLE_NONE
, (char *) 0, 0, TRUE
),
1529 mtmp
->mcan
? coynames
[SIZE(coynames
) - 1]
1530 : coynames
[mtmp
->m_id
% (SIZE(coynames
) - 1)]);
1538 static const char *const v
[] = { "a", "ai", "og", "u" };
1539 static const char *const snd
[] = { "gor", "gris", "un", "bane", "ruk",
1540 "oth","ul", "z", "thos","akh","hai" };
1541 int i
, iend
= rn1(2, 3), vstart
= rn2(2);
1545 for (i
= 0; i
< iend
; ++i
) {
1546 vstart
= 1 - vstart
; /* 0 -> 1, 1 -> 0 */
1547 Sprintf(eos(s
), "%s%s", (i
> 0 && !rn2(30)) ? "-" : "",
1548 vstart
? ROLL_FROM(v
) : ROLL_FROM(snd
));
1555 christen_orc(struct monst
*mtmp
, const char *gang
, const char *other
)
1558 char buf
[BUFSZ
], buf2
[BUFSZ
], *orcname
;
1560 orcname
= rndorcname(buf2
);
1561 /* rndorcname() won't return NULL */
1562 sz
= (int) strlen(orcname
);
1564 sz
+= (int) (strlen(gang
) + sizeof " of " - sizeof "");
1566 sz
+= (int) strlen(other
);
1570 boolean nameit
= FALSE
;
1573 Sprintf(buf
, "%s of %s", upstart(orcname
),
1574 upstart(strcpy(gbuf
, gang
)));
1577 Sprintf(buf
, "%s%s", upstart(orcname
), other
);
1581 mtmp
= christen_monst(mtmp
, buf
);
1586 /* Discworld novel titles, in the order that they were published; a subset
1587 of them have index macros used for variant spellings; if the titles are
1588 reordered for some reason, make sure that those get renumbered to match */
1589 static const char *const sir_Terry_novels
[] = {
1590 "The Colour of Magic", "The Light Fantastic", "Equal Rites", "Mort",
1591 "Sourcery", "Wyrd Sisters", "Pyramids", "Guards! Guards!", "Eric",
1592 "Moving Pictures", "Reaper Man", "Witches Abroad", "Small Gods",
1593 "Lords and Ladies", "Men at Arms", "Soul Music", "Interesting Times",
1594 "Maskerade", "Feet of Clay", "Hogfather", "Jingo", "The Last Continent",
1595 "Carpe Jugulum", "The Fifth Elephant", "The Truth", "Thief of Time",
1596 "The Last Hero", "The Amazing Maurice and His Educated Rodents",
1597 "Night Watch", "The Wee Free Men", "Monstrous Regiment",
1598 "A Hat Full of Sky", "Going Postal", "Thud!", "Wintersmith",
1599 "Making Money", "Unseen Academicals", "I Shall Wear Midnight", "Snuff",
1600 "Raising Steam", "The Shepherd's Crown"
1602 #define NVL_COLOUR_OF_MAGIC 0
1603 #define NVL_SOURCERY 4
1604 #define NVL_MASKERADE 17
1605 #define NVL_AMAZING_MAURICE 27
1609 noveltitle(int *novidx
)
1611 int j
, k
= SIZE(sir_Terry_novels
);
1617 else if (*novidx
>= 0 && *novidx
< k
)
1620 return sir_Terry_novels
[j
];
1623 /* figure out canonical novel title from player-specified one */
1625 lookup_novel(const char *lookname
, int *idx
)
1630 * Accept variant spellings:
1631 * _The_Colour_of_Magic_ uses British spelling, and American
1632 * editions keep that, but we also recognize American spelling;
1633 * _Sourcery_ is a joke rather than British spelling of "sorcery".
1635 if (!strcmpi(The(lookname
), "The Color of Magic"))
1636 lookname
= sir_Terry_novels
[NVL_COLOUR_OF_MAGIC
];
1637 else if (!strcmpi(lookname
, "Sorcery"))
1638 lookname
= sir_Terry_novels
[NVL_SOURCERY
];
1639 else if (!strcmpi(lookname
, "Masquerade"))
1640 lookname
= sir_Terry_novels
[NVL_MASKERADE
];
1641 else if (!strcmpi(The(lookname
), "The Amazing Maurice"))
1642 lookname
= sir_Terry_novels
[NVL_AMAZING_MAURICE
];
1643 else if (!strcmpi(lookname
, "Thud"))
1644 lookname
= sir_Terry_novels
[NVL_THUD
];
1646 for (k
= 0; k
< SIZE(sir_Terry_novels
); ++k
) {
1647 if (!strcmpi(lookname
, sir_Terry_novels
[k
])
1648 || !strcmpi(The(lookname
), sir_Terry_novels
[k
])) {
1651 return sir_Terry_novels
[k
];
1654 /* name not found; if novelidx is already set, override the name */
1655 if (idx
&& IndexOk(*idx
, sir_Terry_novels
))
1656 return sir_Terry_novels
[*idx
];
1658 return (const char *) 0;