]> git.cameronkatri.com Git - bsdgames-darwin.git/blob - rogue/inventory.c
Coverity CID 1293: not checking for an error return
[bsdgames-darwin.git] / rogue / inventory.c
1 /* $NetBSD: inventory.c,v 1.9 2003/08/07 09:37:38 agc Exp $ */
2
3 /*
4 * Copyright (c) 1988, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Timothy C. Stoehr.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. 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 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35 #include <sys/cdefs.h>
36 #ifndef lint
37 #if 0
38 static char sccsid[] = "@(#)inventory.c 8.1 (Berkeley) 5/31/93";
39 #else
40 __RCSID("$NetBSD: inventory.c,v 1.9 2003/08/07 09:37:38 agc Exp $");
41 #endif
42 #endif /* not lint */
43
44 /*
45 * inventory.c
46 *
47 * This source herein may be modified and/or distributed by anybody who
48 * so desires, with the following restrictions:
49 * 1.) No portion of this notice shall be removed.
50 * 2.) Credit shall not be taken for the creation of this source.
51 * 3.) This code is not to be traded, sold, or used for personal
52 * gain or profit.
53 *
54 */
55
56 #include "rogue.h"
57
58 boolean is_wood[WANDS];
59 const char *press_space = " --press space to continue--";
60
61 const char *const wand_materials[WAND_MATERIALS] = {
62 "steel ",
63 "bronze ",
64 "gold ",
65 "silver ",
66 "copper ",
67 "nickel ",
68 "cobalt ",
69 "tin ",
70 "iron ",
71 "magnesium ",
72 "chrome ",
73 "carbon ",
74 "platinum ",
75 "silicon ",
76 "titanium ",
77
78 "teak ",
79 "oak ",
80 "cherry ",
81 "birch ",
82 "pine ",
83 "cedar ",
84 "redwood ",
85 "balsa ",
86 "ivory ",
87 "walnut ",
88 "maple ",
89 "mahogany ",
90 "elm ",
91 "palm ",
92 "wooden "
93 };
94
95 const char *const gems[GEMS] = {
96 "diamond ",
97 "stibotantalite ",
98 "lapi-lazuli ",
99 "ruby ",
100 "emerald ",
101 "sapphire ",
102 "amethyst ",
103 "quartz ",
104 "tiger-eye ",
105 "opal ",
106 "agate ",
107 "turquoise ",
108 "pearl ",
109 "garnet "
110 };
111
112 const char *const syllables[MAXSYLLABLES] = {
113 "blech ",
114 "foo ",
115 "barf ",
116 "rech ",
117 "bar ",
118 "blech ",
119 "quo ",
120 "bloto ",
121 "oh ",
122 "caca ",
123 "blorp ",
124 "erp ",
125 "festr ",
126 "rot ",
127 "slie ",
128 "snorf ",
129 "iky ",
130 "yuky ",
131 "ooze ",
132 "ah ",
133 "bahl ",
134 "zep ",
135 "druhl ",
136 "flem ",
137 "behil ",
138 "arek ",
139 "mep ",
140 "zihr ",
141 "grit ",
142 "kona ",
143 "kini ",
144 "ichi ",
145 "tims ",
146 "ogr ",
147 "oo ",
148 "ighr ",
149 "coph ",
150 "swerr ",
151 "mihln ",
152 "poxi "
153 };
154
155 #define COMS 48
156
157 struct id_com_s {
158 short com_char;
159 const char *com_desc;
160 };
161
162 const struct id_com_s com_id_tab[COMS] = {
163 {'?', "? prints help"},
164 {'r', "r read scroll"},
165 {'/', "/ identify object"},
166 {'e', "e eat food"},
167 {'h', "h left "},
168 {'w', "w wield a weapon"},
169 {'j', "j down"},
170 {'W', "W wear armor"},
171 {'k', "k up"},
172 {'T', "T take armor off"},
173 {'l', "l right"},
174 {'P', "P put on ring"},
175 {'y', "y up & left"},
176 {'R', "R remove ring"},
177 {'u', "u up & right"},
178 {'d', "d drop object"},
179 {'b', "b down & left"},
180 {'c', "c call object"},
181 {'n', "n down & right"},
182 {'\0', "<SHIFT><dir>: run that way"},
183 {')', ") print current weapon"},
184 {'\0', "<CTRL><dir>: run till adjacent"},
185 {']', "] print current armor"},
186 {'f', "f<dir> fight till death or near death"},
187 {'=', "= print current rings"},
188 {'t', "t<dir> throw something"},
189 {'\001', "^A print Hp-raise average"},
190 {'m', "m<dir> move onto without picking up"},
191 {'z', "z<dir> zap a wand in a direction"},
192 {'o', "o examine/set options"},
193 {'^', "^<dir> identify trap type"},
194 {'\022', "^R redraw screen"},
195 {'&', "& save screen into 'rogue.screen'"},
196 {'s', "s search for trap/secret door"},
197 {'\020', "^P repeat last message"},
198 {'>', "> go down a staircase"},
199 {'\033', "^[ cancel command"},
200 {'<', "< go up a staircase"},
201 {'S', "S save game"},
202 {'.', ". rest for a turn"},
203 {'Q', "Q quit"},
204 {',', ", pick something up"},
205 {'!', "! shell escape"},
206 {'i', "i inventory"},
207 {'F', "F<dir> fight till either of you dies"},
208 {'I', "I inventory single item"},
209 {'v', "v print version number"},
210 {'q', "q quaff potion" }
211 };
212
213 void
214 inventory(pack, mask)
215 const object *pack;
216 unsigned short mask;
217 {
218 object *obj;
219 short i = 0, j, maxlen = 0, n;
220 char descs[MAX_PACK_COUNT+1][DCOLS];
221 short row, col;
222
223 obj = pack->next_object;
224
225 if (!obj) {
226 message("your pack is empty", 0);
227 return;
228 }
229 while (obj) {
230 if (obj->what_is & mask) {
231 descs[i][0] = ' ';
232 descs[i][1] = obj->ichar;
233 descs[i][2] = ((obj->what_is & ARMOR) && obj->is_protected)
234 ? '}' : ')';
235 descs[i][3] = ' ';
236 get_desc(obj, descs[i]+4);
237 if ((n = strlen(descs[i])) > maxlen) {
238 maxlen = n;
239 }
240 i++;
241 }
242 obj = obj->next_object;
243 }
244 (void) strcpy(descs[i++], press_space);
245 if (maxlen < 27) maxlen = 27;
246 col = DCOLS - (maxlen + 2);
247
248 for (row = 0; ((row < i) && (row < DROWS)); row++) {
249 if (row > 0) {
250 for (j = col; j < DCOLS; j++) {
251 descs[row-1][j-col] = mvinch(row, j);
252 }
253 descs[row-1][j-col] = 0;
254 }
255 mvaddstr(row, col, descs[row]);
256 clrtoeol();
257 }
258 refresh();
259 wait_for_ack();
260
261 move(0, 0);
262 clrtoeol();
263
264 for (j = 1; ((j < i) && (j < DROWS)); j++) {
265 mvaddstr(j, col, descs[j-1]);
266 }
267 }
268
269 void
270 id_com()
271 {
272 int ch = 0;
273 short i, j, k;
274
275 while (ch != CANCEL) {
276 check_message();
277 message("Character you want help for (* for all):", 0);
278
279 refresh();
280 ch = getchar();
281
282 switch(ch) {
283 case LIST:
284 {
285 char save[(((COMS / 2) + (COMS % 2)) + 1)][DCOLS];
286 short rows = (((COMS / 2) + (COMS % 2)) + 1);
287 boolean need_two_screens = FALSE;
288
289 if (rows > LINES) {
290 need_two_screens = 1;
291 rows = LINES;
292 }
293 k = 0;
294
295 for (i = 0; i < rows; i++) {
296 for (j = 0; j < DCOLS; j++) {
297 save[i][j] = mvinch(i, j);
298 }
299 }
300 MORE:
301 for (i = 0; i < rows; i++) {
302 move(i, 0);
303 clrtoeol();
304 }
305 for (i = 0; i < (rows-1); i++) {
306 if (i < (LINES-1)) {
307 if (((i + i) < COMS) && ((i+i+k) < COMS)) {
308 mvaddstr(i, 0, com_id_tab[i+i+k].com_desc);
309 }
310 if (((i + i + 1) < COMS) && ((i+i+k+1) < COMS)) {
311 mvaddstr(i, (DCOLS/2),
312 com_id_tab[i+i+k+1].com_desc);
313 }
314 }
315 }
316 mvaddstr(rows - 1, 0, need_two_screens ? more : press_space);
317 refresh();
318 wait_for_ack();
319
320 if (need_two_screens) {
321 k += ((rows-1) * 2);
322 need_two_screens = 0;
323 goto MORE;
324 }
325 for (i = 0; i < rows; i++) {
326 move(i, 0);
327 for (j = 0; j < DCOLS; j++) {
328 addch(save[i][j]);
329 }
330 }
331 }
332 break;
333 default:
334 if (!pr_com_id(ch)) {
335 if (!pr_motion_char(ch)) {
336 check_message();
337 message("unknown character", 0);
338 }
339 }
340 ch = CANCEL;
341 break;
342 }
343 }
344 }
345
346 int
347 pr_com_id(ch)
348 int ch;
349 {
350 int i;
351
352 if (!get_com_id(&i, ch)) {
353 return(0);
354 }
355 check_message();
356 message(com_id_tab[i].com_desc, 0);
357 return(1);
358 }
359
360 int
361 get_com_id(indexp, ch)
362 int *indexp;
363 short ch;
364 {
365 short i;
366
367 for (i = 0; i < COMS; i++) {
368 if (com_id_tab[i].com_char == ch) {
369 *indexp = i;
370 return(1);
371 }
372 }
373 return(0);
374 }
375
376 int
377 pr_motion_char(ch)
378 int ch;
379 {
380 if ( (ch == 'J') ||
381 (ch == 'K') ||
382 (ch == 'L') ||
383 (ch == 'H') ||
384 (ch == 'Y') ||
385 (ch == 'U') ||
386 (ch == 'N') ||
387 (ch == 'B') ||
388 (ch == '\012') ||
389 (ch == '\013') ||
390 (ch == '\010') ||
391 (ch == '\014') ||
392 (ch == '\025') ||
393 (ch == '\031') ||
394 (ch == '\016') ||
395 (ch == '\002')) {
396 char until[18], buf[DCOLS];
397 int n;
398
399 if (ch <= '\031') {
400 ch += 96;
401 (void) strcpy(until, "until adjascent");
402 } else {
403 ch += 32;
404 until[0] = '\0';
405 }
406 (void) get_com_id(&n, ch);
407 sprintf(buf, "run %s %s", com_id_tab[n].com_desc + 8, until);
408 check_message();
409 message(buf, 0);
410 return(1);
411 } else {
412 return(0);
413 }
414 }
415
416 void
417 mix_colors()
418 {
419 short i, j, k;
420 char t[MAX_ID_TITLE_LEN];
421
422 for (i = 0; i <= 32; i++) {
423 j = get_rand(0, (POTIONS - 1));
424 k = get_rand(0, (POTIONS - 1));
425 memcpy(t, id_potions[j].title, MAX_ID_TITLE_LEN);
426 memcpy(id_potions[j].title, id_potions[k].title, MAX_ID_TITLE_LEN);
427 memcpy(id_potions[k].title, t, MAX_ID_TITLE_LEN);
428 }
429 }
430
431 void
432 make_scroll_titles()
433 {
434 short i, j, n;
435 short sylls, s;
436
437 for (i = 0; i < SCROLS; i++) {
438 sylls = get_rand(2, 5);
439 (void) strcpy(id_scrolls[i].title, "'");
440
441 for (j = 0; j < sylls; j++) {
442 s = get_rand(1, (MAXSYLLABLES-1));
443 (void) strcat(id_scrolls[i].title, syllables[s]);
444 }
445 n = strlen(id_scrolls[i].title);
446 (void) strcpy(id_scrolls[i].title+(n-1), "' ");
447 }
448 }
449
450 void
451 get_desc(obj, desc)
452 const object *obj;
453 char *desc;
454 {
455 const char *item_name;
456 struct id *id_table;
457 char more_info[32];
458 short i;
459
460 if (obj->what_is == AMULET) {
461 (void) strcpy(desc, "the amulet of Yendor ");
462 return;
463 }
464 item_name = name_of(obj);
465
466 if (obj->what_is == GOLD) {
467 sprintf(desc, "%d pieces of gold", obj->quantity);
468 return;
469 }
470
471 if (obj->what_is != ARMOR) {
472 if (obj->quantity == 1) {
473 (void) strcpy(desc, "a ");
474 } else {
475 sprintf(desc, "%d ", obj->quantity);
476 }
477 }
478 if (obj->what_is == FOOD) {
479 if (obj->which_kind == RATION) {
480 if (obj->quantity > 1) {
481 sprintf(desc, "%d rations of ", obj->quantity);
482 } else {
483 (void) strcpy(desc, "some ");
484 }
485 } else {
486 (void) strcpy(desc, "a ");
487 }
488 (void) strcat(desc, item_name);
489 goto ANA;
490 }
491 id_table = get_id_table(obj);
492
493 if (wizard) {
494 goto ID;
495 }
496 if (obj->what_is & (WEAPON | ARMOR | WAND | RING)) {
497 goto CHECK;
498 }
499
500 switch(id_table[obj->which_kind].id_status) {
501 case UNIDENTIFIED:
502 CHECK:
503 switch(obj->what_is) {
504 case SCROL:
505 (void) strcat(desc, item_name);
506 (void) strcat(desc, "entitled: ");
507 (void) strcat(desc, id_table[obj->which_kind].title);
508 break;
509 case POTION:
510 (void) strcat(desc, id_table[obj->which_kind].title);
511 (void) strcat(desc, item_name);
512 break;
513 case WAND:
514 case RING:
515 if (obj->identified ||
516 (id_table[obj->which_kind].id_status == IDENTIFIED)) {
517 goto ID;
518 }
519 if (id_table[obj->which_kind].id_status == CALLED) {
520 goto CALL;
521 }
522 (void) strcat(desc, id_table[obj->which_kind].title);
523 (void) strcat(desc, item_name);
524 break;
525 case ARMOR:
526 if (obj->identified) {
527 goto ID;
528 }
529 (void) strcpy(desc, id_table[obj->which_kind].title);
530 break;
531 case WEAPON:
532 if (obj->identified) {
533 goto ID;
534 }
535 (void) strcat(desc, name_of(obj));
536 break;
537 }
538 break;
539 case CALLED:
540 CALL: switch(obj->what_is) {
541 case SCROL:
542 case POTION:
543 case WAND:
544 case RING:
545 (void) strcat(desc, item_name);
546 (void) strcat(desc, "called ");
547 (void) strcat(desc, id_table[obj->which_kind].title);
548 break;
549 }
550 break;
551 case IDENTIFIED:
552 ID: switch(obj->what_is) {
553 case SCROL:
554 case POTION:
555 (void) strcat(desc, item_name);
556 (void) strcat(desc, id_table[obj->which_kind].real);
557 break;
558 case RING:
559 if (wizard || obj->identified) {
560 if ((obj->which_kind == DEXTERITY) ||
561 (obj->which_kind == ADD_STRENGTH)) {
562 sprintf(more_info, "%s%d ", ((obj->class > 0) ? "+" : ""),
563 obj->class);
564 (void) strcat(desc, more_info);
565 }
566 }
567 (void) strcat(desc, item_name);
568 (void) strcat(desc, id_table[obj->which_kind].real);
569 break;
570 case WAND:
571 (void) strcat(desc, item_name);
572 (void) strcat(desc, id_table[obj->which_kind].real);
573 if (wizard || obj->identified) {
574 sprintf(more_info, "[%d]", obj->class);
575 (void) strcat(desc, more_info);
576 }
577 break;
578 case ARMOR:
579 sprintf(desc, "%s%d ", ((obj->d_enchant >= 0) ? "+" : ""),
580 obj->d_enchant);
581 (void) strcat(desc, id_table[obj->which_kind].title);
582 sprintf(more_info, "[%d] ", get_armor_class(obj));
583 (void) strcat(desc, more_info);
584 break;
585 case WEAPON:
586 sprintf(desc+strlen(desc), "%s%d,%s%d ",
587 ((obj->hit_enchant >= 0) ? "+" : ""), obj->hit_enchant,
588 ((obj->d_enchant >= 0) ? "+" : ""), obj->d_enchant);
589 (void) strcat(desc, name_of(obj));
590 break;
591 }
592 break;
593 }
594 ANA:
595 if (!strncmp(desc, "a ", 2)) {
596 if (is_vowel(desc[2])) {
597 for (i = strlen(desc) + 1; i > 1; i--) {
598 desc[i] = desc[i-1];
599 }
600 desc[1] = 'n';
601 }
602 }
603 if (obj->in_use_flags & BEING_WIELDED) {
604 (void) strcat(desc, "in hand");
605 } else if (obj->in_use_flags & BEING_WORN) {
606 (void) strcat(desc, "being worn");
607 } else if (obj->in_use_flags & ON_LEFT_HAND) {
608 (void) strcat(desc, "on left hand");
609 } else if (obj->in_use_flags & ON_RIGHT_HAND) {
610 (void) strcat(desc, "on right hand");
611 }
612 }
613
614 void
615 get_wand_and_ring_materials()
616 {
617 short i, j;
618 boolean used[WAND_MATERIALS];
619
620 for (i = 0; i < WAND_MATERIALS; i++) {
621 used[i] = 0;
622 }
623 for (i = 0; i < WANDS; i++) {
624 do {
625 j = get_rand(0, WAND_MATERIALS-1);
626 } while (used[j]);
627 used[j] = 1;
628 (void) strcpy(id_wands[i].title, wand_materials[j]);
629 is_wood[i] = (j > MAX_METAL);
630 }
631 for (i = 0; i < GEMS; i++) {
632 used[i] = 0;
633 }
634 for (i = 0; i < RINGS; i++) {
635 do {
636 j = get_rand(0, GEMS-1);
637 } while (used[j]);
638 used[j] = 1;
639 (void) strcpy(id_rings[i].title, gems[j]);
640 }
641 }
642
643 void
644 single_inv(ichar)
645 short ichar;
646 {
647 short ch;
648 char desc[DCOLS];
649 object *obj;
650
651 ch = ichar ? ichar : pack_letter("inventory what?", ALL_OBJECTS);
652
653 if (ch == CANCEL) {
654 return;
655 }
656 if (!(obj = get_letter_object(ch))) {
657 message("no such item.", 0);
658 return;
659 }
660 desc[0] = ch;
661 desc[1] = ((obj->what_is & ARMOR) && obj->is_protected) ? '}' : ')';
662 desc[2] = ' ';
663 desc[3] = 0;
664 get_desc(obj, desc+3);
665 message(desc, 0);
666 }
667
668 struct id *
669 get_id_table(obj)
670 const object *obj;
671 {
672 switch(obj->what_is) {
673 case SCROL:
674 return(id_scrolls);
675 case POTION:
676 return(id_potions);
677 case WAND:
678 return(id_wands);
679 case RING:
680 return(id_rings);
681 case WEAPON:
682 return(id_weapons);
683 case ARMOR:
684 return(id_armors);
685 }
686 return((struct id *) 0);
687 }
688
689 void
690 inv_armor_weapon(is_weapon)
691 boolean is_weapon;
692 {
693 if (is_weapon) {
694 if (rogue.weapon) {
695 single_inv(rogue.weapon->ichar);
696 } else {
697 message("not wielding anything", 0);
698 }
699 } else {
700 if (rogue.armor) {
701 single_inv(rogue.armor->ichar);
702 } else {
703 message("not wearing anything", 0);
704 }
705 }
706 }
707
708 void
709 id_type()
710 {
711 const char *id;
712 int ch;
713 char buf[DCOLS];
714
715 message("what do you want identified?", 0);
716
717 ch = rgetchar();
718
719 if ((ch >= 'A') && (ch <= 'Z')) {
720 id = m_names[ch-'A'];
721 } else if (ch < 32) {
722 check_message();
723 return;
724 } else {
725 switch(ch) {
726 case '@':
727 id = "you";
728 break;
729 case '%':
730 id = "staircase";
731 break;
732 case '^':
733 id = "trap";
734 break;
735 case '+':
736 id = "door";
737 break;
738 case '-':
739 case '|':
740 id = "wall of a room";
741 break;
742 case '.':
743 id = "floor";
744 break;
745 case '#':
746 id = "passage";
747 break;
748 case ' ':
749 id = "solid rock";
750 break;
751 case '=':
752 id = "ring";
753 break;
754 case '?':
755 id = "scroll";
756 break;
757 case '!':
758 id = "potion";
759 break;
760 case '/':
761 id = "wand or staff";
762 break;
763 case ')':
764 id = "weapon";
765 break;
766 case ']':
767 id = "armor";
768 break;
769 case '*':
770 id = "gold";
771 break;
772 case ':':
773 id = "food";
774 break;
775 case ',':
776 id = "the Amulet of Yendor";
777 break;
778 default:
779 id = "unknown character";
780 break;
781 }
782 }
783 check_message();
784 sprintf(buf, "'%c': %s", ch, id);
785 message(buf, 0);
786 }