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