1 /* $NetBSD: inventory.c,v 1.13 2008/01/14 03:50:01 dholland Exp $ */
4 * Copyright (c) 1988, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 #include <sys/cdefs.h>
38 static char sccsid
[] = "@(#)inventory.c 8.1 (Berkeley) 5/31/93";
40 __RCSID("$NetBSD: inventory.c,v 1.13 2008/01/14 03:50:01 dholland Exp $");
47 * This source herein may be modified and/or distributed by anybody who
48 * so desires, with the following restrictions:
49 * 1.) No portion of this notice shall be removed.
50 * 2.) Credit shall not be taken for the creation of this source.
51 * 3.) This code is not to be traded, sold, or used for personal
59 boolean is_wood
[WANDS
];
60 const char *press_space
= " --press space to continue--";
62 static const char *const wand_materials
[WAND_MATERIALS
] = {
96 static const char *const gems
[GEMS
] = {
113 static const char *const syllables
[MAXSYLLABLES
] = {
160 const char *com_desc
;
163 static const struct id_com_s com_id_tab
[COMS
] = {
164 {'?', "? prints help"},
165 {'r', "r read scroll"},
166 {'/', "/ identify object"},
169 {'w', "w wield a weapon"},
171 {'W', "W wear armor"},
173 {'T', "T take armor off"},
175 {'P', "P put on ring"},
176 {'y', "y up & left"},
177 {'R', "R remove ring"},
178 {'u', "u up & right"},
179 {'d', "d drop object"},
180 {'b', "b down & left"},
181 {'c', "c call object"},
182 {'n', "n down & right"},
183 {'\0', "<SHIFT><dir>: run that way"},
184 {')', ") print current weapon"},
185 {'\0', "<CTRL><dir>: run till adjacent"},
186 {']', "] print current armor"},
187 {'f', "f<dir> fight till death or near death"},
188 {'=', "= print current rings"},
189 {'t', "t<dir> throw something"},
190 {'\001', "^A print Hp-raise average"},
191 {'m', "m<dir> move onto without picking up"},
192 {'z', "z<dir> zap a wand in a direction"},
193 {'o', "o examine/set options"},
194 {'^', "^<dir> identify trap type"},
195 {'\022', "^R redraw screen"},
196 {'&', "& save screen into 'rogue.screen'"},
197 {'s', "s search for trap/secret door"},
198 {'\020', "^P repeat last message"},
199 {'>', "> go down a staircase"},
200 {'\033', "^[ cancel command"},
201 {'<', "< go up a staircase"},
202 {'S', "S save game"},
203 {'.', ". rest for a turn"},
205 {',', ", pick something up"},
206 {'!', "! shell escape"},
207 {'i', "i inventory"},
208 {'F', "F<dir> fight till either of you dies"},
209 {'I', "I inventory single item"},
210 {'v', "v print version number"},
211 {'q', "q quaff potion" }
214 static int get_com_id(int *, short);
215 static int pr_com_id(int);
216 static int pr_motion_char(int);
219 inventory(const object
*pack
, unsigned short mask
)
223 size_t maxlen
= 0, n
;
230 char savebuf
[DCOLS
+8];
231 } descs
[MAX_PACK_COUNT
+1];
234 obj
= pack
->next_object
;
237 messagef(0, "your pack is empty");
241 if (obj
->what_is
& mask
) {
242 descs
[i
].letter
= obj
->ichar
;
243 descs
[i
].sepchar
= ((obj
->what_is
& ARMOR
) && obj
->is_protected
)
245 get_desc(obj
, descs
[i
].desc
, sizeof(descs
[i
].desc
));
246 n
= strlen(descs
[i
].desc
) + 4;
251 /*assert(i<=MAX_PACK_COUNT);*/
253 obj
= obj
->next_object
;
255 if (maxlen
< 27) maxlen
= 27;
256 if (maxlen
> DCOLS
-2) maxlen
= DCOLS
-2;
257 col
= DCOLS
- (maxlen
+ 2);
259 for (row
= 0; ((row
<= i
) && (row
< DROWS
)); row
++) {
260 for (j
= col
; j
< DCOLS
; j
++) {
261 descs
[row
].savebuf
[j
-col
] = mvinch(row
, j
);
263 descs
[row
].savebuf
[j
-col
] = 0;
265 mvprintw(row
, col
, " %c%c %s",
266 descs
[row
].letter
, descs
[row
].sepchar
,
270 mvaddstr(row
, col
, press_space
);
280 for (j
= 1; ((j
<= i
) && (j
< DROWS
)); j
++) {
281 mvaddstr(j
, col
, descs
[j
].savebuf
);
291 while (ch
!= CANCEL
) {
293 messagef(0, "Character you want help for (* for all):");
301 char save
[(((COMS
/ 2) + (COMS
% 2)) + 1)][DCOLS
];
302 short rows
= (((COMS
/ 2) + (COMS
% 2)) + 1);
303 boolean need_two_screens
= FALSE
;
306 need_two_screens
= 1;
311 for (i
= 0; i
< rows
; i
++) {
312 for (j
= 0; j
< DCOLS
; j
++) {
313 save
[i
][j
] = mvinch(i
, j
);
317 for (i
= 0; i
< rows
; i
++) {
321 for (i
= 0; i
< (rows
-1); i
++) {
323 if (((i
+ i
) < COMS
) && ((i
+i
+k
) < COMS
)) {
324 mvaddstr(i
, 0, com_id_tab
[i
+i
+k
].com_desc
);
326 if (((i
+ i
+ 1) < COMS
) && ((i
+i
+k
+1) < COMS
)) {
327 mvaddstr(i
, (DCOLS
/2),
328 com_id_tab
[i
+i
+k
+1].com_desc
);
332 mvaddstr(rows
- 1, 0, need_two_screens
? more
: press_space
);
336 if (need_two_screens
) {
338 need_two_screens
= 0;
341 for (i
= 0; i
< rows
; i
++) {
343 for (j
= 0; j
< DCOLS
; j
++) {
350 if (!pr_com_id(ch
)) {
351 if (!pr_motion_char(ch
)) {
353 messagef(0, "unknown character");
367 if (!get_com_id(&i
, ch
)) {
371 messagef(0, "%s", com_id_tab
[i
].com_desc
);
376 get_com_id(int *indexp
, short ch
)
380 for (i
= 0; i
< COMS
; i
++) {
381 if (com_id_tab
[i
].com_char
== ch
) {
390 pr_motion_char(int ch
)
409 int n
= 0; /* XXX: GCC */
412 until
= " until adjacent";
417 (void)get_com_id(&n
, ch
);
419 messagef(0, "run %s%s", com_id_tab
[n
].com_desc
+ 8, until
);
430 char t
[MAX_ID_TITLE_LEN
];
432 for (i
= 0; i
<= 32; i
++) {
433 j
= get_rand(0, (POTIONS
- 1));
434 k
= get_rand(0, (POTIONS
- 1));
435 strlcpy(t
, id_potions
[j
].title
, sizeof(t
));
436 strlcpy(id_potions
[j
].title
, id_potions
[k
].title
,
437 sizeof(id_potions
[j
].title
));
438 strlcpy(id_potions
[k
].title
, t
, sizeof(id_potions
[k
].title
));
443 make_scroll_titles(void)
447 size_t maxlen
= sizeof(id_scrolls
[0].title
);
449 for (i
= 0; i
< SCROLS
; i
++) {
450 sylls
= get_rand(2, 5);
451 (void)strlcpy(id_scrolls
[i
].title
, "'", maxlen
);
453 for (j
= 0; j
< sylls
; j
++) {
454 s
= get_rand(1, (MAXSYLLABLES
-1));
455 (void)strlcat(id_scrolls
[i
].title
, syllables
[s
],
458 /* trim trailing space */
459 n
= strlen(id_scrolls
[i
].title
);
460 id_scrolls
[i
].title
[n
-1] = 0;
462 (void)strlcat(id_scrolls
[i
].title
, "' ", maxlen
);
471 static void sbuf_init(struct sbuf
*s
, char *buf
, size_t maxlen
);
472 static void sbuf_addstr(struct sbuf
*s
, const char *str
);
473 static void sbuf_addf(struct sbuf
*s
, const char *fmt
, ...)
474 __attribute__((__format__(__printf__
, 2, 3)));
475 static void desc_count(struct sbuf
*s
, int n
);
476 static void desc_called(struct sbuf
*s
, const object
*);
480 sbuf_init(struct sbuf
*s
, char *buf
, size_t maxlen
)
484 /*assert(maxlen>0);*/
490 sbuf_addstr(struct sbuf
*s
, const char *str
)
492 strlcat(s
->buf
, str
, s
->maxlen
);
497 sbuf_addf(struct sbuf
*s
, const char *fmt
, ...)
502 initlen
= strlen(s
->buf
);
504 vsnprintf(s
->buf
+initlen
, s
->maxlen
-initlen
, fmt
, ap
);
510 desc_count(struct sbuf
*s
, int n
)
513 sbuf_addstr(s
, "an ");
515 sbuf_addf(s
, "%d ", n
);
521 desc_called(struct sbuf
*s
, const object
*obj
)
525 id_table
= get_id_table(obj
);
526 sbuf_addstr(s
, name_of(obj
));
527 sbuf_addstr(s
, "called ");
528 sbuf_addstr(s
, id_table
[obj
->which_kind
].title
);
532 get_desc(const object
*obj
, char *desc
, size_t desclen
)
534 const char *item_name
;
537 unsigned short objtype_id_status
;
539 if (obj
->what_is
== AMULET
) {
540 (void)strlcpy(desc
, "the amulet of Yendor ", desclen
);
544 if (obj
->what_is
== GOLD
) {
545 snprintf(desc
, desclen
, "%d pieces of gold", obj
->quantity
);
549 item_name
= name_of(obj
);
550 id_table
= get_id_table(obj
);
551 if (wizard
|| id_table
== NULL
) {
552 objtype_id_status
= IDENTIFIED
;
555 objtype_id_status
= id_table
[obj
->which_kind
].id_status
;
557 if (obj
->what_is
& (WEAPON
| ARMOR
| WAND
| RING
)) {
558 if (obj
->identified
) {
559 objtype_id_status
= IDENTIFIED
;
563 sbuf_init(&db
, desc
, desclen
);
565 switch (obj
->what_is
) {
567 if (obj
->which_kind
== RATION
) {
568 if (obj
->quantity
> 1) {
570 "%d rations of %s", obj
->quantity
,
573 sbuf_addf(&db
, "some %s", item_name
);
576 sbuf_addf(&db
, "an %s", item_name
);
580 desc_count(&db
, obj
->quantity
);
581 if (objtype_id_status
==UNIDENTIFIED
) {
582 sbuf_addstr(&db
, item_name
);
583 sbuf_addstr(&db
, "entitled: ");
584 sbuf_addstr(&db
, id_table
[obj
->which_kind
].title
);
585 } else if (objtype_id_status
==CALLED
) {
586 desc_called(&db
, obj
);
588 sbuf_addstr(&db
, item_name
);
589 sbuf_addstr(&db
, id_table
[obj
->which_kind
].real
);
593 desc_count(&db
, obj
->quantity
);
594 if (objtype_id_status
==UNIDENTIFIED
) {
595 sbuf_addstr(&db
, id_table
[obj
->which_kind
].title
);
596 sbuf_addstr(&db
, item_name
);
597 } else if (objtype_id_status
==CALLED
) {
598 desc_called(&db
, obj
);
600 sbuf_addstr(&db
, item_name
);
601 sbuf_addstr(&db
, id_table
[obj
->which_kind
].real
);
605 desc_count(&db
, obj
->quantity
);
606 if (objtype_id_status
==UNIDENTIFIED
) {
607 sbuf_addstr(&db
, id_table
[obj
->which_kind
].title
);
608 sbuf_addstr(&db
, item_name
);
609 } else if (objtype_id_status
==CALLED
) {
610 desc_called(&db
, obj
);
612 sbuf_addstr(&db
, item_name
);
613 sbuf_addstr(&db
, id_table
[obj
->which_kind
].real
);
614 if (wizard
|| obj
->identified
) {
615 sbuf_addf(&db
, "[%d]", obj
->class);
620 desc_count(&db
, obj
->quantity
);
621 if (objtype_id_status
==UNIDENTIFIED
) {
622 sbuf_addstr(&db
, id_table
[obj
->which_kind
].title
);
623 sbuf_addstr(&db
, item_name
);
624 } else if (objtype_id_status
==CALLED
) {
625 desc_called(&db
, obj
);
627 if ((wizard
|| obj
->identified
) &&
628 (obj
->which_kind
== DEXTERITY
||
629 obj
->which_kind
== ADD_STRENGTH
)) {
630 sbuf_addf(&db
, "%+d ", obj
->class);
632 sbuf_addstr(&db
, item_name
);
633 sbuf_addstr(&db
, id_table
[obj
->which_kind
].real
);
637 /* no desc_count() */
638 if (objtype_id_status
==UNIDENTIFIED
) {
639 sbuf_addstr(&db
, id_table
[obj
->which_kind
].title
);
641 sbuf_addf(&db
, "%+d %s[%d] ", obj
->d_enchant
,
642 id_table
[obj
->which_kind
].title
,
643 get_armor_class(obj
));
647 desc_count(&db
, obj
->quantity
);
648 if (objtype_id_status
==UNIDENTIFIED
) {
649 sbuf_addstr(&db
, name_of(obj
));
651 sbuf_addf(&db
, "%+d,%+d %s",
652 obj
->hit_enchant
, obj
->d_enchant
,
658 if (obj
->in_use_flags
& BEING_WIELDED
) {
659 sbuf_addstr(&db
, "in hand");
660 } else if (obj
->in_use_flags
& BEING_WORN
) {
661 sbuf_addstr(&db
, "being worn");
662 } else if (obj
->in_use_flags
& ON_LEFT_HAND
) {
663 sbuf_addstr(&db
, "on left hand");
664 } else if (obj
->in_use_flags
& ON_RIGHT_HAND
) {
665 sbuf_addstr(&db
, "on right hand");
668 if (!strncmp(db
.buf
, "an ", 3)) {
669 if (!is_vowel(db
.buf
[3])) {
670 memmove(db
.buf
+2, db
.buf
+3, strlen(db
.buf
+3)+1);
677 get_wand_and_ring_materials(void)
680 boolean used
[WAND_MATERIALS
];
682 for (i
= 0; i
< WAND_MATERIALS
; i
++) {
685 for (i
= 0; i
< WANDS
; i
++) {
687 j
= get_rand(0, WAND_MATERIALS
-1);
690 (void)strlcpy(id_wands
[i
].title
, wand_materials
[j
],
691 sizeof(id_wands
[i
].title
));
692 is_wood
[i
] = (j
> MAX_METAL
);
694 for (i
= 0; i
< GEMS
; i
++) {
697 for (i
= 0; i
< RINGS
; i
++) {
699 j
= get_rand(0, GEMS
-1);
702 (void)strlcpy(id_rings
[i
].title
, gems
[j
],
703 sizeof(id_rings
[i
].title
));
708 single_inv(short ichar
)
714 ch
= ichar
? ichar
: pack_letter("inventory what?", ALL_OBJECTS
);
719 if (!(obj
= get_letter_object(ch
))) {
720 messagef(0, "no such item.");
723 ch2
= ((obj
->what_is
& ARMOR
) && obj
->is_protected
) ? '}' : ')';
724 get_desc(obj
, desc
, sizeof(desc
));
725 messagef(0, "%c%c %s", ch
, ch2
, desc
);
729 get_id_table(const object
*obj
)
731 switch(obj
->what_is
) {
745 return((struct id
*)0);
749 inv_armor_weapon(boolean is_weapon
)
753 single_inv(rogue
.weapon
->ichar
);
755 messagef(0, "not wielding anything");
759 single_inv(rogue
.armor
->ichar
);
761 messagef(0, "not wearing anything");
772 messagef(0, "what do you want identified?");
776 if ((ch
>= 'A') && (ch
<= 'Z')) {
777 id
= m_names
[ch
-'A'];
778 } else if (ch
< 32) {
797 id
= "wall of a room";
818 id
= "wand or staff";
833 id
= "the Amulet of Yendor";
836 id
= "unknown character";
841 messagef(0, "'%c': %s", ch
, id
);