xref: /netbsd/games/rogue/inventory.c (revision 70862b7a)
1 /*	$NetBSD: inventory.c,v 1.15 2011/08/26 06:18:17 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.15 2011/08/26 06:18:17 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
inventory(const object * pack,unsigned short mask)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
id_com(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
pr_com_id(int ch)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
get_com_id(int * indexp,short ch)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
pr_motion_char(int ch)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
mix_colors(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
make_scroll_titles(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, ...) __printflike(2,3);
474 static void desc_count(struct sbuf *s, int n);
475 static void desc_called(struct sbuf *s, const object *);
476 
477 static
478 void
sbuf_init(struct sbuf * s,char * buf,size_t maxlen)479 sbuf_init(struct sbuf *s, char *buf, size_t maxlen)
480 {
481 	s->buf = buf;
482 	s->maxlen = maxlen;
483 	/*assert(maxlen>0);*/
484 	s->buf[0] = 0;
485 }
486 
487 static
488 void
sbuf_addstr(struct sbuf * s,const char * str)489 sbuf_addstr(struct sbuf *s, const char *str)
490 {
491 	strlcat(s->buf, str, s->maxlen);
492 }
493 
494 static
495 void
sbuf_addf(struct sbuf * s,const char * fmt,...)496 sbuf_addf(struct sbuf *s, const char *fmt, ...)
497 {
498 	va_list ap;
499 	size_t initlen;
500 
501 	initlen = strlen(s->buf);
502 	va_start(ap, fmt);
503 	vsnprintf(s->buf+initlen, s->maxlen-initlen, fmt, ap);
504 	va_end(ap);
505 }
506 
507 static
508 void
desc_count(struct sbuf * s,int n)509 desc_count(struct sbuf *s, int n)
510 {
511 	if (n == 1) {
512 		sbuf_addstr(s, "an ");
513 	} else {
514 		sbuf_addf(s, "%d ", n);
515 	}
516 }
517 
518 static
519 void
desc_called(struct sbuf * s,const object * obj)520 desc_called(struct sbuf *s, const object *obj)
521 {
522 	struct id *id_table;
523 
524 	id_table = get_id_table(obj);
525 	sbuf_addstr(s, name_of(obj));
526 	sbuf_addstr(s, "called ");
527 	sbuf_addstr(s, id_table[obj->which_kind].title);
528 }
529 
530 void
get_desc(const object * obj,char * desc,size_t desclen)531 get_desc(const object *obj, char *desc, size_t desclen)
532 {
533 	const char *item_name;
534 	struct id *id_table;
535 	struct sbuf db;
536 	unsigned short objtype_id_status;
537 
538 	if (obj->what_is == AMULET) {
539 		(void)strlcpy(desc, "the amulet of Yendor ", desclen);
540 		return;
541 	}
542 
543 	if (obj->what_is == GOLD) {
544 		snprintf(desc, desclen, "%d pieces of gold", obj->quantity);
545 		return;
546 	}
547 
548 	item_name = name_of(obj);
549 	id_table = get_id_table(obj);
550 	if (wizard || id_table == NULL) {
551 		objtype_id_status = IDENTIFIED;
552 	}
553 	else {
554 		objtype_id_status = id_table[obj->which_kind].id_status;
555 	}
556 	if (obj->what_is & (WEAPON | ARMOR | WAND | RING)) {
557 		if (obj->identified) {
558 			objtype_id_status = IDENTIFIED;
559 		}
560 	}
561 
562 	sbuf_init(&db, desc, desclen);
563 
564 	switch (obj->what_is) {
565 	case FOOD:
566 		if (obj->which_kind == RATION) {
567 			if (obj->quantity > 1) {
568 				sbuf_addf(&db,
569 					 "%d rations of %s", obj->quantity,
570 					 item_name);
571 			} else {
572 				sbuf_addf(&db, "some %s", item_name);
573 			}
574 		} else {
575 			sbuf_addf(&db, "an %s", item_name);
576 		}
577 		break;
578 	case SCROL:
579 		desc_count(&db, obj->quantity);
580 		if (objtype_id_status==UNIDENTIFIED) {
581 			sbuf_addstr(&db, item_name);
582 			sbuf_addstr(&db, "entitled: ");
583 			sbuf_addstr(&db, id_table[obj->which_kind].title);
584 		} else if (objtype_id_status==CALLED) {
585 			desc_called(&db, obj);
586 		} else {
587 			sbuf_addstr(&db, item_name);
588 			sbuf_addstr(&db, id_table[obj->which_kind].real);
589 		}
590 		break;
591 	case POTION:
592 		desc_count(&db, obj->quantity);
593 		if (objtype_id_status==UNIDENTIFIED) {
594 			sbuf_addstr(&db, id_table[obj->which_kind].title);
595 			sbuf_addstr(&db, item_name);
596 		} else if (objtype_id_status==CALLED) {
597 			desc_called(&db, obj);
598 		} else {
599 			sbuf_addstr(&db, item_name);
600 			sbuf_addstr(&db, id_table[obj->which_kind].real);
601 		}
602 		break;
603 	case WAND:
604 		desc_count(&db, obj->quantity);
605 		if (objtype_id_status==UNIDENTIFIED) {
606 			sbuf_addstr(&db, id_table[obj->which_kind].title);
607 			sbuf_addstr(&db, item_name);
608 		} else if (objtype_id_status==CALLED) {
609 			desc_called(&db, obj);
610 		} else {
611 			sbuf_addstr(&db, item_name);
612 			sbuf_addstr(&db, id_table[obj->which_kind].real);
613 			if (wizard || obj->identified) {
614 				sbuf_addf(&db, "[%d]", obj->class);
615 			}
616 		}
617 		break;
618 	case RING:
619 		desc_count(&db, obj->quantity);
620 		if (objtype_id_status==UNIDENTIFIED) {
621 			sbuf_addstr(&db, id_table[obj->which_kind].title);
622 			sbuf_addstr(&db, item_name);
623 		} else if (objtype_id_status==CALLED) {
624 			desc_called(&db, obj);
625 		} else {
626 			if ((wizard || obj->identified) &&
627 			    (obj->which_kind == DEXTERITY ||
628 			     obj->which_kind == ADD_STRENGTH)) {
629 				sbuf_addf(&db, "%+d ", obj->class);
630 			}
631 			sbuf_addstr(&db, item_name);
632 			sbuf_addstr(&db, id_table[obj->which_kind].real);
633 		}
634 		break;
635 	case ARMOR:
636 		/* no desc_count() */
637 		if (objtype_id_status==UNIDENTIFIED) {
638 			sbuf_addstr(&db, id_table[obj->which_kind].title);
639 		} else {
640 			sbuf_addf(&db, "%+d %s[%d] ", obj->d_enchant,
641 				id_table[obj->which_kind].title,
642 				get_armor_class(obj));
643     		}
644 		break;
645 	case WEAPON:
646 		desc_count(&db, obj->quantity);
647 		if (objtype_id_status==UNIDENTIFIED) {
648 			sbuf_addstr(&db, name_of(obj));
649 		} else {
650 			sbuf_addf(&db, "%+d,%+d %s",
651 				obj->hit_enchant, obj->d_enchant,
652 				name_of(obj));
653 		}
654 		break;
655 	}
656 
657 	if (obj->in_use_flags & BEING_WIELDED) {
658 		sbuf_addstr(&db, "in hand");
659 	} else if (obj->in_use_flags & BEING_WORN) {
660 		sbuf_addstr(&db, "being worn");
661 	} else if (obj->in_use_flags & ON_LEFT_HAND) {
662 		sbuf_addstr(&db, "on left hand");
663 	} else if (obj->in_use_flags & ON_RIGHT_HAND) {
664 		sbuf_addstr(&db, "on right hand");
665 	}
666 
667 	if (!strncmp(db.buf, "an ", 3)) {
668 		if (!is_vowel(db.buf[3])) {
669 			memmove(db.buf+2, db.buf+3, strlen(db.buf+3)+1);
670 			db.buf[1] = ' ';
671 		}
672 	}
673 }
674 
675 void
get_wand_and_ring_materials(void)676 get_wand_and_ring_materials(void)
677 {
678 	short i, j;
679 	boolean used[WAND_MATERIALS];
680 
681 	for (i = 0; i < WAND_MATERIALS; i++) {
682 		used[i] = 0;
683 	}
684 	for (i = 0; i < WANDS; i++) {
685 		do {
686 			j = get_rand(0, WAND_MATERIALS-1);
687 		} while (used[j]);
688 		used[j] = 1;
689 		(void)strlcpy(id_wands[i].title, wand_materials[j],
690 			       sizeof(id_wands[i].title));
691 		is_wood[i] = (j > MAX_METAL);
692 	}
693 	for (i = 0; i < GEMS; i++) {
694 		used[i] = 0;
695 	}
696 	for (i = 0; i < RINGS; i++) {
697 		do {
698 			j = get_rand(0, GEMS-1);
699 		} while (used[j]);
700 		used[j] = 1;
701 		(void)strlcpy(id_rings[i].title, gems[j],
702 			       sizeof(id_rings[i].title));
703 	}
704 }
705 
706 void
single_inv(short ichar)707 single_inv(short ichar)
708 {
709 	short ch, ch2;
710 	char desc[DCOLS];
711 	object *obj;
712 
713 	ch = ichar ? ichar : pack_letter("inventory what?", ALL_OBJECTS);
714 
715 	if (ch == CANCEL) {
716 		return;
717 	}
718 	if (!(obj = get_letter_object(ch))) {
719 		messagef(0, "no such item.");
720 		return;
721 	}
722 	ch2 = ((obj->what_is & ARMOR) && obj->is_protected) ? '}' : ')';
723 	get_desc(obj, desc, sizeof(desc));
724 	messagef(0, "%c%c %s", ch, ch2, desc);
725 }
726 
727 struct id *
get_id_table(const object * obj)728 get_id_table(const object *obj)
729 {
730 	switch(obj->what_is) {
731 	case SCROL:
732 		return(id_scrolls);
733 	case POTION:
734 		return(id_potions);
735 	case WAND:
736 		return(id_wands);
737 	case RING:
738 		return(id_rings);
739 	case WEAPON:
740 		return(id_weapons);
741 	case ARMOR:
742 		return(id_armors);
743 	}
744 	return((struct id *)0);
745 }
746 
747 void
inv_armor_weapon(boolean is_weapon)748 inv_armor_weapon(boolean is_weapon)
749 {
750 	if (is_weapon) {
751 		if (rogue.weapon) {
752 			single_inv(rogue.weapon->ichar);
753 		} else {
754 			messagef(0, "not wielding anything");
755 		}
756 	} else {
757 		if (rogue.armor) {
758 			single_inv(rogue.armor->ichar);
759 		} else {
760 			messagef(0, "not wearing anything");
761 		}
762 	}
763 }
764 
765 void
id_type(void)766 id_type(void)
767 {
768 	const char *id;
769 	int ch;
770 
771 	messagef(0, "what do you want identified?");
772 
773 	ch = rgetchar();
774 
775 	if ((ch >= 'A') && (ch <= 'Z')) {
776 		id = m_names[ch-'A'];
777 	} else if (ch < 32) {
778 		check_message();
779 		return;
780 	} else {
781 		switch(ch) {
782 		case '@':
783 			id = "you";
784 			break;
785 		case '%':
786 			id = "staircase";
787 			break;
788 		case '^':
789 			id = "trap";
790 			break;
791 		case '+':
792 			id = "door";
793 			break;
794 		case '-':
795 		case '|':
796 			id = "wall of a room";
797 			break;
798 		case '.':
799 			id = "floor";
800 			break;
801 		case '#':
802 			id = "passage";
803 			break;
804 		case ' ':
805 			id = "solid rock";
806 			break;
807 		case '=':
808 			id = "ring";
809 			break;
810 		case '?':
811 			id = "scroll";
812 			break;
813 		case '!':
814 			id = "potion";
815 			break;
816 		case '/':
817 			id = "wand or staff";
818 			break;
819 		case ')':
820 			id = "weapon";
821 			break;
822 		case ']':
823 			id = "armor";
824 			break;
825 		case '*':
826 			id = "gold";
827 			break;
828 		case ':':
829 			id = "food";
830 			break;
831 		case ',':
832 			id = "the Amulet of Yendor";
833 			break;
834 		default:
835 			id = "unknown character";
836 			break;
837 		}
838 	}
839 	check_message();
840 	messagef(0, "'%c': %s", ch, id);
841 }
842