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