xref: /netbsd/games/rogue/inventory.c (revision 6550d01e)
1 /*	$NetBSD: inventory.c,v 1.14 2009/08/12 08:44:45 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.14 2009/08/12 08:44:45 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 static 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 static 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 static 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 static 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 static int get_com_id(int *, short);
215 static int pr_com_id(int);
216 static int pr_motion_char(int);
217 
218 void
219 inventory(const object *pack, unsigned short mask)
220 {
221 	object *obj;
222 	short i = 0, j;
223 	size_t maxlen = 0, n;
224 	short row, col;
225 
226 	struct {
227 		short letter;
228 		short sepchar;
229 		char desc[DCOLS];
230 		char savebuf[DCOLS+8];
231 	} descs[MAX_PACK_COUNT+1];
232 
233 
234 	obj = pack->next_object;
235 
236 	if (!obj) {
237 		messagef(0, "your pack is empty");
238 		return;
239 	}
240 	while (obj) {
241 		if (obj->what_is & mask) {
242 			descs[i].letter = obj->ichar;
243 			descs[i].sepchar = ((obj->what_is & ARMOR) && obj->is_protected)
244 				? '}' : ')';
245 			get_desc(obj, descs[i].desc, sizeof(descs[i].desc));
246 			n = strlen(descs[i].desc) + 4;
247 			if (n > maxlen) {
248 				maxlen = n;
249 			}
250 			i++;
251 			/*assert(i<=MAX_PACK_COUNT);*/
252 		}
253 		obj = obj->next_object;
254 	}
255 	if (maxlen < 27) maxlen = 27;
256 	if (maxlen > DCOLS-2) maxlen = DCOLS-2;
257 	col = DCOLS - (maxlen + 2);
258 
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);
262 		}
263 		descs[row].savebuf[j-col] = 0;
264 		if (row < i) {
265 			mvprintw(row, col, " %c%c %s",
266 				descs[row].letter, descs[row].sepchar,
267 				descs[row].desc);
268 		}
269 		else {
270 			mvaddstr(row, col, press_space);
271 		}
272 		clrtoeol();
273 	}
274 	refresh();
275 	wait_for_ack();
276 
277 	move(0, 0);
278 	clrtoeol();
279 
280 	for (j = 1; ((j <= i) && (j < DROWS)); j++) {
281 		mvaddstr(j, col, descs[j].savebuf);
282 	}
283 }
284 
285 void
286 id_com(void)
287 {
288 	int ch = 0;
289 	short i, j, k;
290 
291 	while (ch != CANCEL) {
292 		check_message();
293 		messagef(0, "Character you want help for (* for all):");
294 
295 		refresh();
296 		ch = getchar();
297 
298 		switch(ch) {
299 		case LIST:
300 			{
301 				char save[(((COMS / 2) + (COMS % 2)) + 1)][DCOLS];
302 				short rows = (((COMS / 2) + (COMS % 2)) + 1);
303 				boolean need_two_screens = FALSE;
304 
305 				if (rows > LINES) {
306 					need_two_screens = 1;
307 					rows = LINES;
308 				}
309 				k = 0;
310 
311 				for (i = 0; i < rows; i++) {
312 					for (j = 0; j < DCOLS; j++) {
313 						save[i][j] = mvinch(i, j);
314 					}
315 				}
316 MORE:
317 				for (i = 0; i < rows; i++) {
318 					move(i, 0);
319 					clrtoeol();
320 				}
321 				for (i = 0; i < (rows-1); i++) {
322 					if (i < (LINES-1)) {
323 						if (((i + i) < COMS) && ((i+i+k) < COMS)) {
324 							mvaddstr(i, 0, com_id_tab[i+i+k].com_desc);
325 						}
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);
329 						}
330 					}
331 				}
332 				mvaddstr(rows - 1, 0, need_two_screens ? more : press_space);
333 				refresh();
334 				wait_for_ack();
335 
336 				if (need_two_screens) {
337 					k += ((rows-1) * 2);
338 					need_two_screens = 0;
339 					goto MORE;
340 				}
341 				for (i = 0; i < rows; i++) {
342 					move(i, 0);
343 					for (j = 0; j < DCOLS; j++) {
344 						addch(save[i][j]);
345 					}
346 				}
347 			}
348 			break;
349 		default:
350 			if (!pr_com_id(ch)) {
351 				if (!pr_motion_char(ch)) {
352 					check_message();
353 					messagef(0, "unknown character");
354 				}
355 			}
356 			ch = CANCEL;
357 			break;
358 		}
359 	}
360 }
361 
362 static int
363 pr_com_id(int ch)
364 {
365 	int i;
366 
367 	if (!get_com_id(&i, ch)) {
368 		return(0);
369 	}
370 	check_message();
371 	messagef(0, "%s", com_id_tab[i].com_desc);
372 	return(1);
373 }
374 
375 static int
376 get_com_id(int *indexp, short ch)
377 {
378 	short i;
379 
380 	for (i = 0; i < COMS; i++) {
381 		if (com_id_tab[i].com_char == ch) {
382 			*indexp = i;
383 			return(1);
384 		}
385 	}
386 	return(0);
387 }
388 
389 static int
390 pr_motion_char(int ch)
391 {
392 	if (	(ch == 'J') ||
393 			(ch == 'K') ||
394 			(ch == 'L') ||
395 			(ch == 'H') ||
396 			(ch == 'Y') ||
397 			(ch == 'U') ||
398 			(ch == 'N') ||
399 			(ch == 'B') ||
400 			(ch == '\012') ||
401 			(ch == '\013') ||
402 			(ch == '\010') ||
403 			(ch == '\014') ||
404 			(ch == '\025') ||
405 			(ch == '\031') ||
406 			(ch == '\016') ||
407 			(ch == '\002')) {
408 		const char *until;
409 		int n = 0;	/* XXX: GCC */
410 		if (ch <= '\031') {
411 			ch += 96;
412 			until = " until adjacent";
413 		} else {
414 			ch += 32;
415 			until = "";
416 		}
417 		(void)get_com_id(&n, ch);
418 		check_message();
419 		messagef(0, "run %s%s", com_id_tab[n].com_desc + 8, until);
420 		return(1);
421 	} else {
422 		return(0);
423 	}
424 }
425 
426 void
427 mix_colors(void)
428 {
429 	short i, j, k;
430 	char t[MAX_ID_TITLE_LEN];
431 
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));
439 	}
440 }
441 
442 void
443 make_scroll_titles(void)
444 {
445 	short i, j, n;
446 	short sylls, s;
447 	size_t maxlen = sizeof(id_scrolls[0].title);
448 
449 	for (i = 0; i < SCROLS; i++) {
450 		sylls = get_rand(2, 5);
451 		(void)strlcpy(id_scrolls[i].title, "'", maxlen);
452 
453 		for (j = 0; j < sylls; j++) {
454 			s = get_rand(1, (MAXSYLLABLES-1));
455 			(void)strlcat(id_scrolls[i].title, syllables[s],
456 					maxlen);
457 		}
458 		/* trim trailing space */
459 		n = strlen(id_scrolls[i].title);
460 		id_scrolls[i].title[n-1] = 0;
461 
462 		(void)strlcat(id_scrolls[i].title, "' ", maxlen);
463 	}
464 }
465 
466 struct sbuf {
467 	char *buf;
468 	size_t maxlen;
469 };
470 
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 *);
477 
478 static
479 void
480 sbuf_init(struct sbuf *s, char *buf, size_t maxlen)
481 {
482 	s->buf = buf;
483 	s->maxlen = maxlen;
484 	/*assert(maxlen>0);*/
485 	s->buf[0] = 0;
486 }
487 
488 static
489 void
490 sbuf_addstr(struct sbuf *s, const char *str)
491 {
492 	strlcat(s->buf, str, s->maxlen);
493 }
494 
495 static
496 void
497 sbuf_addf(struct sbuf *s, const char *fmt, ...)
498 {
499 	va_list ap;
500 	size_t initlen;
501 
502 	initlen = strlen(s->buf);
503 	va_start(ap, fmt);
504 	vsnprintf(s->buf+initlen, s->maxlen-initlen, fmt, ap);
505 	va_end(ap);
506 }
507 
508 static
509 void
510 desc_count(struct sbuf *s, int n)
511 {
512 	if (n == 1) {
513 		sbuf_addstr(s, "an ");
514 	} else {
515 		sbuf_addf(s, "%d ", n);
516 	}
517 }
518 
519 static
520 void
521 desc_called(struct sbuf *s, const object *obj)
522 {
523 	struct id *id_table;
524 
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);
529 }
530 
531 void
532 get_desc(const object *obj, char *desc, size_t desclen)
533 {
534 	const char *item_name;
535 	struct id *id_table;
536 	struct sbuf db;
537 	unsigned short objtype_id_status;
538 
539 	if (obj->what_is == AMULET) {
540 		(void)strlcpy(desc, "the amulet of Yendor ", desclen);
541 		return;
542 	}
543 
544 	if (obj->what_is == GOLD) {
545 		snprintf(desc, desclen, "%d pieces of gold", obj->quantity);
546 		return;
547 	}
548 
549 	item_name = name_of(obj);
550 	id_table = get_id_table(obj);
551 	if (wizard || id_table == NULL) {
552 		objtype_id_status = IDENTIFIED;
553 	}
554 	else {
555 		objtype_id_status = id_table[obj->which_kind].id_status;
556 	}
557 	if (obj->what_is & (WEAPON | ARMOR | WAND | RING)) {
558 		if (obj->identified) {
559 			objtype_id_status = IDENTIFIED;
560 		}
561 	}
562 
563 	sbuf_init(&db, desc, desclen);
564 
565 	switch (obj->what_is) {
566 	case FOOD:
567 		if (obj->which_kind == RATION) {
568 			if (obj->quantity > 1) {
569 				sbuf_addf(&db,
570 					 "%d rations of %s", obj->quantity,
571 					 item_name);
572 			} else {
573 				sbuf_addf(&db, "some %s", item_name);
574 			}
575 		} else {
576 			sbuf_addf(&db, "an %s", item_name);
577 		}
578 		break;
579 	case SCROL:
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);
587 		} else {
588 			sbuf_addstr(&db, item_name);
589 			sbuf_addstr(&db, id_table[obj->which_kind].real);
590 		}
591 		break;
592 	case POTION:
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);
599 		} else {
600 			sbuf_addstr(&db, item_name);
601 			sbuf_addstr(&db, id_table[obj->which_kind].real);
602 		}
603 		break;
604 	case WAND:
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);
611 		} else {
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);
616 			}
617 		}
618 		break;
619 	case RING:
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);
626 		} else {
627 			if ((wizard || obj->identified) &&
628 			    (obj->which_kind == DEXTERITY ||
629 			     obj->which_kind == ADD_STRENGTH)) {
630 				sbuf_addf(&db, "%+d ", obj->class);
631 			}
632 			sbuf_addstr(&db, item_name);
633 			sbuf_addstr(&db, id_table[obj->which_kind].real);
634 		}
635 		break;
636 	case ARMOR:
637 		/* no desc_count() */
638 		if (objtype_id_status==UNIDENTIFIED) {
639 			sbuf_addstr(&db, id_table[obj->which_kind].title);
640 		} else {
641 			sbuf_addf(&db, "%+d %s[%d] ", obj->d_enchant,
642 				id_table[obj->which_kind].title,
643 				get_armor_class(obj));
644     		}
645 		break;
646 	case WEAPON:
647 		desc_count(&db, obj->quantity);
648 		if (objtype_id_status==UNIDENTIFIED) {
649 			sbuf_addstr(&db, name_of(obj));
650 		} else {
651 			sbuf_addf(&db, "%+d,%+d %s",
652 				obj->hit_enchant, obj->d_enchant,
653 				name_of(obj));
654 		}
655 		break;
656 	}
657 
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");
666 	}
667 
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);
671 			db.buf[1] = ' ';
672 		}
673 	}
674 }
675 
676 void
677 get_wand_and_ring_materials(void)
678 {
679 	short i, j;
680 	boolean used[WAND_MATERIALS];
681 
682 	for (i = 0; i < WAND_MATERIALS; i++) {
683 		used[i] = 0;
684 	}
685 	for (i = 0; i < WANDS; i++) {
686 		do {
687 			j = get_rand(0, WAND_MATERIALS-1);
688 		} while (used[j]);
689 		used[j] = 1;
690 		(void)strlcpy(id_wands[i].title, wand_materials[j],
691 			       sizeof(id_wands[i].title));
692 		is_wood[i] = (j > MAX_METAL);
693 	}
694 	for (i = 0; i < GEMS; i++) {
695 		used[i] = 0;
696 	}
697 	for (i = 0; i < RINGS; i++) {
698 		do {
699 			j = get_rand(0, GEMS-1);
700 		} while (used[j]);
701 		used[j] = 1;
702 		(void)strlcpy(id_rings[i].title, gems[j],
703 			       sizeof(id_rings[i].title));
704 	}
705 }
706 
707 void
708 single_inv(short ichar)
709 {
710 	short ch, ch2;
711 	char desc[DCOLS];
712 	object *obj;
713 
714 	ch = ichar ? ichar : pack_letter("inventory what?", ALL_OBJECTS);
715 
716 	if (ch == CANCEL) {
717 		return;
718 	}
719 	if (!(obj = get_letter_object(ch))) {
720 		messagef(0, "no such item.");
721 		return;
722 	}
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);
726 }
727 
728 struct id *
729 get_id_table(const object *obj)
730 {
731 	switch(obj->what_is) {
732 	case SCROL:
733 		return(id_scrolls);
734 	case POTION:
735 		return(id_potions);
736 	case WAND:
737 		return(id_wands);
738 	case RING:
739 		return(id_rings);
740 	case WEAPON:
741 		return(id_weapons);
742 	case ARMOR:
743 		return(id_armors);
744 	}
745 	return((struct id *)0);
746 }
747 
748 void
749 inv_armor_weapon(boolean is_weapon)
750 {
751 	if (is_weapon) {
752 		if (rogue.weapon) {
753 			single_inv(rogue.weapon->ichar);
754 		} else {
755 			messagef(0, "not wielding anything");
756 		}
757 	} else {
758 		if (rogue.armor) {
759 			single_inv(rogue.armor->ichar);
760 		} else {
761 			messagef(0, "not wearing anything");
762 		}
763 	}
764 }
765 
766 void
767 id_type(void)
768 {
769 	const char *id;
770 	int ch;
771 
772 	messagef(0, "what do you want identified?");
773 
774 	ch = rgetchar();
775 
776 	if ((ch >= 'A') && (ch <= 'Z')) {
777 		id = m_names[ch-'A'];
778 	} else if (ch < 32) {
779 		check_message();
780 		return;
781 	} else {
782 		switch(ch) {
783 		case '@':
784 			id = "you";
785 			break;
786 		case '%':
787 			id = "staircase";
788 			break;
789 		case '^':
790 			id = "trap";
791 			break;
792 		case '+':
793 			id = "door";
794 			break;
795 		case '-':
796 		case '|':
797 			id = "wall of a room";
798 			break;
799 		case '.':
800 			id = "floor";
801 			break;
802 		case '#':
803 			id = "passage";
804 			break;
805 		case ' ':
806 			id = "solid rock";
807 			break;
808 		case '=':
809 			id = "ring";
810 			break;
811 		case '?':
812 			id = "scroll";
813 			break;
814 		case '!':
815 			id = "potion";
816 			break;
817 		case '/':
818 			id = "wand or staff";
819 			break;
820 		case ')':
821 			id = "weapon";
822 			break;
823 		case ']':
824 			id = "armor";
825 			break;
826 		case '*':
827 			id = "gold";
828 			break;
829 		case ':':
830 			id = "food";
831 			break;
832 		case ',':
833 			id = "the Amulet of Yendor";
834 			break;
835 		default:
836 			id = "unknown character";
837 			break;
838 		}
839 	}
840 	check_message();
841 	messagef(0, "'%c': %s", ch, id);
842 }
843