Commit | Line | Data |
---|---|---|
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 | |
9 | extern char *eos(); | |
10 | extern int bases[]; | |
11 | ||
12 | char * | |
13 | strprepend(s,pref) register char *s, *pref; { | |
14 | register 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 | ||
24 | char * | |
25 | sitoa(a) int a; { | |
26 | static char buf[13]; | |
27 | Sprintf(buf, (a < 0) ? "%d" : "+%d", a); | |
28 | return(buf); | |
29 | } | |
30 | ||
31 | char * | |
32 | typename(otyp) | |
33 | register int otyp; | |
34 | { | |
35 | static char buf[BUFSZ]; | |
36 | register struct objclass *ocl = &objects[otyp]; | |
37 | register char *an = ocl->oc_name; | |
38 | register char *dn = ocl->oc_descr; | |
39 | register char *un = ocl->oc_uname; | |
40 | register 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 | ||
82 | char * | |
83 | xname(obj) | |
84 | register struct obj *obj; | |
85 | { | |
86 | static char bufr[BUFSZ]; | |
87 | register char *buf = &(bufr[PREFIX]); /* leave room for "17 -3 " */ | |
88 | register int nn = objects[obj->otyp].oc_name_known; | |
89 | register char *an = objects[obj->otyp].oc_name; | |
90 | register char *dn = objects[obj->otyp].oc_descr; | |
91 | register char *un = objects[obj->otyp].oc_uname; | |
92 | register 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 | } | |
234 | nopl: | |
235 | if(obj->onamelth) { | |
236 | Strcat(buf, " named "); | |
237 | Strcat(buf, ONAME(obj)); | |
238 | } | |
239 | return(buf); | |
240 | } | |
241 | ||
242 | char * | |
243 | doname(obj) | |
244 | register struct obj *obj; | |
245 | { | |
246 | char prefix[PREFIX]; | |
247 | register 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) */ | |
291 | setan(str,buf) | |
292 | register 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 | ||
300 | char * | |
301 | aobjnam(otmp,verb) register struct obj *otmp; register char *verb; { | |
302 | register char *bp = xname(otmp); | |
303 | char 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 | ||
324 | char * | |
325 | Doname(obj) | |
326 | register 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 | ||
334 | char *wrp[] = { "wand", "ring", "potion", "scroll", "gem" }; | |
335 | char wrpsym[] = { WAND_SYM, RING_SYM, POTION_SYM, SCROLL_SYM, GEM_SYM }; | |
336 | ||
337 | struct obj * | |
338 | readobjnam(bp) register char *bp; { | |
339 | register char *p; | |
340 | register int i; | |
341 | int cnt, spe, spesgn, typ, heavy; | |
342 | char let; | |
343 | char *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 | } | |
451 | sing: | |
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; | |
492 | srch: | |
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 | } | |
512 | any: | |
513 | if(!let) let = wrpsym[rn2(sizeof(wrpsym))]; | |
514 | typ = probtype(let); | |
515 | typfnd: | |
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 | } |