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