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