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