make rank() static again
[NetHack.git] / src / do_name.c
blob37876700e272e178a242e53404754a9f6ba42d90
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. */
6 #include "hack.h"
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);
16 #define NUMMBUF 5
18 /* manage a pool of BUFSZ buffers, so callers don't have to */
19 staticfn char *
20 nextmbuf(void)
22 static char NEARDATA bufs[NUMMBUF][BUFSZ];
23 static int bufidx = 0;
25 bufidx = (bufidx + 1) % NUMMBUF;
26 return bufs[bufidx];
29 /* allocate space for a monster's name; removes old name if there is one */
30 void
31 new_mgivenname(
32 struct monst *mon,
33 int lth) /* desired length (caller handles adding 1 for terminator) */
35 if (lth) {
36 /* allocate mextra if necessary; otherwise get rid of old name */
37 if (!mon->mextra)
38 mon->mextra = newmextra();
39 else
40 free_mgivenname(mon); /* has mextra, might also have name */
41 MGIVENNAME(mon) = (char *) alloc((unsigned) lth);
42 } else {
43 /* zero length: the new name is empty; get rid of the old name */
44 if (has_mgivenname(mon))
45 free_mgivenname(mon);
49 /* release a monster's name; retains mextra even if all fields are now null */
50 void
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 */
60 void
61 new_oname(
62 struct obj *obj,
63 int lth) /* desired length (caller handles adding 1 for terminator) */
65 if (lth) {
66 /* allocate oextra if necessary; otherwise get rid of old name */
67 if (!obj->oextra)
68 obj->oextra = newoextra();
69 else
70 free_oname(obj); /* already has oextra, might also have name */
71 ONAME(obj) = (char *) alloc((unsigned) lth);
72 } else {
73 /* zero length: the new name is empty; get rid of the old name */
74 if (has_oname(obj))
75 free_oname(obj);
79 /* release an object's name; retains oextra even if all fields are now null */
80 void
81 free_oname(struct obj *obj)
83 if (has_oname(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
92 * if it doesn't.
94 const char *
95 safe_oname(struct obj *obj)
97 if (has_oname(obj))
98 return ONAME(obj);
99 return "";
102 /* get a name for a monster or an object from player;
103 truncate if longer than PL_PSIZ, then return it */
104 staticfn char *
105 name_from_player(
106 char *outbuf, /* output buffer, assumed to be at least BUFSZ long;
107 * anything longer than PL_PSIZ will be truncated */
108 const char *prompt,
109 const char *defres) /* only used if EDIT_GETLIN is enabled; only useful
110 * if windowport xxx's xxx_getlin() supports that */
112 outbuf[0] = '\0';
113 #ifdef EDIT_GETLIN
114 if (defres && *defres)
115 Strcpy(outbuf, defres); /* default response from getlin() */
116 #else
117 nhUse(defres);
118 #endif
119 getlin(prompt, outbuf);
120 if (!*outbuf || *outbuf == '\033')
121 return NULL;
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';
127 return outbuf;
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 */
132 struct monst *
133 christen_monst(struct monst *mtmp, const char *name)
135 int lth;
136 char buf[PL_PSIZ];
138 /* dogname & catname are PL_PSIZ arrays; object names have same limit */
139 lth = (name && *name) ? ((int) strlen(name) + 1) : 0;
140 if (lth > PL_PSIZ) {
141 lth = PL_PSIZ;
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 */
146 if (lth)
147 Strcpy(MGIVENNAME(mtmp), name);
148 /* if 'mtmp' is leashed, persistent inventory window needs updating */
149 if (mtmp->mleashed)
150 update_inventory(); /* x - leash (attached to Fido) */
151 return mtmp;
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() */
157 staticfn boolean
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)
165 || mtmp->isshk);
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");
169 return TRUE;
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));
183 } else {
184 pline("%s is already called %s.",
185 upstart(strcpy(pronounbuf, mhe(mtmp))), monnambuf);
187 return TRUE;
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);
192 return TRUE;
194 return FALSE;
197 /* allow player to assign a name to some chosen monster */
198 staticfn void
199 do_mgivenname(void)
201 char buf[BUFSZ], monnambuf[BUFSZ], qbuf[QBUFSZ];
202 coord cc;
203 int cx, cy;
204 struct monst *mtmp = 0;
205 boolean do_swallow = FALSE;
207 if (Hallucination) {
208 You("would never recognize it anyway.");
209 return;
211 cc.x = u.ux;
212 cc.y = u.uy;
213 if (getpos(&cc, FALSE, "the monster you want to name") < 0
214 || !isok(cc.x, cc.y))
215 return;
216 cx = cc.x, cy = cc.y;
218 if (u_at(cx, cy)) {
219 if (u.usteed && canspotmon(u.usteed)) {
220 mtmp = u.usteed;
221 } else {
222 pline("This %s creature is called %s and cannot be renamed.",
223 beautiful(), svp.plname);
224 return;
226 } else
227 mtmp = m_at(cx, cy);
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)) {
234 mtmp = u.ustuck;
235 do_swallow = TRUE;
239 if (!do_swallow && (!mtmp
240 || (!sensemon(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.");
247 return;
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))
255 return;
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);
279 } else {
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.
289 staticfn void
290 do_oname(struct obj *obj)
292 char *bufp, buf[BUFSZ], bufcpy[BUFSZ], qbuf[QBUFSZ];
293 const char *aname;
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));
299 return;
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)))
307 return;
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");
326 return;
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 */
333 Strcpy(buf, aname);
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) */
345 Strcpy(bufcpy, buf);
346 /* for "the Foo of Bar", only scuff "Foo of Bar" part */
347 bufp = !strncmpi(buf, "the ", 4) ? (buf + 4) : buf;
348 do {
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 */
359 assert(aname != 0);
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) */
364 Strcpy(buf, aname);
367 obj = oname(obj, buf, ONAME_VIA_NAMING | ONAME_KNOW_ARTI);
368 nhUse(obj);
371 struct obj *
372 oname(
373 struct obj *obj, /* item to assign name to */
374 const char *name, /* name to assign */
375 unsigned oflgs) /* flags, mostly for artifact creation */
377 int lth;
378 char buf[PL_PSIZ];
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;
383 if (lth > PL_PSIZ) {
384 lth = PL_PSIZ;
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)))
393 return obj;
395 new_oname(obj, lth); /* removes old name if one is present */
396 if (lth)
397 Strcpy(ONAME(obj), name);
399 if (lth)
400 artifact_exists(obj, name, TRUE, oflgs);
401 if (obj->oartifact) {
402 /* can't dual-wield with artifact as secondary weapon */
403 if (obj == uswapwep)
404 untwoweapon();
405 /* activate warning if you've just named your weapon "Sting" */
406 if (obj == uwep)
407 set_artifact_intrinsic(obj, TRUE, W_WEP);
408 /* if obj is owned by a shop, increase your bill */
409 if (obj->unpaid)
410 alter_cost(obj, 0L);
411 if (via_naming) {
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));
417 else
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)
424 update_inventory();
425 return obj;
428 boolean
429 objtyp_is_callable(int i)
431 if (objects[i].oc_uname)
432 return TRUE;
434 switch(objects[i].oc_class) {
435 case AMULET_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 */
445 FALLTHROUGH;
446 /*FALLTHRU*/
447 case SCROLL_CLASS:
448 case POTION_CLASS:
449 case WAND_CLASS:
450 case RING_CLASS:
451 case GEM_CLASS:
452 case SPBOOK_CLASS:
453 case ARMOR_CLASS:
454 case TOOL_CLASS:
455 case VENOM_CLASS:
456 if (OBJ_DESCR(objects[i]))
457 return TRUE;
458 break;
459 default:
460 break;
462 return FALSE;
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 */
499 docallcmd(void)
501 struct obj *obj;
502 winid win;
503 anything any;
504 menu_item *pick_list = 0;
505 struct _cmd_queue cq, *cmdq;
506 char ch = 0;
507 /* if player wants a,b,c instead of i,o when looting, do that here too */
508 boolean abc = flags.lootabc;
509 int clr = NO_COLOR;
511 if ((cmdq = cmdq_pop()) != 0) {
512 cq = *cmdq;
513 free((genericptr_t) cmdq);
514 if (cq.typ == CMDQ_KEY)
515 ch = cq.key;
516 else
517 cmdq_clear(CQ_CANNED);
518 goto docallcmd;
520 win = create_nhwindow(NHW_MENU);
521 start_menu(win, MENU_BEHAVE_STANDARD);
522 any = cg.zeroany;
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);
526 if (gi.invent) {
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);
554 } else
555 ch = 'q';
556 destroy_nhwindow(win);
558 docallcmd:
559 switch (ch) {
560 default:
561 case 'q':
562 break;
563 case 'm': /* name a visible monster */
564 do_mgivenname();
565 break;
566 case 'i': /* name an individual object in inventory */
567 obj = getobj("name", name_ok, GETOBJ_PROMPT);
568 if (obj)
569 do_oname(obj);
570 break;
571 case 'o': /* name a type of object in inventory */
572 obj = getobj("call", call_ok, GETOBJ_NOFLAGS);
573 if (obj) {
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 */
577 (void) xname(obj);
579 if (!obj->dknown) {
580 You("would never recognize another one.");
581 #if 0
582 } else if (call_ok(obj) == GETOBJ_EXCLUDE) {
583 You("know those as well as you ever will.");
584 #endif
585 } else {
586 docall(obj);
589 break;
590 case 'f': /* name a type of object visible on the floor */
591 namefloorobj();
592 break;
593 case 'd': /* name a type of object on the discoveries list */
594 rename_disco();
595 break;
596 case 'a': /* annotate level */
597 donamelevel();
598 break;
600 return ECMD_OK;
603 /* for use by safe_qbuf() */
604 staticfn char *
605 docall_xname(struct obj *obj)
607 struct obj otemp;
609 otemp = *obj;
610 otemp.oextra = (struct oextra *) 0;
611 otemp.quan = 1L;
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));
635 void
636 docall(struct obj *obj)
638 char buf[BUFSZ], qbuf[QBUFSZ];
639 char **uname_p;
640 boolean had_name = FALSE;
642 if (!obj->dknown)
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]));
650 else
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))
657 return;
659 /* clear old name */
660 if (*uname_p) {
661 had_name = TRUE;
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);
667 if (!*buf) {
668 if (had_name) /* possibly remove from disco[]; old *uname_p is gone */
669 undiscover_object(obj->otyp);
670 } else {
671 *uname_p = dupstr(buf);
672 discover_object(obj->otyp, FALSE, TRUE); /* possibly add to disco[] */
676 staticfn void
677 namefloorobj(void)
679 coord cc;
680 int glyph;
681 char buf[BUFSZ];
682 struct obj *obj = 0;
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))
691 ? "over" : "under");
692 if (getpos(&cc, FALSE, buf) < 0 || cc.x <= 0)
693 return;
694 if (u_at(cc.x, cc.y)) {
695 obj = vobj_at(u.ux, u.uy);
696 } else {
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 */
702 if (!obj) {
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");
706 return;
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)
714 ? simpleonames(obj)
715 : obj_descr[STRANGE_OBJECT].oc_name);
716 use_plural = (obj->quan > 1L);
717 if (Hallucination) {
718 const char *unames[6];
719 char tmpbuf[BUFSZ];
721 /* straight role name */
722 unames[0] = ((Upolyd ? u.mfemale : flags.female) && gu.urole.name.f)
723 ? gu.urole.name.f
724 : gu.urole.name.m;
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];
735 /* traditional */
736 unames[4] = roguename();
737 /* silly */
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");
748 } else {
749 docall(obj);
751 if (fakeobj) {
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 */
769 const char *
770 rndghostname(void)
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
783 * or something
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
788 * or Something
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
800 * article
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.
809 * suppress
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.
824 char *
825 x_monnam(
826 struct monst *mtmp,
827 int article,
828 const char *adjective,
829 int suppress,
830 boolean called)
832 char *buf = nextmbuf();
833 struct permonst *mdat = mtmp->data;
834 const char *pm_name;
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;
870 buf[0] = '\0';
872 /* unseen monsters, etc.; usually "it" but sometimes more specific;
873 when hallucinating, the more specific values might be inverted */
874 if (do_it) {
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"
880 : "something");
881 return buf;
884 /* priests and minions: don't even use this function */
885 if ((mtmp->ispriest || mtmp->isminion) && !do_mappear) {
886 char *name;
887 long save_prop = EHalluc_resistance;
888 unsigned save_invis = mtmp->minvis;
890 /* when true name is wanted, explicitly block Hallucination */
891 if (!do_hallu)
892 EHalluc_resistance = 1L;
893 if (!do_invis)
894 mtmp->minvis = 0;
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))
900 name += 4;
901 return strcpy(buf, name);
904 /* 'pm_name' is the base part of most names */
905 if (do_mappear) {
906 /*assert(ismnum(mtmp->mappearance));*/
907 pm_name = pmname(&mons[mtmp->mappearance], Mgender(mtmp));
908 } else {
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"
920 sounds silly */
921 Strcpy(buf, "the ");
922 Strcat(strcat(buf, adjective), " ");
923 Strcat(buf, shkname(mtmp));
924 } else {
925 Strcat(buf, shkname(mtmp));
926 if (mdat != &mons[PM_SHOPKEEPER] || do_invis){
927 Strcat(buf, " the ");
928 if (do_invis)
929 Strcat(buf, "invisible ");
930 Strcat(buf, pm_name);
933 return buf;
936 /* Put the adjectives in the buffer */
937 if (adjective)
938 Strcat(strcat(buf, adjective), " ");
939 if (do_invis)
940 Strcat(buf, "invisible ");
941 if (do_saddle && (mtmp->misc_worn_check & W_SADDLE) && !Blind
942 && !Hallucination)
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. */
948 if (do_hallu) {
949 char rnamecode;
950 char *rname = rndmonnam(&rnamecode);
952 Strcat(buf, rname);
953 name_at_start = bogon_is_pname(rnamecode);
954 } else if (do_name && has_mgivenname(mtmp)) {
955 char *name = MGIVENNAME(mtmp);
957 #if 0
958 /* hardfought */
959 if (has_ebones(mtmp)) {
960 #endif
961 if (mdat == &mons[PM_GHOST]) {
962 Sprintf(eos(buf), "%s ghost", s_suffix(name));
963 name_at_start = TRUE;
964 } else if (called) {
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> */
969 char pbuf[BUFSZ];
971 Strcpy(pbuf, name);
972 pbuf[bp - name + 5] = '\0'; /* adjectives right after " the " */
973 if (has_adjectives)
974 Strcat(pbuf, buf);
975 Strcat(pbuf, bp + 5); /* append the rest of the name */
976 Strcpy(buf, pbuf);
977 article = ARTICLE_NONE;
978 name_at_start = TRUE;
979 } else {
980 Strcat(buf, name);
981 name_at_start = TRUE;
983 #if 0 /* hardfought */
985 #endif
986 } else if (is_mplayer(mdat) && !In_endgame(&u.uz)) {
987 char pbuf[BUFSZ];
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;
993 } else {
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;
1001 else
1002 article = ARTICLE_NONE;
1003 } else if ((mdat->geno & G_UNIQ) != 0 && article == ARTICLE_A) {
1004 article = ARTICLE_THE;
1007 insertbuf2 = TRUE;
1008 buf2[0] = '\0'; /* lint suppression */
1009 switch (article) {
1010 case ARTICLE_YOUR:
1011 Strcpy(buf2, "your ");
1012 break;
1013 case ARTICLE_THE:
1014 Strcpy(buf2, "the ");
1015 break;
1016 case ARTICLE_A:
1017 /* avoid an() here */
1018 (void) just_an(buf2, buf); /* copy "a " or "an " into buf2[] */
1019 break;
1020 case ARTICLE_NONE:
1021 default:
1022 insertbuf2 = FALSE;
1023 break;
1025 if (insertbuf2) {
1026 Strcat(buf2, buf); /* buf2[] isn't viable to return, */
1027 Strcpy(buf, buf2); /* so transfer the result to buf[] */
1029 return buf;
1032 char *
1033 l_monnam(struct monst *mtmp)
1035 return x_monnam(mtmp, ARTICLE_NONE, (char *) 0,
1036 (has_mgivenname(mtmp)) ? SUPPRESS_SADDLE : 0, TRUE);
1039 char *
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 */
1051 char *
1052 noit_mon_nam(struct monst *mtmp)
1054 return x_monnam(mtmp, ARTICLE_YOUR, (char *) 0,
1055 (has_mgivenname(mtmp) ? (SUPPRESS_SADDLE | SUPPRESS_IT)
1056 : SUPPRESS_IT),
1057 FALSE);
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 */
1062 char *
1063 some_mon_nam(struct monst *mtmp)
1065 return x_monnam(mtmp, ARTICLE_THE, (char *) 0,
1066 (has_mgivenname(mtmp) ? (SUPPRESS_SADDLE | AUGMENT_IT)
1067 : AUGMENT_IT),
1068 FALSE);
1071 char *
1072 Monnam(struct monst *mtmp)
1074 char *bp = mon_nam(mtmp);
1076 *bp = highc(*bp);
1077 return bp;
1080 char *
1081 noit_Monnam(struct monst *mtmp)
1083 char *bp = noit_mon_nam(mtmp);
1085 *bp = highc(*bp);
1086 return bp;
1089 char *
1090 Some_Monnam(struct monst *mtmp)
1092 char *bp = some_mon_nam(mtmp);
1094 *bp = highc(*bp);
1095 return bp;
1098 /* return "a dog" rather than "Fido", honoring hallucination and visibility */
1099 char *
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) */
1107 char *
1108 m_monnam(struct monst *mtmp)
1110 return x_monnam(mtmp, ARTICLE_NONE, (char *) 0, EXACT_NAME, FALSE);
1113 /* pet name: "your little dog" */
1114 char *
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)
1123 ? SUPPRESS_SADDLE
1124 : 0;
1126 return x_monnam(mtmp, prefix, (char *) 0, suppression_flag, FALSE);
1129 /* y_monnam() for start of sentence */
1130 char *
1131 YMonnam(struct monst *mtmp)
1133 char *bp = y_monnam(mtmp);
1135 *bp = highc(*bp);
1136 return bp;
1139 char *
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);
1145 *bp = highc(*bp);
1146 return bp;
1149 char *
1150 a_monnam(struct monst *mtmp)
1152 return x_monnam(mtmp, ARTICLE_A, (char *) 0,
1153 has_mgivenname(mtmp) ? SUPPRESS_SADDLE : 0, FALSE);
1156 char *
1157 Amonnam(struct monst *mtmp)
1159 char *bp = a_monnam(mtmp);
1161 *bp = highc(*bp);
1162 return bp;
1165 /* used for monster ID by the '/', ';', and 'C' commands to block remote
1166 identification of the endgame altars via their attending priests */
1167 char *
1168 distant_monnam(
1169 struct monst *mon,
1170 int article, /* only ARTICLE_NONE and ARTICLE_THE are handled here */
1171 char *outbuf)
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");
1180 } else {
1181 Strcpy(outbuf, x_monnam(mon, article, (char *) 0, 0, TRUE));
1183 return outbuf;
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 */
1188 char *
1189 mon_nam_too(struct monst *mon, struct monst *other_mon)
1191 char *outbuf;
1193 if (mon != other_mon) {
1194 outbuf = mon_nam(mon);
1195 } else {
1196 outbuf = nextmbuf();
1197 switch (pronoun_gender(mon, PRONOUN_HALLU)) {
1198 case 0:
1199 Strcpy(outbuf, "himself");
1200 break;
1201 case 1:
1202 Strcpy(outbuf, "herself");
1203 break;
1204 default:
1205 case 2:
1206 Strcpy(outbuf, "itself");
1207 break;
1208 case 3: /* could happen when hallucinating */
1209 Strcpy(outbuf, "themselves");
1210 break;
1213 return outbuf;
1216 /* construct "<monnamtext> <verb> <othertext> {him|her|it}self" which might
1217 be distorted by Hallu; if that's plural, adjust monnamtext and verb */
1218 char *
1219 monverbself(
1220 struct monst *mon,
1221 char *monnamtext, /* modifiable 'mbuf' with adequate room at end */
1222 const char *verb,
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);
1238 if (capitaliz)
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);
1246 return monnamtext;
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 */
1251 char *
1252 minimal_monnam(struct monst *mon, boolean ckloc)
1254 struct permonst *ptr;
1255 char *outbuf = nextmbuf();
1257 if (!mon) {
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)),
1273 mon->mx, mon->my);
1274 } else {
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)));
1282 return outbuf;
1285 #ifndef PMNAME_MACROS
1287 Mgender(struct monst *mtmp)
1289 int mgender = MALE;
1291 if (mtmp == &gy.youmonst) {
1292 if (Upolyd ? u.mfemale : flags.female)
1293 mgender = FEMALE;
1294 } else if (mtmp->female) {
1295 mgender = FEMALE;
1297 return mgender;
1300 const char *
1301 pmname(struct permonst *pm, int mgender)
1303 if (mgender < MALE || mgender >= NUM_MGENDERS || !pm->pmnames[mgender])
1304 mgender = NEUTRAL;
1305 return pm->pmnames[mgender];
1307 #endif /* PMNAME_MACROS */
1309 /* mons[]->pmname for a monster */
1310 const char *
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 */
1318 const char *
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));
1332 #endif
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
1338 : NEUTRAL),
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)
1351 mndx = PM_CLERIC;
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
1361 use this list.
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 */
1366 char *
1367 bogusmon(char *buf, char *code)
1369 char *mnam = buf;
1371 if (code)
1372 *code = '\0';
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);
1375 if (!*mnam) {
1376 Strcpy(buf, "bogon");
1377 } else if (strchr(bogon_codes, *mnam)) { /* strip prefix if present */
1378 if (code)
1379 *code = *mnam;
1380 ++mnam;
1382 return mnam;
1385 /* return a random monster name, for hallucination */
1386 char *
1387 rndmonnam(char *code)
1389 static char buf[BUFSZ];
1390 char *mnam;
1391 int name;
1392 #define BOGUSMONSIZE 100 /* arbitrary */
1394 if (code)
1395 *code = '\0';
1397 do {
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);
1404 } else {
1405 mnam = strcpy(buf, pmname(&mons[name], rn2_on_display_rng(2)));
1407 return mnam;
1408 #undef BOGUSMONSIZE
1411 /* check bogusmon prefix to decide whether it's a personal name */
1412 boolean
1413 bogon_is_pname(char code)
1415 if (!code)
1416 return FALSE;
1417 return strchr("-+=", code) ? TRUE : FALSE;
1420 /* name of a Rogue player */
1421 const char *
1422 roguename(void)
1424 char *i, *opts;
1426 if ((opts = nh_getenv("ROGUEOPTS")) != 0) {
1427 for (i = opts; *i; i++)
1428 if (!strncmp("name=", i, 5)) {
1429 char *j;
1430 if ((j = strchr(i + 5, ',')) != 0)
1431 *j = (char) 0;
1432 return i + 5;
1435 return rn2(3) ? (rn2(2) ? "Michael Toy" : "Kenneth Arnold")
1436 : "Glenn Wichman";
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",
1458 const char *
1459 hcolor(const char *colorpref)
1461 return (Hallucination || !colorpref)
1462 ? hcolors[rn2_on_display_rng(SIZE(hcolors))]
1463 : colorpref;
1466 /* return a random real color unless hallucinating */
1467 const char *
1468 rndcolor(void)
1470 int k = rn2(CLR_MAX);
1472 return Hallucination ? hcolor((char *) 0)
1473 : (k == NO_COLOR) ? "colorless"
1474 : c_obj_colors[k];
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",
1485 "cosmic latte",
1486 /* "new coke (tm)", --better not */
1489 /* if hallucinating, return a random liquid instead of 'liquidpref' */
1490 const char *
1491 hliquid(
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)
1502 ++count;
1503 indx = rn2_on_display_rng(count);
1504 if (IndexOk(indx, hliquids))
1505 return hliquids[indx];
1507 return liquidpref;
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",
1520 "Canis latrans"
1523 char *
1524 coyotename(struct monst *mtmp, char *buf)
1526 if (mtmp && 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)]);
1532 return buf;
1535 char *
1536 rndorcname(char *s)
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);
1543 if (s) {
1544 *s = '\0';
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));
1551 return s;
1554 struct monst *
1555 christen_orc(struct monst *mtmp, const char *gang, const char *other)
1557 int sz = 0;
1558 char buf[BUFSZ], buf2[BUFSZ], *orcname;
1560 orcname = rndorcname(buf2);
1561 /* rndorcname() won't return NULL */
1562 sz = (int) strlen(orcname);
1563 if (gang)
1564 sz += (int) (strlen(gang) + sizeof " of " - sizeof "");
1565 else if (other)
1566 sz += (int) strlen(other);
1568 if (sz < BUFSZ) {
1569 char gbuf[BUFSZ];
1570 boolean nameit = FALSE;
1572 if (gang) {
1573 Sprintf(buf, "%s of %s", upstart(orcname),
1574 upstart(strcpy(gbuf, gang)));
1575 nameit = TRUE;
1576 } else if (other) {
1577 Sprintf(buf, "%s%s", upstart(orcname), other);
1578 nameit = TRUE;
1580 if (nameit)
1581 mtmp = christen_monst(mtmp, buf);
1583 return mtmp;
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
1606 #define NVL_THUD 33
1608 const char *
1609 noveltitle(int *novidx)
1611 int j, k = SIZE(sir_Terry_novels);
1613 j = rn2(k);
1614 if (novidx) {
1615 if (*novidx == -1)
1616 *novidx = j;
1617 else if (*novidx >= 0 && *novidx < k)
1618 j = *novidx;
1620 return sir_Terry_novels[j];
1623 /* figure out canonical novel title from player-specified one */
1624 const char *
1625 lookup_novel(const char *lookname, int *idx)
1627 int k;
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])) {
1649 if (idx)
1650 *idx = 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;
1661 /*do_name.c*/