1*d5b021c7Sdholland /* $NetBSD: hack.objnam.c,v 1.11 2011/08/07 06:03:45 dholland Exp $ */
23ea4a95cSchristos
302ded532Smycroft /*
41c7f94e5Sjsm * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
51c7f94e5Sjsm * Amsterdam
61c7f94e5Sjsm * All rights reserved.
71c7f94e5Sjsm *
81c7f94e5Sjsm * Redistribution and use in source and binary forms, with or without
91c7f94e5Sjsm * modification, are permitted provided that the following conditions are
101c7f94e5Sjsm * met:
111c7f94e5Sjsm *
121c7f94e5Sjsm * - Redistributions of source code must retain the above copyright notice,
131c7f94e5Sjsm * this list of conditions and the following disclaimer.
141c7f94e5Sjsm *
151c7f94e5Sjsm * - Redistributions in binary form must reproduce the above copyright
161c7f94e5Sjsm * notice, this list of conditions and the following disclaimer in the
171c7f94e5Sjsm * documentation and/or other materials provided with the distribution.
181c7f94e5Sjsm *
191c7f94e5Sjsm * - Neither the name of the Stichting Centrum voor Wiskunde en
201c7f94e5Sjsm * Informatica, nor the names of its contributors may be used to endorse or
211c7f94e5Sjsm * promote products derived from this software without specific prior
221c7f94e5Sjsm * written permission.
231c7f94e5Sjsm *
241c7f94e5Sjsm * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
251c7f94e5Sjsm * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
261c7f94e5Sjsm * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
271c7f94e5Sjsm * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
281c7f94e5Sjsm * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
291c7f94e5Sjsm * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
301c7f94e5Sjsm * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
311c7f94e5Sjsm * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
321c7f94e5Sjsm * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
331c7f94e5Sjsm * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
341c7f94e5Sjsm * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
351c7f94e5Sjsm */
361c7f94e5Sjsm
371c7f94e5Sjsm /*
381c7f94e5Sjsm * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
391c7f94e5Sjsm * All rights reserved.
401c7f94e5Sjsm *
411c7f94e5Sjsm * Redistribution and use in source and binary forms, with or without
421c7f94e5Sjsm * modification, are permitted provided that the following conditions
431c7f94e5Sjsm * are met:
441c7f94e5Sjsm * 1. Redistributions of source code must retain the above copyright
451c7f94e5Sjsm * notice, this list of conditions and the following disclaimer.
461c7f94e5Sjsm * 2. Redistributions in binary form must reproduce the above copyright
471c7f94e5Sjsm * notice, this list of conditions and the following disclaimer in the
481c7f94e5Sjsm * documentation and/or other materials provided with the distribution.
491c7f94e5Sjsm * 3. The name of the author may not be used to endorse or promote products
501c7f94e5Sjsm * derived from this software without specific prior written permission.
511c7f94e5Sjsm *
521c7f94e5Sjsm * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
531c7f94e5Sjsm * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
541c7f94e5Sjsm * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
551c7f94e5Sjsm * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
561c7f94e5Sjsm * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
571c7f94e5Sjsm * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
581c7f94e5Sjsm * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
591c7f94e5Sjsm * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
601c7f94e5Sjsm * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
611c7f94e5Sjsm * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
6202ded532Smycroft */
6302ded532Smycroft
643ea4a95cSchristos #include <sys/cdefs.h>
6502ded532Smycroft #ifndef lint
66*d5b021c7Sdholland __RCSID("$NetBSD: hack.objnam.c,v 1.11 2011/08/07 06:03:45 dholland Exp $");
6702ded532Smycroft #endif /* not lint */
6861f28255Scgd
693ea4a95cSchristos #include <stdlib.h>
7061f28255Scgd #include "hack.h"
713ea4a95cSchristos #include "extern.h"
72907fca1bSdholland #define Snprintf (void) snprintf
7361f28255Scgd #define Strcat (void) strcat
7461f28255Scgd #define Strcpy (void) strcpy
7561f28255Scgd #define PREFIX 15
7661f28255Scgd
779b92b189Sdholland static char *strprepend(char *, char *);
789b92b189Sdholland static char *sitoa(int);
799b92b189Sdholland
809b92b189Sdholland static char *
strprepend(char * s,char * pref)811fa8a9a6Sdholland strprepend(char *s, char *pref)
823ea4a95cSchristos {
833ea4a95cSchristos int i = strlen(pref);
8461f28255Scgd if (i > PREFIX) {
8561f28255Scgd pline("WARNING: prefix too short.");
8661f28255Scgd return (s);
8761f28255Scgd }
8861f28255Scgd s -= i;
8961f28255Scgd (void) strncpy(s, pref, i); /* do not copy trailing 0 */
9061f28255Scgd return (s);
9161f28255Scgd }
9261f28255Scgd
939b92b189Sdholland static char *
sitoa(int a)941fa8a9a6Sdholland sitoa(int a)
953ea4a95cSchristos {
9661f28255Scgd static char buf[13];
97907fca1bSdholland Snprintf(buf, sizeof(buf), (a < 0) ? "%d" : "+%d", a);
9861f28255Scgd return (buf);
9961f28255Scgd }
10061f28255Scgd
10161f28255Scgd char *
typename(int otyp)1021fa8a9a6Sdholland typename(int otyp)
10361f28255Scgd {
10461f28255Scgd static char buf[BUFSZ];
105907fca1bSdholland size_t bufpos;
1063ea4a95cSchristos struct objclass *ocl = &objects[otyp];
107ab8b6343Sjsm const char *an = ocl->oc_name;
108ab8b6343Sjsm const char *dn = ocl->oc_descr;
1093ea4a95cSchristos char *un = ocl->oc_uname;
1103ea4a95cSchristos int nn = ocl->oc_name_known;
11161f28255Scgd switch (ocl->oc_olet) {
11261f28255Scgd case POTION_SYM:
11361f28255Scgd Strcpy(buf, "potion");
11461f28255Scgd break;
11561f28255Scgd case SCROLL_SYM:
11661f28255Scgd Strcpy(buf, "scroll");
11761f28255Scgd break;
11861f28255Scgd case WAND_SYM:
11961f28255Scgd Strcpy(buf, "wand");
12061f28255Scgd break;
12161f28255Scgd case RING_SYM:
12261f28255Scgd Strcpy(buf, "ring");
12361f28255Scgd break;
12461f28255Scgd default:
12561f28255Scgd if (nn) {
12661f28255Scgd Strcpy(buf, an);
12761f28255Scgd if (otyp >= TURQUOISE && otyp <= JADE)
12861f28255Scgd Strcat(buf, " stone");
129907fca1bSdholland if (un) {
130907fca1bSdholland bufpos = strlen(buf);
131907fca1bSdholland Snprintf(buf+bufpos, sizeof(buf)-bufpos,
132907fca1bSdholland " called %s", un);
133907fca1bSdholland }
134907fca1bSdholland if (dn) {
135907fca1bSdholland bufpos = strlen(buf);
136907fca1bSdholland Snprintf(buf+bufpos, sizeof(buf)-bufpos,
137907fca1bSdholland " (%s)", dn);
138907fca1bSdholland }
13961f28255Scgd } else {
140907fca1bSdholland strlcpy(buf, dn ? dn : an, sizeof(buf));
141907fca1bSdholland if (ocl->oc_olet == GEM_SYM) {
142907fca1bSdholland strlcat(buf, " gem", sizeof(buf));
143907fca1bSdholland }
144907fca1bSdholland if (un) {
145907fca1bSdholland bufpos = strlen(buf);
146907fca1bSdholland Snprintf(buf+bufpos, sizeof(buf)-bufpos,
147907fca1bSdholland " called %s", un);
148907fca1bSdholland }
14961f28255Scgd }
15061f28255Scgd return (buf);
15161f28255Scgd }
15261f28255Scgd /* here for ring/scroll/potion/wand */
153907fca1bSdholland if (nn) {
154907fca1bSdholland bufpos = strlen(buf);
155907fca1bSdholland Snprintf(buf+bufpos, sizeof(buf)-bufpos, " of %s", an);
156907fca1bSdholland }
157907fca1bSdholland if (un) {
158907fca1bSdholland bufpos = strlen(buf);
159907fca1bSdholland Snprintf(buf+bufpos, sizeof(buf)-bufpos, " called %s", un);
160907fca1bSdholland }
161907fca1bSdholland if (dn) {
162907fca1bSdholland bufpos = strlen(buf);
163907fca1bSdholland Snprintf(buf+bufpos, sizeof(buf)-bufpos, " (%s)", dn);
164907fca1bSdholland }
16561f28255Scgd return (buf);
16661f28255Scgd }
16761f28255Scgd
16861f28255Scgd char *
xname(struct obj * obj)1691fa8a9a6Sdholland xname(struct obj *obj)
17061f28255Scgd {
17161f28255Scgd static char bufr[BUFSZ];
172907fca1bSdholland /* caution: doname() and aobjnam() below "know" these sizes */
1733ea4a95cSchristos char *buf = &(bufr[PREFIX]); /* leave room for "17 -3 " */
174907fca1bSdholland size_t bufmax = sizeof(bufr) - PREFIX;
1753ea4a95cSchristos int nn = objects[obj->otyp].oc_name_known;
176ab8b6343Sjsm const char *an = objects[obj->otyp].oc_name;
177ab8b6343Sjsm const char *dn = objects[obj->otyp].oc_descr;
1783ea4a95cSchristos char *un = objects[obj->otyp].oc_uname;
1793ea4a95cSchristos int pl = (obj->quan != 1);
180907fca1bSdholland
1813ea4a95cSchristos if (!obj->dknown && !Blind)
1823ea4a95cSchristos obj->dknown = 1;/* %% doesnt belong here */
18361f28255Scgd switch (obj->olet) {
18461f28255Scgd case AMULET_SYM:
18561f28255Scgd Strcpy(buf, (obj->spe < 0 && obj->known)
18661f28255Scgd ? "cheap plastic imitation of the " : "");
18761f28255Scgd Strcat(buf, "Amulet of Yendor");
18861f28255Scgd break;
18961f28255Scgd case TOOL_SYM:
19061f28255Scgd if (!nn) {
191907fca1bSdholland strlcpy(buf, dn, bufmax);
19261f28255Scgd break;
19361f28255Scgd }
194907fca1bSdholland strlcpy(buf, an, bufmax);
19561f28255Scgd break;
19661f28255Scgd case FOOD_SYM:
19761f28255Scgd if (obj->otyp == DEAD_HOMUNCULUS && pl) {
19861f28255Scgd pl = 0;
19961f28255Scgd Strcpy(buf, "dead homunculi");
20061f28255Scgd break;
20161f28255Scgd }
20261f28255Scgd /* fungis ? */
203*d5b021c7Sdholland /* FALLTHROUGH */
20461f28255Scgd case WEAPON_SYM:
20561f28255Scgd if (obj->otyp == WORM_TOOTH && pl) {
20661f28255Scgd pl = 0;
20761f28255Scgd Strcpy(buf, "worm teeth");
20861f28255Scgd break;
20961f28255Scgd }
21061f28255Scgd if (obj->otyp == CRYSKNIFE && pl) {
21161f28255Scgd pl = 0;
21261f28255Scgd Strcpy(buf, "crysknives");
21361f28255Scgd break;
21461f28255Scgd }
215*d5b021c7Sdholland /* FALLTHROUGH */
21661f28255Scgd case ARMOR_SYM:
21761f28255Scgd case CHAIN_SYM:
21861f28255Scgd case ROCK_SYM:
219907fca1bSdholland strlcpy(buf, an, bufmax);
22061f28255Scgd break;
22161f28255Scgd case BALL_SYM:
222907fca1bSdholland Snprintf(buf, bufmax, "%sheavy iron ball",
22361f28255Scgd (obj->owt > objects[obj->otyp].oc_weight) ? "very " : "");
22461f28255Scgd break;
22561f28255Scgd case POTION_SYM:
22661f28255Scgd if (nn || un || !obj->dknown) {
22761f28255Scgd Strcpy(buf, "potion");
22861f28255Scgd if (pl) {
22961f28255Scgd pl = 0;
23061f28255Scgd Strcat(buf, "s");
23161f28255Scgd }
2323ea4a95cSchristos if (!obj->dknown)
2333ea4a95cSchristos break;
23461f28255Scgd if (un) {
23561f28255Scgd Strcat(buf, " called ");
236907fca1bSdholland strlcat(buf, un, bufmax);
23761f28255Scgd } else {
23861f28255Scgd Strcat(buf, " of ");
239907fca1bSdholland strlcat(buf, an, bufmax);
24061f28255Scgd }
24161f28255Scgd } else {
242907fca1bSdholland strlcpy(buf, dn, bufmax);
243907fca1bSdholland strlcat(buf, " potion", bufmax);
24461f28255Scgd }
24561f28255Scgd break;
24661f28255Scgd case SCROLL_SYM:
24761f28255Scgd Strcpy(buf, "scroll");
24861f28255Scgd if (pl) {
24961f28255Scgd pl = 0;
25061f28255Scgd Strcat(buf, "s");
25161f28255Scgd }
2523ea4a95cSchristos if (!obj->dknown)
2533ea4a95cSchristos break;
25461f28255Scgd if (nn) {
25561f28255Scgd Strcat(buf, " of ");
256907fca1bSdholland strlcat(buf, an, bufmax);
25761f28255Scgd } else if (un) {
25861f28255Scgd Strcat(buf, " called ");
259907fca1bSdholland strlcat(buf, un, bufmax);
26061f28255Scgd } else {
26161f28255Scgd Strcat(buf, " labeled ");
262907fca1bSdholland strlcat(buf, dn, bufmax);
26361f28255Scgd }
26461f28255Scgd break;
26561f28255Scgd case WAND_SYM:
26661f28255Scgd if (!obj->dknown)
267907fca1bSdholland Snprintf(buf, bufmax, "wand");
26861f28255Scgd else if (nn)
269907fca1bSdholland Snprintf(buf, bufmax, "wand of %s", an);
27061f28255Scgd else if (un)
271907fca1bSdholland Snprintf(buf, bufmax, "wand called %s", un);
27261f28255Scgd else
273907fca1bSdholland Snprintf(buf, bufmax, "%s wand", dn);
27461f28255Scgd break;
27561f28255Scgd case RING_SYM:
27661f28255Scgd if (!obj->dknown)
277907fca1bSdholland Snprintf(buf, bufmax, "ring");
27861f28255Scgd else if (nn)
279907fca1bSdholland Snprintf(buf, bufmax, "ring of %s", an);
28061f28255Scgd else if (un)
281907fca1bSdholland Snprintf(buf, bufmax, "ring called %s", un);
28261f28255Scgd else
283907fca1bSdholland Snprintf(buf, bufmax, "%s ring", dn);
28461f28255Scgd break;
28561f28255Scgd case GEM_SYM:
28661f28255Scgd if (!obj->dknown) {
28761f28255Scgd Strcpy(buf, "gem");
28861f28255Scgd break;
28961f28255Scgd }
29061f28255Scgd if (!nn) {
291907fca1bSdholland Snprintf(buf, bufmax, "%s gem", dn);
29261f28255Scgd break;
29361f28255Scgd }
294907fca1bSdholland strlcpy(buf, an, bufmax);
29561f28255Scgd if (obj->otyp >= TURQUOISE && obj->otyp <= JADE)
296907fca1bSdholland strlcat(buf, " stone", bufmax);
29761f28255Scgd break;
29861f28255Scgd default:
299907fca1bSdholland Snprintf(buf, bufmax, "glorkum %c (0%o) %u %d",
30061f28255Scgd obj->olet, obj->olet, obj->otyp, obj->spe);
30161f28255Scgd }
30261f28255Scgd if (pl) {
3033ea4a95cSchristos char *p;
30461f28255Scgd
30561f28255Scgd for (p = buf; *p; p++) {
30661f28255Scgd if (!strncmp(" of ", p, 4)) {
30761f28255Scgd /* pieces of, cloves of, lumps of */
3083ea4a95cSchristos int c1, c2 = 's';
30961f28255Scgd
31061f28255Scgd do {
3113ea4a95cSchristos c1 = c2;
3123ea4a95cSchristos c2 = *p;
3133ea4a95cSchristos *p++ = c1;
31461f28255Scgd } while (c1);
31561f28255Scgd goto nopl;
31661f28255Scgd }
31761f28255Scgd }
31861f28255Scgd p = eos(buf) - 1;
31961f28255Scgd if (*p == 's' || *p == 'z' || *p == 'x' ||
320907fca1bSdholland (*p == 'h' && p[-1] == 's')) {
321907fca1bSdholland /* boxes */
322907fca1bSdholland strlcat(buf, "es", bufmax);
323907fca1bSdholland } else if (*p == 'y' && !strchr(vowels, p[-1])) {
324907fca1bSdholland /* rubies, zruties */
325907fca1bSdholland *p = '\0';
326907fca1bSdholland strlcat(buf, "ies", bufmax);
327907fca1bSdholland } else {
328907fca1bSdholland strlcat(buf, "s", bufmax);
329907fca1bSdholland }
33061f28255Scgd }
33161f28255Scgd nopl:
33261f28255Scgd if (obj->onamelth) {
333907fca1bSdholland strlcat(buf, " named ", bufmax);
334907fca1bSdholland strlcat(buf, ONAME(obj), bufmax);
33561f28255Scgd }
33661f28255Scgd return (buf);
33761f28255Scgd }
33861f28255Scgd
33961f28255Scgd char *
doname(struct obj * obj)3401fa8a9a6Sdholland doname(struct obj *obj)
34161f28255Scgd {
34261f28255Scgd char prefix[PREFIX];
3433ea4a95cSchristos char *bp = xname(obj);
344907fca1bSdholland size_t bppos, bpmax;
345907fca1bSdholland
346907fca1bSdholland /* XXX do this better somehow w/o knowing internals of xname() */
347907fca1bSdholland bpmax = BUFSZ - PREFIX;
348907fca1bSdholland
34961f28255Scgd if (obj->quan != 1)
350907fca1bSdholland Snprintf(prefix, sizeof(prefix), "%u ", obj->quan);
35161f28255Scgd else
35261f28255Scgd Strcpy(prefix, "a ");
35361f28255Scgd switch (obj->olet) {
35461f28255Scgd case AMULET_SYM:
35561f28255Scgd if (strncmp(bp, "cheap ", 6))
35661f28255Scgd Strcpy(prefix, "the ");
35761f28255Scgd break;
35861f28255Scgd case ARMOR_SYM:
35961f28255Scgd if (obj->owornmask & W_ARMOR)
360907fca1bSdholland strlcat(bp, " (being worn)", bpmax);
361*d5b021c7Sdholland /* FALLTHROUGH */
36261f28255Scgd case WEAPON_SYM:
36361f28255Scgd if (obj->known) {
364907fca1bSdholland strlcat(prefix, sitoa(obj->spe), sizeof(prefix));
365907fca1bSdholland strlcat(prefix, " ", sizeof(prefix));
36661f28255Scgd }
36761f28255Scgd break;
36861f28255Scgd case WAND_SYM:
369907fca1bSdholland if (obj->known) {
370907fca1bSdholland bppos = strlen(bp);
371907fca1bSdholland Snprintf(bp+bppos, bpmax-bppos, " (%d)", obj->spe);
372907fca1bSdholland }
37361f28255Scgd break;
37461f28255Scgd case RING_SYM:
3753ea4a95cSchristos if (obj->owornmask & W_RINGR)
376907fca1bSdholland strlcat(bp, " (on right hand)", bpmax);
3773ea4a95cSchristos if (obj->owornmask & W_RINGL)
378907fca1bSdholland strlcat(bp, " (on left hand)", bpmax);
37961f28255Scgd if (obj->known && (objects[obj->otyp].bits & SPEC)) {
380907fca1bSdholland strlcat(prefix, sitoa(obj->spe), sizeof(prefix));
381907fca1bSdholland strlcat(prefix, " ", sizeof(prefix));
38261f28255Scgd }
38361f28255Scgd break;
38461f28255Scgd }
38561f28255Scgd if (obj->owornmask & W_WEP)
386907fca1bSdholland strlcat(bp, " (weapon in hand)", bpmax);
38761f28255Scgd if (obj->unpaid)
388907fca1bSdholland strlcat(bp, " (unpaid)", bpmax);
3893ea4a95cSchristos if (!strcmp(prefix, "a ") && strchr(vowels, *bp))
39061f28255Scgd Strcpy(prefix, "an ");
39161f28255Scgd bp = strprepend(bp, prefix);
39261f28255Scgd return (bp);
39361f28255Scgd }
39461f28255Scgd
39561f28255Scgd /* used only in hack.fight.c (thitu) */
3963ea4a95cSchristos void
setan(const char * str,char * buf,size_t bufmax)397907fca1bSdholland setan(const char *str, char *buf, size_t bufmax)
39861f28255Scgd {
3993ea4a95cSchristos if (strchr(vowels, *str))
400907fca1bSdholland Snprintf(buf, bufmax, "an %s", str);
40161f28255Scgd else
402907fca1bSdholland Snprintf(buf, bufmax, "a %s", str);
40361f28255Scgd }
40461f28255Scgd
40561f28255Scgd char *
aobjnam(struct obj * otmp,const char * verb)4061fa8a9a6Sdholland aobjnam(struct obj *otmp, const char *verb)
4073ea4a95cSchristos {
4083ea4a95cSchristos char *bp = xname(otmp);
40961f28255Scgd char prefix[PREFIX];
410907fca1bSdholland size_t bpmax;
411907fca1bSdholland
412907fca1bSdholland /* XXX do this better somehow w/o knowing internals of xname() */
413907fca1bSdholland bpmax = BUFSZ - PREFIX;
414907fca1bSdholland
41561f28255Scgd if (otmp->quan != 1) {
416907fca1bSdholland Snprintf(prefix, sizeof(prefix), "%u ", otmp->quan);
41761f28255Scgd bp = strprepend(bp, prefix);
41861f28255Scgd }
41961f28255Scgd if (verb) {
42061f28255Scgd /* verb is given in plural (i.e., without trailing s) */
421907fca1bSdholland strlcat(bp, " ", bpmax);
42261f28255Scgd if (otmp->quan != 1)
423907fca1bSdholland strlcat(bp, verb, bpmax);
42461f28255Scgd else if (!strcmp(verb, "are"))
425907fca1bSdholland strlcat(bp, "is", bpmax);
42661f28255Scgd else {
427907fca1bSdholland strlcat(bp, verb, bpmax);
428907fca1bSdholland strlcat(bp, "s", bpmax);
42961f28255Scgd }
43061f28255Scgd }
43161f28255Scgd return (bp);
43261f28255Scgd }
43361f28255Scgd
43461f28255Scgd char *
Doname(struct obj * obj)4351fa8a9a6Sdholland Doname(struct obj *obj)
43661f28255Scgd {
4373ea4a95cSchristos char *s = doname(obj);
43861f28255Scgd
4393ea4a95cSchristos if ('a' <= *s && *s <= 'z')
4403ea4a95cSchristos *s -= ('a' - 'A');
44161f28255Scgd return (s);
44261f28255Scgd }
44361f28255Scgd
4449b92b189Sdholland static const char *const wrp[] = {"wand", "ring", "potion", "scroll", "gem"};
4459b92b189Sdholland static const char wrpsym[] = {WAND_SYM, RING_SYM, POTION_SYM, SCROLL_SYM, GEM_SYM};
44661f28255Scgd
44761f28255Scgd struct obj *
readobjnam(char * bp)4481fa8a9a6Sdholland readobjnam(char *bp)
4493ea4a95cSchristos {
4503ea4a95cSchristos char *p;
4513c439f43Sdholland unsigned ii;
4523ea4a95cSchristos int i;
45361f28255Scgd int cnt, spe, spesgn, typ, heavy;
45461f28255Scgd char let;
45561f28255Scgd char *un, *dn, *an;
45661f28255Scgd /* int the = 0; char *oname = 0; */
45761f28255Scgd cnt = spe = spesgn = typ = heavy = 0;
45861f28255Scgd let = 0;
45961f28255Scgd an = dn = un = 0;
46061f28255Scgd for (p = bp; *p; p++)
4613ea4a95cSchristos if ('A' <= *p && *p <= 'Z')
4623ea4a95cSchristos *p += 'a' - 'A';
46361f28255Scgd if (!strncmp(bp, "the ", 4)) {
46461f28255Scgd /* the = 1; */
46561f28255Scgd bp += 4;
46661f28255Scgd } else if (!strncmp(bp, "an ", 3)) {
46761f28255Scgd cnt = 1;
46861f28255Scgd bp += 3;
46961f28255Scgd } else if (!strncmp(bp, "a ", 2)) {
47061f28255Scgd cnt = 1;
47161f28255Scgd bp += 2;
47261f28255Scgd }
47361f28255Scgd if (!cnt && digit(*bp)) {
47461f28255Scgd cnt = atoi(bp);
4753ea4a95cSchristos while (digit(*bp))
4763ea4a95cSchristos bp++;
4773ea4a95cSchristos while (*bp == ' ')
4783ea4a95cSchristos bp++;
47961f28255Scgd }
4803ea4a95cSchristos if (!cnt)
4813ea4a95cSchristos cnt = 1; /* %% what with "gems" etc. ? */
48261f28255Scgd
48361f28255Scgd if (*bp == '+' || *bp == '-') {
48461f28255Scgd spesgn = (*bp++ == '+') ? 1 : -1;
48561f28255Scgd spe = atoi(bp);
4863ea4a95cSchristos while (digit(*bp))
4873ea4a95cSchristos bp++;
4883ea4a95cSchristos while (*bp == ' ')
4893ea4a95cSchristos bp++;
49061f28255Scgd } else {
4913ea4a95cSchristos p = strrchr(bp, '(');
49261f28255Scgd if (p) {
4933ea4a95cSchristos if (p > bp && p[-1] == ' ')
4943ea4a95cSchristos p[-1] = 0;
4953ea4a95cSchristos else
4963ea4a95cSchristos *p = 0;
49761f28255Scgd p++;
49861f28255Scgd spe = atoi(p);
4993ea4a95cSchristos while (digit(*p))
5003ea4a95cSchristos p++;
5013ea4a95cSchristos if (strcmp(p, ")"))
5023ea4a95cSchristos spe = 0;
5033ea4a95cSchristos else
5043ea4a95cSchristos spesgn = 1;
50561f28255Scgd }
50661f28255Scgd }
5073ea4a95cSchristos /*
5083ea4a95cSchristos * now we have the actual name, as delivered by xname, say green
5093ea4a95cSchristos * potions called whisky scrolls labeled "QWERTY" egg dead zruties
5103ea4a95cSchristos * fortune cookies very heavy iron ball named hoei wand of wishing
5113ea4a95cSchristos * elven cloak
51261f28255Scgd */
5133ea4a95cSchristos for (p = bp; *p; p++)
5143ea4a95cSchristos if (!strncmp(p, " named ", 7)) {
51561f28255Scgd *p = 0;
51661f28255Scgd /* oname = p+7; */
51761f28255Scgd }
5183ea4a95cSchristos for (p = bp; *p; p++)
5193ea4a95cSchristos if (!strncmp(p, " called ", 8)) {
52061f28255Scgd *p = 0;
52161f28255Scgd un = p + 8;
52261f28255Scgd }
5233ea4a95cSchristos for (p = bp; *p; p++)
5243ea4a95cSchristos if (!strncmp(p, " labeled ", 9)) {
52561f28255Scgd *p = 0;
52661f28255Scgd dn = p + 9;
52761f28255Scgd }
52861f28255Scgd /* first change to singular if necessary */
52961f28255Scgd if (cnt != 1) {
53061f28255Scgd /* find "cloves of garlic", "worthless pieces of blue glass" */
5313ea4a95cSchristos for (p = bp; *p; p++)
5323ea4a95cSchristos if (!strncmp(p, "s of ", 5)) {
5333ea4a95cSchristos while ((*p = p[1]) != '\0')
5343ea4a95cSchristos p++;
53561f28255Scgd goto sing;
53661f28255Scgd }
53761f28255Scgd /* remove -s or -es (boxes) or -ies (rubies, zruties) */
53861f28255Scgd p = eos(bp);
53961f28255Scgd if (p[-1] == 's') {
54061f28255Scgd if (p[-2] == 'e') {
54161f28255Scgd if (p[-3] == 'i') {
54261f28255Scgd if (!strcmp(p - 7, "cookies"))
54361f28255Scgd goto mins;
54461f28255Scgd Strcpy(p - 3, "y");
54561f28255Scgd goto sing;
54661f28255Scgd }
54761f28255Scgd /* note: cloves / knives from clove / knife */
54861f28255Scgd if (!strcmp(p - 6, "knives")) {
54961f28255Scgd Strcpy(p - 3, "fe");
55061f28255Scgd goto sing;
55161f28255Scgd }
55261f28255Scgd /* note: nurses, axes but boxes */
55361f28255Scgd if (!strcmp(p - 5, "boxes")) {
55461f28255Scgd p[-2] = 0;
55561f28255Scgd goto sing;
55661f28255Scgd }
55761f28255Scgd }
55861f28255Scgd mins:
55961f28255Scgd p[-1] = 0;
56061f28255Scgd } else {
56161f28255Scgd if (!strcmp(p - 9, "homunculi")) {
5623ea4a95cSchristos Strcpy(p - 1, "us"); /* !! makes string
5633ea4a95cSchristos * longer */
56461f28255Scgd goto sing;
56561f28255Scgd }
56661f28255Scgd if (!strcmp(p - 5, "teeth")) {
56761f28255Scgd Strcpy(p - 5, "tooth");
56861f28255Scgd goto sing;
56961f28255Scgd }
57061f28255Scgd /* here we cannot find the plural suffix */
57161f28255Scgd }
57261f28255Scgd }
57361f28255Scgd sing:
57461f28255Scgd if (!strcmp(bp, "amulet of yendor")) {
57561f28255Scgd typ = AMULET_OF_YENDOR;
57661f28255Scgd goto typfnd;
57761f28255Scgd }
57861f28255Scgd p = eos(bp);
57961f28255Scgd if (!strcmp(p - 5, " mail")) { /* Note: ring mail is not a ring ! */
58061f28255Scgd let = ARMOR_SYM;
58161f28255Scgd an = bp;
58261f28255Scgd goto srch;
58361f28255Scgd }
5843c439f43Sdholland for (ii = 0; ii < sizeof(wrpsym); ii++) {
5853c439f43Sdholland int j = strlen(wrp[ii]);
5863c439f43Sdholland if (!strncmp(bp, wrp[ii], j)) {
5873c439f43Sdholland let = wrpsym[ii];
58861f28255Scgd bp += j;
5893ea4a95cSchristos if (!strncmp(bp, " of ", 4))
5903ea4a95cSchristos an = bp + 4;
59161f28255Scgd /* else if(*bp) ?? */
59261f28255Scgd goto srch;
59361f28255Scgd }
5943c439f43Sdholland if (!strcmp(p - j, wrp[ii])) {
5953c439f43Sdholland let = wrpsym[ii];
59661f28255Scgd p -= j;
59761f28255Scgd *p = 0;
5983ea4a95cSchristos if (p[-1] == ' ')
5993ea4a95cSchristos p[-1] = 0;
60061f28255Scgd dn = bp;
60161f28255Scgd goto srch;
60261f28255Scgd }
60361f28255Scgd }
60461f28255Scgd if (!strcmp(p - 6, " stone")) {
60561f28255Scgd p[-6] = 0;
60661f28255Scgd let = GEM_SYM;
60761f28255Scgd an = bp;
60861f28255Scgd goto srch;
60961f28255Scgd }
61061f28255Scgd if (!strcmp(bp, "very heavy iron ball")) {
61161f28255Scgd heavy = 1;
61261f28255Scgd typ = HEAVY_IRON_BALL;
61361f28255Scgd goto typfnd;
61461f28255Scgd }
61561f28255Scgd an = bp;
61661f28255Scgd srch:
61761f28255Scgd if (!an && !dn && !un)
61861f28255Scgd goto any;
61961f28255Scgd i = 1;
6203ea4a95cSchristos if (let)
6213ea4a95cSchristos i = bases[letindex(let)];
62261f28255Scgd while (i <= NROFOBJECTS && (!let || objects[i].oc_olet == let)) {
623ab8b6343Sjsm const char *zn = objects[i].oc_name;
62461f28255Scgd
6253ea4a95cSchristos if (!zn)
6263ea4a95cSchristos goto nxti;
62761f28255Scgd if (an && strcmp(an, zn))
62861f28255Scgd goto nxti;
62961f28255Scgd if (dn && (!(zn = objects[i].oc_descr) || strcmp(dn, zn)))
63061f28255Scgd goto nxti;
63161f28255Scgd if (un && (!(zn = objects[i].oc_uname) || strcmp(un, zn)))
63261f28255Scgd goto nxti;
63361f28255Scgd typ = i;
63461f28255Scgd goto typfnd;
63561f28255Scgd nxti:
63661f28255Scgd i++;
63761f28255Scgd }
63861f28255Scgd any:
6393ea4a95cSchristos if (!let)
6403ea4a95cSchristos let = wrpsym[rn2(sizeof(wrpsym))];
64161f28255Scgd typ = probtype(let);
64261f28255Scgd typfnd:
6433ea4a95cSchristos {
6443ea4a95cSchristos struct obj *otmp;
64561f28255Scgd let = objects[typ].oc_olet;
64661f28255Scgd otmp = mksobj(typ);
64761f28255Scgd if (heavy)
64861f28255Scgd otmp->owt += 15;
6493ea4a95cSchristos if (cnt > 0 && strchr("%?!*)", let) &&
65061f28255Scgd (cnt < 4 || (let == WEAPON_SYM && typ <= ROCK && cnt < 20)))
65161f28255Scgd otmp->quan = cnt;
65261f28255Scgd
65361f28255Scgd if (spe > 3 && spe > otmp->spe)
65461f28255Scgd spe = 0;
65561f28255Scgd else if (let == WAND_SYM)
65661f28255Scgd spe = otmp->spe;
65761f28255Scgd if (spe == 3 && u.uluck < 0)
65861f28255Scgd spesgn = -1;
65961f28255Scgd if (let != WAND_SYM && spesgn == -1)
66061f28255Scgd spe = -spe;
66161f28255Scgd if (let == BALL_SYM)
66261f28255Scgd spe = 0;
66361f28255Scgd else if (let == AMULET_SYM)
66461f28255Scgd spe = -1;
66561f28255Scgd else if (typ == WAN_WISHING && rn2(10))
66661f28255Scgd spe = (rn2(10) ? -1 : 0);
66761f28255Scgd otmp->spe = spe;
66861f28255Scgd
66961f28255Scgd if (spesgn == -1)
67061f28255Scgd otmp->cursed = 1;
67161f28255Scgd
67261f28255Scgd return (otmp);
67361f28255Scgd }
67461f28255Scgd }
675