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