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