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