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