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 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, ...) __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 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 489 sbuf_addstr(struct sbuf *s, const char *str) 490 { 491 strlcat(s->buf, str, s->maxlen); 492 } 493 494 static 495 void 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 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 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 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 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 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 * 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 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 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