MFC: Make apps using '#define _POSIX_C_SOURCE' compile.
[dragonfly.git] / games / hack / hack.objnam.c
blob99e9112322ed346435850b1c3e33c02938770d69
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 $ */
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[];
13 static char *strprepend(char *, char *);
14 static char *sitoa(int);
16 static char *
17 strprepend(char *s, char *pref)
19 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];
33 Sprintf(buf, (a < 0) ? "%d" : "+%d", a);
34 return(buf);
37 char *
38 typename(int otyp)
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);
75 return(buf);
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);
87 char *
88 xname(struct obj *obj)
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;
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;
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;
125 if(obj->otyp == CRYSKNIFE && pl) {
126 pl = 0;
127 Strcpy(buf, "crysknives");
128 break;
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");
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);
155 } else {
156 Strcpy(buf, dn);
157 Strcat(buf, " potion");
159 break;
160 case SCROLL_SYM:
161 Strcpy(buf, "scroll");
162 if(pl) {
163 pl = 0;
164 Strcat(buf, "s");
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);
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;
203 if(!nn) {
204 Sprintf(buf, "%s gem", dn);
205 break;
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);
215 if(pl) {
216 char *p;
218 for(p = buf; *p; p++) {
219 if(!strncmp(" of ", p, 4)) {
220 /* pieces of, cloves of, lumps of */
221 int c1, c2 = 's';
223 do {
224 c1 = c2; c2 = *p; *p++ = c1;
225 } while(c1);
226 goto nopl;
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");
238 nopl:
239 if(obj->onamelth) {
240 Strcat(buf, " named ");
241 Strcat(buf, ONAME(obj));
243 return(buf);
246 char *
247 doname(struct obj *obj)
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, " ");
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, " ");
281 break;
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);
293 /* used only in hack.fight.c (thitu) */
294 void
295 setan(const char *str, char *buf)
297 if(index(vowels,*str))
298 Sprintf(buf, "an %s", str);
299 else
300 Sprintf(buf, "a %s", str);
303 char *
304 aobjnam(struct obj *otmp, const char *verb)
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);
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");
325 return(bp);
328 char *
329 Doname(struct obj *obj)
331 char *s = doname(obj);
333 if('a' <= *s && *s <= 'z') *s -= ('a' - 'A');
334 return(s);
337 static const char *wrp[] = { "wand", "ring", "potion", "scroll", "gem" };
338 char wrpsym[] = { WAND_SYM, RING_SYM, POTION_SYM, SCROLL_SYM, GEM_SYM };
340 struct obj *
341 readobjnam(char *bp)
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;
362 if(!cnt && digit(*bp)){
363 cnt = atoi(bp);
364 while(digit(*bp)) bp++;
365 while(*bp == ' ') bp++;
367 if(!cnt) cnt = 1; /* %% what with "gems" etc. ? */
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;
386 /* now we have the actual name, as delivered by xname, say
387 green potions called whisky
388 scrolls labeled "QWERTY"
390 dead zruties
391 fortune cookies
392 very heavy iron ball named hoei
393 wand of wishing
394 elven cloak
396 for(p = bp; *p; p++) if(!strncmp(p, " named ", 7)) {
397 *p = 0;
399 for(p = bp; *p; p++) if(!strncmp(p, " called ", 8)) {
400 *p = 0;
401 un = p+8;
403 for(p = bp; *p; p++) if(!strncmp(p, " labeled ", 9)) {
404 *p = 0;
405 dn = p+9;
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;
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;
426 /* note: cloves / knives from clove / knife */
427 if(!strcmp(p-6, "knives")) {
428 Strcpy(p-3, "fe");
429 goto sing;
432 /* note: nurses, axes but boxes */
433 if(!strcmp(p-5, "boxes")) {
434 p[-2] = 0;
435 goto sing;
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;
445 if(!strcmp(p-5, "teeth")) {
446 Strcpy(p-5, "tooth");
447 goto sing;
449 /* here we cannot find the plural suffix */
452 sing:
453 if(!strcmp(bp, "amulet of yendor")) {
454 typ = AMULET_OF_YENDOR;
455 goto typfnd;
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;
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;
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;
481 if(!strcmp(p-6, " stone")){
482 p[-6] = 0;
483 let = GEM_SYM;
484 an = bp;
485 goto srch;
487 if(!strcmp(bp, "very heavy iron ball")){
488 heavy = 1;
489 typ = HEAVY_IRON_BALL;
490 goto typfnd;
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;
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++;
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;
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;
542 if(spesgn == -1)
543 otmp->cursed = 1;
545 return(otmp);