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