xref: /dragonfly/games/hack/hack.objnam.c (revision 2ee85085)
1 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
2 /* hack.objnam.c - version 1.0.2 */
3 /* $FreeBSD: src/games/hack/hack.objnam.c,v 1.3 1999/11/16 02:57:08 billf Exp $ */
4 /* $DragonFly: src/games/hack/hack.objnam.c,v 1.3 2005/05/22 03:37:05 y0netan1 Exp $ */
5 
6 #include	"hack.h"
7 #define Sprintf (void) sprintf
8 #define Strcat  (void) strcat
9 #define	Strcpy	(void) strcpy
10 #define	PREFIX	15
11 extern char *eos();
12 extern int bases[];
13 
14 char *
15 strprepend(s,pref) char *s, *pref; {
16 int i = strlen(pref);
17 	if(i > PREFIX) {
18 		pline("WARNING: prefix too short.");
19 		return(s);
20 	}
21 	s -= i;
22 	(void) strncpy(s, pref, i);	/* do not copy trailing 0 */
23 	return(s);
24 }
25 
26 char *
27 sitoa(a) int a; {
28 static char buf[13];
29 	Sprintf(buf, (a < 0) ? "%d" : "+%d", a);
30 	return(buf);
31 }
32 
33 char *
34 typename(otyp)
35 int otyp;
36 {
37 static char buf[BUFSZ];
38 struct objclass *ocl = &objects[otyp];
39 const char *an = ocl->oc_name;
40 const char *dn = ocl->oc_descr;
41 char *un = ocl->oc_uname;
42 int nn = ocl->oc_name_known;
43 	switch(ocl->oc_olet) {
44 	case POTION_SYM:
45 		Strcpy(buf, "potion");
46 		break;
47 	case SCROLL_SYM:
48 		Strcpy(buf, "scroll");
49 		break;
50 	case WAND_SYM:
51 		Strcpy(buf, "wand");
52 		break;
53 	case RING_SYM:
54 		Strcpy(buf, "ring");
55 		break;
56 	default:
57 		if(nn) {
58 			Strcpy(buf, an);
59 			if(otyp >= TURQUOISE && otyp <= JADE)
60 				Strcat(buf, " stone");
61 			if(un)
62 				Sprintf(eos(buf), " called %s", un);
63 			if(dn)
64 				Sprintf(eos(buf), " (%s)", dn);
65 		} else {
66 			Strcpy(buf, dn ? dn : an);
67 			if(ocl->oc_olet == GEM_SYM)
68 				Strcat(buf, " gem");
69 			if(un)
70 				Sprintf(eos(buf), " called %s", un);
71 		}
72 		return(buf);
73 	}
74 	/* here for ring/scroll/potion/wand */
75 	if(nn)
76 		Sprintf(eos(buf), " of %s", an);
77 	if(un)
78 		Sprintf(eos(buf), " called %s", un);
79 	if(dn)
80 		Sprintf(eos(buf), " (%s)", dn);
81 	return(buf);
82 }
83 
84 char *
85 xname(obj)
86 struct obj *obj;
87 {
88 static char bufr[BUFSZ];
89 char *buf = &(bufr[PREFIX]);	/* leave room for "17 -3 " */
90 int nn = objects[obj->otyp].oc_name_known;
91 const char *an = objects[obj->otyp].oc_name;
92 const char *dn = objects[obj->otyp].oc_descr;
93 char *un = objects[obj->otyp].oc_uname;
94 int pl = (obj->quan != 1);
95 	if(!obj->dknown && !Blind) obj->dknown = 1; /* %% doesnt belong here */
96 	switch(obj->olet) {
97 	case AMULET_SYM:
98 		Strcpy(buf, (obj->spe < 0 && obj->known)
99 			? "cheap plastic imitation of the " : "");
100 		Strcat(buf,"Amulet of Yendor");
101 		break;
102 	case TOOL_SYM:
103 		if(!nn) {
104 			Strcpy(buf, dn);
105 			break;
106 		}
107 		Strcpy(buf,an);
108 		break;
109 	case FOOD_SYM:
110 		if(obj->otyp == DEAD_HOMUNCULUS && pl) {
111 			pl = 0;
112 			Strcpy(buf, "dead homunculi");
113 			break;
114 		}
115 		/* fungis ? */
116 		/* fall into next case */
117 	case WEAPON_SYM:
118 		if(obj->otyp == WORM_TOOTH && pl) {
119 			pl = 0;
120 			Strcpy(buf, "worm teeth");
121 			break;
122 		}
123 		if(obj->otyp == CRYSKNIFE && pl) {
124 			pl = 0;
125 			Strcpy(buf, "crysknives");
126 			break;
127 		}
128 		/* fall into next case */
129 	case ARMOR_SYM:
130 	case CHAIN_SYM:
131 	case ROCK_SYM:
132 		Strcpy(buf,an);
133 		break;
134 	case BALL_SYM:
135 		Sprintf(buf, "%sheavy iron ball",
136 		  (obj->owt > objects[obj->otyp].oc_weight) ? "very " : "");
137 		break;
138 	case POTION_SYM:
139 		if(nn || un || !obj->dknown) {
140 			Strcpy(buf, "potion");
141 			if(pl) {
142 				pl = 0;
143 				Strcat(buf, "s");
144 			}
145 			if(!obj->dknown) break;
146 			if(un) {
147 				Strcat(buf, " called ");
148 				Strcat(buf, un);
149 			} else {
150 				Strcat(buf, " of ");
151 				Strcat(buf, an);
152 			}
153 		} else {
154 			Strcpy(buf, dn);
155 			Strcat(buf, " potion");
156 		}
157 		break;
158 	case SCROLL_SYM:
159 		Strcpy(buf, "scroll");
160 		if(pl) {
161 			pl = 0;
162 			Strcat(buf, "s");
163 		}
164 		if(!obj->dknown) break;
165 		if(nn) {
166 			Strcat(buf, " of ");
167 			Strcat(buf, an);
168 		} else if(un) {
169 			Strcat(buf, " called ");
170 			Strcat(buf, un);
171 		} else {
172 			Strcat(buf, " labeled ");
173 			Strcat(buf, dn);
174 		}
175 		break;
176 	case WAND_SYM:
177 		if(!obj->dknown)
178 			Sprintf(buf, "wand");
179 		else if(nn)
180 			Sprintf(buf, "wand of %s", an);
181 		else if(un)
182 			Sprintf(buf, "wand called %s", un);
183 		else
184 			Sprintf(buf, "%s wand", dn);
185 		break;
186 	case RING_SYM:
187 		if(!obj->dknown)
188 			Sprintf(buf, "ring");
189 		else if(nn)
190 			Sprintf(buf, "ring of %s", an);
191 		else if(un)
192 			Sprintf(buf, "ring called %s", un);
193 		else
194 			Sprintf(buf, "%s ring", dn);
195 		break;
196 	case GEM_SYM:
197 		if(!obj->dknown) {
198 			Strcpy(buf, "gem");
199 			break;
200 		}
201 		if(!nn) {
202 			Sprintf(buf, "%s gem", dn);
203 			break;
204 		}
205 		Strcpy(buf, an);
206 		if(obj->otyp >= TURQUOISE && obj->otyp <= JADE)
207 			Strcat(buf, " stone");
208 		break;
209 	default:
210 		Sprintf(buf,"glorkum %c (0%o) %u %d",
211 			obj->olet,obj->olet,obj->otyp,obj->spe);
212 	}
213 	if(pl) {
214 		char *p;
215 
216 		for(p = buf; *p; p++) {
217 			if(!strncmp(" of ", p, 4)) {
218 				/* pieces of, cloves of, lumps of */
219 				int c1, c2 = 's';
220 
221 				do {
222 					c1 = c2; c2 = *p; *p++ = c1;
223 				} while(c1);
224 				goto nopl;
225 			}
226 		}
227 		p = eos(buf)-1;
228 		if(*p == 's' || *p == 'z' || *p == 'x' ||
229 		    (*p == 'h' && p[-1] == 's'))
230 			Strcat(buf, "es");	/* boxes */
231 		else if(*p == 'y' && !index(vowels, p[-1]))
232 			Strcpy(p, "ies");	/* rubies, zruties */
233 		else
234 			Strcat(buf, "s");
235 	}
236 nopl:
237 	if(obj->onamelth) {
238 		Strcat(buf, " named ");
239 		Strcat(buf, ONAME(obj));
240 	}
241 	return(buf);
242 }
243 
244 char *
245 doname(obj)
246 struct obj *obj;
247 {
248 char prefix[PREFIX];
249 char *bp = xname(obj);
250 	if(obj->quan != 1)
251 		Sprintf(prefix, "%u ", obj->quan);
252 	else
253 		Strcpy(prefix, "a ");
254 	switch(obj->olet) {
255 	case AMULET_SYM:
256 		if(strncmp(bp, "cheap ", 6))
257 			Strcpy(prefix, "the ");
258 		break;
259 	case ARMOR_SYM:
260 		if(obj->owornmask & W_ARMOR)
261 			Strcat(bp, " (being worn)");
262 		/* fall into next case */
263 	case WEAPON_SYM:
264 		if(obj->known) {
265 			Strcat(prefix, sitoa(obj->spe));
266 			Strcat(prefix, " ");
267 		}
268 		break;
269 	case WAND_SYM:
270 		if(obj->known)
271 			Sprintf(eos(bp), " (%d)", obj->spe);
272 		break;
273 	case RING_SYM:
274 		if(obj->owornmask & W_RINGR) Strcat(bp, " (on right hand)");
275 		if(obj->owornmask & W_RINGL) Strcat(bp, " (on left hand)");
276 		if(obj->known && (objects[obj->otyp].bits & SPEC)) {
277 			Strcat(prefix, sitoa(obj->spe));
278 			Strcat(prefix, " ");
279 		}
280 		break;
281 	}
282 	if(obj->owornmask & W_WEP)
283 		Strcat(bp, " (weapon in hand)");
284 	if(obj->unpaid)
285 		Strcat(bp, " (unpaid)");
286 	if(!strcmp(prefix, "a ") && index(vowels, *bp))
287 		Strcpy(prefix, "an ");
288 	bp = strprepend(bp, prefix);
289 	return(bp);
290 }
291 
292 /* used only in hack.fight.c (thitu) */
293 setan(str,buf)
294 char *str,*buf;
295 {
296 	if(index(vowels,*str))
297 		Sprintf(buf, "an %s", str);
298 	else
299 		Sprintf(buf, "a %s", str);
300 }
301 
302 char *
303 aobjnam(otmp,verb) struct obj *otmp; char *verb; {
304 char *bp = xname(otmp);
305 char prefix[PREFIX];
306 	if(otmp->quan != 1) {
307 		Sprintf(prefix, "%u ", otmp->quan);
308 		bp = strprepend(bp, prefix);
309 	}
310 
311 	if(verb) {
312 		/* verb is given in plural (i.e., without trailing s) */
313 		Strcat(bp, " ");
314 		if(otmp->quan != 1)
315 			Strcat(bp, verb);
316 		else if(!strcmp(verb, "are"))
317 			Strcat(bp, "is");
318 		else {
319 			Strcat(bp, verb);
320 			Strcat(bp, "s");
321 		}
322 	}
323 	return(bp);
324 }
325 
326 char *
327 Doname(obj)
328 struct obj *obj;
329 {
330 	char *s = doname(obj);
331 
332 	if('a' <= *s && *s <= 'z') *s -= ('a' - 'A');
333 	return(s);
334 }
335 
336 static	const char *wrp[] = { "wand", "ring", "potion", "scroll", "gem" };
337 char wrpsym[] = { WAND_SYM, RING_SYM, POTION_SYM, SCROLL_SYM, GEM_SYM };
338 
339 struct obj *
340 readobjnam(bp) char *bp; {
341 char *p;
342 int i;
343 int cnt, spe, spesgn, typ, heavy;
344 char let;
345 char *un, *dn, *an;
346 /* int the = 0; char *oname = 0; */
347 	cnt = spe = spesgn = typ = heavy = 0;
348 	let = 0;
349 	an = dn = un = 0;
350 	for(p = bp; *p; p++)
351 		if('A' <= *p && *p <= 'Z') *p += 'a'-'A';
352 	if(!strncmp(bp, "the ", 4)){
353 /*		the = 1; */
354 		bp += 4;
355 	} else if(!strncmp(bp, "an ", 3)){
356 		cnt = 1;
357 		bp += 3;
358 	} else if(!strncmp(bp, "a ", 2)){
359 		cnt = 1;
360 		bp += 2;
361 	}
362 	if(!cnt && digit(*bp)){
363 		cnt = atoi(bp);
364 		while(digit(*bp)) bp++;
365 		while(*bp == ' ') bp++;
366 	}
367 	if(!cnt) cnt = 1;		/* %% what with "gems" etc. ? */
368 
369 	if(*bp == '+' || *bp == '-'){
370 		spesgn = (*bp++ == '+') ? 1 : -1;
371 		spe = atoi(bp);
372 		while(digit(*bp)) bp++;
373 		while(*bp == ' ') bp++;
374 	} else {
375 		p = rindex(bp, '(');
376 		if(p) {
377 			if(p > bp && p[-1] == ' ') p[-1] = 0;
378 			else *p = 0;
379 			p++;
380 			spe = atoi(p);
381 			while(digit(*p)) p++;
382 			if(strcmp(p, ")")) spe = 0;
383 			else spesgn = 1;
384 		}
385 	}
386 	/* now we have the actual name, as delivered by xname, say
387 		green potions called whisky
388 		scrolls labeled "QWERTY"
389 		egg
390 		dead zruties
391 		fortune cookies
392 		very heavy iron ball named hoei
393 		wand of wishing
394 		elven cloak
395 	*/
396 	for(p = bp; *p; p++) if(!strncmp(p, " named ", 7)) {
397 		*p = 0;
398 /*		oname = p+7; */
399 	}
400 	for(p = bp; *p; p++) if(!strncmp(p, " called ", 8)) {
401 		*p = 0;
402 		un = p+8;
403 	}
404 	for(p = bp; *p; p++) if(!strncmp(p, " labeled ", 9)) {
405 		*p = 0;
406 		dn = p+9;
407 	}
408 
409 	/* first change to singular if necessary */
410 	if(cnt != 1) {
411 		/* find "cloves of garlic", "worthless pieces of blue glass" */
412 		for(p = bp; *p; p++) if(!strncmp(p, "s of ", 5)){
413 			while(*p = p[1]) p++;
414 			goto sing;
415 		}
416 		/* remove -s or -es (boxes) or -ies (rubies, zruties) */
417 		p = eos(bp);
418 		if(p[-1] == 's') {
419 			if(p[-2] == 'e') {
420 				if(p[-3] == 'i') {
421 					if(!strcmp(p-7, "cookies"))
422 						goto mins;
423 					Strcpy(p-3, "y");
424 					goto sing;
425 				}
426 
427 				/* note: cloves / knives from clove / knife */
428 				if(!strcmp(p-6, "knives")) {
429 					Strcpy(p-3, "fe");
430 					goto sing;
431 				}
432 
433 				/* note: nurses, axes but boxes */
434 				if(!strcmp(p-5, "boxes")) {
435 					p[-2] = 0;
436 					goto sing;
437 				}
438 			}
439 		mins:
440 			p[-1] = 0;
441 		} else {
442 			if(!strcmp(p-9, "homunculi")) {
443 				Strcpy(p-1, "us"); /* !! makes string longer */
444 				goto sing;
445 			}
446 			if(!strcmp(p-5, "teeth")) {
447 				Strcpy(p-5, "tooth");
448 				goto sing;
449 			}
450 			/* here we cannot find the plural suffix */
451 		}
452 	}
453 sing:
454 	if(!strcmp(bp, "amulet of yendor")) {
455 		typ = AMULET_OF_YENDOR;
456 		goto typfnd;
457 	}
458 	p = eos(bp);
459 	if(!strcmp(p-5, " mail")){	/* Note: ring mail is not a ring ! */
460 		let = ARMOR_SYM;
461 		an = bp;
462 		goto srch;
463 	}
464 	for(i = 0; i < sizeof(wrpsym); i++) {
465 		int j = strlen(wrp[i]);
466 		if(!strncmp(bp, wrp[i], j)){
467 			let = wrpsym[i];
468 			bp += j;
469 			if(!strncmp(bp, " of ", 4)) an = bp+4;
470 			/* else if(*bp) ?? */
471 			goto srch;
472 		}
473 		if(!strcmp(p-j, wrp[i])){
474 			let = wrpsym[i];
475 			p -= j;
476 			*p = 0;
477 			if(p[-1] == ' ') p[-1] = 0;
478 			dn = bp;
479 			goto srch;
480 		}
481 	}
482 	if(!strcmp(p-6, " stone")){
483 		p[-6] = 0;
484 		let = GEM_SYM;
485 		an = bp;
486 		goto srch;
487 	}
488 	if(!strcmp(bp, "very heavy iron ball")){
489 		heavy = 1;
490 		typ = HEAVY_IRON_BALL;
491 		goto typfnd;
492 	}
493 	an = bp;
494 srch:
495 	if(!an && !dn && !un)
496 		goto any;
497 	i = 1;
498 	if(let) i = bases[letindex(let)];
499 	while(i <= NROFOBJECTS && (!let || objects[i].oc_olet == let)){
500 		const char *zn = objects[i].oc_name;
501 
502 		if(!zn) goto nxti;
503 		if(an && strcmp(an, zn))
504 			goto nxti;
505 		if(dn && (!(zn = objects[i].oc_descr) || strcmp(dn, zn)))
506 			goto nxti;
507 		if(un && (!(zn = objects[i].oc_uname) || strcmp(un, zn)))
508 			goto nxti;
509 		typ = i;
510 		goto typfnd;
511 	nxti:
512 		i++;
513 	}
514 any:
515 	if(!let) let = wrpsym[rn2(sizeof(wrpsym))];
516 	typ = probtype(let);
517 typfnd:
518 	{ struct obj *otmp;
519 	  extern struct obj *mksobj();
520 	let = objects[typ].oc_olet;
521 	otmp = mksobj(typ);
522 	if(heavy)
523 		otmp->owt += 15;
524 	if(cnt > 0 && index("%?!*)", let) &&
525 		(cnt < 4 || (let == WEAPON_SYM && typ <= ROCK && cnt < 20)))
526 		otmp->quan = cnt;
527 
528 	if(spe > 3 && spe > otmp->spe)
529 		spe = 0;
530 	else if(let == WAND_SYM)
531 		spe = otmp->spe;
532 	if(spe == 3 && u.uluck < 0)
533 		spesgn = -1;
534 	if(let != WAND_SYM && spesgn == -1)
535 		spe = -spe;
536 	if(let == BALL_SYM)
537 		spe = 0;
538 	else if(let == AMULET_SYM)
539 		spe = -1;
540 	else if(typ == WAN_WISHING && rn2(10))
541 		spe = (rn2(10) ? -1 : 0);
542 	otmp->spe = spe;
543 
544 	if(spesgn == -1)
545 		otmp->cursed = 1;
546 
547 	return(otmp);
548     }
549 }
550