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