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