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