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