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