xref: /openbsd-src/games/hack/hack.objnam.c (revision 25fdf8020ce93e69e03a0bba36e4e3ee71ad0a59)
1*25fdf802Sjsg /*	$OpenBSD: hack.objnam.c,v 1.12 2023/09/06 11:53:56 jsg Exp $	*/
2d0b779f3Sniklas 
3df930be7Sderaadt /*
4d25013f2Scamield  * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
5d25013f2Scamield  * Amsterdam
6d25013f2Scamield  * All rights reserved.
7d25013f2Scamield  *
8d25013f2Scamield  * Redistribution and use in source and binary forms, with or without
9d25013f2Scamield  * modification, are permitted provided that the following conditions are
10d25013f2Scamield  * met:
11d25013f2Scamield  *
12d25013f2Scamield  * - Redistributions of source code must retain the above copyright notice,
13d25013f2Scamield  * this list of conditions and the following disclaimer.
14d25013f2Scamield  *
15d25013f2Scamield  * - Redistributions in binary form must reproduce the above copyright
16d25013f2Scamield  * notice, this list of conditions and the following disclaimer in the
17d25013f2Scamield  * documentation and/or other materials provided with the distribution.
18d25013f2Scamield  *
19d25013f2Scamield  * - Neither the name of the Stichting Centrum voor Wiskunde en
20d25013f2Scamield  * Informatica, nor the names of its contributors may be used to endorse or
21d25013f2Scamield  * promote products derived from this software without specific prior
22d25013f2Scamield  * written permission.
23d25013f2Scamield  *
24d25013f2Scamield  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
25d25013f2Scamield  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26d25013f2Scamield  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
27d25013f2Scamield  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
28d25013f2Scamield  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29d25013f2Scamield  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30d25013f2Scamield  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31d25013f2Scamield  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32d25013f2Scamield  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33d25013f2Scamield  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34d25013f2Scamield  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35d25013f2Scamield  */
36d25013f2Scamield 
37d25013f2Scamield /*
38d25013f2Scamield  * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
39d25013f2Scamield  * All rights reserved.
40d25013f2Scamield  *
41d25013f2Scamield  * Redistribution and use in source and binary forms, with or without
42d25013f2Scamield  * modification, are permitted provided that the following conditions
43d25013f2Scamield  * are met:
44d25013f2Scamield  * 1. Redistributions of source code must retain the above copyright
45d25013f2Scamield  *    notice, this list of conditions and the following disclaimer.
46d25013f2Scamield  * 2. Redistributions in binary form must reproduce the above copyright
47d25013f2Scamield  *    notice, this list of conditions and the following disclaimer in the
48d25013f2Scamield  *    documentation and/or other materials provided with the distribution.
49d25013f2Scamield  * 3. The name of the author may not be used to endorse or promote products
50d25013f2Scamield  *    derived from this software without specific prior written permission.
51d25013f2Scamield  *
52d25013f2Scamield  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
53d25013f2Scamield  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
54d25013f2Scamield  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
55d25013f2Scamield  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
56d25013f2Scamield  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
57d25013f2Scamield  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
58d25013f2Scamield  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
59d25013f2Scamield  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
60d25013f2Scamield  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
61d25013f2Scamield  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62df930be7Sderaadt  */
63df930be7Sderaadt 
644a5fbbc4Spjanzen #include <ctype.h>
654a5fbbc4Spjanzen #include <stdio.h>
664a5fbbc4Spjanzen #include <stdlib.h>
67aed906e4Smestre 
68df930be7Sderaadt #include "hack.h"
69aed906e4Smestre 
70df930be7Sderaadt #define	PREFIX	15
71df930be7Sderaadt extern int bases[];
72df930be7Sderaadt 
73846311fcStdeval static char bufr[BUFSZ];
74846311fcStdeval 
754a5fbbc4Spjanzen static char *sitoa(int);
764a5fbbc4Spjanzen 
77df930be7Sderaadt char *
strprepend(char * s,char * pref)784a5fbbc4Spjanzen strprepend(char *s, char *pref)
794a5fbbc4Spjanzen {
804a5fbbc4Spjanzen 	int i = strlen(pref);
814a5fbbc4Spjanzen 
82df930be7Sderaadt 	if(i > PREFIX) {
83df930be7Sderaadt 		pline("WARNING: prefix too short.");
84df930be7Sderaadt 		return(s);
85df930be7Sderaadt 	}
86df930be7Sderaadt 	s -= i;
87df930be7Sderaadt 	(void) strncpy(s, pref, i);	/* do not copy trailing 0 */
88df930be7Sderaadt 	return(s);
89df930be7Sderaadt }
90df930be7Sderaadt 
914a5fbbc4Spjanzen static char *
sitoa(int a)924a5fbbc4Spjanzen sitoa(int a)
934a5fbbc4Spjanzen {
94df930be7Sderaadt 	static char buf[13];
954a5fbbc4Spjanzen 
9642ceebb3Sderaadt 	snprintf(buf, sizeof buf, (a < 0) ? "%d" : "+%d", a);
97df930be7Sderaadt 	return(buf);
98df930be7Sderaadt }
99df930be7Sderaadt 
100df930be7Sderaadt char *
typename(int otyp)1014a5fbbc4Spjanzen typename(int otyp)
102df930be7Sderaadt {
103df930be7Sderaadt 	static char buf[BUFSZ];
1044a5fbbc4Spjanzen 	struct objclass *ocl = &objects[otyp];
1054a5fbbc4Spjanzen 	char *an = ocl->oc_name;
1064a5fbbc4Spjanzen 	char *dn = ocl->oc_descr;
1074a5fbbc4Spjanzen 	char *un = ocl->oc_uname;
1084a5fbbc4Spjanzen 	char *bp;
1094a5fbbc4Spjanzen 	int nn = ocl->oc_name_known;
1104a5fbbc4Spjanzen 
111df930be7Sderaadt 	switch(ocl->oc_olet) {
112df930be7Sderaadt 	case POTION_SYM:
11342ceebb3Sderaadt 		strlcpy(buf, "potion", sizeof buf);
114df930be7Sderaadt 		break;
115df930be7Sderaadt 	case SCROLL_SYM:
11642ceebb3Sderaadt 		strlcpy(buf, "scroll", sizeof buf);
117df930be7Sderaadt 		break;
118df930be7Sderaadt 	case WAND_SYM:
11942ceebb3Sderaadt 		strlcpy(buf, "wand", sizeof buf);
120df930be7Sderaadt 		break;
121df930be7Sderaadt 	case RING_SYM:
12242ceebb3Sderaadt 		strlcpy(buf, "ring", sizeof buf);
123df930be7Sderaadt 		break;
124df930be7Sderaadt 	default:
125df930be7Sderaadt 		if(nn) {
12642ceebb3Sderaadt 			strlcpy(buf, an, sizeof buf);
127df930be7Sderaadt 			if(otyp >= TURQUOISE && otyp <= JADE)
12842ceebb3Sderaadt 				strlcat(buf, " stone", sizeof buf);
129846311fcStdeval 			if(un) {
130846311fcStdeval 				bp = eos(buf);
131846311fcStdeval 				snprintf(bp, buf + sizeof buf - bp,
132846311fcStdeval 				    " called %s", un);
133846311fcStdeval 			}
134846311fcStdeval 			if(dn) {
135846311fcStdeval 				bp = eos(buf);
136846311fcStdeval 				snprintf(bp, buf + sizeof buf - bp,
137846311fcStdeval 				    " (%s)", dn);
138846311fcStdeval 			}
139df930be7Sderaadt 		} else {
14042ceebb3Sderaadt 			strlcpy(buf, dn ? dn : an, sizeof buf);
141df930be7Sderaadt 			if(ocl->oc_olet == GEM_SYM)
14242ceebb3Sderaadt 				strlcat(buf, " gem", sizeof buf);
143846311fcStdeval 			if(un) {
144846311fcStdeval 				bp = eos(buf);
145846311fcStdeval 				snprintf(bp, buf + sizeof buf - bp,
146846311fcStdeval 				    " called %s", un);
147846311fcStdeval 			}
148df930be7Sderaadt 		}
149df930be7Sderaadt 		return(buf);
150df930be7Sderaadt 	}
151df930be7Sderaadt 	/* here for ring/scroll/potion/wand */
152846311fcStdeval 	if(nn) {
153846311fcStdeval 		bp = eos(buf);
154846311fcStdeval 		snprintf(bp, buf + sizeof buf - bp, " of %s", an);
155846311fcStdeval 	}
156846311fcStdeval 	if(un) {
157846311fcStdeval 		bp = eos(buf);
158846311fcStdeval 		snprintf(bp, buf + sizeof buf - bp, " called %s", un);
159846311fcStdeval 	}
160846311fcStdeval 	if(dn) {
161846311fcStdeval 		bp = eos(buf);
162846311fcStdeval 		snprintf(bp, buf + sizeof buf - bp, " (%s)", dn);
163846311fcStdeval 	}
164df930be7Sderaadt 	return(buf);
165df930be7Sderaadt }
166df930be7Sderaadt 
167df930be7Sderaadt char *
xname(struct obj * obj)1684a5fbbc4Spjanzen xname(struct obj *obj)
169df930be7Sderaadt {
1704a5fbbc4Spjanzen 	char *buf = &(bufr[PREFIX]);	/* leave room for "17 -3 " */
1714a5fbbc4Spjanzen 	int nn = objects[obj->otyp].oc_name_known;
1724a5fbbc4Spjanzen 	char *an = objects[obj->otyp].oc_name;
1734a5fbbc4Spjanzen 	char *dn = objects[obj->otyp].oc_descr;
1744a5fbbc4Spjanzen 	char *un = objects[obj->otyp].oc_uname;
1754a5fbbc4Spjanzen 	int pl = (obj->quan != 1);
176846311fcStdeval 	size_t len = bufr + sizeof bufr - buf;
1774a5fbbc4Spjanzen 
1781ccb6c7bStodd 	if(!obj->dknown && !Blind) obj->dknown = 1; /* %% doesn't belong here */
179df930be7Sderaadt 	switch(obj->olet) {
180df930be7Sderaadt 	case AMULET_SYM:
181846311fcStdeval 		strlcpy(buf, (obj->spe < 0 && obj->known)
182846311fcStdeval 			? "cheap plastic imitation of the " : "", len);
183846311fcStdeval 		strlcat(buf,"Amulet of Yendor", len);
184df930be7Sderaadt 		break;
185df930be7Sderaadt 	case TOOL_SYM:
186df930be7Sderaadt 		if(!nn) {
187846311fcStdeval 			strlcpy(buf, dn, len);
188df930be7Sderaadt 			break;
189df930be7Sderaadt 		}
190846311fcStdeval 		strlcpy(buf,an,len);
191df930be7Sderaadt 		break;
192df930be7Sderaadt 	case FOOD_SYM:
193df930be7Sderaadt 		if(obj->otyp == DEAD_HOMUNCULUS && pl) {
194df930be7Sderaadt 			pl = 0;
195846311fcStdeval 			strlcpy(buf, "dead homunculi", len);
196df930be7Sderaadt 			break;
197df930be7Sderaadt 		}
198df930be7Sderaadt 		/* fungis ? */
199df930be7Sderaadt 		/* fall into next case */
200df930be7Sderaadt 	case WEAPON_SYM:
201df930be7Sderaadt 		if(obj->otyp == WORM_TOOTH && pl) {
202df930be7Sderaadt 			pl = 0;
203846311fcStdeval 			strlcpy(buf, "worm teeth", len);
204df930be7Sderaadt 			break;
205df930be7Sderaadt 		}
206df930be7Sderaadt 		if(obj->otyp == CRYSKNIFE && pl) {
207df930be7Sderaadt 			pl = 0;
208846311fcStdeval 			strlcpy(buf, "crysknives", len);
209df930be7Sderaadt 			break;
210df930be7Sderaadt 		}
211df930be7Sderaadt 		/* fall into next case */
212df930be7Sderaadt 	case ARMOR_SYM:
213df930be7Sderaadt 	case CHAIN_SYM:
214df930be7Sderaadt 	case ROCK_SYM:
215846311fcStdeval 		strlcpy(buf,an,len);
216df930be7Sderaadt 		break;
217df930be7Sderaadt 	case BALL_SYM:
218846311fcStdeval 		snprintf(buf, len, "%sheavy iron ball",
219df930be7Sderaadt 		  (obj->owt > objects[obj->otyp].oc_weight) ? "very " : "");
220df930be7Sderaadt 		break;
221df930be7Sderaadt 	case POTION_SYM:
222df930be7Sderaadt 		if(nn || un || !obj->dknown) {
223846311fcStdeval 			strlcpy(buf, "potion", len);
224df930be7Sderaadt 			if(pl) {
225df930be7Sderaadt 				pl = 0;
226846311fcStdeval 				strlcat(buf, "s", len);
227df930be7Sderaadt 			}
228df930be7Sderaadt 			if(!obj->dknown) break;
229df930be7Sderaadt 			if(un) {
230846311fcStdeval 				strlcat(buf, " called ", len);
231846311fcStdeval 				strlcat(buf, un, len);
232df930be7Sderaadt 			} else {
233846311fcStdeval 				strlcat(buf, " of ", len);
234846311fcStdeval 				strlcat(buf, an, len);
235df930be7Sderaadt 			}
236df930be7Sderaadt 		} else {
237846311fcStdeval 			strlcpy(buf, dn, len);
238846311fcStdeval 			strlcat(buf, " potion", len);
239df930be7Sderaadt 		}
240df930be7Sderaadt 		break;
241df930be7Sderaadt 	case SCROLL_SYM:
242846311fcStdeval 		strlcpy(buf, "scroll", len);
243df930be7Sderaadt 		if(pl) {
244df930be7Sderaadt 			pl = 0;
245846311fcStdeval 			strlcat(buf, "s", len);
246df930be7Sderaadt 		}
247df930be7Sderaadt 		if(!obj->dknown) break;
248df930be7Sderaadt 		if(nn) {
249846311fcStdeval 			strlcat(buf, " of ", len);
250846311fcStdeval 			strlcat(buf, an, len);
251df930be7Sderaadt 		} else if(un) {
252846311fcStdeval 			strlcat(buf, " called ", len);
253846311fcStdeval 			strlcat(buf, un, len);
254df930be7Sderaadt 		} else {
255846311fcStdeval 			strlcat(buf, " labeled ", len);
256846311fcStdeval 			strlcat(buf, dn, len);
257df930be7Sderaadt 		}
258df930be7Sderaadt 		break;
259df930be7Sderaadt 	case WAND_SYM:
260df930be7Sderaadt 		if(!obj->dknown)
261846311fcStdeval 			snprintf(buf, len, "wand");
262df930be7Sderaadt 		else if(nn)
263846311fcStdeval 			snprintf(buf, len, "wand of %s", an);
264df930be7Sderaadt 		else if(un)
265846311fcStdeval 			snprintf(buf, len, "wand called %s", un);
266df930be7Sderaadt 		else
267846311fcStdeval 			snprintf(buf, len, "%s wand", dn);
268df930be7Sderaadt 		break;
269df930be7Sderaadt 	case RING_SYM:
270df930be7Sderaadt 		if(!obj->dknown)
271846311fcStdeval 			snprintf(buf, len, "ring");
272df930be7Sderaadt 		else if(nn)
273846311fcStdeval 			snprintf(buf, len, "ring of %s", an);
274df930be7Sderaadt 		else if(un)
275846311fcStdeval 			snprintf(buf, len, "ring called %s", un);
276df930be7Sderaadt 		else
277846311fcStdeval 			snprintf(buf, len, "%s ring", dn);
278df930be7Sderaadt 		break;
279df930be7Sderaadt 	case GEM_SYM:
280df930be7Sderaadt 		if(!obj->dknown) {
281846311fcStdeval 			strlcpy(buf, "gem", len);
282df930be7Sderaadt 			break;
283df930be7Sderaadt 		}
284df930be7Sderaadt 		if(!nn) {
285846311fcStdeval 			snprintf(buf, len, "%s gem", dn);
286df930be7Sderaadt 			break;
287df930be7Sderaadt 		}
288846311fcStdeval 		strlcpy(buf, an, len);
289df930be7Sderaadt 		if(obj->otyp >= TURQUOISE && obj->otyp <= JADE)
290846311fcStdeval 			strlcat(buf, " stone", len);
291df930be7Sderaadt 		break;
292df930be7Sderaadt 	default:
293846311fcStdeval 		snprintf(buf,len,"glorkum %c (0%o) %u %d",
294df930be7Sderaadt 			obj->olet,obj->olet,obj->otyp,obj->spe);
295df930be7Sderaadt 	}
296df930be7Sderaadt 	if(pl) {
2974a5fbbc4Spjanzen 		char *p;
298df930be7Sderaadt 
299df930be7Sderaadt 		for(p = buf; *p; p++) {
300df930be7Sderaadt 			if(!strncmp(" of ", p, 4)) {
301df930be7Sderaadt 				/* pieces of, cloves of, lumps of */
3024a5fbbc4Spjanzen 				int c1, c2 = 's';
303df930be7Sderaadt 
304df930be7Sderaadt 				do {
305df930be7Sderaadt 					c1 = c2; c2 = *p; *p++ = c1;
306df930be7Sderaadt 				} while(c1);
307df930be7Sderaadt 				goto nopl;
308df930be7Sderaadt 			}
309df930be7Sderaadt 		}
310df930be7Sderaadt 		p = eos(buf)-1;
311df930be7Sderaadt 		if(*p == 's' || *p == 'z' || *p == 'x' ||
312df930be7Sderaadt 		    (*p == 'h' && p[-1] == 's'))
313846311fcStdeval 			strlcat(buf, "es", len);	/* boxes */
314180acc8fSmillert 		else if(*p == 'y' && !strchr(vowels, p[-1]))
315846311fcStdeval 				/* rubies, zruties */
316846311fcStdeval 			strlcpy(p, "ies", bufr + sizeof bufr - p);
317df930be7Sderaadt 		else
318846311fcStdeval 			strlcat(buf, "s", len);
319df930be7Sderaadt 	}
320df930be7Sderaadt nopl:
321df930be7Sderaadt 	if(obj->onamelth) {
322846311fcStdeval 		strlcat(buf, " named ", len);
323846311fcStdeval 		strlcat(buf, ONAME(obj), len);
324df930be7Sderaadt 	}
325df930be7Sderaadt 	return(buf);
326df930be7Sderaadt }
327df930be7Sderaadt 
328df930be7Sderaadt char *
doname(struct obj * obj)3294a5fbbc4Spjanzen doname(struct obj *obj)
330df930be7Sderaadt {
331df930be7Sderaadt 	char prefix[PREFIX];
3324a5fbbc4Spjanzen 	char *bp = xname(obj);
3334a5fbbc4Spjanzen 	char *p;
3344a5fbbc4Spjanzen 
335df930be7Sderaadt 	if(obj->quan != 1)
33642ceebb3Sderaadt 		snprintf(prefix, sizeof prefix, "%u ", obj->quan);
337df930be7Sderaadt 	else
33842ceebb3Sderaadt 		strlcpy(prefix, "a ", sizeof prefix);
339df930be7Sderaadt 	switch(obj->olet) {
340df930be7Sderaadt 	case AMULET_SYM:
341df930be7Sderaadt 		if(strncmp(bp, "cheap ", 6))
34242ceebb3Sderaadt 			strlcpy(prefix, "the ", sizeof prefix);
343df930be7Sderaadt 		break;
344df930be7Sderaadt 	case ARMOR_SYM:
345df930be7Sderaadt 		if(obj->owornmask & W_ARMOR)
346846311fcStdeval 			strlcat(bp, " (being worn)", bufr + sizeof bufr - bp);
347df930be7Sderaadt 		/* fall into next case */
348df930be7Sderaadt 	case WEAPON_SYM:
349df930be7Sderaadt 		if(obj->known) {
35042ceebb3Sderaadt 			strlcat(prefix, sitoa(obj->spe), sizeof prefix);
35142ceebb3Sderaadt 			strlcat(prefix, " ", sizeof prefix);
352df930be7Sderaadt 		}
353df930be7Sderaadt 		break;
354df930be7Sderaadt 	case WAND_SYM:
355846311fcStdeval 		if(obj->known) {
356846311fcStdeval 			p = eos(bp);
357846311fcStdeval 			snprintf(p, bufr + sizeof bufr - p, " (%d)", obj->spe);
358846311fcStdeval 		}
359df930be7Sderaadt 		break;
360df930be7Sderaadt 	case RING_SYM:
361846311fcStdeval 		if(obj->owornmask & W_RINGR)
362846311fcStdeval 			strlcat(bp, " (on right hand)", bufr + sizeof bufr - bp);
363846311fcStdeval 		if(obj->owornmask & W_RINGL)
364846311fcStdeval 			strlcat(bp, " (on left hand)", bufr + sizeof bufr - bp);
365df930be7Sderaadt 		if(obj->known && (objects[obj->otyp].bits & SPEC)) {
36642ceebb3Sderaadt 			strlcat(prefix, sitoa(obj->spe), sizeof prefix);
36742ceebb3Sderaadt 			strlcat(prefix, " ", sizeof prefix);
368df930be7Sderaadt 		}
369df930be7Sderaadt 		break;
370df930be7Sderaadt 	}
371df930be7Sderaadt 	if(obj->owornmask & W_WEP)
372846311fcStdeval 		strlcat(bp, " (weapon in hand)", bufr + sizeof bufr - bp);
373df930be7Sderaadt 	if(obj->unpaid)
374846311fcStdeval 		strlcat(bp, " (unpaid)", bufr + sizeof bufr - bp);
375180acc8fSmillert 	if(!strcmp(prefix, "a ") && strchr(vowels, *bp))
37642ceebb3Sderaadt 		strlcpy(prefix, "an ", sizeof prefix);
377df930be7Sderaadt 	bp = strprepend(bp, prefix);
378df930be7Sderaadt 	return(bp);
379df930be7Sderaadt }
380df930be7Sderaadt 
381df930be7Sderaadt /* used only in hack.fight.c (thitu) */
3824a5fbbc4Spjanzen void
setan(char * str,char * buf,size_t len)3834a5fbbc4Spjanzen setan(char *str, char *buf, size_t len)
384df930be7Sderaadt {
385180acc8fSmillert 	if(strchr(vowels,*str))
386846311fcStdeval 		snprintf(buf, len, "an %s", str);
387df930be7Sderaadt 	else
388846311fcStdeval 		snprintf(buf, len, "a %s", str);
389df930be7Sderaadt }
390df930be7Sderaadt 
391df930be7Sderaadt char *
aobjnam(struct obj * otmp,char * verb)3924a5fbbc4Spjanzen aobjnam(struct obj *otmp, char *verb)
3934a5fbbc4Spjanzen {
3944a5fbbc4Spjanzen 	char *bp = xname(otmp);
395df930be7Sderaadt 	char prefix[PREFIX];
3964a5fbbc4Spjanzen 
397df930be7Sderaadt 	if(otmp->quan != 1) {
39842ceebb3Sderaadt 		snprintf(prefix, sizeof prefix, "%u ", otmp->quan);
399df930be7Sderaadt 		bp = strprepend(bp, prefix);
400df930be7Sderaadt 	}
401df930be7Sderaadt 
402df930be7Sderaadt 	if(verb) {
403df930be7Sderaadt 		/* verb is given in plural (i.e., without trailing s) */
404846311fcStdeval 		strlcat(bp, " ", bufr + sizeof bufr - bp);
405df930be7Sderaadt 		if(otmp->quan != 1)
406846311fcStdeval 			strlcat(bp, verb, bufr + sizeof bufr - bp);
407df930be7Sderaadt 		else if(!strcmp(verb, "are"))
408846311fcStdeval 			strlcat(bp, "is", bufr + sizeof bufr - bp);
409df930be7Sderaadt 		else {
410846311fcStdeval 			strlcat(bp, verb, bufr + sizeof bufr - bp);
411846311fcStdeval 			strlcat(bp, "s", bufr + sizeof bufr - bp);
412df930be7Sderaadt 		}
413df930be7Sderaadt 	}
414df930be7Sderaadt 	return(bp);
415df930be7Sderaadt }
416df930be7Sderaadt 
417df930be7Sderaadt char *
Doname(struct obj * obj)4184a5fbbc4Spjanzen Doname(struct obj *obj)
419df930be7Sderaadt {
4204a5fbbc4Spjanzen 	char *s = doname(obj);
421df930be7Sderaadt 
422df930be7Sderaadt 	if('a' <= *s && *s <= 'z') *s -= ('a' - 'A');
423df930be7Sderaadt 	return(s);
424df930be7Sderaadt }
425df930be7Sderaadt 
426df930be7Sderaadt char *wrp[] = { "wand", "ring", "potion", "scroll", "gem" };
427df930be7Sderaadt char wrpsym[] = { WAND_SYM, RING_SYM, POTION_SYM, SCROLL_SYM, GEM_SYM };
428df930be7Sderaadt 
429df930be7Sderaadt struct obj *
readobjnam(char * bp,size_t len)4304a5fbbc4Spjanzen readobjnam(char *bp, size_t len)
431846311fcStdeval {
4324a5fbbc4Spjanzen 	char *p, *cp = bp;
4334a5fbbc4Spjanzen 	int i;
434df930be7Sderaadt 	int cnt, spe, spesgn, typ, heavy;
435df930be7Sderaadt 	char let;
436df930be7Sderaadt 	char *un, *dn, *an;
4374a5fbbc4Spjanzen 
438df930be7Sderaadt /* int the = 0; char *oname = 0; */
439df930be7Sderaadt 	cnt = spe = spesgn = typ = heavy = 0;
440df930be7Sderaadt 	let = 0;
441df930be7Sderaadt 	an = dn = un = 0;
442846311fcStdeval 	for(p = cp; *p; p++)
443df930be7Sderaadt 		if('A' <= *p && *p <= 'Z') *p += 'a'-'A';
444846311fcStdeval 	if(!strncmp(cp, "the ", 4)){
445df930be7Sderaadt /*		the = 1; */
446846311fcStdeval 		cp += 4;
447846311fcStdeval 	} else if(!strncmp(cp, "an ", 3)){
448df930be7Sderaadt 		cnt = 1;
449846311fcStdeval 		cp += 3;
450846311fcStdeval 	} else if(!strncmp(cp, "a ", 2)){
451df930be7Sderaadt 		cnt = 1;
452846311fcStdeval 		cp += 2;
453df930be7Sderaadt 	}
454cb40a3d3Smmcc 	if(!cnt && isdigit((unsigned char)*cp)){
455846311fcStdeval 		cnt = atoi(cp);
456cb40a3d3Smmcc 		while(isdigit((unsigned char)*cp)) cp++;
457846311fcStdeval 		while(*cp == ' ') cp++;
458df930be7Sderaadt 	}
459df930be7Sderaadt 	if(!cnt) cnt = 1;		/* %% what with "gems" etc. ? */
460df930be7Sderaadt 
461846311fcStdeval 	if(*cp == '+' || *cp == '-'){
462846311fcStdeval 		spesgn = (*cp++ == '+') ? 1 : -1;
463846311fcStdeval 		spe = atoi(cp);
464cb40a3d3Smmcc 		while(isdigit((unsigned char)*cp)) cp++;
465846311fcStdeval 		while(*cp == ' ') cp++;
466df930be7Sderaadt 	} else {
467846311fcStdeval 		p = strrchr(cp, '(');
468df930be7Sderaadt 		if(p) {
469846311fcStdeval 			if(p > cp && p[-1] == ' ') p[-1] = 0;
470df930be7Sderaadt 			else *p = 0;
471df930be7Sderaadt 			p++;
472df930be7Sderaadt 			spe = atoi(p);
473cb40a3d3Smmcc 			while(isdigit((unsigned char)*p)) p++;
474df930be7Sderaadt 			if(strcmp(p, ")")) spe = 0;
475df930be7Sderaadt 			else spesgn = 1;
476df930be7Sderaadt 		}
477df930be7Sderaadt 	}
478df930be7Sderaadt 	/* now we have the actual name, as delivered by xname, say
479df930be7Sderaadt 		green potions called whisky
480df930be7Sderaadt 		scrolls labeled "QWERTY"
481df930be7Sderaadt 		egg
482df930be7Sderaadt 		dead zruties
483df930be7Sderaadt 		fortune cookies
484df930be7Sderaadt 		very heavy iron ball named hoei
485df930be7Sderaadt 		wand of wishing
486df930be7Sderaadt 		elven cloak
487df930be7Sderaadt 	*/
488846311fcStdeval 	for(p = cp; *p; p++) if(!strncmp(p, " named ", 7)) {
489df930be7Sderaadt 		*p = 0;
490df930be7Sderaadt /*		oname = p+7; */
491df930be7Sderaadt 	}
492846311fcStdeval 	for(p = cp; *p; p++) if(!strncmp(p, " called ", 8)) {
493df930be7Sderaadt 		*p = 0;
494df930be7Sderaadt 		un = p+8;
495df930be7Sderaadt 	}
496846311fcStdeval 	for(p = cp; *p; p++) if(!strncmp(p, " labeled ", 9)) {
497df930be7Sderaadt 		*p = 0;
498df930be7Sderaadt 		dn = p+9;
499df930be7Sderaadt 	}
500df930be7Sderaadt 
501df930be7Sderaadt 	/* first change to singular if necessary */
502df930be7Sderaadt 	if(cnt != 1) {
503df930be7Sderaadt 		/* find "cloves of garlic", "worthless pieces of blue glass" */
504846311fcStdeval 		for(p = cp; *p; p++) if(!strncmp(p, "s of ", 5)){
5054a5fbbc4Spjanzen 			while ((*p = p[1]))
5064a5fbbc4Spjanzen 				p++;
507df930be7Sderaadt 			goto sing;
508df930be7Sderaadt 		}
509df930be7Sderaadt 		/* remove -s or -es (boxes) or -ies (rubies, zruties) */
510846311fcStdeval 		p = eos(cp);
511df930be7Sderaadt 		if(p[-1] == 's') {
512df930be7Sderaadt 			if(p[-2] == 'e') {
513df930be7Sderaadt 				if(p[-3] == 'i') {
514df930be7Sderaadt 					if(!strcmp(p-7, "cookies"))
515df930be7Sderaadt 						goto mins;
516846311fcStdeval 					strlcpy(p-3, "y", bp + len - (p-3));
517df930be7Sderaadt 					goto sing;
518df930be7Sderaadt 				}
519df930be7Sderaadt 
520df930be7Sderaadt 				/* note: cloves / knives from clove / knife */
521df930be7Sderaadt 				if(!strcmp(p-6, "knives")) {
522846311fcStdeval 					strlcpy(p-3, "fe", bp + len - (p-3));
523df930be7Sderaadt 					goto sing;
524df930be7Sderaadt 				}
525df930be7Sderaadt 
526df930be7Sderaadt 				/* note: nurses, axes but boxes */
527df930be7Sderaadt 				if(!strcmp(p-5, "boxes")) {
528df930be7Sderaadt 					p[-2] = 0;
529df930be7Sderaadt 					goto sing;
530df930be7Sderaadt 				}
531df930be7Sderaadt 			}
532df930be7Sderaadt 		mins:
533df930be7Sderaadt 			p[-1] = 0;
534df930be7Sderaadt 		} else {
535df930be7Sderaadt 			if(!strcmp(p-9, "homunculi")) {
536846311fcStdeval 				strlcpy(p-1, "us", bp + len - (p-1));
537df930be7Sderaadt 				goto sing;
538df930be7Sderaadt 			}
539df930be7Sderaadt 			if(!strcmp(p-5, "teeth")) {
540846311fcStdeval 				strlcpy(p-5, "tooth", bp + len - (p-5));
541df930be7Sderaadt 				goto sing;
542df930be7Sderaadt 			}
543df930be7Sderaadt 			/* here we cannot find the plural suffix */
544df930be7Sderaadt 		}
545df930be7Sderaadt 	}
546df930be7Sderaadt sing:
547846311fcStdeval 	if(!strcmp(cp, "amulet of yendor")) {
548df930be7Sderaadt 		typ = AMULET_OF_YENDOR;
549df930be7Sderaadt 		goto typfnd;
550df930be7Sderaadt 	}
551846311fcStdeval 	p = eos(cp);
552df930be7Sderaadt 	if(!strcmp(p-5, " mail")){	/* Note: ring mail is not a ring ! */
553df930be7Sderaadt 		let = ARMOR_SYM;
554846311fcStdeval 		an = cp;
555df930be7Sderaadt 		goto srch;
556df930be7Sderaadt 	}
557df930be7Sderaadt 	for(i = 0; i < sizeof(wrpsym); i++) {
5584a5fbbc4Spjanzen 		int j = strlen(wrp[i]);
559846311fcStdeval 		if(!strncmp(cp, wrp[i], j)){
560df930be7Sderaadt 			let = wrpsym[i];
561846311fcStdeval 			cp += j;
562846311fcStdeval 			if(!strncmp(cp, " of ", 4)) an = cp+4;
563846311fcStdeval 			/* else if(*cp) ?? */
564df930be7Sderaadt 			goto srch;
565df930be7Sderaadt 		}
566df930be7Sderaadt 		if(!strcmp(p-j, wrp[i])){
567df930be7Sderaadt 			let = wrpsym[i];
568df930be7Sderaadt 			p -= j;
569df930be7Sderaadt 			*p = 0;
570df930be7Sderaadt 			if(p[-1] == ' ') p[-1] = 0;
571846311fcStdeval 			dn = cp;
572df930be7Sderaadt 			goto srch;
573df930be7Sderaadt 		}
574df930be7Sderaadt 	}
575df930be7Sderaadt 	if(!strcmp(p-6, " stone")){
576df930be7Sderaadt 		p[-6] = 0;
577df930be7Sderaadt 		let = GEM_SYM;
578846311fcStdeval 		an = cp;
579df930be7Sderaadt 		goto srch;
580df930be7Sderaadt 	}
581846311fcStdeval 	if(!strcmp(cp, "very heavy iron ball")){
582df930be7Sderaadt 		heavy = 1;
583df930be7Sderaadt 		typ = HEAVY_IRON_BALL;
584df930be7Sderaadt 		goto typfnd;
585df930be7Sderaadt 	}
586846311fcStdeval 	an = cp;
587df930be7Sderaadt srch:
588df930be7Sderaadt 	if(!an && !dn && !un)
589df930be7Sderaadt 		goto any;
590df930be7Sderaadt 	i = 1;
591df930be7Sderaadt 	if(let) i = bases[letindex(let)];
592df930be7Sderaadt 	while(i <= NROFOBJECTS && (!let || objects[i].oc_olet == let)){
5934a5fbbc4Spjanzen 		char *zn = objects[i].oc_name;
594df930be7Sderaadt 
595df930be7Sderaadt 		if(!zn) goto nxti;
596df930be7Sderaadt 		if(an && strcmp(an, zn))
597df930be7Sderaadt 			goto nxti;
598df930be7Sderaadt 		if(dn && (!(zn = objects[i].oc_descr) || strcmp(dn, zn)))
599df930be7Sderaadt 			goto nxti;
600df930be7Sderaadt 		if(un && (!(zn = objects[i].oc_uname) || strcmp(un, zn)))
601df930be7Sderaadt 			goto nxti;
602df930be7Sderaadt 		typ = i;
603df930be7Sderaadt 		goto typfnd;
604df930be7Sderaadt 	nxti:
605df930be7Sderaadt 		i++;
606df930be7Sderaadt 	}
607df930be7Sderaadt any:
608df930be7Sderaadt 	if(!let) let = wrpsym[rn2(sizeof(wrpsym))];
609df930be7Sderaadt 	typ = probtype(let);
610df930be7Sderaadt typfnd:
6114a5fbbc4Spjanzen 	{ struct obj *otmp;
612df930be7Sderaadt 	let = objects[typ].oc_olet;
613df930be7Sderaadt 	otmp = mksobj(typ);
614df930be7Sderaadt 	if(heavy)
615df930be7Sderaadt 		otmp->owt += 15;
616180acc8fSmillert 	if(cnt > 0 && strchr("%?!*)", let) &&
617df930be7Sderaadt 		(cnt < 4 || (let == WEAPON_SYM && typ <= ROCK && cnt < 20)))
618df930be7Sderaadt 		otmp->quan = cnt;
619df930be7Sderaadt 
620df930be7Sderaadt 	if(spe > 3 && spe > otmp->spe)
621df930be7Sderaadt 		spe = 0;
622df930be7Sderaadt 	else if(let == WAND_SYM)
623df930be7Sderaadt 		spe = otmp->spe;
624df930be7Sderaadt 	if(spe == 3 && u.uluck < 0)
625df930be7Sderaadt 		spesgn = -1;
626df930be7Sderaadt 	if(let != WAND_SYM && spesgn == -1)
627df930be7Sderaadt 		spe = -spe;
628df930be7Sderaadt 	if(let == BALL_SYM)
629df930be7Sderaadt 		spe = 0;
630df930be7Sderaadt 	else if(let == AMULET_SYM)
631df930be7Sderaadt 		spe = -1;
632df930be7Sderaadt 	else if(typ == WAN_WISHING && rn2(10))
633df930be7Sderaadt 		spe = (rn2(10) ? -1 : 0);
634df930be7Sderaadt 	otmp->spe = spe;
635df930be7Sderaadt 
636df930be7Sderaadt 	if(spesgn == -1)
637df930be7Sderaadt 		otmp->cursed = 1;
638df930be7Sderaadt 
639df930be7Sderaadt 	return(otmp);
640df930be7Sderaadt     }
641df930be7Sderaadt }
642