File: | src/games/hack/hack.invent.c |
Warning: | line 840, column 14 Value stored to 'otmp' during its initialization is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: hack.invent.c,v 1.14 2016/01/09 21:54:11 mestre Exp $ */ |
2 | |
3 | /* |
4 | * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica, |
5 | * Amsterdam |
6 | * All rights reserved. |
7 | * |
8 | * Redistribution and use in source and binary forms, with or without |
9 | * modification, are permitted provided that the following conditions are |
10 | * met: |
11 | * |
12 | * - Redistributions of source code must retain the above copyright notice, |
13 | * this list of conditions and the following disclaimer. |
14 | * |
15 | * - Redistributions in binary form must reproduce the above copyright |
16 | * notice, this list of conditions and the following disclaimer in the |
17 | * documentation and/or other materials provided with the distribution. |
18 | * |
19 | * - Neither the name of the Stichting Centrum voor Wiskunde en |
20 | * Informatica, nor the names of its contributors may be used to endorse or |
21 | * promote products derived from this software without specific prior |
22 | * written permission. |
23 | * |
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS |
25 | * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
26 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
27 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER |
28 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
29 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
30 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
31 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
32 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
33 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
34 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
35 | */ |
36 | |
37 | /* |
38 | * Copyright (c) 1982 Jay Fenlason <hack@gnu.org> |
39 | * All rights reserved. |
40 | * |
41 | * Redistribution and use in source and binary forms, with or without |
42 | * modification, are permitted provided that the following conditions |
43 | * are met: |
44 | * 1. Redistributions of source code must retain the above copyright |
45 | * notice, this list of conditions and the following disclaimer. |
46 | * 2. Redistributions in binary form must reproduce the above copyright |
47 | * notice, this list of conditions and the following disclaimer in the |
48 | * documentation and/or other materials provided with the distribution. |
49 | * 3. The name of the author may not be used to endorse or promote products |
50 | * derived from this software without specific prior written permission. |
51 | * |
52 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, |
53 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY |
54 | * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL |
55 | * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
56 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
57 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
58 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
59 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
60 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
61 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
62 | */ |
63 | |
64 | #include <ctype.h> |
65 | #include <stdio.h> |
66 | #include <stdlib.h> |
67 | |
68 | #include "hack.h" |
69 | |
70 | extern struct obj zeroobj; |
71 | extern char morc; |
72 | extern char quitchars[]; |
73 | |
74 | #ifndef NOWORM |
75 | extern struct wseg *wsegs[32]; |
76 | #endif /* NOWORM */ |
77 | |
78 | #define NOINVSYM'#' '#' |
79 | |
80 | static int lastinvnr = 51; /* 0 ... 51 */ |
81 | |
82 | static void assigninvlet(struct obj *); |
83 | static char obj_to_let(struct obj *); |
84 | static char *xprname(struct obj *, char); |
85 | static void doinv(char *); |
86 | static int merged(struct obj *, struct obj *, int); |
87 | |
88 | |
89 | static void |
90 | assigninvlet(struct obj *otmp) |
91 | { |
92 | boolean inuse[52]; |
93 | int i; |
94 | struct obj *obj; |
95 | |
96 | for(i = 0; i < 52; i++) inuse[i] = FALSE0; |
97 | for(obj = invent; obj; obj = obj->nobj) if(obj != otmp) { |
98 | i = obj->invlet; |
99 | if('a' <= i && i <= 'z') inuse[i - 'a'] = TRUE1; else |
100 | if('A' <= i && i <= 'Z') inuse[i - 'A' + 26] = TRUE1; |
101 | if(i == otmp->invlet) otmp->invlet = 0; |
102 | } |
103 | if((i = otmp->invlet) && |
104 | (('a' <= i && i <= 'z') || ('A' <= i && i <= 'Z'))) |
105 | return; |
106 | for(i = lastinvnr+1; i != lastinvnr; i++) { |
107 | if(i == 52) { i = -1; continue; } |
108 | if(!inuse[i]) break; |
109 | } |
110 | otmp->invlet = (inuse[i] ? NOINVSYM'#' : |
111 | (i < 26) ? ('a'+i) : ('A'+i-26)); |
112 | lastinvnr = i; |
113 | } |
114 | |
115 | struct obj * |
116 | addinv(struct obj *obj) |
117 | { |
118 | struct obj *otmp; |
119 | |
120 | /* merge or attach to end of chain */ |
121 | if(!invent) { |
122 | invent = obj; |
123 | otmp = 0; |
124 | } else |
125 | for(otmp = invent; /* otmp */; otmp = otmp->nobj) { |
126 | if(merged(otmp, obj, 0)) |
127 | return(otmp); |
128 | if(!otmp->nobj) { |
129 | otmp->nobj = obj; |
130 | break; |
131 | } |
132 | } |
133 | obj->nobj = 0; |
134 | |
135 | if(flags.invlet_constant) { |
136 | assigninvlet(obj); |
137 | /* |
138 | * The ordering of the chain is nowhere significant |
139 | * so in case you prefer some other order than the |
140 | * historical one, change the code below. |
141 | */ |
142 | if(otmp) { /* find proper place in chain */ |
143 | otmp->nobj = 0; |
144 | if((invent->invlet ^ 040) > (obj->invlet ^ 040)) { |
145 | obj->nobj = invent; |
146 | invent = obj; |
147 | } else |
148 | for(otmp = invent; ; otmp = otmp->nobj) { |
149 | if(!otmp->nobj || |
150 | (otmp->nobj->invlet ^ 040) > (obj->invlet ^ 040)){ |
151 | obj->nobj = otmp->nobj; |
152 | otmp->nobj = obj; |
153 | break; |
154 | } |
155 | } |
156 | } |
157 | } |
158 | |
159 | return(obj); |
160 | } |
161 | |
162 | void |
163 | useup(struct obj *obj) |
164 | { |
165 | if(obj->quan > 1){ |
166 | obj->quan--; |
167 | obj->owt = weight(obj); |
168 | } else { |
169 | setnotworn(obj); |
170 | freeinv(obj); |
171 | obfree(obj, (struct obj *) 0); |
172 | } |
173 | } |
174 | |
175 | void |
176 | freeinv(struct obj *obj) |
177 | { |
178 | struct obj *otmp; |
179 | |
180 | if(obj == invent) |
181 | invent = invent->nobj; |
182 | else { |
183 | for(otmp = invent; otmp->nobj != obj; otmp = otmp->nobj) |
184 | if(!otmp->nobj) panic("freeinv"); |
185 | otmp->nobj = obj->nobj; |
186 | } |
187 | } |
188 | |
189 | /* destroy object in fobj chain (if unpaid, it remains on the bill) */ |
190 | void |
191 | delobj(struct obj *obj) |
192 | { |
193 | freeobj(obj); |
194 | unpobj(obj); |
195 | obfree(obj, (struct obj *) 0); |
196 | } |
197 | |
198 | /* unlink obj from chain starting with fobj */ |
199 | void |
200 | freeobj(struct obj *obj) |
201 | { |
202 | struct obj *otmp; |
203 | |
204 | if(obj == fobj) fobj = fobj->nobj; |
205 | else { |
206 | for(otmp = fobj; otmp->nobj != obj; otmp = otmp->nobj) |
207 | if(!otmp) panic("error in freeobj"); |
208 | otmp->nobj = obj->nobj; |
209 | } |
210 | } |
211 | |
212 | /* Note: freegold throws away its argument! */ |
213 | void |
214 | freegold(struct gold *gold) |
215 | { |
216 | struct gold *gtmp; |
217 | |
218 | if(gold == fgold) fgold = gold->ngold; |
219 | else { |
220 | for(gtmp = fgold; gtmp->ngold != gold; gtmp = gtmp->ngold) |
221 | if(!gtmp) panic("error in freegold"); |
222 | gtmp->ngold = gold->ngold; |
223 | } |
224 | free(gold); |
225 | } |
226 | |
227 | void |
228 | deltrap(struct trap *trap) |
229 | { |
230 | struct trap *ttmp; |
231 | |
232 | if(trap == ftrap) |
233 | ftrap = ftrap->ntrap; |
234 | else { |
235 | for(ttmp = ftrap; ttmp->ntrap != trap; ttmp = ttmp->ntrap) ; |
236 | ttmp->ntrap = trap->ntrap; |
237 | } |
238 | free(trap); |
239 | } |
240 | |
241 | struct wseg *m_atseg; |
242 | |
243 | struct monst * |
244 | m_at(int x, int y) |
245 | { |
246 | struct monst *mtmp; |
247 | #ifndef NOWORM |
248 | struct wseg *wtmp; |
249 | #endif /* NOWORM */ |
250 | |
251 | m_atseg = 0; |
252 | for(mtmp = fmon; mtmp; mtmp = mtmp->nmon){ |
253 | if(mtmp->mx == x && mtmp->my == y) |
254 | return(mtmp); |
255 | #ifndef NOWORM |
256 | if(mtmp->wormno){ |
257 | for(wtmp = wsegs[mtmp->wormno]; wtmp; wtmp = wtmp->nseg) |
258 | if(wtmp->wx == x && wtmp->wy == y){ |
259 | m_atseg = wtmp; |
260 | return(mtmp); |
261 | } |
262 | } |
263 | #endif /* NOWORM */ |
264 | } |
265 | return(0); |
266 | } |
267 | |
268 | struct obj * |
269 | o_at(int x, int y) |
270 | { |
271 | struct obj *otmp; |
272 | |
273 | for(otmp = fobj; otmp; otmp = otmp->nobj) |
274 | if(otmp->ox == x && otmp->oy == y) return(otmp); |
275 | return(0); |
276 | } |
277 | |
278 | struct obj * |
279 | sobj_at(int n, int x, int y) |
280 | { |
281 | struct obj *otmp; |
282 | |
283 | for(otmp = fobj; otmp; otmp = otmp->nobj) |
284 | if(otmp->ox == x && otmp->oy == y && otmp->otyp == n) |
285 | return(otmp); |
286 | return(0); |
287 | } |
288 | |
289 | int |
290 | carried(struct obj *obj) |
291 | { |
292 | struct obj *otmp; |
293 | |
294 | for(otmp = invent; otmp; otmp = otmp->nobj) |
295 | if(otmp == obj) return(1); |
296 | return(0); |
297 | } |
298 | |
299 | boolean |
300 | carrying(int type) |
301 | { |
302 | struct obj *otmp; |
303 | |
304 | for(otmp = invent; otmp; otmp = otmp->nobj) |
305 | if(otmp->otyp == type) |
306 | return(TRUE1); |
307 | return(FALSE0); |
308 | } |
309 | |
310 | struct obj * |
311 | o_on(unsigned int id, struct obj *objchn) |
312 | { |
313 | while(objchn) { |
314 | if(objchn->o_id == id) return(objchn); |
315 | objchn = objchn->nobj; |
316 | } |
317 | return(NULL((void *)0)); |
318 | } |
319 | |
320 | struct trap * |
321 | t_at(int x, int y) |
322 | { |
323 | struct trap *trap = ftrap; |
324 | |
325 | while(trap) { |
326 | if(trap->tx == x && trap->ty == y) return(trap); |
327 | trap = trap->ntrap; |
328 | } |
329 | return(NULL((void *)0)); |
330 | } |
331 | |
332 | struct gold * |
333 | g_at(int x, int y) |
334 | { |
335 | struct gold *gold = fgold; |
336 | |
337 | while(gold) { |
338 | if(gold->gx == x && gold->gy == y) return(gold); |
339 | gold = gold->ngold; |
340 | } |
341 | return(NULL((void *)0)); |
342 | } |
343 | |
344 | /* make dummy object structure containing gold - for temporary use only */ |
345 | struct obj * |
346 | mkgoldobj(long q) |
347 | { |
348 | struct obj *otmp; |
349 | |
350 | otmp = newobj(0)(struct obj *) alloc((unsigned)(0) + sizeof(struct obj)); |
351 | /* should set o_id etc. but otmp will be freed soon */ |
352 | otmp->olet = '$'; |
353 | u.ugold -= q; |
354 | OGOLD(otmp)(otmp->oextra[0]) = q; |
355 | flags.botl = 1; |
356 | return(otmp); |
357 | } |
358 | |
359 | /* |
360 | * getobj returns: |
361 | * struct obj *xxx: object to do something with. |
362 | * (struct obj *) 0 error return: no object. |
363 | * &zeroobj explicitly no object (as in w-). |
364 | */ |
365 | struct obj * |
366 | getobj(char *let, char *word) |
367 | { |
368 | struct obj *otmp; |
369 | char ilet,ilet1,ilet2; |
370 | char buf[BUFSZ256]; |
371 | char lets[BUFSZ256]; |
372 | int foo = 0, foo2; |
373 | char *bp = buf; |
374 | xchar allowcnt = 0; /* 0, 1 or 2 */ |
375 | boolean allowgold = FALSE0; |
376 | boolean allowall = FALSE0; |
377 | boolean allownone = FALSE0; |
378 | xchar foox = 0; |
379 | long cnt; |
380 | |
381 | if(*let == '0') let++, allowcnt = 1; |
382 | if(*let == '$') let++, allowgold = TRUE1; |
383 | if(*let == '#') let++, allowall = TRUE1; |
384 | if(*let == '-') let++, allownone = TRUE1; |
385 | if(allownone) *bp++ = '-'; |
386 | if(allowgold) *bp++ = '$'; |
387 | if(bp > buf && bp[-1] == '-') *bp++ = ' '; |
388 | |
389 | ilet = 'a'; |
390 | for(otmp = invent; otmp; otmp = otmp->nobj){ |
391 | if(!*let || strchr(let, otmp->olet)) { |
392 | bp[foo++] = flags.invlet_constant ? otmp->invlet : ilet; |
393 | |
394 | /* ugly check: remove inappropriate things */ |
395 | if((!strcmp(word, "take off") && |
396 | !(otmp->owornmask & (W_ARMOR(01L | 02L | 04L | 010L | 020L) - W_ARM202L))) |
397 | || (!strcmp(word, "wear") && |
398 | (otmp->owornmask & (W_ARMOR(01L | 02L | 04L | 010L | 020L) | W_RING(010000L | 020000L)))) |
399 | || (!strcmp(word, "wield") && |
400 | (otmp->owornmask & W_WEP01000L))) { |
401 | foo--; |
402 | foox++; |
403 | } |
404 | } |
405 | if(ilet == 'z') ilet = 'A'; else ilet++; |
406 | } |
407 | bp[foo] = 0; |
408 | if(foo == 0 && bp > buf && bp[-1] == ' ') *--bp = 0; |
409 | (void) strlcpy(lets, bp, sizeof lets); /* necessary since we destroy buf */ |
410 | if(foo > 5) { /* compactify string */ |
411 | foo = foo2 = 1; |
412 | ilet2 = bp[0]; |
413 | ilet1 = bp[1]; |
414 | while ((ilet = bp[++foo2] = bp[++foo])) { |
415 | if(ilet == ilet1+1){ |
416 | if(ilet1 == ilet2+1) |
417 | bp[foo2 - 1] = ilet1 = '-'; |
418 | else if(ilet2 == '-') { |
419 | bp[--foo2] = ++ilet1; |
420 | continue; |
421 | } |
422 | } |
423 | ilet2 = ilet1; |
424 | ilet1 = ilet; |
425 | } |
426 | } |
427 | if(!foo && !allowall && !allowgold && !allownone) { |
428 | pline("You don't have anything %sto %s.", |
429 | foox ? "else " : "", word); |
430 | return(0); |
431 | } |
432 | for(;;) { |
433 | if(!buf[0]) |
434 | pline("What do you want to %s [*]? ", word); |
435 | else |
436 | pline("What do you want to %s [%s or ?*]? ", |
437 | word, buf); |
438 | |
439 | cnt = 0; |
440 | ilet = readchar(); |
441 | while(isdigit((unsigned char)ilet) && allowcnt) { |
442 | if (cnt < 100000000) |
443 | cnt = 10*cnt + (ilet - '0'); |
444 | else |
445 | cnt = 999999999; |
446 | allowcnt = 2; /* signal presence of cnt */ |
447 | ilet = readchar(); |
448 | } |
449 | if(isdigit((unsigned char)ilet)) { |
450 | pline("No count allowed with this command."); |
451 | continue; |
452 | } |
453 | if(strchr(quitchars,ilet)) |
454 | return((struct obj *)0); |
455 | if(ilet == '-') { |
456 | return(allownone ? &zeroobj : (struct obj *) 0); |
457 | } |
458 | if(ilet == '$') { |
459 | if(!allowgold){ |
460 | pline("You cannot %s gold.", word); |
461 | continue; |
462 | } |
463 | if(!(allowcnt == 2 && cnt < u.ugold)) |
464 | cnt = u.ugold; |
465 | return(mkgoldobj(cnt)); |
466 | } |
467 | if(ilet == '?') { |
468 | doinv(lets); |
469 | if(!(ilet = morc)) continue; |
470 | /* he typed a letter (not a space) to more() */ |
471 | } else if(ilet == '*') { |
472 | doinv(NULL((void *)0)); |
473 | if(!(ilet = morc)) continue; |
474 | /* ... */ |
475 | } |
476 | if(flags.invlet_constant) { |
477 | for(otmp = invent; otmp; otmp = otmp->nobj) |
478 | if(otmp->invlet == ilet) break; |
479 | } else { |
480 | if(ilet >= 'A' && ilet <= 'Z') ilet += 'z'-'A'+1; |
481 | ilet -= 'a'; |
482 | for(otmp = invent; otmp && ilet; |
483 | ilet--, otmp = otmp->nobj) ; |
484 | } |
485 | if(!otmp) { |
486 | pline("You don't have that object."); |
487 | continue; |
488 | } |
489 | if(cnt < 0 || otmp->quan < cnt) { |
490 | pline("You don't have that many! [You have %u]" |
491 | , otmp->quan); |
492 | continue; |
493 | } |
494 | break; |
495 | } |
496 | if(!allowall && let && !strchr(let,otmp->olet)) { |
497 | pline("That is a silly thing to %s.",word); |
498 | return(0); |
499 | } |
500 | if(allowcnt == 2) { /* cnt given */ |
501 | if(cnt == 0) return(0); |
502 | if(cnt != otmp->quan) { |
503 | struct obj *obj; |
504 | obj = splitobj(otmp, (int) cnt); |
505 | if(otmp == uwep) setuwep(obj); |
506 | } |
507 | } |
508 | return(otmp); |
509 | } |
510 | |
511 | int |
512 | ckunpaid(struct obj *otmp) |
513 | { |
514 | return( otmp->unpaid ); |
515 | } |
516 | |
517 | /* interactive version of getobj - used for Drop and Identify */ |
518 | /* return the number of times fn was called successfully */ |
519 | int |
520 | ggetobj(char *word, int (*fn)(struct obj *), int max) |
521 | { |
522 | char buf[BUFSZ256]; |
523 | char *ip; |
524 | char sym; |
525 | int oletct = 0, iletct = 0; |
526 | boolean allflag = FALSE0; |
527 | char olets[20], ilets[20]; |
528 | int (*ckfn)(struct obj *) = NULL((void *)0); |
529 | xchar allowgold = (u.ugold && !strcmp(word, "drop")) ? 1 : 0; /* BAH */ |
530 | |
531 | if(!invent && !allowgold){ |
532 | pline("You have nothing to %s.", word); |
533 | return(0); |
534 | } else { |
535 | struct obj *otmp = invent; |
536 | int uflg = 0; |
537 | |
538 | if(allowgold) ilets[iletct++] = '$'; |
539 | ilets[iletct] = 0; |
540 | while(otmp) { |
541 | if(!strchr(ilets, otmp->olet)){ |
542 | ilets[iletct++] = otmp->olet; |
543 | ilets[iletct] = 0; |
544 | } |
545 | if(otmp->unpaid) uflg = 1; |
546 | otmp = otmp->nobj; |
547 | } |
548 | ilets[iletct++] = ' '; |
549 | if(uflg) ilets[iletct++] = 'u'; |
550 | if(invent) ilets[iletct++] = 'a'; |
551 | ilets[iletct] = 0; |
552 | } |
553 | pline("What kinds of thing do you want to %s? [%s] ", |
554 | word, ilets); |
555 | getlin(buf); |
556 | if(buf[0] == '\033') { |
557 | clrlin(); |
558 | return(0); |
559 | } |
560 | ip = buf; |
561 | olets[0] = 0; |
562 | while ((sym = *ip++)) { |
563 | if (sym == ' ') |
564 | continue; |
565 | if (sym == '$') { |
566 | if (allowgold == 1) |
567 | (*fn)(mkgoldobj(u.ugold)); |
568 | else if (!u.ugold) |
569 | pline("You have no gold."); |
570 | allowgold = 2; |
571 | } else if (sym == 'a' || sym == 'A') |
572 | allflag = TRUE1; |
573 | else if (sym == 'u' || sym == 'U') |
574 | ckfn = ckunpaid; |
575 | else if (strchr("!%?[()=*/\"0", sym)) { |
576 | if (!strchr(olets, sym)) { |
577 | olets[oletct++] = sym; |
578 | olets[oletct] = 0; |
579 | } |
580 | } |
581 | else pline("You don't have any %c's.", sym); |
582 | } |
583 | if (allowgold == 2 && !oletct) |
584 | return(1); /* he dropped gold (or at least tried to) */ |
585 | else |
586 | return(askchain(invent, olets, allflag, fn, ckfn, max)); |
587 | } |
588 | |
589 | /* |
590 | * Walk through the chain starting at objchn and ask for all objects |
591 | * with olet in olets (if nonNULL) and satisfying ckfn (if nonNULL) |
592 | * whether the action in question (i.e., fn) has to be performed. |
593 | * If allflag then no questions are asked. Max gives the max nr of |
594 | * objects to be treated. Return the number of objects treated. |
595 | */ |
596 | int |
597 | askchain(struct obj *objchn, char *olets, int allflag, int (*fn)(struct obj *), |
598 | int (*ckfn)(struct obj *), int max) |
599 | { |
600 | struct obj *otmp, *otmp2; |
601 | char sym, ilet; |
602 | int cnt = 0; |
603 | |
604 | ilet = 'a'-1; |
605 | for(otmp = objchn; otmp; otmp = otmp2){ |
606 | if(ilet == 'z') ilet = 'A'; else ilet++; |
607 | otmp2 = otmp->nobj; |
608 | if(olets && *olets && !strchr(olets, otmp->olet)) continue; |
609 | if(ckfn && !(*ckfn)(otmp)) continue; |
610 | if(!allflag) { |
611 | pline("%s", xprname(otmp, ilet)); |
612 | addtopl(" [nyaq]? "); |
613 | sym = readchar(); |
614 | } |
615 | else sym = 'y'; |
616 | |
617 | switch(sym){ |
618 | case 'a': |
619 | allflag = 1; |
620 | case 'y': |
621 | cnt += (*fn)(otmp); |
622 | if(--max == 0) goto ret; |
623 | case 'n': |
624 | default: |
625 | break; |
626 | case 'q': |
627 | goto ret; |
628 | } |
629 | } |
630 | pline(cnt ? "That was all." : "No applicable objects."); |
631 | ret: |
632 | return(cnt); |
633 | } |
634 | |
635 | /* should of course only be called for things in invent */ |
636 | static char |
637 | obj_to_let(struct obj *obj) |
638 | { |
639 | struct obj *otmp; |
640 | char ilet; |
641 | |
642 | if(flags.invlet_constant) |
643 | return(obj->invlet); |
644 | ilet = 'a'; |
645 | for(otmp = invent; otmp && otmp != obj; otmp = otmp->nobj) |
646 | if(++ilet > 'z') ilet = 'A'; |
647 | return(otmp ? ilet : NOINVSYM'#'); |
648 | } |
649 | |
650 | void |
651 | prinv(struct obj *obj) |
652 | { |
653 | pline("%s", xprname(obj, obj_to_let(obj))); |
654 | } |
655 | |
656 | static char * |
657 | xprname(struct obj *obj, char let) |
658 | { |
659 | static char li[BUFSZ256]; |
660 | |
661 | (void) snprintf(li, sizeof li, "%c - %s.", |
662 | flags.invlet_constant ? obj->invlet : let, |
663 | doname(obj)); |
664 | return(li); |
665 | } |
666 | |
667 | int |
668 | ddoinv(void) |
669 | { |
670 | doinv(NULL((void *)0)); |
671 | return(0); |
672 | } |
673 | |
674 | /* called with 0 or "": all objects in inventory */ |
675 | /* otherwise: all objects with (serial) letter in lets */ |
676 | static void |
677 | doinv(char *lets) |
678 | { |
679 | struct obj *otmp; |
680 | char ilet; |
681 | int ct = 0; |
682 | char any[BUFSZ256]; |
683 | |
684 | morc = 0; /* just to be sure */ |
685 | |
686 | if(!invent){ |
687 | pline("Not carrying anything."); |
688 | return; |
689 | } |
690 | |
691 | cornline(0, NULL((void *)0)); |
692 | ilet = 'a'; |
693 | for(otmp = invent; otmp; otmp = otmp->nobj) { |
694 | if(flags.invlet_constant) ilet = otmp->invlet; |
695 | if(!lets || !*lets || strchr(lets, ilet)) { |
696 | cornline(1, xprname(otmp, ilet)); |
697 | any[ct++] = ilet; |
698 | } |
699 | if(!flags.invlet_constant) if(++ilet > 'z') ilet = 'A'; |
700 | } |
701 | any[ct] = 0; |
702 | cornline(2, any); |
703 | } |
704 | |
705 | int |
706 | dotypeinv(void) /* free after Robert Viduya */ |
707 | /* Changed to one type only, so he doesn't have to type cr */ |
708 | { |
709 | char c, ilet; |
710 | char stuff[BUFSZ256]; |
711 | int stct; |
712 | struct obj *otmp; |
713 | boolean billx = inshop() && doinvbill(0); |
714 | boolean unpd = FALSE0; |
715 | |
716 | if (!invent && !u.ugold && !billx) { |
717 | pline ("You aren't carrying anything."); |
718 | return(0); |
719 | } |
720 | |
721 | stct = 0; |
722 | if(u.ugold) stuff[stct++] = '$'; |
723 | stuff[stct] = 0; |
724 | for(otmp = invent; otmp; otmp = otmp->nobj) { |
725 | if (!strchr (stuff, otmp->olet)) { |
726 | stuff[stct++] = otmp->olet; |
727 | stuff[stct] = 0; |
728 | } |
729 | if(otmp->unpaid) |
730 | unpd = TRUE1; |
731 | } |
732 | if(unpd) stuff[stct++] = 'u'; |
733 | if(billx) stuff[stct++] = 'x'; |
734 | stuff[stct] = 0; |
735 | |
736 | if(stct > 1) { |
737 | pline ("What type of object [%s] do you want an inventory of? ", |
738 | stuff); |
739 | c = readchar(); |
740 | if(strchr(quitchars,c)) return(0); |
741 | } else |
742 | c = stuff[0]; |
743 | |
744 | if(c == '$') |
745 | return(doprgold()); |
746 | |
747 | if(c == 'x' || c == 'X') { |
748 | if(billx) |
749 | (void) doinvbill(1); |
750 | else |
751 | pline("No used-up objects on the shopping bill."); |
752 | return(0); |
753 | } |
754 | |
755 | if((c == 'u' || c == 'U') && !unpd) { |
756 | pline("You are not carrying any unpaid objects."); |
757 | return(0); |
758 | } |
759 | |
760 | stct = 0; |
761 | ilet = 'a'; |
762 | for (otmp = invent; otmp; otmp = otmp -> nobj) { |
763 | if(flags.invlet_constant) ilet = otmp->invlet; |
764 | if (c == otmp -> olet || (c == 'u' && otmp -> unpaid)) |
765 | stuff[stct++] = ilet; |
766 | if(!flags.invlet_constant) if(++ilet > 'z') ilet = 'A'; |
767 | } |
768 | stuff[stct] = '\0'; |
769 | if(stct == 0) |
770 | pline("You have no such objects."); |
771 | else |
772 | doinv (stuff); |
773 | |
774 | return(0); |
775 | } |
776 | |
777 | /* look at what is here */ |
778 | int |
779 | dolook(void) |
780 | { |
781 | struct obj *otmp, *otmp0; |
782 | struct gold *gold; |
783 | char *verb = Blindu.uprops[(19 +7)].p_flgs ? "feel" : "see"; |
784 | int ct = 0; |
785 | |
786 | if(!u.uswallow) { |
787 | if(Blindu.uprops[(19 +7)].p_flgs) { |
788 | pline("You try to feel what is lying here on the floor."); |
789 | if(Levitationu.uprops[6].p_flgs) { /* ab@unido */ |
790 | pline("You cannot reach the floor!"); |
791 | return(1); |
792 | } |
793 | } |
794 | otmp0 = o_at(u.ux, u.uy); |
795 | gold = g_at(u.ux, u.uy); |
796 | } |
797 | |
798 | if(u.uswallow || (!otmp0 && !gold)) { |
799 | pline("You %s no objects here.", verb); |
800 | return(!!Blindu.uprops[(19 +7)].p_flgs); |
801 | } |
802 | |
803 | cornline(0, "Things that are here:"); |
804 | for(otmp = otmp0; otmp; otmp = otmp->nobj) { |
805 | if(otmp->ox == u.ux && otmp->oy == u.uy) { |
806 | ct++; |
807 | cornline(1, doname(otmp)); |
808 | if(Blindu.uprops[(19 +7)].p_flgs && otmp->otyp == DEAD_COCKATRICE47 && !uarmg) { |
809 | pline("Touching the dead cockatrice is a fatal mistake ..."); |
810 | pline("You die ..."); |
811 | killer = "dead cockatrice"; |
812 | done("died"); |
813 | } |
814 | } |
815 | } |
816 | |
817 | if(gold) { |
818 | char gbuf[30]; |
819 | |
820 | (void) snprintf(gbuf, sizeof gbuf, "%ld gold piece%s", |
821 | gold->amount, plur(gold->amount)(((gold->amount) == 1) ? "" : "s")); |
822 | if(!ct++) |
823 | pline("You %s here %s.", verb, gbuf); |
824 | else |
825 | cornline(1, gbuf); |
826 | } |
827 | |
828 | if(ct == 1 && !gold) { |
829 | pline("You %s here %s.", verb, doname(otmp0)); |
830 | cornline(3, NULL((void *)0)); |
831 | } |
832 | if(ct > 1) |
833 | cornline(2, NULL((void *)0)); |
834 | return(!!Blindu.uprops[(19 +7)].p_flgs); |
835 | } |
836 | |
837 | void |
838 | stackobj(struct obj *obj) |
839 | { |
840 | struct obj *otmp = fobj; |
Value stored to 'otmp' during its initialization is never read | |
841 | |
842 | for(otmp = fobj; otmp; otmp = otmp->nobj) if(otmp != obj) |
843 | if(otmp->ox == obj->ox && otmp->oy == obj->oy && |
844 | merged(obj,otmp,1)) |
845 | return; |
846 | } |
847 | |
848 | /* merge obj with otmp and delete obj if types agree */ |
849 | static int |
850 | merged(struct obj *otmp, struct obj *obj, int lose) |
851 | { |
852 | if(obj->otyp == otmp->otyp && |
853 | obj->unpaid == otmp->unpaid && |
854 | obj->spe == otmp->spe && |
855 | obj->dknown == otmp->dknown && |
856 | obj->cursed == otmp->cursed && |
857 | (strchr("%*?!", obj->olet) || |
858 | (obj->known == otmp->known && |
859 | (obj->olet == WEAPON_SYM')' && obj->otyp < BOOMERANG76)))) { |
860 | otmp->quan += obj->quan; |
861 | otmp->owt += obj->owt; |
862 | if(lose) freeobj(obj); |
863 | obfree(obj,otmp); /* free(obj), bill->otmp */ |
864 | return(1); |
865 | } else return(0); |
866 | } |
867 | |
868 | /* |
869 | * Gold is no longer displayed; in fact, when you have a lot of money, |
870 | * it may take a while before you have counted it all. |
871 | * [Bug: d$ and pickup still tell you how much it was.] |
872 | */ |
873 | extern int (*occupation)(void); |
874 | extern char *occtxt; |
875 | static long goldcounted; |
876 | |
877 | int |
878 | countgold(void) |
879 | { |
880 | if((goldcounted += 100*(u.ulevel + 1)) >= u.ugold) { |
881 | long eps = 0; |
882 | if(!rn2(2)) eps = rnd((int) (u.ugold/100 + 1)); |
883 | pline("You probably have about %ld gold pieces.", |
884 | u.ugold + eps); |
885 | return(0); /* done */ |
886 | } |
887 | return(1); /* continue */ |
888 | } |
889 | |
890 | int |
891 | doprgold(void) |
892 | { |
893 | if(!u.ugold) |
894 | pline("You do not carry any gold."); |
895 | else if(u.ugold <= 500) |
896 | pline("You are carrying %ld gold pieces.", u.ugold); |
897 | else { |
898 | pline("You sit down in order to count your gold pieces."); |
899 | goldcounted = 500; |
900 | occupation = countgold; |
901 | occtxt = "counting your gold"; |
902 | } |
903 | return(1); |
904 | } |
905 | |
906 | /* --- end of gold counting section --- */ |
907 | |
908 | int |
909 | doprwep(void) |
910 | { |
911 | if(!uwep) pline("You are empty handed."); |
912 | else prinv(uwep); |
913 | return(0); |
914 | } |
915 | |
916 | int |
917 | doprarm(void) |
918 | { |
919 | if(!uarm && !uarmg && !uarms && !uarmh) |
920 | pline("You are not wearing any armor."); |
921 | else { |
922 | char lets[6]; |
923 | int ct = 0; |
924 | |
925 | if(uarm) lets[ct++] = obj_to_let(uarm); |
926 | if(uarm2) lets[ct++] = obj_to_let(uarm2); |
927 | if(uarmh) lets[ct++] = obj_to_let(uarmh); |
928 | if(uarms) lets[ct++] = obj_to_let(uarms); |
929 | if(uarmg) lets[ct++] = obj_to_let(uarmg); |
930 | lets[ct] = 0; |
931 | doinv(lets); |
932 | } |
933 | return(0); |
934 | } |
935 | |
936 | int |
937 | doprring(void) |
938 | { |
939 | if(!uleft && !uright) |
940 | pline("You are not wearing any rings."); |
941 | else { |
942 | char lets[3]; |
943 | int ct = 0; |
944 | |
945 | if(uleft) lets[ct++] = obj_to_let(uleft); |
946 | if(uright) lets[ct++] = obj_to_let(uright); |
947 | lets[ct] = 0; |
948 | doinv(lets); |
949 | } |
950 | return(0); |
951 | } |