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