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