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