1/*	SCCS Id: @(#)do_name.c	3.4	2003/01/14	*/
2/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3/* NetHack may be freely redistributed.  See license for details. */
4
5#include "hack.h"
6
7#ifdef OVLB
8
9STATIC_DCL void FDECL(do_oname, (struct obj *));
10static void FDECL(getpos_help, (BOOLEAN_P,const char *));
11
12extern const char what_is_an_unknown_object[];		/* from pager.c */
13
14/* the response for '?' help request in getpos() */
15static void
16getpos_help(force, goal)
17boolean force;
18const 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
42int
43getpos(cc, force, goal)
44coord *cc;
45boolean force;
46const 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
193struct monst *
194christen_monst(mtmp, name)
195struct monst *mtmp;
196const 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
224int
225do_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	(void) distant_monnam(mtmp, ARTICLE_THE, buf);
272	Sprintf(qbuf, "What do you want to call %s?", buf);
273	getlin(qbuf,buf);
274	if(!*buf || *buf == '\033') return(0);
275	/* strip leading and trailing spaces; unnames monster if all spaces */
276	(void)mungspaces(buf);
277
278	if (mtmp->data->geno & G_UNIQ)
279	    pline("%s doesn't like being called names!", Monnam(mtmp));
280	else
281	    (void) christen_monst(mtmp, buf);
282	return(0);
283}
284
285/*
286 * This routine changes the address of obj. Be careful not to call it
287 * when there might be pointers around in unknown places. For now: only
288 * when obj is in the inventory.
289 */
290STATIC_OVL
291void
292do_oname(obj)
293register struct obj *obj;
294{
295	char buf[BUFSZ], qbuf[QBUFSZ];
296	const char *aname;
297	short objtyp;
298
299	Sprintf(qbuf, "What do you want to name %s %s?",
300		is_plural(obj) ? "these" : "this", xname(obj));
301	getlin(qbuf, buf);
302	if(!*buf || *buf == '\033')	return;
303	/* strip leading and trailing spaces; unnames item if all spaces */
304	(void)mungspaces(buf);
305
306	/* relax restrictions over proper capitalization for artifacts */
307	if ((aname = artifact_name(buf, &objtyp)) != 0 && objtyp == obj->otyp)
308		Strcpy(buf, aname);
309
310	if (obj->oartifact) {
311		pline_The("artifact seems to resist the attempt.");
312		return;
313	} else if (restrict_name(obj, buf) || exist_artifact(obj->otyp, buf)) {
314		int n = rn2((int)strlen(buf));
315		register char c1, c2;
316
317		c1 = lowc(buf[n]);
318		do c2 = 'a' + rn2('z'-'a'); while (c1 == c2);
319		buf[n] = (buf[n] == c1) ? c2 : highc(c2);  /* keep same case */
320		pline("While engraving your %s slips.", body_part(HAND));
321		display_nhwindow(WIN_MESSAGE, FALSE);
322		You("engrave: \"%s\".",buf);
323	}
324	obj = oname(obj, buf);
325}
326
327/*
328 * Allocate a new and possibly larger storage space for an obj.
329 */
330struct obj *
331realloc_obj(obj, oextra_size, oextra_src, oname_size, name)
332struct obj *obj;
333int oextra_size;		/* storage to allocate for oextra            */
334genericptr_t oextra_src;
335int oname_size;			/* size of name string + 1 (null terminator) */
336const char *name;
337{
338	struct obj *otmp;
339
340	otmp = newobj(oextra_size + oname_size);
341	*otmp = *obj;	/* the cobj pointer is copied to otmp */
342	if (oextra_size) {
343	    if (oextra_src)
344		(void) memcpy((genericptr_t)otmp->oextra, oextra_src,
345							oextra_size);
346	} else {
347	    otmp->oattached = OATTACHED_NOTHING;
348	}
349	otmp->oxlth = oextra_size;
350
351	otmp->onamelth = oname_size;
352	otmp->timed = 0;	/* not timed, yet */
353	otmp->lamplit = 0;	/* ditto */
354	/* __GNUC__ note:  if the assignment of otmp->onamelth immediately
355	   precedes this `if' statement, a gcc bug will miscompile the
356	   test on vax (`insv' instruction used to store bitfield does
357	   not set condition codes, but optimizer behaves as if it did).
358	   gcc-2.7.2.1 finally fixed this. */
359	if (oname_size) {
360	    if (name)
361		Strcpy(ONAME(otmp), name);
362	}
363
364	if (obj->owornmask) {
365		boolean save_twoweap = u.twoweap;
366		/* unwearing the old instance will clear dual-wield mode
367		   if this object is either of the two weapons */
368		setworn((struct obj *)0, obj->owornmask);
369		setworn(otmp, otmp->owornmask);
370		u.twoweap = save_twoweap;
371	}
372
373	/* replace obj with otmp */
374	replace_object(obj, otmp);
375
376	/* fix ocontainer pointers */
377	if (Has_contents(obj)) {
378		struct obj *inside;
379
380		for(inside = obj->cobj; inside; inside = inside->nobj)
381			inside->ocontainer = otmp;
382	}
383
384	/* move timers and light sources from obj to otmp */
385	if (obj->timed) obj_move_timers(obj, otmp);
386	if (obj->lamplit) obj_move_light_source(obj, otmp);
387
388	/* objects possibly being manipulated by multi-turn occupations
389	   which have been interrupted but might be subsequently resumed */
390	if (obj->oclass == FOOD_CLASS)
391	    food_substitution(obj, otmp);	/* eat food or open tin */
392	else if (obj->oclass == SPBOOK_CLASS)
393	    book_substitution(obj, otmp);	/* read spellbook */
394
395	/* obfree(obj, otmp);	now unnecessary: no pointers on bill */
396	dealloc_obj(obj);	/* let us hope nobody else saved a pointer */
397	return otmp;
398}
399
400struct obj *
401oname(obj, name)
402struct obj *obj;
403const char *name;
404{
405	int lth;
406	char buf[PL_PSIZ];
407
408	lth = *name ? (int)(strlen(name) + 1) : 0;
409	if (lth > PL_PSIZ) {
410		lth = PL_PSIZ;
411		name = strncpy(buf, name, PL_PSIZ - 1);
412		buf[PL_PSIZ - 1] = '\0';
413	}
414	/* If named artifact exists in the game, do not create another.
415	 * Also trying to create an artifact shouldn't de-artifact
416	 * it (e.g. Excalibur from prayer). In this case the object
417	 * will retain its current name. */
418	if (obj->oartifact || (lth && exist_artifact(obj->otyp, name)))
419		return obj;
420
421	if (lth == obj->onamelth) {
422		/* no need to replace entire object */
423		if (lth) Strcpy(ONAME(obj), name);
424	} else {
425		obj = realloc_obj(obj, obj->oxlth,
426			      (genericptr_t)obj->oextra, lth, name);
427	}
428	if (lth) artifact_exists(obj, name, TRUE);
429	if (obj->oartifact) {
430	    /* can't dual-wield with artifact as secondary weapon */
431	    if (obj == uswapwep) untwoweapon();
432	    /* activate warning if you've just named your weapon "Sting" */
433	    if (obj == uwep) set_artifact_intrinsic(obj, TRUE, W_WEP);
434	}
435	if (carried(obj)) update_inventory();
436	return obj;
437}
438
439static NEARDATA const char callable[] = {
440	SCROLL_CLASS, POTION_CLASS, WAND_CLASS, RING_CLASS, AMULET_CLASS,
441	GEM_CLASS, SPBOOK_CLASS, ARMOR_CLASS, TOOL_CLASS, 0 };
442
443int
444ddocall()
445{
446	register struct obj *obj;
447#ifdef REDO
448	char	ch;
449#endif
450	char allowall[2];
451
452	switch(
453#ifdef REDO
454		ch =
455#endif
456		ynq("Name an individual object?")) {
457	case 'q':
458		break;
459	case 'y':
460#ifdef REDO
461		savech(ch);
462#endif
463		allowall[0] = ALL_CLASSES; allowall[1] = '\0';
464		obj = getobj(allowall, "name");
465		if(obj) do_oname(obj);
466		break;
467	default :
468#ifdef REDO
469		savech(ch);
470#endif
471		obj = getobj(callable, "call");
472		if (obj) {
473			/* behave as if examining it in inventory;
474			   this might set dknown if it was picked up
475			   while blind and the hero can now see */
476			(void) xname(obj);
477
478			if (!obj->dknown) {
479				You("would never recognize another one.");
480				return 0;
481			}
482			docall(obj);
483		}
484		break;
485	}
486	return 0;
487}
488
489void
490docall(obj)
491register struct obj *obj;
492{
493	char buf[BUFSZ], qbuf[QBUFSZ];
494	struct obj otemp;
495	register char **str1;
496
497	if (!obj->dknown) return; /* probably blind */
498	otemp = *obj;
499	otemp.quan = 1L;
500	otemp.onamelth = 0;
501	otemp.oxlth = 0;
502	if (objects[otemp.otyp].oc_class == POTION_CLASS && otemp.fromsink)
503	    /* kludge, meaning it's sink water */
504	    Sprintf(qbuf,"Call a stream of %s fluid:",
505		    OBJ_DESCR(objects[otemp.otyp]));
506	else
507	    Sprintf(qbuf, "Call %s:", an(xname(&otemp)));
508	getlin(qbuf, buf);
509	if(!*buf || *buf == '\033')
510		return;
511
512	/* clear old name */
513	str1 = &(objects[obj->otyp].oc_uname);
514	if(*str1) free((genericptr_t)*str1);
515
516	/* strip leading and trailing spaces; uncalls item if all spaces */
517	(void)mungspaces(buf);
518	if (!*buf) {
519	    if (*str1) {	/* had name, so possibly remove from disco[] */
520		/* strip name first, for the update_inventory() call
521		   from undiscover_object() */
522		*str1 = (char *)0;
523		undiscover_object(obj->otyp);
524	    }
525	} else {
526	    *str1 = strcpy((char *) alloc((unsigned)strlen(buf)+1), buf);
527	    discover_object(obj->otyp, FALSE, TRUE); /* possibly add to disco[] */
528	}
529}
530
531#endif /*OVLB*/
532#ifdef OVL0
533
534static const char * const ghostnames[] = {
535	/* these names should have length < PL_NSIZ */
536	/* Capitalize the names for aesthetics -dgk */
537	"Adri", "Andries", "Andreas", "Bert", "David", "Dirk", "Emile",
538	"Frans", "Fred", "Greg", "Hether", "Jay", "John", "Jon", "Karnov",
539	"Kay", "Kenny", "Kevin", "Maud", "Michiel", "Mike", "Peter", "Robert",
540	"Ron", "Tom", "Wilmar", "Nick Danger", "Phoenix", "Jiro", "Mizue",
541	"Stephan", "Lance Braccus", "Shadowhawk"
542};
543
544/* ghost names formerly set by x_monnam(), now by makemon() instead */
545const char *
546rndghostname()
547{
548    return rn2(7) ? ghostnames[rn2(SIZE(ghostnames))] : (const char *)plname;
549}
550
551/* Monster naming functions:
552 * x_monnam is the generic monster-naming function.
553 *		  seen	      unseen	   detected		  named
554 * mon_nam:	the newt	it	the invisible orc	Fido
555 * noit_mon_nam:the newt (as if detected) the invisible orc	Fido
556 * l_monnam:	newt		it	invisible orc		dog called fido
557 * Monnam:	The newt	It	The invisible orc	Fido
558 * noit_Monnam: The newt (as if detected) The invisible orc	Fido
559 * Adjmonnam:	The poor newt	It	The poor invisible orc	The poor Fido
560 * Amonnam:	A newt		It	An invisible orc	Fido
561 * a_monnam:	a newt		it	an invisible orc	Fido
562 * m_monnam:	newt		xan	orc			Fido
563 * y_monnam:	your newt     your xan	your invisible orc	Fido
564 */
565
566/* Bug: if the monster is a priest or shopkeeper, not every one of these
567 * options works, since those are special cases.
568 */
569char *
570x_monnam(mtmp, article, adjective, suppress, called)
571register struct monst *mtmp;
572int article;
573/* ARTICLE_NONE, ARTICLE_THE, ARTICLE_A: obvious
574 * ARTICLE_YOUR: "your" on pets, "the" on everything else
575 *
576 * If the monster would be referred to as "it" or if the monster has a name
577 * _and_ there is no adjective, "invisible", "saddled", etc., override this
578 * and always use no article.
579 */
580const char *adjective;
581int suppress;
582/* SUPPRESS_IT, SUPPRESS_INVISIBLE, SUPPRESS_HALLUCINATION, SUPPRESS_SADDLE.
583 * EXACT_NAME: combination of all the above
584 */
585boolean called;
586{
587#ifdef LINT	/* static char buf[BUFSZ]; */
588	char buf[BUFSZ];
589#else
590	static char buf[BUFSZ];
591#endif
592	struct permonst *mdat = mtmp->data;
593	boolean do_hallu, do_invis, do_it, do_saddle;
594	boolean name_at_start, has_adjectives;
595	char *bp;
596
597	if (program_state.gameover)
598	    suppress |= SUPPRESS_HALLUCINATION;
599	if (article == ARTICLE_YOUR && !mtmp->mtame)
600	    article = ARTICLE_THE;
601
602	do_hallu = Hallucination && !(suppress & SUPPRESS_HALLUCINATION);
603	do_invis = mtmp->minvis && !(suppress & SUPPRESS_INVISIBLE);
604	do_it = !canspotmon(mtmp) &&
605	    article != ARTICLE_YOUR &&
606	    !program_state.gameover &&
607#ifdef STEED
608	    mtmp != u.usteed &&
609#endif
610	    !(u.uswallow && mtmp == u.ustuck) &&
611	    !(suppress & SUPPRESS_IT);
612	do_saddle = !(suppress & SUPPRESS_SADDLE);
613
614	buf[0] = 0;
615
616	/* unseen monsters, etc.  Use "it" */
617	if (do_it) {
618	    Strcpy(buf, "it");
619	    return buf;
620	}
621
622	/* priests and minions: don't even use this function */
623	if (mtmp->ispriest || mtmp->isminion) {
624	    char priestnambuf[BUFSZ];
625	    char *name;
626	    long save_prop = EHalluc_resistance;
627	    unsigned save_invis = mtmp->minvis;
628
629	    /* when true name is wanted, explicitly block Hallucination */
630	    if (!do_hallu) EHalluc_resistance = 1L;
631	    if (!do_invis) mtmp->minvis = 0;
632	    name = priestname(mtmp, priestnambuf);
633	    EHalluc_resistance = save_prop;
634	    mtmp->minvis = save_invis;
635	    if (article == ARTICLE_NONE && !strncmp(name, "the ", 4))
636		name += 4;
637	    return strcpy(buf, name);
638	}
639
640	/* Shopkeepers: use shopkeeper name.  For normal shopkeepers, just
641	 * "Asidonhopo"; for unusual ones, "Asidonhopo the invisible
642	 * shopkeeper" or "Asidonhopo the blue dragon".  If hallucinating,
643	 * none of this applies.
644	 */
645	if (mtmp->isshk && !do_hallu) {
646	    if (adjective && article == ARTICLE_THE) {
647		/* pathological case: "the angry Asidonhopo the blue dragon"
648		   sounds silly */
649		Strcpy(buf, "the ");
650		Strcat(strcat(buf, adjective), " ");
651		Strcat(buf, shkname(mtmp));
652		return buf;
653	    }
654	    Strcat(buf, shkname(mtmp));
655	    if (mdat == &mons[PM_SHOPKEEPER] && !do_invis)
656		return buf;
657	    Strcat(buf, " the ");
658	    if (do_invis)
659		Strcat(buf, "invisible ");
660	    Strcat(buf, mdat->mname);
661	    return buf;
662	}
663
664	/* Put the adjectives in the buffer */
665	if (adjective)
666	    Strcat(strcat(buf, adjective), " ");
667	if (do_invis)
668	    Strcat(buf, "invisible ");
669#ifdef STEED
670	if (do_saddle && (mtmp->misc_worn_check & W_SADDLE) &&
671	    !Blind && !Hallucination)
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 if (is_mplayer(mdat) && (bp = strstri(name, " the ")) != 0) {
694		/* <name> the <adjective> <invisible> <saddled> <rank> */
695		char pbuf[BUFSZ];
696
697		Strcpy(pbuf, name);
698		pbuf[bp - name + 5] = '\0'; /* adjectives right after " the " */
699		if (has_adjectives)
700		    Strcat(pbuf, buf);
701		Strcat(pbuf, bp + 5);	/* append the rest of the name */
702		Strcpy(buf, pbuf);
703		article = ARTICLE_NONE;
704		name_at_start = TRUE;
705	    } else {
706		Strcat(buf, name);
707		name_at_start = TRUE;
708	    }
709	} else if (is_mplayer(mdat) && !In_endgame(&u.uz)) {
710	    char pbuf[BUFSZ];
711	    Strcpy(pbuf, rank_of((int)mtmp->m_lev,
712				 monsndx(mdat),
713				 (boolean)mtmp->female));
714	    Strcat(buf, lcase(pbuf));
715	    name_at_start = FALSE;
716	} else {
717	    Strcat(buf, mdat->mname);
718	    name_at_start = (boolean)type_is_pname(mdat);
719	}
720
721	if (name_at_start && (article == ARTICLE_YOUR || !has_adjectives)) {
722	    if (mdat == &mons[PM_WIZARD_OF_YENDOR])
723		article = ARTICLE_THE;
724	    else
725		article = ARTICLE_NONE;
726	} else if ((mdat->geno & G_UNIQ) && article == ARTICLE_A) {
727	    article = ARTICLE_THE;
728	}
729
730	{
731	    char buf2[BUFSZ];
732
733	    switch(article) {
734		case ARTICLE_YOUR:
735		    Strcpy(buf2, "your ");
736		    Strcat(buf2, buf);
737		    Strcpy(buf, buf2);
738		    return buf;
739		case ARTICLE_THE:
740		    Strcpy(buf2, "the ");
741		    Strcat(buf2, buf);
742		    Strcpy(buf, buf2);
743		    return buf;
744		case ARTICLE_A:
745		    return(an(buf));
746		case ARTICLE_NONE:
747		default:
748		    return buf;
749	    }
750	}
751}
752
753#endif /* OVL0 */
754#ifdef OVLB
755
756char *
757l_monnam(mtmp)
758register struct monst *mtmp;
759{
760	return(x_monnam(mtmp, ARTICLE_NONE, (char *)0,
761		mtmp->mnamelth ? SUPPRESS_SADDLE : 0, TRUE));
762}
763
764#endif /* OVLB */
765#ifdef OVL0
766
767char *
768mon_nam(mtmp)
769register struct monst *mtmp;
770{
771	return(x_monnam(mtmp, ARTICLE_THE, (char *)0,
772		mtmp->mnamelth ? SUPPRESS_SADDLE : 0, FALSE));
773}
774
775/* print the name as if mon_nam() was called, but assume that the player
776 * can always see the monster--used for probing and for monsters aggravating
777 * the player with a cursed potion of invisibility
778 */
779char *
780noit_mon_nam(mtmp)
781register struct monst *mtmp;
782{
783	return(x_monnam(mtmp, ARTICLE_THE, (char *)0,
784		mtmp->mnamelth ? (SUPPRESS_SADDLE|SUPPRESS_IT) :
785		    SUPPRESS_IT, FALSE));
786}
787
788char *
789Monnam(mtmp)
790register struct monst *mtmp;
791{
792	register char *bp = mon_nam(mtmp);
793
794	*bp = highc(*bp);
795	return(bp);
796}
797
798char *
799noit_Monnam(mtmp)
800register struct monst *mtmp;
801{
802	register char *bp = noit_mon_nam(mtmp);
803
804	*bp = highc(*bp);
805	return(bp);
806}
807
808/* monster's own name */
809char *
810m_monnam(mtmp)
811struct monst *mtmp;
812{
813	return x_monnam(mtmp, ARTICLE_NONE, (char *)0, EXACT_NAME, FALSE);
814}
815
816/* pet name: "your little dog" */
817char *
818y_monnam(mtmp)
819struct monst *mtmp;
820{
821	int prefix, suppression_flag;
822
823	prefix = mtmp->mtame ? ARTICLE_YOUR : ARTICLE_THE;
824	suppression_flag = (mtmp->mnamelth
825#ifdef STEED
826			    /* "saddled" is redundant when mounted */
827			    || mtmp == u.usteed
828#endif
829			    ) ? SUPPRESS_SADDLE : 0;
830
831	return x_monnam(mtmp, prefix, (char *)0, suppression_flag, FALSE);
832}
833
834#endif /* OVL0 */
835#ifdef OVLB
836
837char *
838Adjmonnam(mtmp, adj)
839register struct monst *mtmp;
840register const char *adj;
841{
842	register char *bp = x_monnam(mtmp, ARTICLE_THE, adj,
843		mtmp->mnamelth ? SUPPRESS_SADDLE : 0, FALSE);
844
845	*bp = highc(*bp);
846	return(bp);
847}
848
849char *
850a_monnam(mtmp)
851register struct monst *mtmp;
852{
853	return x_monnam(mtmp, ARTICLE_A, (char *)0,
854		mtmp->mnamelth ? SUPPRESS_SADDLE : 0, FALSE);
855}
856
857char *
858Amonnam(mtmp)
859register struct monst *mtmp;
860{
861	register char *bp = a_monnam(mtmp);
862
863	*bp = highc(*bp);
864	return(bp);
865}
866
867/* used for monster ID by the '/', ';', and 'C' commands to block remote
868   identification of the endgame altars via their attending priests */
869char *
870distant_monnam(mon, article, outbuf)
871struct monst *mon;
872int article;	/* only ARTICLE_NONE and ARTICLE_THE are handled here */
873char *outbuf;
874{
875    /* high priest(ess)'s identity is concealed on the Astral Plane,
876       unless you're adjacent (overridden for hallucination which does
877       its own obfuscation) */
878    if (mon->data == &mons[PM_HIGH_PRIEST] && !Hallucination &&
879	    Is_astralevel(&u.uz) && distu(mon->mx, mon->my) > 2) {
880	Strcpy(outbuf, article == ARTICLE_THE ? "the " : "");
881	Strcat(outbuf, mon->female ? "high priestess" : "high priest");
882    } else {
883	Strcpy(outbuf, x_monnam(mon, article, (char *)0, 0, TRUE));
884    }
885    return outbuf;
886}
887
888static const char * const bogusmons[] = {
889	"jumbo shrimp", "giant pigmy", "gnu", "killer penguin",
890	"giant cockroach", "giant slug", "maggot", "pterodactyl",
891	"tyrannosaurus rex", "basilisk", "beholder", "nightmare",
892	"efreeti", "marid", "rot grub", "bookworm", "master lichen",
893	"shadow", "hologram", "jester", "attorney", "sleazoid",
894	"killer tomato", "amazon", "robot", "battlemech",
895	"rhinovirus", "harpy", "lion-dog", "rat-ant", "Y2K bug",
896						/* misc. */
897	"grue", "Christmas-tree monster", "luck sucker", "paskald",
898	"brogmoid", "dornbeast",		/* Quendor (Zork, &c.) */
899	"Ancient Multi-Hued Dragon", "Evil Iggy",
900						/* Moria */
901	"emu", "kestrel", "xeroc", "venus flytrap",
902						/* Rogue */
903	"creeping coins",			/* Wizardry */
904	"hydra", "siren",			/* Greek legend */
905	"killer bunny",				/* Monty Python */
906	"rodent of unusual size",		/* The Princess Bride */
907	"Smokey the bear",	/* "Only you can prevent forest fires!" */
908	"Luggage",				/* Discworld */
909	"Ent",					/* Lord of the Rings */
910	"tangle tree", "nickelpede", "wiggle",	/* Xanth */
911	"white rabbit", "snark",		/* Lewis Carroll */
912	"pushmi-pullyu",			/* Dr. Doolittle */
913	"smurf",				/* The Smurfs */
914	"tribble", "Klingon", "Borg",		/* Star Trek */
915	"Ewok",					/* Star Wars */
916	"Totoro",				/* Tonari no Totoro */
917	"ohmu",					/* Nausicaa */
918	"youma",				/* Sailor Moon */
919	"nyaasu",				/* Pokemon (Meowth) */
920	"Godzilla", "King Kong",		/* monster movies */
921	"earthquake beast",			/* old L of SH */
922	"Invid",				/* Robotech */
923	"Terminator",				/* The Terminator */
924	"boomer",				/* Bubblegum Crisis */
925	"Dalek",				/* Dr. Who ("Exterminate!") */
926	"microscopic space fleet", "Ravenous Bugblatter Beast of Traal",
927						/* HGttG */
928	"teenage mutant ninja turtle",		/* TMNT */
929	"samurai rabbit",			/* Usagi Yojimbo */
930	"aardvark",				/* Cerebus */
931	"Audrey II",				/* Little Shop of Horrors */
932	"witch doctor", "one-eyed one-horned flying purple people eater",
933						/* 50's rock 'n' roll */
934	"Barney the dinosaur",			/* saccharine kiddy TV */
935	"Morgoth",				/* Angband */
936	"Vorlon",				/* Babylon 5 */
937	"questing beast",		/* King Arthur */
938	"Predator",				/* Movie */
939	"mother-in-law"				/* common pest */
940};
941
942
943/* Return a random monster name, for hallucination.
944 * KNOWN BUG: May be a proper name (Godzilla, Barney), may not
945 * (the Terminator, a Dalek).  There's no elegant way to deal
946 * with this without radically modifying the calling functions.
947 */
948const char *
949rndmonnam()
950{
951	int name;
952
953	do {
954	    name = rn1(SPECIAL_PM + SIZE(bogusmons) - LOW_PM, LOW_PM);
955	} while (name < SPECIAL_PM &&
956	    (type_is_pname(&mons[name]) || (mons[name].geno & G_NOGEN)));
957
958	if (name >= SPECIAL_PM) return bogusmons[name - SPECIAL_PM];
959	return mons[name].mname;
960}
961
962#ifdef REINCARNATION
963const char *
964roguename() /* Name of a Rogue player */
965{
966	char *i, *opts;
967
968	if ((opts = nh_getenv("ROGUEOPTS")) != 0) {
969		for (i = opts; *i; i++)
970			if (!strncmp("name=",i,5)) {
971				char *j;
972				if ((j = index(i+5,',')) != 0)
973					*j = (char)0;
974				return i+5;
975			}
976	}
977	return rn2(3) ? (rn2(2) ? "Michael Toy" : "Kenneth Arnold")
978		: "Glenn Wichman";
979}
980#endif /* REINCARNATION */
981#endif /* OVLB */
982
983#ifdef OVL2
984
985static NEARDATA const char * const hcolors[] = {
986	"ultraviolet", "infrared", "bluish-orange",
987	"reddish-green", "dark white", "light black", "sky blue-pink",
988	"salty", "sweet", "sour", "bitter",
989	"striped", "spiral", "swirly", "plaid", "checkered", "argyle",
990	"paisley", "blotchy", "guernsey-spotted", "polka-dotted",
991	"square", "round", "triangular",
992	"cabernet", "sangria", "fuchsia", "wisteria",
993	"lemon-lime", "strawberry-banana", "peppermint",
994	"romantic", "incandescent"
995};
996
997const char *
998hcolor(colorpref)
999const char *colorpref;
1000{
1001	return (Hallucination || !colorpref) ?
1002		hcolors[rn2(SIZE(hcolors))] : colorpref;
1003}
1004
1005/* return a random real color unless hallucinating */
1006const char *
1007rndcolor()
1008{
1009	int k = rn2(CLR_MAX);
1010	return Hallucination ? hcolor((char *)0) : (k == NO_COLOR) ?
1011		"colorless" : c_obj_colors[k];
1012}
1013
1014/* Aliases for road-runner nemesis
1015 */
1016static const char * const coynames[] = {
1017	"Carnivorous Vulgaris","Road-Runnerus Digestus",
1018	"Eatibus Anythingus"  ,"Famishus-Famishus",
1019	"Eatibus Almost Anythingus","Eatius Birdius",
1020	"Famishius Fantasticus","Eternalii Famishiis",
1021	"Famishus Vulgarus","Famishius Vulgaris Ingeniusi",
1022	"Eatius-Slobbius","Hardheadipus Oedipus",
1023	"Carnivorous Slobbius","Hard-Headipus Ravenus",
1024	"Evereadii Eatibus","Apetitius Giganticus",
1025	"Hungrii Flea-Bagius","Overconfidentii Vulgaris",
1026	"Caninus Nervous Rex","Grotesques Appetitus",
1027	"Nemesis Riduclii","Canis latrans"
1028};
1029
1030char *
1031coyotename(mtmp, buf)
1032struct monst *mtmp;
1033char *buf;
1034{
1035    if (mtmp && buf) {
1036	Sprintf(buf, "%s - %s",
1037	    x_monnam(mtmp, ARTICLE_NONE, (char *)0, 0, TRUE),
1038	    mtmp->mcan ? coynames[SIZE(coynames)-1] : coynames[rn2(SIZE(coynames)-1)]);
1039    }
1040    return buf;
1041}
1042#endif /* OVL2 */
1043
1044/*do_name.c*/
1045