Home | History | Annotate | Line # | Download | only in rogue
inventory.c revision 1.3
      1 /*	$NetBSD: inventory.c,v 1.3 1995/04/22 10:27:35 cgd 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. All advertising materials mentioning features or use of this software
     19  *    must display the following acknowledgement:
     20  *	This product includes software developed by the University of
     21  *	California, Berkeley and its contributors.
     22  * 4. Neither the name of the University nor the names of its contributors
     23  *    may be used to endorse or promote products derived from this software
     24  *    without specific prior written permission.
     25  *
     26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     36  * SUCH DAMAGE.
     37  */
     38 
     39 #ifndef lint
     40 #if 0
     41 static char sccsid[] = "@(#)inventory.c	8.1 (Berkeley) 5/31/93";
     42 #else
     43 static char rcsid[] = "$NetBSD: inventory.c,v 1.3 1995/04/22 10:27:35 cgd Exp $";
     44 #endif
     45 #endif /* not lint */
     46 
     47 /*
     48  * inventory.c
     49  *
     50  * This source herein may be modified and/or distributed by anybody who
     51  * so desires, with the following restrictions:
     52  *    1.)  No portion of this notice shall be removed.
     53  *    2.)  Credit shall not be taken for the creation of this source.
     54  *    3.)  This code is not to be traded, sold, or used for personal
     55  *         gain or profit.
     56  *
     57  */
     58 
     59 #include "rogue.h"
     60 
     61 boolean is_wood[WANDS];
     62 char *press_space = " --press space to continue--";
     63 
     64 char *wand_materials[WAND_MATERIALS] = {
     65 	"steel ",
     66 	"bronze ",
     67 	"gold ",
     68 	"silver ",
     69 	"copper ",
     70 	"nickel ",
     71 	"cobalt ",
     72 	"tin ",
     73 	"iron ",
     74 	"magnesium ",
     75 	"chrome ",
     76 	"carbon ",
     77 	"platinum ",
     78 	"silicon ",
     79 	"titanium ",
     80 
     81 	"teak ",
     82 	"oak ",
     83 	"cherry ",
     84 	"birch ",
     85 	"pine ",
     86 	"cedar ",
     87 	"redwood ",
     88 	"balsa ",
     89 	"ivory ",
     90 	"walnut ",
     91 	"maple ",
     92 	"mahogany ",
     93 	"elm ",
     94 	"palm ",
     95 	"wooden "
     96 };
     97 
     98 char *gems[GEMS] = {
     99 	"diamond ",
    100 	"stibotantalite ",
    101 	"lapi-lazuli ",
    102 	"ruby ",
    103 	"emerald ",
    104 	"sapphire ",
    105 	"amethyst ",
    106 	"quartz ",
    107 	"tiger-eye ",
    108 	"opal ",
    109 	"agate ",
    110 	"turquoise ",
    111 	"pearl ",
    112 	"garnet "
    113 };
    114 
    115 char *syllables[MAXSYLLABLES] = {
    116 	"blech ",
    117 	"foo ",
    118 	"barf ",
    119 	"rech ",
    120 	"bar ",
    121 	"blech ",
    122 	"quo ",
    123 	"bloto ",
    124 	"oh ",
    125 	"caca ",
    126 	"blorp ",
    127 	"erp ",
    128 	"festr ",
    129 	"rot ",
    130 	"slie ",
    131 	"snorf ",
    132 	"iky ",
    133 	"yuky ",
    134 	"ooze ",
    135 	"ah ",
    136 	"bahl ",
    137 	"zep ",
    138 	"druhl ",
    139 	"flem ",
    140 	"behil ",
    141 	"arek ",
    142 	"mep ",
    143 	"zihr ",
    144 	"grit ",
    145 	"kona ",
    146 	"kini ",
    147 	"ichi ",
    148 	"tims ",
    149 	"ogr ",
    150 	"oo ",
    151 	"ighr ",
    152 	"coph ",
    153 	"swerr ",
    154 	"mihln ",
    155 	"poxi "
    156 };
    157 
    158 #define COMS 48
    159 
    160 struct id_com_s {
    161 	short com_char;
    162 	char *com_desc;
    163 };
    164 
    165 struct id_com_s com_id_tab[COMS] = {
    166 	'?',	"?       prints help",
    167 	'r',	"r       read scroll",
    168 	'/',	"/       identify object",
    169 	'e',	"e       eat food",
    170 	'h',	"h       left ",
    171 	'w',	"w       wield a weapon",
    172 	'j',	"j       down",
    173 	'W',	"W       wear armor",
    174 	'k',	"k       up",
    175 	'T',	"T       take armor off",
    176 	'l',	"l       right",
    177 	'P',	"P       put on ring",
    178 	'y',	"y       up & left",
    179 	'R',	"R       remove ring",
    180 	'u',	"u       up & right",
    181 	'd',	"d       drop object",
    182 	'b',	"b       down & left",
    183 	'c',	"c       call object",
    184 	'n',	"n       down & right",
    185 	NULL,	"<SHIFT><dir>: run that way",
    186 	')',	")       print current weapon",
    187 	NULL,	"<CTRL><dir>: run till adjacent",
    188 	']',	"]       print current armor",
    189 	'f',	"f<dir>  fight till death or near death",
    190 	'=',	"=       print current rings",
    191 	't',	"t<dir>  throw something",
    192 	'\001',	"^A      print Hp-raise average",
    193 	'm',	"m<dir>  move onto without picking up",
    194 	'z',	"z<dir>  zap a wand in a direction",
    195 	'o',	"o       examine/set options",
    196 	'^',	"^<dir>  identify trap type",
    197 	'\022',	"^R      redraw screen",
    198 	'&',	"&       save screen into 'rogue.screen'",
    199 	's',	"s       search for trap/secret door",
    200 	'\020',	"^P      repeat last message",
    201 	'>',	">       go down a staircase",
    202 	'\033',	"^[      cancel command",
    203 	'<',	"<       go up a staircase",
    204 	'S',	"S       save game",
    205 	'.',	".       rest for a turn",
    206 	'Q',	"Q       quit",
    207 	',',	",       pick something up",
    208 	'!',	"!       shell escape",
    209 	'i',	"i       inventory",
    210 	'F',	"F<dir>  fight till either of you dies",
    211 	'I',	"I       inventory single item",
    212 	'v',	"v       print version number",
    213 	'q',	"q       quaff potion"
    214 };
    215 
    216 extern boolean wizard;
    217 extern char *m_names[], *more;
    218 
    219 inventory(pack, mask)
    220 object *pack;
    221 unsigned short mask;
    222 {
    223 	object *obj;
    224 	short i = 0, j, maxlen = 0, n;
    225 	char descs[MAX_PACK_COUNT+1][DCOLS];
    226 	short row, col;
    227 
    228 	obj = pack->next_object;
    229 
    230 	if (!obj) {
    231 		message("your pack is empty", 0);
    232 		return;
    233 	}
    234 	while (obj) {
    235 		if (obj->what_is & mask) {
    236 			descs[i][0] = ' ';
    237 			descs[i][1] = obj->ichar;
    238 			descs[i][2] = ((obj->what_is & ARMOR) && obj->is_protected)
    239 				? '}' : ')';
    240 			descs[i][3] = ' ';
    241 			get_desc(obj, descs[i]+4);
    242 			if ((n = strlen(descs[i])) > maxlen) {
    243 				maxlen = n;
    244 			}
    245 		i++;
    246 		}
    247 		obj = obj->next_object;
    248 	}
    249 	(void) strcpy(descs[i++], press_space);
    250 	if (maxlen < 27) maxlen = 27;
    251 	col = DCOLS - (maxlen + 2);
    252 
    253 	for (row = 0; ((row < i) && (row < DROWS)); row++) {
    254 		if (row > 0) {
    255 			for (j = col; j < DCOLS; j++) {
    256 				descs[row-1][j-col] = mvinch(row, j);
    257 			}
    258 			descs[row-1][j-col] = 0;
    259 		}
    260 		mvaddstr(row, col, descs[row]);
    261 		clrtoeol();
    262 	}
    263 	refresh();
    264 	wait_for_ack();
    265 
    266 	move(0, 0);
    267 	clrtoeol();
    268 
    269 	for (j = 1; ((j < i) && (j < DROWS)); j++) {
    270 		mvaddstr(j, col, descs[j-1]);
    271 	}
    272 }
    273 
    274 id_com()
    275 {
    276 	int ch = 0;
    277 	short i, j, k;
    278 
    279 	while (ch != CANCEL) {
    280 		check_message();
    281 		message("Character you want help for (* for all):", 0);
    282 
    283 		refresh();
    284 		ch = getchar();
    285 
    286 		switch(ch) {
    287 		case LIST:
    288 			{
    289 				char save[(((COMS / 2) + (COMS % 2)) + 1)][DCOLS];
    290 				short rows = (((COMS / 2) + (COMS % 2)) + 1);
    291 				boolean need_two_screens;
    292 
    293 				if (rows > LINES) {
    294 					need_two_screens = 1;
    295 					rows = LINES;
    296 				}
    297 				k = 0;
    298 
    299 				for (i = 0; i < rows; i++) {
    300 					for (j = 0; j < DCOLS; j++) {
    301 						save[i][j] = mvinch(i, j);
    302 					}
    303 				}
    304 MORE:
    305 				for (i = 0; i < rows; i++) {
    306 					move(i, 0);
    307 					clrtoeol();
    308 				}
    309 				for (i = 0; i < (rows-1); i++) {
    310 					if (i < (LINES-1)) {
    311 						if (((i + i) < COMS) && ((i+i+k) < COMS)) {
    312 							mvaddstr(i, 0, com_id_tab[i+i+k].com_desc);
    313 						}
    314 						if (((i + i + 1) < COMS) && ((i+i+k+1) < COMS)) {
    315 							mvaddstr(i, (DCOLS/2),
    316 										com_id_tab[i+i+k+1].com_desc);
    317 						}
    318 					}
    319 				}
    320 				mvaddstr(rows - 1, 0, need_two_screens ? more : press_space);
    321 				refresh();
    322 				wait_for_ack();
    323 
    324 				if (need_two_screens) {
    325 					k += ((rows-1) * 2);
    326 					need_two_screens = 0;
    327 					goto MORE;
    328 				}
    329 				for (i = 0; i < rows; i++) {
    330 					move(i, 0);
    331 					for (j = 0; j < DCOLS; j++) {
    332 						addch(save[i][j]);
    333 					}
    334 				}
    335 			}
    336 			break;
    337 		default:
    338 			if (!pr_com_id(ch)) {
    339 				if (!pr_motion_char(ch)) {
    340 					check_message();
    341 					message("unknown character", 0);
    342 				}
    343 			}
    344 			ch = CANCEL;
    345 			break;
    346 		}
    347 	}
    348 }
    349 
    350 pr_com_id(ch)
    351 int ch;
    352 {
    353 	int i;
    354 
    355 	if (!get_com_id(&i, ch)) {
    356 		return(0);
    357 	}
    358 	check_message();
    359 	message(com_id_tab[i].com_desc, 0);
    360 	return(1);
    361 }
    362 
    363 get_com_id(index, ch)
    364 int *index;
    365 short ch;
    366 {
    367 	short i;
    368 
    369 	for (i = 0; i < COMS; i++) {
    370 		if (com_id_tab[i].com_char == ch) {
    371 			*index = i;
    372 			return(1);
    373 		}
    374 	}
    375 	return(0);
    376 }
    377 
    378 pr_motion_char(ch)
    379 int ch;
    380 {
    381 	if (	(ch == 'J') ||
    382 			(ch == 'K') ||
    383 			(ch == 'L') ||
    384 			(ch == 'H') ||
    385 			(ch == 'Y') ||
    386 			(ch == 'U') ||
    387 			(ch == 'N') ||
    388 			(ch == 'B') ||
    389 			(ch == '\012') ||
    390 			(ch == '\013') ||
    391 			(ch == '\010') ||
    392 			(ch == '\014') ||
    393 			(ch == '\025') ||
    394 			(ch == '\031') ||
    395 			(ch == '\016') ||
    396 			(ch == '\002')) {
    397 		char until[18], buf[DCOLS];
    398 		int n;
    399 
    400 		if (ch <= '\031') {
    401 			ch += 96;
    402 			(void) strcpy(until, "until adjascent");
    403 		} else {
    404 			ch += 32;
    405 			until[0] = '\0';
    406 		}
    407 		(void) get_com_id(&n, ch);
    408 		sprintf(buf, "run %s %s", com_id_tab[n].com_desc + 8, until);
    409 		check_message();
    410 		message(buf, 0);
    411 		return(1);
    412 	} else {
    413 		return(0);
    414 	}
    415 }
    416 
    417 mix_colors()
    418 {
    419 	short i, j, k;
    420 	char *t;
    421 
    422 	for (i = 0; i <= 32; i++) {
    423 		j = get_rand(0, (POTIONS - 1));
    424 		k = get_rand(0, (POTIONS - 1));
    425 		t = id_potions[j].title;
    426 		id_potions[j].title = id_potions[k].title;
    427 		id_potions[k].title = t;
    428 	}
    429 }
    430 
    431 make_scroll_titles()
    432 {
    433 	short i, j, n;
    434 	short sylls, s;
    435 
    436 	for (i = 0; i < SCROLS; i++) {
    437 		sylls = get_rand(2, 5);
    438 		(void) strcpy(id_scrolls[i].title, "'");
    439 
    440 		for (j = 0; j < sylls; j++) {
    441 			s = get_rand(1, (MAXSYLLABLES-1));
    442 			(void) strcat(id_scrolls[i].title, syllables[s]);
    443 		}
    444 		n = strlen(id_scrolls[i].title);
    445 		(void) strcpy(id_scrolls[i].title+(n-1), "' ");
    446 	}
    447 }
    448 
    449 get_desc(obj, desc)
    450 object *obj;
    451 char *desc;
    452 {
    453 	char *item_name;
    454 	struct id *id_table;
    455 	char more_info[32];
    456 	short i;
    457 
    458 	if (obj->what_is == AMULET) {
    459 		(void) strcpy(desc, "the amulet of Yendor ");
    460 		return;
    461 	}
    462 	item_name = name_of(obj);
    463 
    464 	if (obj->what_is == GOLD) {
    465 		sprintf(desc, "%d pieces of gold", obj->quantity);
    466 		return;
    467 	}
    468 
    469 	if (obj->what_is != ARMOR) {
    470 		if (obj->quantity == 1) {
    471 			(void) strcpy(desc, "a ");
    472 		} else {
    473 			sprintf(desc, "%d ", obj->quantity);
    474 		}
    475 	}
    476 	if (obj->what_is == FOOD) {
    477 		if (obj->which_kind == RATION) {
    478 			if (obj->quantity > 1) {
    479 				sprintf(desc, "%d rations of ", obj->quantity);
    480 			} else {
    481 				(void) strcpy(desc, "some ");
    482 			}
    483 		} else {
    484 			(void) strcpy(desc, "a ");
    485 		}
    486 		(void) strcat(desc, item_name);
    487 		goto ANA;
    488 	}
    489 	id_table = get_id_table(obj);
    490 
    491 	if (wizard) {
    492 		goto ID;
    493 	}
    494 	if (obj->what_is & (WEAPON | ARMOR | WAND | RING)) {
    495 		goto CHECK;
    496 	}
    497 
    498 	switch(id_table[obj->which_kind].id_status) {
    499 	case UNIDENTIFIED:
    500 CHECK:
    501 		switch(obj->what_is) {
    502 		case SCROL:
    503 			(void) strcat(desc, item_name);
    504 			(void) strcat(desc, "entitled: ");
    505 			(void) strcat(desc, id_table[obj->which_kind].title);
    506 			break;
    507 		case POTION:
    508 			(void) strcat(desc, id_table[obj->which_kind].title);
    509 			(void) strcat(desc, item_name);
    510 			break;
    511 		case WAND:
    512 		case RING:
    513 			if (obj->identified ||
    514 			(id_table[obj->which_kind].id_status == IDENTIFIED)) {
    515 				goto ID;
    516 			}
    517 			if (id_table[obj->which_kind].id_status == CALLED) {
    518 				goto CALL;
    519 			}
    520 			(void) strcat(desc, id_table[obj->which_kind].title);
    521 			(void) strcat(desc, item_name);
    522 			break;
    523 		case ARMOR:
    524 			if (obj->identified) {
    525 				goto ID;
    526 			}
    527 			(void) strcpy(desc, id_table[obj->which_kind].title);
    528 			break;
    529 		case WEAPON:
    530 			if (obj->identified) {
    531 				goto ID;
    532 			}
    533 			(void) strcat(desc, name_of(obj));
    534 			break;
    535 		}
    536 		break;
    537 	case CALLED:
    538 CALL:	switch(obj->what_is) {
    539 		case SCROL:
    540 		case POTION:
    541 		case WAND:
    542 		case RING:
    543 			(void) strcat(desc, item_name);
    544 			(void) strcat(desc, "called ");
    545 			(void) strcat(desc, id_table[obj->which_kind].title);
    546 			break;
    547 		}
    548 		break;
    549 	case IDENTIFIED:
    550 ID:		switch(obj->what_is) {
    551 		case SCROL:
    552 		case POTION:
    553 			(void) strcat(desc, item_name);
    554 			(void) strcat(desc, id_table[obj->which_kind].real);
    555 			break;
    556 		case RING:
    557 			if (wizard || obj->identified) {
    558 				if ((obj->which_kind == DEXTERITY) ||
    559 					(obj->which_kind == ADD_STRENGTH)) {
    560 					sprintf(more_info, "%s%d ", ((obj->class > 0) ? "+" : ""),
    561 						obj->class);
    562 					(void) strcat(desc, more_info);
    563 				}
    564 			}
    565 			(void) strcat(desc, item_name);
    566 			(void) strcat(desc, id_table[obj->which_kind].real);
    567 			break;
    568 		case WAND:
    569 			(void) strcat(desc, item_name);
    570 			(void) strcat(desc, id_table[obj->which_kind].real);
    571 			if (wizard || obj->identified) {
    572 				sprintf(more_info, "[%d]", obj->class);
    573 				(void) strcat(desc, more_info);
    574 			}
    575 			break;
    576 		case ARMOR:
    577 			sprintf(desc, "%s%d ", ((obj->d_enchant >= 0) ? "+" : ""),
    578 			obj->d_enchant);
    579 			(void) strcat(desc, id_table[obj->which_kind].title);
    580 			sprintf(more_info, "[%d] ", get_armor_class(obj));
    581 			(void) strcat(desc, more_info);
    582 			break;
    583 		case WEAPON:
    584 			sprintf(desc+strlen(desc), "%s%d,%s%d ",
    585 			((obj->hit_enchant >= 0) ? "+" : ""), obj->hit_enchant,
    586 			((obj->d_enchant >= 0) ? "+" : ""), obj->d_enchant);
    587 			(void) strcat(desc, name_of(obj));
    588 			break;
    589 		}
    590 		break;
    591 	}
    592 ANA:
    593 	if (!strncmp(desc, "a ", 2)) {
    594 		if (is_vowel(desc[2])) {
    595 			for (i = strlen(desc) + 1; i > 1; i--) {
    596 				desc[i] = desc[i-1];
    597 			}
    598 			desc[1] = 'n';
    599 		}
    600 	}
    601 	if (obj->in_use_flags & BEING_WIELDED) {
    602 		(void) strcat(desc, "in hand");
    603 	} else if (obj->in_use_flags & BEING_WORN) {
    604 		(void) strcat(desc, "being worn");
    605 	} else if (obj->in_use_flags & ON_LEFT_HAND) {
    606 		(void) strcat(desc, "on left hand");
    607 	} else if (obj->in_use_flags & ON_RIGHT_HAND) {
    608 		(void) strcat(desc, "on right hand");
    609 	}
    610 }
    611 
    612 get_wand_and_ring_materials()
    613 {
    614 	short i, j;
    615 	boolean used[WAND_MATERIALS];
    616 
    617 	for (i = 0; i < WAND_MATERIALS; i++) {
    618 		used[i] = 0;
    619 	}
    620 	for (i = 0; i < WANDS; i++) {
    621 		do {
    622 			j = get_rand(0, WAND_MATERIALS-1);
    623 		} while (used[j]);
    624 		used[j] = 1;
    625 		(void) strcpy(id_wands[i].title, wand_materials[j]);
    626 		is_wood[i] = (j > MAX_METAL);
    627 	}
    628 	for (i = 0; i < GEMS; i++) {
    629 		used[i] = 0;
    630 	}
    631 	for (i = 0; i < RINGS; i++) {
    632 		do {
    633 			j = get_rand(0, GEMS-1);
    634 		} while (used[j]);
    635 		used[j] = 1;
    636 		(void) strcpy(id_rings[i].title, gems[j]);
    637 	}
    638 }
    639 
    640 single_inv(ichar)
    641 short ichar;
    642 {
    643 	short ch;
    644 	char desc[DCOLS];
    645 	object *obj;
    646 
    647 	ch = ichar ? ichar : pack_letter("inventory what?", ALL_OBJECTS);
    648 
    649 	if (ch == CANCEL) {
    650 		return;
    651 	}
    652 	if (!(obj = get_letter_object(ch))) {
    653 		message("no such item.", 0);
    654 		return;
    655 	}
    656 	desc[0] = ch;
    657 	desc[1] = ((obj->what_is & ARMOR) && obj->is_protected) ? '}' : ')';
    658 	desc[2] = ' ';
    659 	desc[3] = 0;
    660 	get_desc(obj, desc+3);
    661 	message(desc, 0);
    662 }
    663 
    664 struct id *
    665 get_id_table(obj)
    666 object *obj;
    667 {
    668 	switch(obj->what_is) {
    669 	case SCROL:
    670 		return(id_scrolls);
    671 	case POTION:
    672 		return(id_potions);
    673 	case WAND:
    674 		return(id_wands);
    675 	case RING:
    676 		return(id_rings);
    677 	case WEAPON:
    678 		return(id_weapons);
    679 	case ARMOR:
    680 		return(id_armors);
    681 	}
    682 	return((struct id *) 0);
    683 }
    684 
    685 inv_armor_weapon(is_weapon)
    686 boolean is_weapon;
    687 {
    688 	if (is_weapon) {
    689 		if (rogue.weapon) {
    690 			single_inv(rogue.weapon->ichar);
    691 		} else {
    692 			message("not wielding anything", 0);
    693 		}
    694 	} else {
    695 		if (rogue.armor) {
    696 			single_inv(rogue.armor->ichar);
    697 		} else {
    698 			message("not wearing anything", 0);
    699 		}
    700 	}
    701 }
    702 
    703 id_type()
    704 {
    705 	char *id;
    706 	int ch;
    707 	char buf[DCOLS];
    708 
    709 	message("what do you want identified?", 0);
    710 
    711 	ch = rgetchar();
    712 
    713 	if ((ch >= 'A') && (ch <= 'Z')) {
    714 		id = m_names[ch-'A'];
    715 	} else if (ch < 32) {
    716 		check_message();
    717 		return;
    718 	} else {
    719 		switch(ch) {
    720 		case '@':
    721 			id = "you";
    722 			break;
    723 		case '%':
    724 			id = "staircase";
    725 			break;
    726 		case '^':
    727 			id = "trap";
    728 			break;
    729 		case '+':
    730 			id = "door";
    731 			break;
    732 		case '-':
    733 		case '|':
    734 			id = "wall of a room";
    735 			break;
    736 		case '.':
    737 			id = "floor";
    738 			break;
    739 		case '#':
    740 			id = "passage";
    741 			break;
    742 		case ' ':
    743 			id = "solid rock";
    744 			break;
    745 		case '=':
    746 			id = "ring";
    747 			break;
    748 		case '?':
    749 			id = "scroll";
    750 			break;
    751 		case '!':
    752 			id = "potion";
    753 			break;
    754 		case '/':
    755 			id = "wand or staff";
    756 			break;
    757 		case ')':
    758 			id = "weapon";
    759 			break;
    760 		case ']':
    761 			id = "armor";
    762 			break;
    763 		case '*':
    764 			id = "gold";
    765 			break;
    766 		case ':':
    767 			id = "food";
    768 			break;
    769 		case ',':
    770 			id = "the Amulet of Yendor";
    771 			break;
    772 		default:
    773 			id = "unknown character";
    774 			break;
    775 		}
    776 	}
    777 	check_message();
    778 	sprintf(buf, "'%c': %s", ch, id);
    779 	message(buf, 0);
    780 }
    781