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