-WARNS6 cleanup (7422 warnings)
[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 /* $DragonFly: src/games/hack/hack.objnam.c,v 1.4 2006/08/21 19:45:32 pavalos Exp $ */
5
6 #include        "hack.h"
7 #define Sprintf (void) sprintf
8 #define Strcat  (void) strcat
9 #define Strcpy  (void) strcpy
10 #define PREFIX  15
11 extern int bases[];
12
13 static char     *strprepend(char *, char *);
14 static char     *sitoa(int);
15
16 static char *
17 strprepend(char *s, char *pref)
18 {
19 int i = strlen(pref);
20         if(i > PREFIX) {
21                 pline("WARNING: prefix too short.");
22                 return(s);
23         }
24         s -= i;
25         strncpy(s, pref, i);    /* do not copy trailing 0 */
26         return(s);
27 }
28
29 static char *
30 sitoa(int a)
31 {
32 static char buf[13];
33         Sprintf(buf, (a < 0) ? "%d" : "+%d", a);
34         return(buf);
35 }
36
37 char *
38 typename(int otyp)
39 {
40 static char buf[BUFSZ];
41 struct objclass *ocl = &objects[otyp];
42 const char *an = ocl->oc_name;
43 const char *dn = ocl->oc_descr;
44 char *un = ocl->oc_uname;
45 int nn = ocl->oc_name_known;
46         switch(ocl->oc_olet) {
47         case POTION_SYM:
48                 Strcpy(buf, "potion");
49                 break;
50         case SCROLL_SYM:
51                 Strcpy(buf, "scroll");
52                 break;
53         case WAND_SYM:
54                 Strcpy(buf, "wand");
55                 break;
56         case RING_SYM:
57                 Strcpy(buf, "ring");
58                 break;
59         default:
60                 if(nn) {
61                         Strcpy(buf, an);
62                         if(otyp >= TURQUOISE && otyp <= JADE)
63                                 Strcat(buf, " stone");
64                         if(un)
65                                 Sprintf(eos(buf), " called %s", un);
66                         if(dn)
67                                 Sprintf(eos(buf), " (%s)", dn);
68                 } else {
69                         Strcpy(buf, dn ? dn : an);
70                         if(ocl->oc_olet == GEM_SYM)
71                                 Strcat(buf, " gem");
72                         if(un)
73                                 Sprintf(eos(buf), " called %s", un);
74                 }
75                 return(buf);
76         }
77         /* here for ring/scroll/potion/wand */
78         if(nn)
79                 Sprintf(eos(buf), " of %s", an);
80         if(un)
81                 Sprintf(eos(buf), " called %s", un);
82         if(dn)
83                 Sprintf(eos(buf), " (%s)", dn);
84         return(buf);
85 }
86
87 char *
88 xname(struct obj *obj)
89 {
90 static char bufr[BUFSZ];
91 char *buf = &(bufr[PREFIX]);    /* leave room for "17 -3 " */
92 int nn = objects[obj->otyp].oc_name_known;
93 const char *an = objects[obj->otyp].oc_name;
94 const char *dn = objects[obj->otyp].oc_descr;
95 char *un = objects[obj->otyp].oc_uname;
96 int pl = (obj->quan != 1);
97         if(!obj->dknown && !Blind) obj->dknown = 1; /* %% doesnt belong here */
98         switch(obj->olet) {
99         case AMULET_SYM:
100                 Strcpy(buf, (obj->spe < 0 && obj->known)
101                         ? "cheap plastic imitation of the " : "");
102                 Strcat(buf,"Amulet of Yendor");
103                 break;
104         case TOOL_SYM:
105                 if(!nn) {
106                         Strcpy(buf, dn);
107                         break;
108                 }
109                 Strcpy(buf,an);
110                 break;
111         case FOOD_SYM:
112                 if(obj->otyp == DEAD_HOMUNCULUS && pl) {
113                         pl = 0;
114                         Strcpy(buf, "dead homunculi");
115                         break;
116                 }
117                 /* fungis ? */
118                 /* fall into next case */
119         case WEAPON_SYM:
120                 if(obj->otyp == WORM_TOOTH && pl) {
121                         pl = 0;
122                         Strcpy(buf, "worm teeth");
123                         break;
124                 }
125                 if(obj->otyp == CRYSKNIFE && pl) {
126                         pl = 0;
127                         Strcpy(buf, "crysknives");
128                         break;
129                 }
130                 /* fall into next case */
131         case ARMOR_SYM:
132         case CHAIN_SYM:
133         case ROCK_SYM:
134                 Strcpy(buf,an);
135                 break;
136         case BALL_SYM:
137                 Sprintf(buf, "%sheavy iron ball",
138                   (obj->owt > objects[obj->otyp].oc_weight) ? "very " : "");
139                 break;
140         case POTION_SYM:
141                 if(nn || un || !obj->dknown) {
142                         Strcpy(buf, "potion");
143                         if(pl) {
144                                 pl = 0;
145                                 Strcat(buf, "s");
146                         }
147                         if(!obj->dknown) break;
148                         if(un) {
149                                 Strcat(buf, " called ");
150                                 Strcat(buf, un);
151                         } else {
152                                 Strcat(buf, " of ");
153                                 Strcat(buf, an);
154                         }
155                 } else {
156                         Strcpy(buf, dn);
157                         Strcat(buf, " potion");
158                 }
159                 break;
160         case SCROLL_SYM:
161                 Strcpy(buf, "scroll");
162                 if(pl) {
163                         pl = 0;
164                         Strcat(buf, "s");
165                 }
166                 if(!obj->dknown) break;
167                 if(nn) {
168                         Strcat(buf, " of ");
169                         Strcat(buf, an);
170                 } else if(un) {
171                         Strcat(buf, " called ");
172                         Strcat(buf, un);
173                 } else {
174                         Strcat(buf, " labeled ");
175                         Strcat(buf, dn);
176                 }
177                 break;
178         case WAND_SYM:
179                 if(!obj->dknown)
180                         Sprintf(buf, "wand");
181                 else if(nn)
182                         Sprintf(buf, "wand of %s", an);
183                 else if(un)
184                         Sprintf(buf, "wand called %s", un);
185                 else
186                         Sprintf(buf, "%s wand", dn);
187                 break;
188         case RING_SYM:
189                 if(!obj->dknown)
190                         Sprintf(buf, "ring");
191                 else if(nn)
192                         Sprintf(buf, "ring of %s", an);
193                 else if(un)
194                         Sprintf(buf, "ring called %s", un);
195                 else
196                         Sprintf(buf, "%s ring", dn);
197                 break;
198         case GEM_SYM:
199                 if(!obj->dknown) {
200                         Strcpy(buf, "gem");
201                         break;
202                 }
203                 if(!nn) {
204                         Sprintf(buf, "%s gem", dn);
205                         break;
206                 }
207                 Strcpy(buf, an);
208                 if(obj->otyp >= TURQUOISE && obj->otyp <= JADE)
209                         Strcat(buf, " stone");
210                 break;
211         default:
212                 Sprintf(buf,"glorkum %c (0%o) %u %d",
213                         obj->olet,obj->olet,obj->otyp,obj->spe);
214         }
215         if(pl) {
216                 char *p;
217
218                 for(p = buf; *p; p++) {
219                         if(!strncmp(" of ", p, 4)) {
220                                 /* pieces of, cloves of, lumps of */
221                                 int c1, c2 = 's';
222
223                                 do {
224                                         c1 = c2; c2 = *p; *p++ = c1;
225                                 } while(c1);
226                                 goto nopl;
227                         }
228                 }
229                 p = eos(buf)-1;
230                 if(*p == 's' || *p == 'z' || *p == 'x' ||
231                     (*p == 'h' && p[-1] == 's'))
232                         Strcat(buf, "es");      /* boxes */
233                 else if(*p == 'y' && !index(vowels, p[-1]))
234                         Strcpy(p, "ies");       /* rubies, zruties */
235                 else
236                         Strcat(buf, "s");
237         }
238 nopl:
239         if(obj->onamelth) {
240                 Strcat(buf, " named ");
241                 Strcat(buf, ONAME(obj));
242         }
243         return(buf);
244 }
245
246 char *
247 doname(struct obj *obj)
248 {
249 char prefix[PREFIX];
250 char *bp = xname(obj);
251         if(obj->quan != 1)
252                 Sprintf(prefix, "%u ", obj->quan);
253         else
254                 Strcpy(prefix, "a ");
255         switch(obj->olet) {
256         case AMULET_SYM:
257                 if(strncmp(bp, "cheap ", 6))
258                         Strcpy(prefix, "the ");
259                 break;
260         case ARMOR_SYM:
261                 if(obj->owornmask & W_ARMOR)
262                         Strcat(bp, " (being worn)");
263                 /* fall into next case */
264         case WEAPON_SYM:
265                 if(obj->known) {
266                         Strcat(prefix, sitoa(obj->spe));
267                         Strcat(prefix, " ");
268                 }
269                 break;
270         case WAND_SYM:
271                 if(obj->known)
272                         Sprintf(eos(bp), " (%d)", obj->spe);
273                 break;
274         case RING_SYM:
275                 if(obj->owornmask & W_RINGR) Strcat(bp, " (on right hand)");
276                 if(obj->owornmask & W_RINGL) Strcat(bp, " (on left hand)");
277                 if(obj->known && (objects[obj->otyp].bits & SPEC)) {
278                         Strcat(prefix, sitoa(obj->spe));
279                         Strcat(prefix, " ");
280                 }
281                 break;
282         }
283         if(obj->owornmask & W_WEP)
284                 Strcat(bp, " (weapon in hand)");
285         if(obj->unpaid)
286                 Strcat(bp, " (unpaid)");
287         if(!strcmp(prefix, "a ") && index(vowels, *bp))
288                 Strcpy(prefix, "an ");
289         bp = strprepend(bp, prefix);
290         return(bp);
291 }
292
293 /* used only in hack.fight.c (thitu) */
294 void
295 setan(const char *str, char *buf)
296 {
297         if(index(vowels,*str))
298                 Sprintf(buf, "an %s", str);
299         else
300                 Sprintf(buf, "a %s", str);
301 }
302
303 char *
304 aobjnam(struct obj *otmp, const char *verb)
305 {
306 char *bp = xname(otmp);
307 char prefix[PREFIX];
308         if(otmp->quan != 1) {
309                 Sprintf(prefix, "%u ", otmp->quan);
310                 bp = strprepend(bp, prefix);
311         }
312
313         if(verb) {
314                 /* verb is given in plural (i.e., without trailing s) */
315                 Strcat(bp, " ");
316                 if(otmp->quan != 1)
317                         Strcat(bp, verb);
318                 else if(!strcmp(verb, "are"))
319                         Strcat(bp, "is");
320                 else {
321                         Strcat(bp, verb);
322                         Strcat(bp, "s");
323                 }
324         }
325         return(bp);
326 }
327
328 char *
329 Doname(struct obj *obj)
330 {
331         char *s = doname(obj);
332
333         if('a' <= *s && *s <= 'z') *s -= ('a' - 'A');
334         return(s);
335 }
336
337 static  const char *wrp[] = { "wand", "ring", "potion", "scroll", "gem" };
338 char wrpsym[] = { WAND_SYM, RING_SYM, POTION_SYM, SCROLL_SYM, GEM_SYM };
339
340 struct obj *
341 readobjnam(char *bp)
342 {
343 char *p;
344 int i;
345 int cnt, spe, spesgn, typ, heavy;
346 char let;
347 char *un, *dn, *an;
348         cnt = spe = spesgn = typ = heavy = 0;
349         let = 0;
350         an = dn = un = 0;
351         for(p = bp; *p; p++)
352                 if('A' <= *p && *p <= 'Z') *p += 'a'-'A';
353         if(!strncmp(bp, "the ", 4)){
354                 bp += 4;
355         } else if(!strncmp(bp, "an ", 3)){
356                 cnt = 1;
357                 bp += 3;
358         } else if(!strncmp(bp, "a ", 2)){
359                 cnt = 1;
360                 bp += 2;
361         }
362         if(!cnt && digit(*bp)){
363                 cnt = atoi(bp);
364                 while(digit(*bp)) bp++;
365                 while(*bp == ' ') bp++;
366         }
367         if(!cnt) cnt = 1;               /* %% what with "gems" etc. ? */
368
369         if(*bp == '+' || *bp == '-'){
370                 spesgn = (*bp++ == '+') ? 1 : -1;
371                 spe = atoi(bp);
372                 while(digit(*bp)) bp++;
373                 while(*bp == ' ') bp++;
374         } else {
375                 p = rindex(bp, '(');
376                 if(p) {
377                         if(p > bp && p[-1] == ' ') p[-1] = 0;
378                         else *p = 0;
379                         p++;
380                         spe = atoi(p);
381                         while(digit(*p)) p++;
382                         if(strcmp(p, ")")) spe = 0;
383                         else spesgn = 1;
384                 }
385         }
386         /* now we have the actual name, as delivered by xname, say
387                 green potions called whisky
388                 scrolls labeled "QWERTY"
389                 egg
390                 dead zruties
391                 fortune cookies
392                 very heavy iron ball named hoei
393                 wand of wishing
394                 elven cloak
395         */
396         for(p = bp; *p; p++) if(!strncmp(p, " named ", 7)) {
397                 *p = 0;
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; (unsigned)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                 const 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         let = objects[typ].oc_olet;
519         otmp = mksobj(typ);
520         if(heavy)
521                 otmp->owt += 15;
522         if(cnt > 0 && index("%?!*)", let) &&
523                 (cnt < 4 || (let == WEAPON_SYM && typ <= ROCK && cnt < 20)))
524                 otmp->quan = cnt;
525
526         if(spe > 3 && spe > otmp->spe)
527                 spe = 0;
528         else if(let == WAND_SYM)
529                 spe = otmp->spe;
530         if(spe == 3 && u.uluck < 0)
531                 spesgn = -1;
532         if(let != WAND_SYM && spesgn == -1)
533                 spe = -spe;
534         if(let == BALL_SYM)
535                 spe = 0;
536         else if(let == AMULET_SYM)
537                 spe = -1;
538         else if(typ == WAN_WISHING && rn2(10))
539                 spe = (rn2(10) ? -1 : 0);
540         otmp->spe = spe;
541
542         if(spesgn == -1)
543                 otmp->cursed = 1;
544
545         return(otmp);
546     }
547 }