1 /* SCCS Id: @(#)do_name.c 3.4 2003/01/14 */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
4
5 #include "hack.h"
6
7 #ifdef VULTURE_GRAPHICS
8 # include "vulture_main.h"
9 #endif
10 #ifdef OVLB
11
12 STATIC_DCL void FDECL(do_oname, (struct obj *));
13 static void FDECL(getpos_help, (BOOLEAN_P,const char *));
14
15 extern const char what_is_an_unknown_object[]; /* from pager.c */
16
17 /* the response for '?' help request in getpos() */
18 static void
getpos_help(force,goal)19 getpos_help(force, goal)
20 boolean force;
21 const char *goal;
22 {
23 char sbuf[BUFSZ];
24 boolean doing_what_is;
25 winid tmpwin = create_nhwindow(NHW_MENU);
26
27 Sprintf(sbuf, "Use [%s] to move the cursor to %s.",
28 iflags.num_pad ? "2468" : "hjkl", goal);
29 putstr(tmpwin, 0, sbuf);
30 putstr(tmpwin, 0, "Use [HJKL] to move the cursor 8 units at a time.");
31 putstr(tmpwin, 0, "Or enter a background symbol (ex. <).");
32 /* disgusting hack; the alternate selection characters work for any
33 getpos call, but they only matter for dowhatis (and doquickwhatis) */
34 doing_what_is = (goal == what_is_an_unknown_object);
35 Sprintf(sbuf, "Type a .%s when you are at the right place.",
36 doing_what_is ? " or , or ; or :" : "");
37 putstr(tmpwin, 0, sbuf);
38 if (!force)
39 putstr(tmpwin, 0, "Type Space or Escape when you're done.");
40 putstr(tmpwin, 0, "");
41 display_nhwindow(tmpwin, TRUE);
42 destroy_nhwindow(tmpwin);
43 }
44
45 int
getpos(cc,force,goal)46 getpos(cc, force, goal)
47 coord *cc;
48 boolean force;
49 const char *goal;
50 {
51 int result = 0;
52 int cx, cy, i, c;
53 int sidx, tx, ty;
54 boolean msg_given = TRUE; /* clear message window by default */
55 static const char pick_chars[] = ".,;:";
56 const char *cp;
57 const char *sdp;
58 if(iflags.num_pad) sdp = ndir; else sdp = sdir; /* DICE workaround */
59
60 if (flags.verbose) {
61 pline("(For instructions type a ?)");
62 msg_given = TRUE;
63 }
64 cx = cc->x;
65 cy = cc->y;
66 #ifdef CLIPPING
67 cliparound(cx, cy);
68 #endif
69 curs(WIN_MAP, cx,cy);
70 flush_screen(0);
71 #ifdef MAC
72 lock_mouse_cursor(TRUE);
73 #endif
74 for (;;) {
75 #ifdef VULTURE_GRAPHICS
76 /* Hack to allow nh_poskey to detect the calling function (yuck!). */
77 vulture_whatis_active = 1;
78 #endif
79 c = nh_poskey(&tx, &ty, &sidx);
80 if (c == '\033') {
81 cx = cy = -10;
82 msg_given = TRUE; /* force clear */
83 result = -1;
84 break;
85 }
86 if(c == 0) {
87 if (!isok(tx, ty)) continue;
88 /* a mouse click event, just assign and return */
89 cx = tx;
90 cy = ty;
91 break;
92 }
93 if ((cp = index(pick_chars, c)) != 0) {
94 /* '.' => 0, ',' => 1, ';' => 2, ':' => 3 */
95 result = cp - pick_chars;
96 break;
97 }
98 for (i = 0; i < 8; i++) {
99 int dx, dy;
100
101 if (sdp[i] == c) {
102 /* a normal movement letter or digit */
103 dx = xdir[i];
104 dy = ydir[i];
105 } else if (sdir[i] == lowc((char)c)) {
106 /* a shifted movement letter */
107 dx = 8 * xdir[i];
108 dy = 8 * ydir[i];
109 } else
110 continue;
111
112 /* truncate at map edge; diagonal moves complicate this... */
113 if (cx + dx < 1) {
114 dy -= sgn(dy) * (1 - (cx + dx));
115 dx = 1 - cx; /* so that (cx+dx == 1) */
116 } else if (cx + dx > COLNO-1) {
117 dy += sgn(dy) * ((COLNO-1) - (cx + dx));
118 dx = (COLNO-1) - cx;
119 }
120 if (cy + dy < 0) {
121 dx -= sgn(dx) * (0 - (cy + dy));
122 dy = 0 - cy; /* so that (cy+dy == 0) */
123 } else if (cy + dy > ROWNO-1) {
124 dx += sgn(dx) * ((ROWNO-1) - (cy + dy));
125 dy = (ROWNO-1) - cy;
126 }
127 cx += dx;
128 cy += dy;
129 goto nxtc;
130 }
131
132 if(c == '?'){
133 getpos_help(force, goal);
134 } else {
135 if (!index(quitchars, c)) {
136 char matching[MAXPCHARS];
137 int pass, lo_x, lo_y, hi_x, hi_y, k = 0;
138 (void)memset((genericptr_t)matching, 0, sizeof matching);
139 for (sidx = 1; sidx < MAXPCHARS; sidx++)
140 if (c == defsyms[sidx].sym || c == (int)showsyms[sidx])
141 matching[sidx] = (char) ++k;
142 if (k) {
143 for (pass = 0; pass <= 1; pass++) {
144 /* pass 0: just past current pos to lower right;
145 pass 1: upper left corner to current pos */
146 lo_y = (pass == 0) ? cy : 0;
147 hi_y = (pass == 0) ? ROWNO - 1 : cy;
148 for (ty = lo_y; ty <= hi_y; ty++) {
149 lo_x = (pass == 0 && ty == lo_y) ? cx + 1 : 1;
150 hi_x = (pass == 1 && ty == hi_y) ? cx : COLNO - 1;
151 for (tx = lo_x; tx <= hi_x; tx++) {
152 /* look at dungeon feature, not at user-visible glyph */
153 k = back_to_glyph(tx,ty);
154 /* uninteresting background glyph */
155 if (glyph_is_cmap(k) &&
156 (IS_DOOR(levl[tx][ty].typ) || /* monsters mimicking a door */
157 glyph_to_cmap(k) == S_darkroom ||
158 glyph_to_cmap(k) == S_room ||
159 glyph_to_cmap(k) == S_corr ||
160 glyph_to_cmap(k) == S_litcorr)) {
161 /* what the user remembers to be at tx,ty */
162 k = glyph_at(tx, ty);
163 }
164 /* TODO: - open doors are only matched with '-' */
165 /* should remembered or seen items be matched? */
166 if (glyph_is_cmap(k) &&
167 matching[glyph_to_cmap(k)] &&
168 levl[tx][ty].seenv && /* only if already seen */
169 (!IS_WALL(levl[tx][ty].typ) &&
170 (levl[tx][ty].typ != SDOOR) &&
171 glyph_to_cmap(k) != S_room &&
172 glyph_to_cmap(k) != S_corr &&
173 glyph_to_cmap(k) != S_litcorr)
174 ) {
175 cx = tx, cy = ty;
176 if (msg_given) {
177 clear_nhwindow(WIN_MESSAGE);
178 msg_given = FALSE;
179 }
180 goto nxtc;
181 }
182 } /* column */
183 } /* row */
184 } /* pass */
185 pline("Can't find dungeon feature '%c'.", c);
186 msg_given = TRUE;
187 goto nxtc;
188 } else {
189 pline("Unknown direction: '%s' (%s).",
190 visctrl((char)c),
191 !force ? "aborted" :
192 iflags.num_pad ? "use 2468 or ." : "use hjkl or .");
193 msg_given = TRUE;
194 } /* k => matching */
195 } /* !quitchars */
196 if (force) goto nxtc;
197 pline("Done.");
198 msg_given = FALSE; /* suppress clear */
199 cx = -1;
200 cy = 0;
201 result = 0; /* not -1 */
202 break;
203 }
204 nxtc: ;
205 #ifdef CLIPPING
206 cliparound(cx, cy);
207 #endif
208 curs(WIN_MAP,cx,cy);
209 flush_screen(0);
210 }
211 #ifdef MAC
212 lock_mouse_cursor(FALSE);
213 #endif
214 if (msg_given) clear_nhwindow(WIN_MESSAGE);
215 cc->x = cx;
216 cc->y = cy;
217 #ifdef VULTURE_GRAPHICS
218 /* Hack to allow nh_poskey to detect the calling function (yuck!). */
219 vulture_whatis_active = 0;
220 #endif
221 return result;
222 }
223
224 struct monst *
christen_monst(mtmp,name)225 christen_monst(mtmp, name)
226 struct monst *mtmp;
227 const char *name;
228 {
229 int lth;
230 struct monst *mtmp2;
231 char buf[PL_PSIZ];
232
233 /* dogname & catname are PL_PSIZ arrays; object names have same limit */
234 lth = *name ? (int)(strlen(name) + 1) : 0;
235 if(lth > PL_PSIZ){
236 lth = PL_PSIZ;
237 name = strncpy(buf, name, PL_PSIZ - 1);
238 buf[PL_PSIZ - 1] = '\0';
239 }
240 if (lth == mtmp->mnamelth) {
241 /* don't need to allocate a new monst struct */
242 if (lth) Strcpy(NAME(mtmp), name);
243 return mtmp;
244 }
245 mtmp2 = newmonst(mtmp->mxlth + lth);
246 *mtmp2 = *mtmp;
247 (void) memcpy((genericptr_t)mtmp2->mextra,
248 (genericptr_t)mtmp->mextra, mtmp->mxlth);
249 mtmp2->mnamelth = lth;
250 if (lth) Strcpy(NAME(mtmp2), name);
251 replmon(mtmp,mtmp2);
252 return(mtmp2);
253 }
254
255 int
do_mname()256 do_mname()
257 {
258 char buf[BUFSZ];
259 coord cc;
260 register int cx,cy;
261 register struct monst *mtmp;
262 char qbuf[QBUFSZ];
263
264 if (Hallucination) {
265 You("would never recognize it anyway.");
266 return 0;
267 }
268 cc.x = u.ux;
269 cc.y = u.uy;
270 if (getpos(&cc, FALSE, "the monster you want to name") < 0 ||
271 (cx = cc.x) < 0)
272 return 0;
273 cy = cc.y;
274
275 if (cx == u.ux && cy == u.uy) {
276 #ifdef STEED
277 if (u.usteed && canspotmon(u.usteed))
278 mtmp = u.usteed;
279 else {
280 #endif
281 pline("This %s creature is called %s and cannot be renamed.",
282 beautiful(),
283 plname);
284 return(0);
285 #ifdef STEED
286 }
287 #endif
288 } else
289 mtmp = m_at(cx, cy);
290
291 if (!mtmp || (!sensemon(mtmp) &&
292 (!(cansee(cx,cy) || see_with_infrared(mtmp)) || mtmp->mundetected
293 || mtmp->m_ap_type == M_AP_FURNITURE
294 || mtmp->m_ap_type == M_AP_OBJECT
295 || (mtmp->minvis && !See_invisible)))) {
296 pline("I see no monster there.");
297 return(0);
298 }
299 /* special case similar to the one in lookat() */
300 (void) distant_monnam(mtmp, ARTICLE_THE, buf);
301 Sprintf(qbuf, "What do you want to call %s?", buf);
302 getlin(qbuf,buf);
303 if(!*buf || *buf == '\033') return(0);
304 /* strip leading and trailing spaces; unnames monster if all spaces */
305 (void)mungspaces(buf);
306
307 if (mtmp->data->geno & G_UNIQ)
308 pline("%s doesn't like being called names!", Monnam(mtmp));
309 else
310 (void) christen_monst(mtmp, buf);
311 return(0);
312 }
313
314 /*
315 * This routine changes the address of obj. Be careful not to call it
316 * when there might be pointers around in unknown places. For now: only
317 * when obj is in the inventory.
318 */
319 STATIC_OVL
320 void
do_oname(obj)321 do_oname(obj)
322 register struct obj *obj;
323 {
324 char buf[BUFSZ], qbuf[QBUFSZ];
325 const char *aname;
326 short objtyp;
327
328 Sprintf(qbuf, "What do you want to name %s %s?",
329 is_plural(obj) ? "these" : "this",
330 safe_qbuf("", sizeof("What do you want to name these ?"),
331 xname(obj), simple_typename(obj->otyp),
332 is_plural(obj) ? "things" : "thing"));
333 getlin(qbuf, buf);
334 if(!*buf || *buf == '\033') return;
335 /* strip leading and trailing spaces; unnames item if all spaces */
336 (void)mungspaces(buf);
337
338 /* relax restrictions over proper capitalization for artifacts */
339 if ((aname = artifact_name(buf, &objtyp)) != 0 && objtyp == obj->otyp)
340 Strcpy(buf, aname);
341
342 if (obj->oartifact) {
343 pline_The("artifact seems to resist the attempt.");
344 return;
345 } else if (restrict_name(obj, buf, FALSE) || exist_artifact(obj->otyp, buf)) {
346 int n = rn2((int)strlen(buf));
347 register char c1, c2;
348
349 c1 = lowc(buf[n]);
350 do c2 = 'a' + rn2('z'-'a'); while (c1 == c2);
351 buf[n] = (buf[n] == c1) ? c2 : highc(c2); /* keep same case */
352 pline("While engraving your %s slips.", body_part(HAND));
353 display_nhwindow(WIN_MESSAGE, FALSE);
354 You("engrave: \"%s\".",buf);
355 }
356 obj = oname(obj, buf);
357 }
358
359 /*
360 * Allocate a new and possibly larger storage space for an obj.
361 */
362 struct obj *
realloc_obj(obj,oextra_size,oextra_src,oname_size,name)363 realloc_obj(obj, oextra_size, oextra_src, oname_size, name)
364 struct obj *obj;
365 int oextra_size; /* storage to allocate for oextra */
366 genericptr_t oextra_src;
367 int oname_size; /* size of name string + 1 (null terminator) */
368 const char *name;
369 {
370 struct obj *otmp;
371
372 otmp = newobj(oextra_size + oname_size);
373 *otmp = *obj; /* the cobj pointer is copied to otmp */
374 if (oextra_size) {
375 if (oextra_src)
376 (void) memcpy((genericptr_t)otmp->oextra, oextra_src,
377 oextra_size);
378 } else {
379 otmp->oattached = OATTACHED_NOTHING;
380 }
381 otmp->oxlth = oextra_size;
382
383 otmp->onamelth = oname_size;
384 otmp->timed = 0; /* not timed, yet */
385 otmp->lamplit = 0; /* ditto */
386 /* __GNUC__ note: if the assignment of otmp->onamelth immediately
387 precedes this `if' statement, a gcc bug will miscompile the
388 test on vax (`insv' instruction used to store bitfield does
389 not set condition codes, but optimizer behaves as if it did).
390 gcc-2.7.2.1 finally fixed this. */
391 if (oname_size) {
392 if (name)
393 Strcpy(ONAME(otmp), name);
394 }
395
396 if (obj->owornmask) {
397 boolean save_twoweap = u.twoweap;
398 /* unwearing the old instance will clear dual-wield mode
399 if this object is either of the two weapons */
400 setworn((struct obj *)0, obj->owornmask);
401 setworn(otmp, otmp->owornmask);
402 u.twoweap = save_twoweap;
403 }
404
405 /* replace obj with otmp */
406 replace_object(obj, otmp);
407
408 /* fix ocontainer pointers */
409 if (Has_contents(obj)) {
410 struct obj *inside;
411
412 for(inside = obj->cobj; inside; inside = inside->nobj)
413 inside->ocontainer = otmp;
414 }
415
416 /* move timers and light sources from obj to otmp */
417 if (obj->timed) obj_move_timers(obj, otmp);
418 if (obj->lamplit) obj_move_light_source(obj, otmp);
419
420 /* objects possibly being manipulated by multi-turn occupations
421 which have been interrupted but might be subsequently resumed */
422 if (obj->oclass == FOOD_CLASS)
423 food_substitution(obj, otmp); /* eat food or open tin */
424 else if (obj->oclass == SPBOOK_CLASS)
425 book_substitution(obj, otmp); /* read spellbook */
426
427 /* obfree(obj, otmp); now unnecessary: no pointers on bill */
428 dealloc_obj(obj); /* let us hope nobody else saved a pointer */
429 return otmp;
430 }
431
432 struct obj *
oname(obj,name)433 oname(obj, name)
434 struct obj *obj;
435 const char *name;
436 {
437 int lth;
438 char buf[PL_PSIZ];
439
440 lth = *name ? (int)(strlen(name) + 1) : 0;
441 if (lth > PL_PSIZ) {
442 lth = PL_PSIZ;
443 name = strncpy(buf, name, PL_PSIZ - 1);
444 buf[PL_PSIZ - 1] = '\0';
445 }
446 /* If named artifact exists in the game, do not create another.
447 * Also trying to create an artifact shouldn't de-artifact
448 * it (e.g. Excalibur from prayer). In this case the object
449 * will retain its current name. */
450 if (obj->oartifact || (lth && exist_artifact(obj->otyp, name)))
451 return obj;
452
453 if (lth == obj->onamelth) {
454 /* no need to replace entire object */
455 if (lth) Strcpy(ONAME(obj), name);
456 } else {
457 obj = realloc_obj(obj, obj->oxlth,
458 (genericptr_t)obj->oextra, lth, name);
459 }
460 if (lth) artifact_exists(obj, name, TRUE);
461 if (obj->oartifact) {
462 /* can't dual-wield with artifact as secondary weapon */
463 if (obj == uswapwep) untwoweapon();
464 /* activate warning if you've just named your weapon "Sting" */
465 if (obj == uwep) set_artifact_intrinsic(obj, TRUE, W_WEP);
466 }
467 if (carried(obj)) update_inventory();
468 return obj;
469 }
470
471 static NEARDATA const char callable[] = {
472 SCROLL_CLASS, POTION_CLASS, WAND_CLASS, RING_CLASS, AMULET_CLASS,
473 GEM_CLASS, SPBOOK_CLASS, ARMOR_CLASS, TOOL_CLASS, 0 };
474
475 int
ddocall()476 ddocall()
477 {
478 register struct obj *obj;
479 #ifdef REDO
480 char ch;
481 #endif
482 char allowall[2];
483
484 switch(
485 #ifdef REDO
486 ch =
487 #endif
488 ynq("Name an individual object?")) {
489 case 'q':
490 break;
491 case 'y':
492 #ifdef REDO
493 savech(ch);
494 #endif
495 allowall[0] = ALL_CLASSES; allowall[1] = '\0';
496 obj = getobj(allowall, "name");
497 if(obj) do_oname(obj);
498 break;
499 default :
500 #ifdef REDO
501 savech(ch);
502 #endif
503 obj = getobj(callable, "call");
504 if (obj) {
505 /* behave as if examining it in inventory;
506 this might set dknown if it was picked up
507 while blind and the hero can now see */
508 (void) xname(obj);
509
510 if (!obj->dknown) {
511 You("would never recognize another one.");
512 return 0;
513 }
514 docall(obj);
515 }
516 break;
517 }
518 return 0;
519 }
520
521 void
docall(obj)522 docall(obj)
523 register struct obj *obj;
524 {
525 char buf[BUFSZ], qbuf[QBUFSZ];
526 struct obj otemp;
527 register char **str1;
528
529 if (!obj->dknown) return; /* probably blind */
530 check_tutorial_message(QT_T_CALLITEM);
531 otemp = *obj;
532 otemp.quan = 1L;
533 otemp.onamelth = 0;
534 otemp.oxlth = 0;
535 if (objects[otemp.otyp].oc_class == POTION_CLASS && otemp.fromsink)
536 /* kludge, meaning it's sink water */
537 Sprintf(qbuf,"Call a stream of %s fluid:",
538 OBJ_DESCR(objects[otemp.otyp]));
539 else
540 Sprintf(qbuf, "Call %s:", an(xname(&otemp)));
541 getlin(qbuf, buf);
542 if(!*buf || *buf == '\033')
543 return;
544
545 /* clear old name */
546 str1 = &(objects[obj->otyp].oc_uname);
547 if(*str1) free((genericptr_t)*str1);
548
549 /* strip leading and trailing spaces; uncalls item if all spaces */
550 (void)mungspaces(buf);
551 if (!*buf) {
552 if (*str1) { /* had name, so possibly remove from disco[] */
553 /* strip name first, for the update_inventory() call
554 from undiscover_object() */
555 *str1 = (char *)0;
556 undiscover_object(obj->otyp);
557 }
558 } else {
559 *str1 = strcpy((char *) alloc((unsigned)strlen(buf)+1), buf);
560 discover_object(obj->otyp, FALSE, TRUE); /* possibly add to disco[] */
561 }
562 }
563
564 #endif /*OVLB*/
565 #ifdef OVL0
566
567 static const char * const ghostnames[] = {
568 /* these names should have length < PL_NSIZ */
569 /* Capitalize the names for aesthetics -dgk */
570 "Adri", "Andries", "Andreas", "Bert", "David", "Dirk", "Emile",
571 "Frans", "Fred", "Greg", "Hether", "Jay", "John", "Jon", "Karnov",
572 "Kay", "Kenny", "Kevin", "Maud", "Michiel", "Mike", "Peter", "Robert",
573 "Ron", "Tom", "Wilmar", "Nick Danger", "Phoenix", "Jiro", "Mizue",
574 "Stephan", "Lance Braccus", "Shadowhawk"
575 };
576
577 /* ghost names formerly set by x_monnam(), now by makemon() instead */
578 const char *
rndghostname()579 rndghostname()
580 {
581 return rn2(7) ? ghostnames[rn2(SIZE(ghostnames))] : (const char *)plname;
582 }
583
584 /* Monster naming functions:
585 * x_monnam is the generic monster-naming function.
586 * seen unseen detected named
587 * mon_nam: the newt it the invisible orc Fido
588 * noit_mon_nam:the newt (as if detected) the invisible orc Fido
589 * l_monnam: newt it invisible orc dog called fido
590 * Monnam: The newt It The invisible orc Fido
591 * noit_Monnam: The newt (as if detected) The invisible orc Fido
592 * Adjmonnam: The poor newt It The poor invisible orc The poor Fido
593 * Amonnam: A newt It An invisible orc Fido
594 * a_monnam: a newt it an invisible orc Fido
595 * m_monnam: newt xan orc Fido
596 * y_monnam: your newt your xan your invisible orc Fido
597 */
598
599 /* Bug: if the monster is a priest or shopkeeper, not every one of these
600 * options works, since those are special cases.
601 */
602 char *
x_monnam(mtmp,article,adjective,suppress,called)603 x_monnam(mtmp, article, adjective, suppress, called)
604 register struct monst *mtmp;
605 int article;
606 /* ARTICLE_NONE, ARTICLE_THE, ARTICLE_A: obvious
607 * ARTICLE_YOUR: "your" on pets, "the" on everything else
608 *
609 * If the monster would be referred to as "it" or if the monster has a name
610 * _and_ there is no adjective, "invisible", "saddled", etc., override this
611 * and always use no article.
612 */
613 const char *adjective;
614 int suppress;
615 /* SUPPRESS_IT, SUPPRESS_INVISIBLE, SUPPRESS_HALLUCINATION, SUPPRESS_SADDLE.
616 * EXACT_NAME: combination of all the above
617 */
618 boolean called;
619 {
620 #ifdef LINT /* static char buf[BUFSZ]; */
621 char buf[BUFSZ];
622 #else
623 static char buf[BUFSZ];
624 #endif
625 struct permonst *mdat = mtmp->data;
626 boolean do_hallu, do_invis, do_it, do_saddle;
627 boolean name_at_start, has_adjectives;
628 char *bp;
629
630 if (program_state.gameover)
631 suppress |= SUPPRESS_HALLUCINATION;
632 if (article == ARTICLE_YOUR && !mtmp->mtame)
633 article = ARTICLE_THE;
634
635 do_hallu = Hallucination && !(suppress & SUPPRESS_HALLUCINATION);
636 do_invis = mtmp->minvis && !(suppress & SUPPRESS_INVISIBLE);
637 do_it = !canspotmon(mtmp) &&
638 article != ARTICLE_YOUR &&
639 !program_state.gameover &&
640 #ifdef STEED
641 mtmp != u.usteed &&
642 #endif
643 !(u.uswallow && mtmp == u.ustuck) &&
644 !(suppress & SUPPRESS_IT);
645 do_saddle = !(suppress & SUPPRESS_SADDLE);
646
647 buf[0] = 0;
648
649 /* unseen monsters, etc. Use "it" */
650 if (do_it) {
651 Strcpy(buf, "it");
652 return buf;
653 }
654
655 /* priests and minions: don't even use this function */
656 if (mtmp->ispriest || mtmp->isminion) {
657 char priestnambuf[BUFSZ];
658 char *name;
659 long save_prop = EHalluc_resistance;
660 unsigned save_invis = mtmp->minvis;
661
662 /* when true name is wanted, explicitly block Hallucination */
663 if (!do_hallu) EHalluc_resistance = 1L;
664 if (!do_invis) mtmp->minvis = 0;
665 name = priestname(mtmp, priestnambuf);
666 EHalluc_resistance = save_prop;
667 mtmp->minvis = save_invis;
668 if (article == ARTICLE_NONE && !strncmp(name, "the ", 4))
669 name += 4;
670 return strcpy(buf, name);
671 }
672
673 /* Shopkeepers: use shopkeeper name. For normal shopkeepers, just
674 * "Asidonhopo"; for unusual ones, "Asidonhopo the invisible
675 * shopkeeper" or "Asidonhopo the blue dragon". If hallucinating,
676 * none of this applies.
677 */
678 if (mtmp->isshk && !do_hallu) {
679 if (adjective && article == ARTICLE_THE) {
680 /* pathological case: "the angry Asidonhopo the blue dragon"
681 sounds silly */
682 Strcpy(buf, "the ");
683 Strcat(strcat(buf, adjective), " ");
684 Strcat(buf, shkname(mtmp));
685 return buf;
686 }
687 Strcat(buf, shkname(mtmp));
688 if (mdat == &mons[PM_SHOPKEEPER] && !do_invis)
689 return buf;
690 Strcat(buf, " the ");
691 if (do_invis)
692 Strcat(buf, "invisible ");
693 Strcat(buf, mdat->mname);
694 return buf;
695 }
696
697 /* Put the adjectives in the buffer */
698 if (adjective)
699 Strcat(strcat(buf, adjective), " ");
700 if (do_invis)
701 Strcat(buf, "invisible ");
702 #ifdef STEED
703 if (do_saddle && (mtmp->misc_worn_check & W_SADDLE) &&
704 !Blind && !Hallucination)
705 Strcat(buf, "saddled ");
706 #endif
707 if (buf[0] != 0)
708 has_adjectives = TRUE;
709 else
710 has_adjectives = FALSE;
711
712 /* Put the actual monster name or type into the buffer now */
713 /* Be sure to remember whether the buffer starts with a name */
714 if (do_hallu) {
715 Strcat(buf, rndmonnam());
716 name_at_start = FALSE;
717 } else if (mtmp->mnamelth) {
718 char *name = NAME(mtmp);
719
720 if (mdat == &mons[PM_GHOST]) {
721 Sprintf(eos(buf), "%s ghost", s_suffix(name));
722 name_at_start = TRUE;
723 } else if (called) {
724 Sprintf(eos(buf), "%s called %s", mdat->mname, name);
725 name_at_start = (boolean)type_is_pname(mdat);
726 } else if (is_mplayer(mdat) && (bp = strstri(name, " the ")) != 0) {
727 /* <name> the <adjective> <invisible> <saddled> <rank> */
728 char pbuf[BUFSZ];
729
730 Strcpy(pbuf, name);
731 pbuf[bp - name + 5] = '\0'; /* adjectives right after " the " */
732 if (has_adjectives)
733 Strcat(pbuf, buf);
734 Strcat(pbuf, bp + 5); /* append the rest of the name */
735 Strcpy(buf, pbuf);
736 article = ARTICLE_NONE;
737 name_at_start = TRUE;
738 } else {
739 Strcat(buf, name);
740 name_at_start = TRUE;
741 }
742 } else if (is_mplayer(mdat) && !In_endgame(&u.uz)) {
743 char pbuf[BUFSZ];
744 Strcpy(pbuf, rank_of((int)mtmp->m_lev,
745 monsndx(mdat),
746 (boolean)mtmp->female));
747 Strcat(buf, lcase(pbuf));
748 name_at_start = FALSE;
749 } else if (is_rider(mtmp->data) &&
750 (distu(mtmp->mx, mtmp->my) > 2) &&
751 !(canseemon(mtmp)) &&
752 /* for livelog reporting */
753 !(suppress & SUPPRESS_IT)) {
754 /* prevent the three horsemen to be identified from afar */
755 Strcat(buf, "Rider");
756 name_at_start = FALSE;
757 } else {
758 Strcat(buf, mdat->mname);
759 name_at_start = (boolean)type_is_pname(mdat);
760 }
761
762 if (name_at_start && (article == ARTICLE_YOUR || !has_adjectives)) {
763 if (mdat == &mons[PM_WIZARD_OF_YENDOR])
764 article = ARTICLE_THE;
765 else
766 article = ARTICLE_NONE;
767 } else if ((mdat->geno & G_UNIQ) && article == ARTICLE_A) {
768 article = ARTICLE_THE;
769 }
770
771 {
772 char buf2[BUFSZ];
773
774 switch(article) {
775 case ARTICLE_YOUR:
776 Strcpy(buf2, "your ");
777 Strcat(buf2, buf);
778 Strcpy(buf, buf2);
779 return buf;
780 case ARTICLE_THE:
781 Strcpy(buf2, "the ");
782 Strcat(buf2, buf);
783 Strcpy(buf, buf2);
784 return buf;
785 case ARTICLE_A:
786 return(an(buf));
787 case ARTICLE_NONE:
788 default:
789 return buf;
790 }
791 }
792 }
793
794 #endif /* OVL0 */
795 #ifdef OVLB
796
797 char *
l_monnam(mtmp)798 l_monnam(mtmp)
799 register struct monst *mtmp;
800 {
801 return(x_monnam(mtmp, ARTICLE_NONE, (char *)0,
802 mtmp->mnamelth ? SUPPRESS_SADDLE : 0, TRUE));
803 }
804
805 #endif /* OVLB */
806 #ifdef OVL0
807
808 char *
mon_nam(mtmp)809 mon_nam(mtmp)
810 register struct monst *mtmp;
811 {
812 return(x_monnam(mtmp, ARTICLE_THE, (char *)0,
813 mtmp->mnamelth ? SUPPRESS_SADDLE : 0, FALSE));
814 }
815
816 /* print the name as if mon_nam() was called, but assume that the player
817 * can always see the monster--used for probing and for monsters aggravating
818 * the player with a cursed potion of invisibility
819 */
820 char *
noit_mon_nam(mtmp)821 noit_mon_nam(mtmp)
822 register struct monst *mtmp;
823 {
824 return(x_monnam(mtmp, ARTICLE_THE, (char *)0,
825 mtmp->mnamelth ? (SUPPRESS_SADDLE|SUPPRESS_IT) :
826 SUPPRESS_IT, FALSE));
827 }
828
829 char *
Monnam(mtmp)830 Monnam(mtmp)
831 register struct monst *mtmp;
832 {
833 register char *bp = mon_nam(mtmp);
834
835 *bp = highc(*bp);
836 return(bp);
837 }
838
839 char *
noit_Monnam(mtmp)840 noit_Monnam(mtmp)
841 register struct monst *mtmp;
842 {
843 register char *bp = noit_mon_nam(mtmp);
844
845 *bp = highc(*bp);
846 return(bp);
847 }
848
849 /* monster's own name */
850 char *
m_monnam(mtmp)851 m_monnam(mtmp)
852 struct monst *mtmp;
853 {
854 return x_monnam(mtmp, ARTICLE_NONE, (char *)0, EXACT_NAME, FALSE);
855 }
856
857 /* pet name: "your little dog" */
858 char *
y_monnam(mtmp)859 y_monnam(mtmp)
860 struct monst *mtmp;
861 {
862 int prefix, suppression_flag;
863
864 prefix = mtmp->mtame ? ARTICLE_YOUR : ARTICLE_THE;
865 suppression_flag = (mtmp->mnamelth
866 #ifdef STEED
867 /* "saddled" is redundant when mounted */
868 || mtmp == u.usteed
869 #endif
870 ) ? SUPPRESS_SADDLE : 0;
871
872 return x_monnam(mtmp, prefix, (char *)0, suppression_flag, FALSE);
873 }
874
875 #endif /* OVL0 */
876 #ifdef OVLB
877
878 char *
Adjmonnam(mtmp,adj)879 Adjmonnam(mtmp, adj)
880 register struct monst *mtmp;
881 register const char *adj;
882 {
883 register char *bp = x_monnam(mtmp, ARTICLE_THE, adj,
884 mtmp->mnamelth ? SUPPRESS_SADDLE : 0, FALSE);
885
886 *bp = highc(*bp);
887 return(bp);
888 }
889
890 char *
a_monnam(mtmp)891 a_monnam(mtmp)
892 register struct monst *mtmp;
893 {
894 return x_monnam(mtmp, ARTICLE_A, (char *)0,
895 mtmp->mnamelth ? SUPPRESS_SADDLE : 0, FALSE);
896 }
897
898 char *
Amonnam(mtmp)899 Amonnam(mtmp)
900 register struct monst *mtmp;
901 {
902 register char *bp = a_monnam(mtmp);
903
904 *bp = highc(*bp);
905 return(bp);
906 }
907
908 /* used for monster ID by the '/', ';', and 'C' commands to block remote
909 identification of the endgame altars via their attending priests */
910 char *
distant_monnam(mon,article,outbuf)911 distant_monnam(mon, article, outbuf)
912 struct monst *mon;
913 int article; /* only ARTICLE_NONE and ARTICLE_THE are handled here */
914 char *outbuf;
915 {
916 /* high priest(ess)'s identity is concealed on the Astral Plane,
917 unless you're adjacent (overridden for hallucination which does
918 its own obfuscation) */
919 if (mon->data == &mons[PM_HIGH_PRIEST] && !Hallucination &&
920 Is_astralevel(&u.uz) && distu(mon->mx, mon->my) > 2) {
921 Strcpy(outbuf, article == ARTICLE_THE ? "the " : "");
922 Strcat(outbuf, mon->female ? "high priestess" : "high priest");
923 } else {
924 Strcpy(outbuf, x_monnam(mon, article, (char *)0, 0, TRUE));
925 }
926 return outbuf;
927 }
928
929 static const char * const bogusmons[] = {
930 "jumbo shrimp", "giant pigmy", "gnu", "killer penguin",
931 "giant cockroach", "giant slug", "maggot", "pterodactyl",
932 "tyrannosaurus rex", "basilisk", "beholder", "nightmare",
933 "efreeti", "marid", "rot grub", "bookworm", "master lichen",
934 "shadow", "hologram", "jester", "attorney", "sleazoid",
935 "killer tomato", "amazon", "robot", "battlemech",
936 "rhinovirus", "harpy", "lion-dog", "rat-ant", "Y2K bug",
937 /* misc. */
938 "grue", "Christmas-tree monster", "luck sucker", "paskald",
939 "brogmoid", "dornbeast", /* Quendor (Zork, &c.) */
940 "Ancient Multi-Hued Dragon", "Evil Iggy",
941 /* Moria */
942 "emu", "kestrel", "xeroc", "venus flytrap",
943 /* Rogue */
944 "creeping coins", /* Wizardry */
945 "hydra", "siren", /* Greek legend */
946 "killer bunny", /* Monty Python */
947 "rodent of unusual size", /* The Princess Bride */
948 "Smokey the bear", /* "Only you can prevent forest fires!" */
949 "Luggage", /* Discworld */
950 "Ent", /* Lord of the Rings */
951 "tangle tree", "nickelpede", "wiggle", /* Xanth */
952 "white rabbit", "snark", /* Lewis Carroll */
953 "pushmi-pullyu", /* Dr. Dolittle */
954 "smurf", /* The Smurfs */
955 "tribble", "Klingon", "Borg", /* Star Trek */
956 "Ewok", /* Star Wars */
957 "Totoro", /* Tonari no Totoro */
958 "ohmu", /* Nausicaa */
959 "youma", /* Sailor Moon */
960 "nyaasu", /* Pokemon (Meowth) */
961 "Godzilla", "King Kong", /* monster movies */
962 "earthquake beast", /* old L of SH */
963 "Invid", /* Robotech */
964 "Terminator", /* The Terminator */
965 "boomer", /* Bubblegum Crisis */
966 "Dalek", /* Dr. Who ("Exterminate!") */
967 "microscopic space fleet", "Ravenous Bugblatter Beast of Traal",
968 /* HGttG */
969 "teenage mutant ninja turtle", /* TMNT */
970 "samurai rabbit", /* Usagi Yojimbo */
971 "aardvark", /* Cerebus */
972 "Audrey II", /* Little Shop of Horrors */
973 "witch doctor", "one-eyed one-horned flying purple people eater",
974 /* 50's rock 'n' roll */
975 "Barney the dinosaur", /* saccharine kiddy TV */
976 "Morgoth", /* Angband */
977 "Vorlon", /* Babylon 5 */
978 "questing beast", /* King Arthur */
979 "Predator", /* Movie */
980 "mother-in-law", /* common pest */
981 /* from NAO */
982 "one-winged dewinged stab-bat", /* KoL */
983 "praying mantis",
984 "arch-pedant",
985 "beluga whale",
986 "bluebird of happiness",
987 "bouncing eye", "floating nose",
988 "buffer overflow", "dangling pointer", "walking disk drive",
989 "cacodemon", "scrag",
990 "cardboard golem", "duct tape golem",
991 "chess pawn",
992 "chicken",
993 "chocolate pudding",
994 "coelacanth",
995 "corpulent porpoise",
996 "Crow T. Robot",
997 "diagonally moving grid bug",
998 "dropbear",
999 "Dudley",
1000 "El Pollo Diablo",
1001 "evil overlord",
1002 "existential angst",
1003 "figment of your imagination", "flash of insight",
1004 "flying pig",
1005 "gazebo",
1006 "gonzo journalist",
1007 "gray goo", "magnetic monopole",
1008 "heisenbug",
1009 "lag monster",
1010 "loan shark",
1011 "Lord British",
1012 "newsgroup troll",
1013 "ninja pirate zombie robot",
1014 "octarine dragon",
1015 "particle man",
1016 "possessed waffle iron",
1017 "poultrygeist",
1018 "raging nerd",
1019 "roomba",
1020 "sea cucumber",
1021 "spelling bee",
1022 "Strong Bad",
1023 "stuffed raccoon puppet",
1024 "tapeworm",
1025 "liger",
1026 "velociraptor",
1027 "vermicious knid",
1028 "viking",
1029 "voluptuous ampersand",
1030 "wee green blobbie",
1031 "wereplatypus",
1032 "zergling",
1033 "hag of bolding",
1034 /* from UnNetHack */
1035 "apostroph golem", "Bob the angry flower",
1036 "bonsai-kitten", "Boxxy", "lonelygirl15",
1037 "looooooooooooong cat", /* internet memes */
1038 "bohrbug", "mandelbug", "schroedinbug", /* bugs */
1039 "Gerbenok", /* Monty Python killer rabbit */
1040 "doenertier", /* Erkan & Stefan */
1041 "Invisible Pink Unicorn",
1042 "Flying Spaghetti Monster", /* deities */
1043 "Bluebear", "Professor Abdullah Nightingale"
1044 "Qwerty Uiop", "troglotroll", /* Zamonien */
1045 "wolpertinger", "elwedritsche", "skvader",
1046 "Nessie", "tatzelwurm", "dahu", /* european cryptids */
1047 "three-headed monkey", /* Monkey Island */
1048 "little green man", /* modern folklore */
1049 "weighted Companion Cube", /* Portal */
1050 "/b/tard", /* /b/ */
1051 "manbearpig", /* South Park */
1052 "ceiling cat", "basement cat",
1053 "monorail cat", /* the Internet is made for cat pix */
1054 "rape golem", /* schnippi */
1055 "tridude", /* POWDER */
1056 "orcus cosmicus", /* Radomir Dopieralski */
1057 "yeek", "quylthulg",
1058 "Greater Hell Beast", /* Angband */
1059 "Vendor of Yizard", /* Souljazz */
1060 "Sigmund", "lernaean hydra", "Ijyb",
1061 "Gloorx Vloq", "Blork the orc", /* Dungeon Crawl Stone Soup */
1062 "unicorn pegasus kitten", /* Wil Wheaton, John Scalzi */
1063 };
1064
1065
1066 /* Return a random monster name, for hallucination.
1067 * KNOWN BUG: May be a proper name (Godzilla, Barney), may not
1068 * (the Terminator, a Dalek). There's no elegant way to deal
1069 * with this without radically modifying the calling functions.
1070 */
1071 const char *
rndmonnam()1072 rndmonnam()
1073 {
1074 int name;
1075
1076 do {
1077 name = rn1(SPECIAL_PM + SIZE(bogusmons) - LOW_PM, LOW_PM);
1078 } while (name < SPECIAL_PM &&
1079 (type_is_pname(&mons[name]) || (mons[name].geno & G_NOGEN)));
1080
1081 if (name >= SPECIAL_PM) return bogusmons[name - SPECIAL_PM];
1082 return mons[name].mname;
1083 }
1084
1085 #ifdef REINCARNATION
1086 const char *
roguename()1087 roguename() /* Name of a Rogue player */
1088 {
1089 char *i, *opts;
1090
1091 if ((opts = nh_getenv("ROGUEOPTS")) != 0) {
1092 for (i = opts; *i; i++)
1093 if (!strncmp("name=",i,5)) {
1094 char *j;
1095 if ((j = index(i+5,',')) != 0)
1096 *j = (char)0;
1097 return i+5;
1098 }
1099 }
1100 return rn2(3) ? (rn2(2) ? "Michael Toy" : "Kenneth Arnold")
1101 : "Glenn Wichman";
1102 }
1103 #endif /* REINCARNATION */
1104 #endif /* OVLB */
1105
1106 #ifdef OVL2
1107
1108 static NEARDATA const char * const hcolors[] = {
1109 "ultraviolet", "infrared", "bluish-orange",
1110 "reddish-green", "dark white", "light black", "sky blue-pink",
1111 "salty", "sweet", "sour", "bitter", "umami",
1112 "striped", "spiral", "swirly", "plaid", "checkered", "argyle",
1113 "paisley", "blotchy", "guernsey-spotted", "polka-dotted",
1114 "square", "round", "triangular",
1115 "cabernet", "sangria", "fuchsia", "wisteria",
1116 "lemon-lime", "strawberry-banana", "peppermint",
1117 "romantic", "incandescent"
1118 };
1119
1120 const char *
hcolor(colorpref)1121 hcolor(colorpref)
1122 const char *colorpref;
1123 {
1124 return (Hallucination || !colorpref) ?
1125 hcolors[rn2(SIZE(hcolors))] : colorpref;
1126 }
1127
1128 /* return a random real color unless hallucinating */
1129 const char *
rndcolor()1130 rndcolor()
1131 {
1132 int k = rn2(CLR_MAX);
1133 return Hallucination ? hcolor((char *)0) : (k == NO_COLOR) ?
1134 "colorless" : c_obj_colors[k];
1135 }
1136
1137 /* Aliases for road-runner nemesis
1138 */
1139 static const char * const coynames[] = {
1140 "Carnivorous Vulgaris","Road-Runnerus Digestus",
1141 "Eatibus Anythingus" ,"Famishus-Famishus",
1142 "Eatibus Almost Anythingus","Eatius Birdius",
1143 "Famishius Fantasticus","Eternalii Famishiis",
1144 "Famishus Vulgarus","Famishius Vulgaris Ingeniusi",
1145 "Eatius-Slobbius","Hardheadipus Oedipus",
1146 "Carnivorous Slobbius","Hard-Headipus Ravenus",
1147 "Evereadii Eatibus","Apetitius Giganticus",
1148 "Hungrii Flea-Bagius","Overconfidentii Vulgaris",
1149 "Caninus Nervous Rex","Grotesques Appetitus",
1150 "Nemesis Riduclii","Canis latrans"
1151 };
1152
1153 char *
coyotename(mtmp,buf)1154 coyotename(mtmp, buf)
1155 struct monst *mtmp;
1156 char *buf;
1157 {
1158 if (mtmp && buf) {
1159 Sprintf(buf, "%s - %s",
1160 x_monnam(mtmp, ARTICLE_NONE, (char *)0, 0, TRUE),
1161 mtmp->mcan ? coynames[SIZE(coynames)-1] : coynames[rn2(SIZE(coynames)-1)]);
1162 }
1163 return buf;
1164 }
1165 #endif /* OVL2 */
1166
1167 /*do_name.c*/
1168