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