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