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