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