Home | History | Annotate | Line # | Download | only in hack
hack.objnam.c revision 1.9
      1 /*	$NetBSD: hack.objnam.c,v 1.9 2009/06/07 20:13:18 dholland Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
      5  * Amsterdam
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions are
     10  * met:
     11  *
     12  * - Redistributions of source code must retain the above copyright notice,
     13  * this list of conditions and the following disclaimer.
     14  *
     15  * - Redistributions in binary form must reproduce the above copyright
     16  * notice, this list of conditions and the following disclaimer in the
     17  * documentation and/or other materials provided with the distribution.
     18  *
     19  * - Neither the name of the Stichting Centrum voor Wiskunde en
     20  * Informatica, nor the names of its contributors may be used to endorse or
     21  * promote products derived from this software without specific prior
     22  * written permission.
     23  *
     24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
     25  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     26  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
     27  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
     28  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     29  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     30  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     31  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     32  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     33  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     34  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     35  */
     36 
     37 /*
     38  * Copyright (c) 1982 Jay Fenlason <hack (at) gnu.org>
     39  * All rights reserved.
     40  *
     41  * Redistribution and use in source and binary forms, with or without
     42  * modification, are permitted provided that the following conditions
     43  * are met:
     44  * 1. Redistributions of source code must retain the above copyright
     45  *    notice, this list of conditions and the following disclaimer.
     46  * 2. Redistributions in binary form must reproduce the above copyright
     47  *    notice, this list of conditions and the following disclaimer in the
     48  *    documentation and/or other materials provided with the distribution.
     49  * 3. The name of the author may not be used to endorse or promote products
     50  *    derived from this software without specific prior written permission.
     51  *
     52  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
     53  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
     54  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
     55  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     56  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     57  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     58  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     59  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     60  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
     61  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     62  */
     63 
     64 #include <sys/cdefs.h>
     65 #ifndef lint
     66 __RCSID("$NetBSD: hack.objnam.c,v 1.9 2009/06/07 20:13:18 dholland Exp $");
     67 #endif				/* not lint */
     68 
     69 #include <stdlib.h>
     70 #include "hack.h"
     71 #include "extern.h"
     72 #define Snprintf (void) snprintf
     73 #define Strcat  (void) strcat
     74 #define	Strcpy	(void) strcpy
     75 #define	PREFIX	15
     76 
     77 char           *
     78 strprepend(char *s, char *pref)
     79 {
     80 	int             i = strlen(pref);
     81 	if (i > PREFIX) {
     82 		pline("WARNING: prefix too short.");
     83 		return (s);
     84 	}
     85 	s -= i;
     86 	(void) strncpy(s, pref, i);	/* do not copy trailing 0 */
     87 	return (s);
     88 }
     89 
     90 char           *
     91 sitoa(int a)
     92 {
     93 	static char     buf[13];
     94 	Snprintf(buf, sizeof(buf), (a < 0) ? "%d" : "+%d", a);
     95 	return (buf);
     96 }
     97 
     98 char           *
     99 typename(int otyp)
    100 {
    101 	static char     buf[BUFSZ];
    102 	size_t bufpos;
    103 	struct objclass *ocl = &objects[otyp];
    104 	const char     *an = ocl->oc_name;
    105 	const char     *dn = ocl->oc_descr;
    106 	char           *un = ocl->oc_uname;
    107 	int             nn = ocl->oc_name_known;
    108 	switch (ocl->oc_olet) {
    109 	case POTION_SYM:
    110 		Strcpy(buf, "potion");
    111 		break;
    112 	case SCROLL_SYM:
    113 		Strcpy(buf, "scroll");
    114 		break;
    115 	case WAND_SYM:
    116 		Strcpy(buf, "wand");
    117 		break;
    118 	case RING_SYM:
    119 		Strcpy(buf, "ring");
    120 		break;
    121 	default:
    122 		if (nn) {
    123 			Strcpy(buf, an);
    124 			if (otyp >= TURQUOISE && otyp <= JADE)
    125 				Strcat(buf, " stone");
    126 			if (un) {
    127 				bufpos = strlen(buf);
    128 				Snprintf(buf+bufpos, sizeof(buf)-bufpos,
    129 					" called %s", un);
    130 			}
    131 			if (dn) {
    132 				bufpos = strlen(buf);
    133 				Snprintf(buf+bufpos, sizeof(buf)-bufpos,
    134 					" (%s)", dn);
    135 			}
    136 		} else {
    137 			strlcpy(buf, dn ? dn : an, sizeof(buf));
    138 			if (ocl->oc_olet == GEM_SYM) {
    139 				strlcat(buf, " gem", sizeof(buf));
    140 			}
    141 			if (un) {
    142 				bufpos = strlen(buf);
    143 				Snprintf(buf+bufpos, sizeof(buf)-bufpos,
    144 					" called %s", un);
    145 			}
    146 		}
    147 		return (buf);
    148 	}
    149 	/* here for ring/scroll/potion/wand */
    150 	if (nn) {
    151 		bufpos = strlen(buf);
    152 		Snprintf(buf+bufpos, sizeof(buf)-bufpos, " of %s", an);
    153 	}
    154 	if (un) {
    155 		bufpos = strlen(buf);
    156 		Snprintf(buf+bufpos, sizeof(buf)-bufpos, " called %s", un);
    157 	}
    158 	if (dn) {
    159 		bufpos = strlen(buf);
    160 		Snprintf(buf+bufpos, sizeof(buf)-bufpos, " (%s)", dn);
    161 	}
    162 	return (buf);
    163 }
    164 
    165 char           *
    166 xname(struct obj *obj)
    167 {
    168 	static char     bufr[BUFSZ];
    169 	/* caution: doname() and aobjnam() below "know" these sizes */
    170 	char           *buf = &(bufr[PREFIX]);	/* leave room for "17 -3 " */
    171 	size_t          bufmax = sizeof(bufr) - PREFIX;
    172 	int             nn = objects[obj->otyp].oc_name_known;
    173 	const char     *an = objects[obj->otyp].oc_name;
    174 	const char     *dn = objects[obj->otyp].oc_descr;
    175 	char           *un = objects[obj->otyp].oc_uname;
    176 	int             pl = (obj->quan != 1);
    177 
    178 	if (!obj->dknown && !Blind)
    179 		obj->dknown = 1;/* %% doesnt belong here */
    180 	switch (obj->olet) {
    181 	case AMULET_SYM:
    182 		Strcpy(buf, (obj->spe < 0 && obj->known)
    183 		       ? "cheap plastic imitation of the " : "");
    184 		Strcat(buf, "Amulet of Yendor");
    185 		break;
    186 	case TOOL_SYM:
    187 		if (!nn) {
    188 			strlcpy(buf, dn, bufmax);
    189 			break;
    190 		}
    191 		strlcpy(buf, an, bufmax);
    192 		break;
    193 	case FOOD_SYM:
    194 		if (obj->otyp == DEAD_HOMUNCULUS && pl) {
    195 			pl = 0;
    196 			Strcpy(buf, "dead homunculi");
    197 			break;
    198 		}
    199 		/* fungis ? */
    200 		/* fall into next case */
    201 	case WEAPON_SYM:
    202 		if (obj->otyp == WORM_TOOTH && pl) {
    203 			pl = 0;
    204 			Strcpy(buf, "worm teeth");
    205 			break;
    206 		}
    207 		if (obj->otyp == CRYSKNIFE && pl) {
    208 			pl = 0;
    209 			Strcpy(buf, "crysknives");
    210 			break;
    211 		}
    212 		/* fall into next case */
    213 	case ARMOR_SYM:
    214 	case CHAIN_SYM:
    215 	case ROCK_SYM:
    216 		strlcpy(buf, an, bufmax);
    217 		break;
    218 	case BALL_SYM:
    219 		Snprintf(buf, bufmax, "%sheavy iron ball",
    220 		  (obj->owt > objects[obj->otyp].oc_weight) ? "very " : "");
    221 		break;
    222 	case POTION_SYM:
    223 		if (nn || un || !obj->dknown) {
    224 			Strcpy(buf, "potion");
    225 			if (pl) {
    226 				pl = 0;
    227 				Strcat(buf, "s");
    228 			}
    229 			if (!obj->dknown)
    230 				break;
    231 			if (un) {
    232 				Strcat(buf, " called ");
    233 				strlcat(buf, un, bufmax);
    234 			} else {
    235 				Strcat(buf, " of ");
    236 				strlcat(buf, an, bufmax);
    237 			}
    238 		} else {
    239 			strlcpy(buf, dn, bufmax);
    240 			strlcat(buf, " potion", bufmax);
    241 		}
    242 		break;
    243 	case SCROLL_SYM:
    244 		Strcpy(buf, "scroll");
    245 		if (pl) {
    246 			pl = 0;
    247 			Strcat(buf, "s");
    248 		}
    249 		if (!obj->dknown)
    250 			break;
    251 		if (nn) {
    252 			Strcat(buf, " of ");
    253 			strlcat(buf, an, bufmax);
    254 		} else if (un) {
    255 			Strcat(buf, " called ");
    256 			strlcat(buf, un, bufmax);
    257 		} else {
    258 			Strcat(buf, " labeled ");
    259 			strlcat(buf, dn, bufmax);
    260 		}
    261 		break;
    262 	case WAND_SYM:
    263 		if (!obj->dknown)
    264 			Snprintf(buf, bufmax, "wand");
    265 		else if (nn)
    266 			Snprintf(buf, bufmax, "wand of %s", an);
    267 		else if (un)
    268 			Snprintf(buf, bufmax, "wand called %s", un);
    269 		else
    270 			Snprintf(buf, bufmax, "%s wand", dn);
    271 		break;
    272 	case RING_SYM:
    273 		if (!obj->dknown)
    274 			Snprintf(buf, bufmax, "ring");
    275 		else if (nn)
    276 			Snprintf(buf, bufmax, "ring of %s", an);
    277 		else if (un)
    278 			Snprintf(buf, bufmax, "ring called %s", un);
    279 		else
    280 			Snprintf(buf, bufmax, "%s ring", dn);
    281 		break;
    282 	case GEM_SYM:
    283 		if (!obj->dknown) {
    284 			Strcpy(buf, "gem");
    285 			break;
    286 		}
    287 		if (!nn) {
    288 			Snprintf(buf, bufmax, "%s gem", dn);
    289 			break;
    290 		}
    291 		strlcpy(buf, an, bufmax);
    292 		if (obj->otyp >= TURQUOISE && obj->otyp <= JADE)
    293 			strlcat(buf, " stone", bufmax);
    294 		break;
    295 	default:
    296 		Snprintf(buf, bufmax, "glorkum %c (0%o) %u %d",
    297 			obj->olet, obj->olet, obj->otyp, obj->spe);
    298 	}
    299 	if (pl) {
    300 		char           *p;
    301 
    302 		for (p = buf; *p; p++) {
    303 			if (!strncmp(" of ", p, 4)) {
    304 				/* pieces of, cloves of, lumps of */
    305 				int             c1, c2 = 's';
    306 
    307 				do {
    308 					c1 = c2;
    309 					c2 = *p;
    310 					*p++ = c1;
    311 				} while (c1);
    312 				goto nopl;
    313 			}
    314 		}
    315 		p = eos(buf) - 1;
    316 		if (*p == 's' || *p == 'z' || *p == 'x' ||
    317 		    (*p == 'h' && p[-1] == 's')) {
    318 			/* boxes */
    319 			strlcat(buf, "es", bufmax);
    320 		} else if (*p == 'y' && !strchr(vowels, p[-1])) {
    321 			/* rubies, zruties */
    322 			*p = '\0';
    323 			strlcat(buf, "ies", bufmax);
    324 		} else {
    325 			strlcat(buf, "s", bufmax);
    326 		}
    327 	}
    328 nopl:
    329 	if (obj->onamelth) {
    330 		strlcat(buf, " named ", bufmax);
    331 		strlcat(buf, ONAME(obj), bufmax);
    332 	}
    333 	return (buf);
    334 }
    335 
    336 char           *
    337 doname(struct obj *obj)
    338 {
    339 	char            prefix[PREFIX];
    340 	char           *bp = xname(obj);
    341 	size_t          bppos, bpmax;
    342 
    343 	/* XXX do this better somehow w/o knowing internals of xname() */
    344 	bpmax = BUFSZ - PREFIX;
    345 
    346 	if (obj->quan != 1)
    347 		Snprintf(prefix, sizeof(prefix), "%u ", obj->quan);
    348 	else
    349 		Strcpy(prefix, "a ");
    350 	switch (obj->olet) {
    351 	case AMULET_SYM:
    352 		if (strncmp(bp, "cheap ", 6))
    353 			Strcpy(prefix, "the ");
    354 		break;
    355 	case ARMOR_SYM:
    356 		if (obj->owornmask & W_ARMOR)
    357 			strlcat(bp, " (being worn)", bpmax);
    358 		/* fall into next case */
    359 	case WEAPON_SYM:
    360 		if (obj->known) {
    361 			strlcat(prefix, sitoa(obj->spe), sizeof(prefix));
    362 			strlcat(prefix, " ", sizeof(prefix));
    363 		}
    364 		break;
    365 	case WAND_SYM:
    366 		if (obj->known) {
    367 			bppos = strlen(bp);
    368 			Snprintf(bp+bppos, bpmax-bppos, " (%d)", obj->spe);
    369 		}
    370 		break;
    371 	case RING_SYM:
    372 		if (obj->owornmask & W_RINGR)
    373 			strlcat(bp, " (on right hand)", bpmax);
    374 		if (obj->owornmask & W_RINGL)
    375 			strlcat(bp, " (on left hand)", bpmax);
    376 		if (obj->known && (objects[obj->otyp].bits & SPEC)) {
    377 			strlcat(prefix, sitoa(obj->spe), sizeof(prefix));
    378 			strlcat(prefix, " ", sizeof(prefix));
    379 		}
    380 		break;
    381 	}
    382 	if (obj->owornmask & W_WEP)
    383 		strlcat(bp, " (weapon in hand)", bpmax);
    384 	if (obj->unpaid)
    385 		strlcat(bp, " (unpaid)", bpmax);
    386 	if (!strcmp(prefix, "a ") && strchr(vowels, *bp))
    387 		Strcpy(prefix, "an ");
    388 	bp = strprepend(bp, prefix);
    389 	return (bp);
    390 }
    391 
    392 /* used only in hack.fight.c (thitu) */
    393 void
    394 setan(const char *str, char *buf, size_t bufmax)
    395 {
    396 	if (strchr(vowels, *str))
    397 		Snprintf(buf, bufmax, "an %s", str);
    398 	else
    399 		Snprintf(buf, bufmax, "a %s", str);
    400 }
    401 
    402 char           *
    403 aobjnam(struct obj *otmp, const char *verb)
    404 {
    405 	char           *bp = xname(otmp);
    406 	char            prefix[PREFIX];
    407 	size_t          bpmax;
    408 
    409 	/* XXX do this better somehow w/o knowing internals of xname() */
    410 	bpmax = BUFSZ - PREFIX;
    411 
    412 	if (otmp->quan != 1) {
    413 		Snprintf(prefix, sizeof(prefix), "%u ", otmp->quan);
    414 		bp = strprepend(bp, prefix);
    415 	}
    416 	if (verb) {
    417 		/* verb is given in plural (i.e., without trailing s) */
    418 		strlcat(bp, " ", bpmax);
    419 		if (otmp->quan != 1)
    420 			strlcat(bp, verb, bpmax);
    421 		else if (!strcmp(verb, "are"))
    422 			strlcat(bp, "is", bpmax);
    423 		else {
    424 			strlcat(bp, verb, bpmax);
    425 			strlcat(bp, "s", bpmax);
    426 		}
    427 	}
    428 	return (bp);
    429 }
    430 
    431 char           *
    432 Doname(struct obj *obj)
    433 {
    434 	char           *s = doname(obj);
    435 
    436 	if ('a' <= *s && *s <= 'z')
    437 		*s -= ('a' - 'A');
    438 	return (s);
    439 }
    440 
    441 const char *const wrp[] = {"wand", "ring", "potion", "scroll", "gem"};
    442 const char wrpsym[] = {WAND_SYM, RING_SYM, POTION_SYM, SCROLL_SYM, GEM_SYM};
    443 
    444 struct obj     *
    445 readobjnam(char *bp)
    446 {
    447 	char           *p;
    448 	unsigned        ii;
    449 	int		i;
    450 	int             cnt, spe, spesgn, typ, heavy;
    451 	char            let;
    452 	char           *un, *dn, *an;
    453 	/* int the = 0; char *oname = 0; */
    454 	cnt = spe = spesgn = typ = heavy = 0;
    455 	let = 0;
    456 	an = dn = un = 0;
    457 	for (p = bp; *p; p++)
    458 		if ('A' <= *p && *p <= 'Z')
    459 			*p += 'a' - 'A';
    460 	if (!strncmp(bp, "the ", 4)) {
    461 		/* the = 1; */
    462 		bp += 4;
    463 	} else if (!strncmp(bp, "an ", 3)) {
    464 		cnt = 1;
    465 		bp += 3;
    466 	} else if (!strncmp(bp, "a ", 2)) {
    467 		cnt = 1;
    468 		bp += 2;
    469 	}
    470 	if (!cnt && digit(*bp)) {
    471 		cnt = atoi(bp);
    472 		while (digit(*bp))
    473 			bp++;
    474 		while (*bp == ' ')
    475 			bp++;
    476 	}
    477 	if (!cnt)
    478 		cnt = 1;	/* %% what with "gems" etc. ? */
    479 
    480 	if (*bp == '+' || *bp == '-') {
    481 		spesgn = (*bp++ == '+') ? 1 : -1;
    482 		spe = atoi(bp);
    483 		while (digit(*bp))
    484 			bp++;
    485 		while (*bp == ' ')
    486 			bp++;
    487 	} else {
    488 		p = strrchr(bp, '(');
    489 		if (p) {
    490 			if (p > bp && p[-1] == ' ')
    491 				p[-1] = 0;
    492 			else
    493 				*p = 0;
    494 			p++;
    495 			spe = atoi(p);
    496 			while (digit(*p))
    497 				p++;
    498 			if (strcmp(p, ")"))
    499 				spe = 0;
    500 			else
    501 				spesgn = 1;
    502 		}
    503 	}
    504 	/*
    505 	 * now we have the actual name, as delivered by xname, say green
    506 	 * potions called whisky scrolls labeled "QWERTY" egg dead zruties
    507 	 * fortune cookies very heavy iron ball named hoei wand of wishing
    508 	 * elven cloak
    509 	 */
    510 	for (p = bp; *p; p++)
    511 		if (!strncmp(p, " named ", 7)) {
    512 			*p = 0;
    513 			/* oname = p+7; */
    514 		}
    515 	for (p = bp; *p; p++)
    516 		if (!strncmp(p, " called ", 8)) {
    517 			*p = 0;
    518 			un = p + 8;
    519 		}
    520 	for (p = bp; *p; p++)
    521 		if (!strncmp(p, " labeled ", 9)) {
    522 			*p = 0;
    523 			dn = p + 9;
    524 		}
    525 	/* first change to singular if necessary */
    526 	if (cnt != 1) {
    527 		/* find "cloves of garlic", "worthless pieces of blue glass" */
    528 		for (p = bp; *p; p++)
    529 			if (!strncmp(p, "s of ", 5)) {
    530 				while ((*p = p[1]) != '\0')
    531 					p++;
    532 				goto sing;
    533 			}
    534 		/* remove -s or -es (boxes) or -ies (rubies, zruties) */
    535 		p = eos(bp);
    536 		if (p[-1] == 's') {
    537 			if (p[-2] == 'e') {
    538 				if (p[-3] == 'i') {
    539 					if (!strcmp(p - 7, "cookies"))
    540 						goto mins;
    541 					Strcpy(p - 3, "y");
    542 					goto sing;
    543 				}
    544 				/* note: cloves / knives from clove / knife */
    545 				if (!strcmp(p - 6, "knives")) {
    546 					Strcpy(p - 3, "fe");
    547 					goto sing;
    548 				}
    549 				/* note: nurses, axes but boxes */
    550 				if (!strcmp(p - 5, "boxes")) {
    551 					p[-2] = 0;
    552 					goto sing;
    553 				}
    554 			}
    555 	mins:
    556 			p[-1] = 0;
    557 		} else {
    558 			if (!strcmp(p - 9, "homunculi")) {
    559 				Strcpy(p - 1, "us");	/* !! makes string
    560 							 * longer */
    561 				goto sing;
    562 			}
    563 			if (!strcmp(p - 5, "teeth")) {
    564 				Strcpy(p - 5, "tooth");
    565 				goto sing;
    566 			}
    567 			/* here we cannot find the plural suffix */
    568 		}
    569 	}
    570 sing:
    571 	if (!strcmp(bp, "amulet of yendor")) {
    572 		typ = AMULET_OF_YENDOR;
    573 		goto typfnd;
    574 	}
    575 	p = eos(bp);
    576 	if (!strcmp(p - 5, " mail")) {	/* Note: ring mail is not a ring ! */
    577 		let = ARMOR_SYM;
    578 		an = bp;
    579 		goto srch;
    580 	}
    581 	for (ii = 0; ii < sizeof(wrpsym); ii++) {
    582 		int             j = strlen(wrp[ii]);
    583 		if (!strncmp(bp, wrp[ii], j)) {
    584 			let = wrpsym[ii];
    585 			bp += j;
    586 			if (!strncmp(bp, " of ", 4))
    587 				an = bp + 4;
    588 			/* else if(*bp) ?? */
    589 			goto srch;
    590 		}
    591 		if (!strcmp(p - j, wrp[ii])) {
    592 			let = wrpsym[ii];
    593 			p -= j;
    594 			*p = 0;
    595 			if (p[-1] == ' ')
    596 				p[-1] = 0;
    597 			dn = bp;
    598 			goto srch;
    599 		}
    600 	}
    601 	if (!strcmp(p - 6, " stone")) {
    602 		p[-6] = 0;
    603 		let = GEM_SYM;
    604 		an = bp;
    605 		goto srch;
    606 	}
    607 	if (!strcmp(bp, "very heavy iron ball")) {
    608 		heavy = 1;
    609 		typ = HEAVY_IRON_BALL;
    610 		goto typfnd;
    611 	}
    612 	an = bp;
    613 srch:
    614 	if (!an && !dn && !un)
    615 		goto any;
    616 	i = 1;
    617 	if (let)
    618 		i = bases[letindex(let)];
    619 	while (i <= NROFOBJECTS && (!let || objects[i].oc_olet == let)) {
    620 		const char           *zn = objects[i].oc_name;
    621 
    622 		if (!zn)
    623 			goto nxti;
    624 		if (an && strcmp(an, zn))
    625 			goto nxti;
    626 		if (dn && (!(zn = objects[i].oc_descr) || strcmp(dn, zn)))
    627 			goto nxti;
    628 		if (un && (!(zn = objects[i].oc_uname) || strcmp(un, zn)))
    629 			goto nxti;
    630 		typ = i;
    631 		goto typfnd;
    632 nxti:
    633 		i++;
    634 	}
    635 any:
    636 	if (!let)
    637 		let = wrpsym[rn2(sizeof(wrpsym))];
    638 	typ = probtype(let);
    639 typfnd:
    640 	{
    641 		struct obj     *otmp;
    642 		let = objects[typ].oc_olet;
    643 		otmp = mksobj(typ);
    644 		if (heavy)
    645 			otmp->owt += 15;
    646 		if (cnt > 0 && strchr("%?!*)", let) &&
    647 		(cnt < 4 || (let == WEAPON_SYM && typ <= ROCK && cnt < 20)))
    648 			otmp->quan = cnt;
    649 
    650 		if (spe > 3 && spe > otmp->spe)
    651 			spe = 0;
    652 		else if (let == WAND_SYM)
    653 			spe = otmp->spe;
    654 		if (spe == 3 && u.uluck < 0)
    655 			spesgn = -1;
    656 		if (let != WAND_SYM && spesgn == -1)
    657 			spe = -spe;
    658 		if (let == BALL_SYM)
    659 			spe = 0;
    660 		else if (let == AMULET_SYM)
    661 			spe = -1;
    662 		else if (typ == WAN_WISHING && rn2(10))
    663 			spe = (rn2(10) ? -1 : 0);
    664 		otmp->spe = spe;
    665 
    666 		if (spesgn == -1)
    667 			otmp->cursed = 1;
    668 
    669 		return (otmp);
    670 	}
    671 }
    672