Home | History | Annotate | Line # | Download | only in rogue
inventory.c revision 1.12
      1 /*	$NetBSD: inventory.c,v 1.12 2008/01/14 00:23:51 dholland Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1988, 1993
      5  *	The Regents of the University of California.  All rights reserved.
      6  *
      7  * This code is derived from software contributed to Berkeley by
      8  * Timothy C. Stoehr.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     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.
     21  *
     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
     32  * SUCH DAMAGE.
     33  */
     34 
     35 #include <sys/cdefs.h>
     36 #ifndef lint
     37 #if 0
     38 static char sccsid[] = "@(#)inventory.c	8.1 (Berkeley) 5/31/93";
     39 #else
     40 __RCSID("$NetBSD: inventory.c,v 1.12 2008/01/14 00:23:51 dholland Exp $");
     41 #endif
     42 #endif /* not lint */
     43 
     44 /*
     45  * inventory.c
     46  *
     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
     52  *         gain or profit.
     53  *
     54  */
     55 
     56 #include <stdarg.h>
     57 #include "rogue.h"
     58 
     59 boolean is_wood[WANDS];
     60 const char *press_space = " --press space to continue--";
     61 
     62 const char *const wand_materials[WAND_MATERIALS] = {
     63 	"steel ",
     64 	"bronze ",
     65 	"gold ",
     66 	"silver ",
     67 	"copper ",
     68 	"nickel ",
     69 	"cobalt ",
     70 	"tin ",
     71 	"iron ",
     72 	"magnesium ",
     73 	"chrome ",
     74 	"carbon ",
     75 	"platinum ",
     76 	"silicon ",
     77 	"titanium ",
     78 
     79 	"teak ",
     80 	"oak ",
     81 	"cherry ",
     82 	"birch ",
     83 	"pine ",
     84 	"cedar ",
     85 	"redwood ",
     86 	"balsa ",
     87 	"ivory ",
     88 	"walnut ",
     89 	"maple ",
     90 	"mahogany ",
     91 	"elm ",
     92 	"palm ",
     93 	"wooden "
     94 };
     95 
     96 const char *const gems[GEMS] = {
     97 	"diamond ",
     98 	"stibotantalite ",
     99 	"lapi-lazuli ",
    100 	"ruby ",
    101 	"emerald ",
    102 	"sapphire ",
    103 	"amethyst ",
    104 	"quartz ",
    105 	"tiger-eye ",
    106 	"opal ",
    107 	"agate ",
    108 	"turquoise ",
    109 	"pearl ",
    110 	"garnet "
    111 };
    112 
    113 const char *const syllables[MAXSYLLABLES] = {
    114 	"blech ",
    115 	"foo ",
    116 	"barf ",
    117 	"rech ",
    118 	"bar ",
    119 	"blech ",
    120 	"quo ",
    121 	"bloto ",
    122 	"oh ",
    123 	"caca ",
    124 	"blorp ",
    125 	"erp ",
    126 	"festr ",
    127 	"rot ",
    128 	"slie ",
    129 	"snorf ",
    130 	"iky ",
    131 	"yuky ",
    132 	"ooze ",
    133 	"ah ",
    134 	"bahl ",
    135 	"zep ",
    136 	"druhl ",
    137 	"flem ",
    138 	"behil ",
    139 	"arek ",
    140 	"mep ",
    141 	"zihr ",
    142 	"grit ",
    143 	"kona ",
    144 	"kini ",
    145 	"ichi ",
    146 	"tims ",
    147 	"ogr ",
    148 	"oo ",
    149 	"ighr ",
    150 	"coph ",
    151 	"swerr ",
    152 	"mihln ",
    153 	"poxi "
    154 };
    155 
    156 #define COMS 48
    157 
    158 struct id_com_s {
    159 	short com_char;
    160 	const char *com_desc;
    161 };
    162 
    163 const struct id_com_s com_id_tab[COMS] = {
    164 	{'?',	"?       prints help"},
    165 	{'r',	"r       read scroll"},
    166 	{'/',	"/       identify object"},
    167 	{'e',	"e       eat food"},
    168 	{'h',	"h       left "},
    169 	{'w',	"w       wield a weapon"},
    170 	{'j',	"j       down"},
    171 	{'W',	"W       wear armor"},
    172 	{'k',	"k       up"},
    173 	{'T',	"T       take armor off"},
    174 	{'l',	"l       right"},
    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"},
    204 	{'Q',	"Q       quit"},
    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" }
    212 };
    213 
    214 void
    215 inventory(pack, mask)
    216 	const object *pack;
    217 	unsigned short mask;
    218 {
    219 	object *obj;
    220 	short i = 0, j;
    221 	size_t maxlen = 0, n;
    222 	short row, col;
    223 
    224 	struct {
    225 		short letter;
    226 		short sepchar;
    227 		char desc[DCOLS];
    228 		char savebuf[DCOLS+8];
    229 	} descs[MAX_PACK_COUNT+1];
    230 
    231 
    232 	obj = pack->next_object;
    233 
    234 	if (!obj) {
    235 		messagef(0, "your pack is empty");
    236 		return;
    237 	}
    238 	while (obj) {
    239 		if (obj->what_is & mask) {
    240 			descs[i].letter = obj->ichar;
    241 			descs[i].sepchar = ((obj->what_is & ARMOR) && obj->is_protected)
    242 				? '}' : ')';
    243 			get_desc(obj, descs[i].desc, sizeof(descs[i].desc));
    244 			n = strlen(descs[i].desc) + 4;
    245 			if (n > maxlen) {
    246 				maxlen = n;
    247 			}
    248 			i++;
    249 			/*assert(i<=MAX_PACK_COUNT);*/
    250 		}
    251 		obj = obj->next_object;
    252 	}
    253 	if (maxlen < 27) maxlen = 27;
    254 	if (maxlen > DCOLS-2) maxlen = DCOLS-2;
    255 	col = DCOLS - (maxlen + 2);
    256 
    257 	for (row = 0; ((row <= i) && (row < DROWS)); row++) {
    258 		for (j = col; j < DCOLS; j++) {
    259 			descs[row].savebuf[j-col] = mvinch(row, j);
    260 		}
    261 		descs[row].savebuf[j-col] = 0;
    262 		if (row < i) {
    263 			mvprintw(row, col, " %c%c %s",
    264 				descs[row].letter, descs[row].sepchar,
    265 				descs[row].desc);
    266 		}
    267 		else {
    268 			mvaddstr(row, col, press_space);
    269 		}
    270 		clrtoeol();
    271 	}
    272 	refresh();
    273 	wait_for_ack();
    274 
    275 	move(0, 0);
    276 	clrtoeol();
    277 
    278 	for (j = 1; ((j <= i) && (j < DROWS)); j++) {
    279 		mvaddstr(j, col, descs[j].savebuf);
    280 	}
    281 }
    282 
    283 void
    284 id_com()
    285 {
    286 	int ch = 0;
    287 	short i, j, k;
    288 
    289 	while (ch != CANCEL) {
    290 		check_message();
    291 		messagef(0, "Character you want help for (* for all):");
    292 
    293 		refresh();
    294 		ch = getchar();
    295 
    296 		switch(ch) {
    297 		case LIST:
    298 			{
    299 				char save[(((COMS / 2) + (COMS % 2)) + 1)][DCOLS];
    300 				short rows = (((COMS / 2) + (COMS % 2)) + 1);
    301 				boolean need_two_screens = FALSE;
    302 
    303 				if (rows > LINES) {
    304 					need_two_screens = 1;
    305 					rows = LINES;
    306 				}
    307 				k = 0;
    308 
    309 				for (i = 0; i < rows; i++) {
    310 					for (j = 0; j < DCOLS; j++) {
    311 						save[i][j] = mvinch(i, j);
    312 					}
    313 				}
    314 MORE:
    315 				for (i = 0; i < rows; i++) {
    316 					move(i, 0);
    317 					clrtoeol();
    318 				}
    319 				for (i = 0; i < (rows-1); i++) {
    320 					if (i < (LINES-1)) {
    321 						if (((i + i) < COMS) && ((i+i+k) < COMS)) {
    322 							mvaddstr(i, 0, com_id_tab[i+i+k].com_desc);
    323 						}
    324 						if (((i + i + 1) < COMS) && ((i+i+k+1) < COMS)) {
    325 							mvaddstr(i, (DCOLS/2),
    326 										com_id_tab[i+i+k+1].com_desc);
    327 						}
    328 					}
    329 				}
    330 				mvaddstr(rows - 1, 0, need_two_screens ? more : press_space);
    331 				refresh();
    332 				wait_for_ack();
    333 
    334 				if (need_two_screens) {
    335 					k += ((rows-1) * 2);
    336 					need_two_screens = 0;
    337 					goto MORE;
    338 				}
    339 				for (i = 0; i < rows; i++) {
    340 					move(i, 0);
    341 					for (j = 0; j < DCOLS; j++) {
    342 						addch(save[i][j]);
    343 					}
    344 				}
    345 			}
    346 			break;
    347 		default:
    348 			if (!pr_com_id(ch)) {
    349 				if (!pr_motion_char(ch)) {
    350 					check_message();
    351 					messagef(0, "unknown character");
    352 				}
    353 			}
    354 			ch = CANCEL;
    355 			break;
    356 		}
    357 	}
    358 }
    359 
    360 int
    361 pr_com_id(ch)
    362 	int ch;
    363 {
    364 	int i;
    365 
    366 	if (!get_com_id(&i, ch)) {
    367 		return(0);
    368 	}
    369 	check_message();
    370 	messagef(0, "%s", com_id_tab[i].com_desc);
    371 	return(1);
    372 }
    373 
    374 int
    375 get_com_id(indexp, ch)
    376 	int *indexp;
    377 	short ch;
    378 {
    379 	short i;
    380 
    381 	for (i = 0; i < COMS; i++) {
    382 		if (com_id_tab[i].com_char == ch) {
    383 			*indexp = i;
    384 			return(1);
    385 		}
    386 	}
    387 	return(0);
    388 }
    389 
    390 int
    391 pr_motion_char(ch)
    392 	int ch;
    393 {
    394 	if (	(ch == 'J') ||
    395 			(ch == 'K') ||
    396 			(ch == 'L') ||
    397 			(ch == 'H') ||
    398 			(ch == 'Y') ||
    399 			(ch == 'U') ||
    400 			(ch == 'N') ||
    401 			(ch == 'B') ||
    402 			(ch == '\012') ||
    403 			(ch == '\013') ||
    404 			(ch == '\010') ||
    405 			(ch == '\014') ||
    406 			(ch == '\025') ||
    407 			(ch == '\031') ||
    408 			(ch == '\016') ||
    409 			(ch == '\002')) {
    410 		const char *until;
    411 		int n = 0;	/* XXX: GCC */
    412 		if (ch <= '\031') {
    413 			ch += 96;
    414 			until = " until adjacent";
    415 		} else {
    416 			ch += 32;
    417 			until = "";
    418 		}
    419 		(void)get_com_id(&n, ch);
    420 		check_message();
    421 		messagef(0, "run %s%s", com_id_tab[n].com_desc + 8, until);
    422 		return(1);
    423 	} else {
    424 		return(0);
    425 	}
    426 }
    427 
    428 void
    429 mix_colors()
    430 {
    431 	short i, j, k;
    432 	char t[MAX_ID_TITLE_LEN];
    433 
    434 	for (i = 0; i <= 32; i++) {
    435 		j = get_rand(0, (POTIONS - 1));
    436 		k = get_rand(0, (POTIONS - 1));
    437 		strlcpy(t, id_potions[j].title, sizeof(t));
    438 		strlcpy(id_potions[j].title, id_potions[k].title,
    439 			sizeof(id_potions[j].title));
    440 		strlcpy(id_potions[k].title, t, sizeof(id_potions[k].title));
    441 	}
    442 }
    443 
    444 void
    445 make_scroll_titles()
    446 {
    447 	short i, j, n;
    448 	short sylls, s;
    449 	size_t maxlen = sizeof(id_scrolls[0].title);
    450 
    451 	for (i = 0; i < SCROLS; i++) {
    452 		sylls = get_rand(2, 5);
    453 		(void)strlcpy(id_scrolls[i].title, "'", maxlen);
    454 
    455 		for (j = 0; j < sylls; j++) {
    456 			s = get_rand(1, (MAXSYLLABLES-1));
    457 			(void)strlcat(id_scrolls[i].title, syllables[s],
    458 					maxlen);
    459 		}
    460 		/* trim trailing space */
    461 		n = strlen(id_scrolls[i].title);
    462 		id_scrolls[i].title[n-1] = 0;
    463 
    464 		(void)strlcat(id_scrolls[i].title, "' ", maxlen);
    465 	}
    466 }
    467 
    468 struct sbuf {
    469 	char *buf;
    470 	size_t maxlen;
    471 };
    472 
    473 static void sbuf_init __P((struct sbuf *s, char *buf, size_t maxlen));
    474 static void sbuf_addstr __P((struct sbuf *s, const char *str));
    475 static void sbuf_addf __P((struct sbuf *s, const char *fmt, ...));
    476 static void desc_count __P((struct sbuf *s, int n));
    477 static void desc_called __P((struct sbuf *s, const object *));
    478 
    479 static
    480 void
    481 sbuf_init(s, buf, maxlen)
    482 	struct sbuf *s;
    483 	char *buf;
    484 	size_t maxlen;
    485 {
    486 	s->buf = buf;
    487 	s->maxlen = maxlen;
    488 	/*assert(maxlen>0);*/
    489 	s->buf[0] = 0;
    490 }
    491 
    492 static
    493 void
    494 sbuf_addstr(s, str)
    495 	struct sbuf *s;
    496 	const char *str;
    497 {
    498 	strlcat(s->buf, str, s->maxlen);
    499 }
    500 
    501 static void sbuf_addf(struct sbuf *s, const char *fmt, ...)
    502 	__attribute__((__format__(__printf__, 2, 3)));
    503 
    504 static
    505 void
    506 sbuf_addf(struct sbuf *s, const char *fmt, ...)
    507 {
    508 	va_list ap;
    509 	size_t initlen;
    510 
    511 	initlen = strlen(s->buf);
    512 	va_start(ap, fmt);
    513 	vsnprintf(s->buf+initlen, s->maxlen-initlen, fmt, ap);
    514 	va_end(ap);
    515 }
    516 
    517 static
    518 void
    519 desc_count(s, n)
    520 	struct sbuf *s;
    521 	int n;
    522 {
    523 	if (n == 1) {
    524 		sbuf_addstr(s, "an ");
    525 	} else {
    526 		sbuf_addf(s, "%d ", n);
    527 	}
    528 }
    529 
    530 static
    531 void
    532 desc_called(s, obj)
    533 	struct sbuf *s;
    534 	const object *obj;
    535 {
    536 	struct id *id_table;
    537 
    538 	id_table = get_id_table(obj);
    539 	sbuf_addstr(s, name_of(obj));
    540 	sbuf_addstr(s, "called ");
    541 	sbuf_addstr(s, id_table[obj->which_kind].title);
    542 }
    543 
    544 void
    545 get_desc(obj, desc, desclen)
    546 	const object *obj;
    547 	char *desc;
    548 	size_t desclen;
    549 {
    550 	const char *item_name;
    551 	struct id *id_table;
    552 	struct sbuf db;
    553 	unsigned short objtype_id_status;
    554 
    555 	if (obj->what_is == AMULET) {
    556 		(void)strlcpy(desc, "the amulet of Yendor ", desclen);
    557 		return;
    558 	}
    559 
    560 	if (obj->what_is == GOLD) {
    561 		snprintf(desc, desclen, "%d pieces of gold", obj->quantity);
    562 		return;
    563 	}
    564 
    565 	item_name = name_of(obj);
    566 	id_table = get_id_table(obj);
    567 	if (wizard || id_table == NULL) {
    568 		objtype_id_status = IDENTIFIED;
    569 	}
    570 	else {
    571 		objtype_id_status = id_table[obj->which_kind].id_status;
    572 	}
    573 	if (obj->what_is & (WEAPON | ARMOR | WAND | RING)) {
    574 		if (obj->identified) {
    575 			objtype_id_status = IDENTIFIED;
    576 		}
    577 	}
    578 
    579 	sbuf_init(&db, desc, desclen);
    580 
    581 	switch (obj->what_is) {
    582 	case FOOD:
    583 		if (obj->which_kind == RATION) {
    584 			if (obj->quantity > 1) {
    585 				sbuf_addf(&db,
    586 					 "%d rations of %s", obj->quantity,
    587 					 item_name);
    588 			} else {
    589 				sbuf_addf(&db, "some %s", item_name);
    590 			}
    591 		} else {
    592 			sbuf_addf(&db, "an %s", item_name);
    593 		}
    594 		break;
    595 	case SCROL:
    596 		desc_count(&db, obj->quantity);
    597 		if (objtype_id_status==UNIDENTIFIED) {
    598 			sbuf_addstr(&db, item_name);
    599 			sbuf_addstr(&db, "entitled: ");
    600 			sbuf_addstr(&db, id_table[obj->which_kind].title);
    601 		} else if (objtype_id_status==CALLED) {
    602 			desc_called(&db, obj);
    603 		} else {
    604 			sbuf_addstr(&db, item_name);
    605 			sbuf_addstr(&db, id_table[obj->which_kind].real);
    606 		}
    607 		break;
    608 	case POTION:
    609 		desc_count(&db, obj->quantity);
    610 		if (objtype_id_status==UNIDENTIFIED) {
    611 			sbuf_addstr(&db, id_table[obj->which_kind].title);
    612 			sbuf_addstr(&db, item_name);
    613 		} else if (objtype_id_status==CALLED) {
    614 			desc_called(&db, obj);
    615 		} else {
    616 			sbuf_addstr(&db, item_name);
    617 			sbuf_addstr(&db, id_table[obj->which_kind].real);
    618 		}
    619 		break;
    620 	case WAND:
    621 		desc_count(&db, obj->quantity);
    622 		if (objtype_id_status==UNIDENTIFIED) {
    623 			sbuf_addstr(&db, id_table[obj->which_kind].title);
    624 			sbuf_addstr(&db, item_name);
    625 		} else if (objtype_id_status==CALLED) {
    626 			desc_called(&db, obj);
    627 		} else {
    628 			sbuf_addstr(&db, item_name);
    629 			sbuf_addstr(&db, id_table[obj->which_kind].real);
    630 			if (wizard || obj->identified) {
    631 				sbuf_addf(&db, "[%d]", obj->class);
    632 			}
    633 		}
    634 		break;
    635 	case RING:
    636 		desc_count(&db, obj->quantity);
    637 		if (objtype_id_status==UNIDENTIFIED) {
    638 			sbuf_addstr(&db, id_table[obj->which_kind].title);
    639 			sbuf_addstr(&db, item_name);
    640 		} else if (objtype_id_status==CALLED) {
    641 			desc_called(&db, obj);
    642 		} else {
    643 			if ((wizard || obj->identified) &&
    644 			    (obj->which_kind == DEXTERITY ||
    645 			     obj->which_kind == ADD_STRENGTH)) {
    646 				sbuf_addf(&db, "%+d ", obj->class);
    647 			}
    648 			sbuf_addstr(&db, item_name);
    649 			sbuf_addstr(&db, id_table[obj->which_kind].real);
    650 		}
    651 		break;
    652 	case ARMOR:
    653 		/* no desc_count() */
    654 		if (objtype_id_status==UNIDENTIFIED) {
    655 			sbuf_addstr(&db, id_table[obj->which_kind].title);
    656 		} else {
    657 			sbuf_addf(&db, "%+d %s[%d] ", obj->d_enchant,
    658 				id_table[obj->which_kind].title,
    659 				get_armor_class(obj));
    660     		}
    661 		break;
    662 	case WEAPON:
    663 		desc_count(&db, obj->quantity);
    664 		if (objtype_id_status==UNIDENTIFIED) {
    665 			sbuf_addstr(&db, name_of(obj));
    666 		} else {
    667 			sbuf_addf(&db, "%+d,%+d %s",
    668 				obj->hit_enchant, obj->d_enchant,
    669 				name_of(obj));
    670 		}
    671 		break;
    672 	}
    673 
    674 	if (obj->in_use_flags & BEING_WIELDED) {
    675 		sbuf_addstr(&db, "in hand");
    676 	} else if (obj->in_use_flags & BEING_WORN) {
    677 		sbuf_addstr(&db, "being worn");
    678 	} else if (obj->in_use_flags & ON_LEFT_HAND) {
    679 		sbuf_addstr(&db, "on left hand");
    680 	} else if (obj->in_use_flags & ON_RIGHT_HAND) {
    681 		sbuf_addstr(&db, "on right hand");
    682 	}
    683 
    684 	if (!strncmp(db.buf, "an ", 3)) {
    685 		if (!is_vowel(db.buf[3])) {
    686 			memmove(db.buf+2, db.buf+3, strlen(db.buf+3)+1);
    687 			db.buf[1] = ' ';
    688 		}
    689 	}
    690 }
    691 
    692 void
    693 get_wand_and_ring_materials()
    694 {
    695 	short i, j;
    696 	boolean used[WAND_MATERIALS];
    697 
    698 	for (i = 0; i < WAND_MATERIALS; i++) {
    699 		used[i] = 0;
    700 	}
    701 	for (i = 0; i < WANDS; i++) {
    702 		do {
    703 			j = get_rand(0, WAND_MATERIALS-1);
    704 		} while (used[j]);
    705 		used[j] = 1;
    706 		(void)strlcpy(id_wands[i].title, wand_materials[j],
    707 			       sizeof(id_wands[i].title));
    708 		is_wood[i] = (j > MAX_METAL);
    709 	}
    710 	for (i = 0; i < GEMS; i++) {
    711 		used[i] = 0;
    712 	}
    713 	for (i = 0; i < RINGS; i++) {
    714 		do {
    715 			j = get_rand(0, GEMS-1);
    716 		} while (used[j]);
    717 		used[j] = 1;
    718 		(void)strlcpy(id_rings[i].title, gems[j],
    719 			       sizeof(id_rings[i].title));
    720 	}
    721 }
    722 
    723 void
    724 single_inv(ichar)
    725 	short ichar;
    726 {
    727 	short ch, ch2;
    728 	char desc[DCOLS];
    729 	object *obj;
    730 
    731 	ch = ichar ? ichar : pack_letter("inventory what?", ALL_OBJECTS);
    732 
    733 	if (ch == CANCEL) {
    734 		return;
    735 	}
    736 	if (!(obj = get_letter_object(ch))) {
    737 		messagef(0, "no such item.");
    738 		return;
    739 	}
    740 	ch2 = ((obj->what_is & ARMOR) && obj->is_protected) ? '}' : ')';
    741 	get_desc(obj, desc, sizeof(desc));
    742 	messagef(0, "%c%c %s", ch, ch2, desc);
    743 }
    744 
    745 struct id *
    746 get_id_table(obj)
    747 	const object *obj;
    748 {
    749 	switch(obj->what_is) {
    750 	case SCROL:
    751 		return(id_scrolls);
    752 	case POTION:
    753 		return(id_potions);
    754 	case WAND:
    755 		return(id_wands);
    756 	case RING:
    757 		return(id_rings);
    758 	case WEAPON:
    759 		return(id_weapons);
    760 	case ARMOR:
    761 		return(id_armors);
    762 	}
    763 	return((struct id *)0);
    764 }
    765 
    766 void
    767 inv_armor_weapon(is_weapon)
    768 	boolean is_weapon;
    769 {
    770 	if (is_weapon) {
    771 		if (rogue.weapon) {
    772 			single_inv(rogue.weapon->ichar);
    773 		} else {
    774 			messagef(0, "not wielding anything");
    775 		}
    776 	} else {
    777 		if (rogue.armor) {
    778 			single_inv(rogue.armor->ichar);
    779 		} else {
    780 			messagef(0, "not wearing anything");
    781 		}
    782 	}
    783 }
    784 
    785 void
    786 id_type()
    787 {
    788 	const char *id;
    789 	int ch;
    790 
    791 	messagef(0, "what do you want identified?");
    792 
    793 	ch = rgetchar();
    794 
    795 	if ((ch >= 'A') && (ch <= 'Z')) {
    796 		id = m_names[ch-'A'];
    797 	} else if (ch < 32) {
    798 		check_message();
    799 		return;
    800 	} else {
    801 		switch(ch) {
    802 		case '@':
    803 			id = "you";
    804 			break;
    805 		case '%':
    806 			id = "staircase";
    807 			break;
    808 		case '^':
    809 			id = "trap";
    810 			break;
    811 		case '+':
    812 			id = "door";
    813 			break;
    814 		case '-':
    815 		case '|':
    816 			id = "wall of a room";
    817 			break;
    818 		case '.':
    819 			id = "floor";
    820 			break;
    821 		case '#':
    822 			id = "passage";
    823 			break;
    824 		case ' ':
    825 			id = "solid rock";
    826 			break;
    827 		case '=':
    828 			id = "ring";
    829 			break;
    830 		case '?':
    831 			id = "scroll";
    832 			break;
    833 		case '!':
    834 			id = "potion";
    835 			break;
    836 		case '/':
    837 			id = "wand or staff";
    838 			break;
    839 		case ')':
    840 			id = "weapon";
    841 			break;
    842 		case ']':
    843 			id = "armor";
    844 			break;
    845 		case '*':
    846 			id = "gold";
    847 			break;
    848 		case ':':
    849 			id = "food";
    850 			break;
    851 		case ',':
    852 			id = "the Amulet of Yendor";
    853 			break;
    854 		default:
    855 			id = "unknown character";
    856 			break;
    857 		}
    858 	}
    859 	check_message();
    860 	messagef(0, "'%c': %s", ch, id);
    861 }
    862