Home | History | Annotate | Line # | Download | only in rogue
object.c revision 1.8
      1 /*	$NetBSD: object.c,v 1.8 1998/11/10 13:01:32 hubertf 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 #include <sys/cdefs.h>
     40 #ifndef lint
     41 #if 0
     42 static char sccsid[] = "@(#)object.c	8.1 (Berkeley) 5/31/93";
     43 #else
     44 __RCSID("$NetBSD: object.c,v 1.8 1998/11/10 13:01:32 hubertf Exp $");
     45 #endif
     46 #endif /* not lint */
     47 
     48 /*
     49  * object.c
     50  *
     51  * This source herein may be modified and/or distributed by anybody who
     52  * so desires, with the following restrictions:
     53  *    1.)  No portion of this notice shall be removed.
     54  *    2.)  Credit shall not be taken for the creation of this source.
     55  *    3.)  This code is not to be traded, sold, or used for personal
     56  *         gain or profit.
     57  *
     58  */
     59 
     60 #include "rogue.h"
     61 
     62 object level_objects;
     63 unsigned short dungeon[DROWS][DCOLS];
     64 short foods = 0;
     65 object *free_list = (object *) 0;
     66 char *fruit = (char *) 0;
     67 
     68 fighter rogue = {
     69 	INIT_AW,	/* armor */
     70 	INIT_AW,	/* weapon */
     71 	INIT_RINGS,	/* left ring */
     72 	INIT_RINGS,	/* right ring */
     73 	INIT_HP,	/* Hp current */
     74 	INIT_HP,	/* Hp max */
     75 	INIT_STR,	/* Str current */
     76 	INIT_STR,	/* Str max */
     77 	INIT_PACK,	/* pack */
     78 	INIT_GOLD,	/* gold */
     79 	INIT_EXPLEVEL,	/* exp level */
     80 	INIT_EXP,	/* exp points */
     81 	0, 0,		/* row, col */
     82 	INIT_CHAR,	/* char */
     83 	INIT_MOVES	/* moves */
     84 };
     85 
     86 struct id id_potions[POTIONS] = {
     87 {100, "blue \0                           ", "of increase strength ", 0},
     88 {250, "red \0                            ", "of restore strength ", 0},
     89 {100, "green \0                          ", "of healing ", 0},
     90 {200, "grey \0                           ", "of extra healing ", 0},
     91  {10, "brown \0                          ", "of poison ", 0},
     92 {300, "clear \0                          ", "of raise level ", 0},
     93  {10, "pink \0                           ", "of blindness ", 0},
     94  {25, "white \0                          ", "of hallucination ", 0},
     95 {100, "purple \0                         ", "of detect monster ", 0},
     96 {100, "black \0                          ", "of detect things ", 0},
     97  {10, "yellow \0                         ", "of confusion ", 0},
     98  {80, "plaid \0                          ", "of levitation ", 0},
     99 {150, "burgundy \0                       ", "of haste self ", 0},
    100 {145, "beige \0                          ", "of see invisible ", 0}
    101 };
    102 
    103 struct id id_scrolls[SCROLS] = {
    104 {505, "                                   ", "of protect armor ", 0},
    105 {200, "                                   ", "of hold monster ", 0},
    106 {235, "                                   ", "of enchant weapon ", 0},
    107 {235, "                                   ", "of enchant armor ", 0},
    108 {175, "                                   ", "of identify ", 0},
    109 {190, "                                   ", "of teleportation ", 0},
    110  {25, "                                   ", "of sleep ", 0},
    111 {610, "                                   ", "of scare monster ", 0},
    112 {210, "                                   ", "of remove curse ", 0},
    113  {80, "                                   ", "of create monster ",0},
    114  {25, "                                   ", "of aggravate monster ",0},
    115 {180, "                                   ", "of magic mapping ", 0},
    116  {90, "                                   ", "of confuse monster ", 0}
    117 };
    118 
    119 struct id id_weapons[WEAPONS] = {
    120 	{150, "short bow ", "", 0},
    121 	  {8, "darts ", "", 0},
    122 	 {15, "arrows ", "", 0},
    123 	 {27, "daggers ", "", 0},
    124 	 {35, "shurikens ", "", 0},
    125 	{360, "mace ", "", 0},
    126 	{470, "long sword ", "", 0},
    127 	{580, "two-handed sword ", "", 0}
    128 };
    129 
    130 struct id id_armors[ARMORS] = {
    131 	{300, "leather armor ", "", (UNIDENTIFIED)},
    132 	{300, "ring mail ", "", (UNIDENTIFIED)},
    133 	{400, "scale mail ", "", (UNIDENTIFIED)},
    134 	{500, "chain mail ", "", (UNIDENTIFIED)},
    135 	{600, "banded mail ", "", (UNIDENTIFIED)},
    136 	{600, "splint mail ", "", (UNIDENTIFIED)},
    137 	{700, "plate mail ", "", (UNIDENTIFIED)}
    138 };
    139 
    140 struct id id_wands[WANDS] = {
    141 	 {25, "                                 ", "of teleport away ",0},
    142 	 {50, "                                 ", "of slow monster ", 0},
    143 	  {8, "                                 ", "of invisibility ",0},
    144 	 {55, "                                 ", "of polymorph ",0},
    145 	  {2, "                                 ", "of haste monster ",0},
    146 	 {20, "                                 ", "of magic missile ",0},
    147 	 {20, "                                 ", "of cancellation ",0},
    148 	  {0, "                                 ", "of do nothing ",0},
    149 	 {35, "                                 ", "of drain life ",0},
    150 	 {20, "                                 ", "of cold ",0},
    151 	 {20, "                                 ", "of fire ",0}
    152 };
    153 
    154 struct id id_rings[RINGS] = {
    155 	 {250, "                                 ", "of stealth ",0},
    156 	 {100, "                                 ", "of teleportation ", 0},
    157 	 {255, "                                 ", "of regeneration ",0},
    158 	 {295, "                                 ", "of slow digestion ",0},
    159 	 {200, "                                 ", "of add strength ",0},
    160 	 {250, "                                 ", "of sustain strength ",0},
    161 	 {250, "                                 ", "of dexterity ",0},
    162 	  {25, "                                 ", "of adornment ",0},
    163 	 {300, "                                 ", "of see invisible ",0},
    164 	 {290, "                                 ", "of maintain armor ",0},
    165 	 {270, "                                 ", "of searching ",0},
    166 };
    167 
    168 void
    169 put_objects()
    170 {
    171 	short i, n;
    172 	object *obj;
    173 
    174 	if (cur_level < max_level) {
    175 		return;
    176 	}
    177 	n = coin_toss() ? get_rand(2, 4) : get_rand(3, 5);
    178 	while (rand_percent(33)) {
    179 		n++;
    180 	}
    181 	if (party_room != NO_ROOM) {
    182 		make_party();
    183 	}
    184 	for (i = 0; i < n; i++) {
    185 		obj = gr_object();
    186 		rand_place(obj);
    187 	}
    188 	put_gold();
    189 }
    190 
    191 void
    192 put_gold()
    193 {
    194 	short i, j;
    195 	short row,col;
    196 	boolean is_maze, is_room;
    197 
    198 	for (i = 0; i < MAXROOMS; i++) {
    199 		is_maze = (rooms[i].is_room & R_MAZE) ? 1 : 0;
    200 		is_room = (rooms[i].is_room & R_ROOM) ? 1 : 0;
    201 
    202 		if (!(is_room || is_maze)) {
    203 			continue;
    204 		}
    205 		if (is_maze || rand_percent(GOLD_PERCENT)) {
    206 			for (j = 0; j < 50; j++) {
    207 				row = get_rand(rooms[i].top_row+1,
    208 				rooms[i].bottom_row-1);
    209 				col = get_rand(rooms[i].left_col+1,
    210 				rooms[i].right_col-1);
    211 				if ((dungeon[row][col] == FLOOR) ||
    212 					(dungeon[row][col] == TUNNEL)) {
    213 					plant_gold(row, col, is_maze);
    214 					break;
    215 				}
    216 			}
    217 		}
    218 	}
    219 }
    220 
    221 void
    222 plant_gold(row, col, is_maze)
    223 	short row, col;
    224 	boolean is_maze;
    225 {
    226 	object *obj;
    227 
    228 	obj = alloc_object();
    229 	obj->row = row; obj->col = col;
    230 	obj->what_is = GOLD;
    231 	obj->quantity = get_rand((2 * cur_level), (16 * cur_level));
    232 	if (is_maze) {
    233 		obj->quantity += obj->quantity / 2;
    234 	}
    235 	dungeon[row][col] |= OBJECT;
    236 	(void) add_to_pack(obj, &level_objects, 0);
    237 }
    238 
    239 void
    240 place_at(obj, row, col)
    241 	object *obj;
    242 	int row, col;
    243 {
    244 	obj->row = row;
    245 	obj->col = col;
    246 	dungeon[row][col] |= OBJECT;
    247 	(void) add_to_pack(obj, &level_objects, 0);
    248 }
    249 
    250 object *
    251 object_at(pack, row, col)
    252 	object *pack;
    253 	short row, col;
    254 {
    255 	object *obj = (object *) 0;
    256 
    257 	if (dungeon[row][col] & (MONSTER | OBJECT)) {
    258 		obj = pack->next_object;
    259 
    260 		while (obj && ((obj->row != row) || (obj->col != col))) {
    261 			obj = obj->next_object;
    262 		}
    263 		if (!obj) {
    264 			message("object_at(): inconsistent", 1);
    265 		}
    266 	}
    267 	return(obj);
    268 }
    269 
    270 object *
    271 get_letter_object(ch)
    272 	int ch;
    273 {
    274 	object *obj;
    275 
    276 	obj = rogue.pack.next_object;
    277 
    278 	while (obj && (obj->ichar != ch)) {
    279 		obj = obj->next_object;
    280 	}
    281 	return(obj);
    282 }
    283 
    284 void
    285 free_stuff(objlist)
    286 	object *objlist;
    287 {
    288 	object *obj;
    289 
    290 	while (objlist->next_object) {
    291 		obj = objlist->next_object;
    292 		objlist->next_object =
    293 			objlist->next_object->next_object;
    294 		free_object(obj);
    295 	}
    296 }
    297 
    298 const char *
    299 name_of(obj)
    300 	const object *obj;
    301 {
    302 	const char *retstring;
    303 
    304 	switch(obj->what_is) {
    305 	case SCROL:
    306 		retstring = obj->quantity > 1 ? "scrolls " : "scroll ";
    307 		break;
    308 	case POTION:
    309 		retstring = obj->quantity > 1 ? "potions " : "potion ";
    310 		break;
    311 	case FOOD:
    312 		if (obj->which_kind == RATION) {
    313 			retstring = "food ";
    314 		} else {
    315 			retstring = fruit;
    316 		}
    317 		break;
    318 	case WAND:
    319 		retstring = is_wood[obj->which_kind] ? "staff " : "wand ";
    320 		break;
    321 	case WEAPON:
    322 		switch(obj->which_kind) {
    323 		case DART:
    324 			retstring=obj->quantity > 1 ? "darts " : "dart ";
    325 			break;
    326 		case ARROW:
    327 			retstring=obj->quantity > 1 ? "arrows " : "arrow ";
    328 			break;
    329 		case DAGGER:
    330 			retstring=obj->quantity > 1 ? "daggers " : "dagger ";
    331 			break;
    332 		case SHURIKEN:
    333 			retstring=obj->quantity > 1?"shurikens ":"shuriken ";
    334 			break;
    335 		default:
    336 			retstring = id_weapons[obj->which_kind].title;
    337 		}
    338 		break;
    339 	case ARMOR:
    340 		retstring = "armor ";
    341 		break;
    342 	case RING:
    343 			retstring = "ring ";
    344 		break;
    345 	case AMULET:
    346 		retstring = "amulet ";
    347 		break;
    348 	default:
    349 		retstring = "unknown ";
    350 		break;
    351 	}
    352 	return(retstring);
    353 }
    354 
    355 object *
    356 gr_object()
    357 {
    358 	object *obj;
    359 
    360 	obj = alloc_object();
    361 
    362 	if (foods < (cur_level / 3)) {
    363 		obj->what_is = FOOD;
    364 		foods++;
    365 	} else {
    366 		obj->what_is = gr_what_is();
    367 	}
    368 	switch(obj->what_is) {
    369 	case SCROL:
    370 		gr_scroll(obj);
    371 		break;
    372 	case POTION:
    373 		gr_potion(obj);
    374 		break;
    375 	case WEAPON:
    376 		gr_weapon(obj, 1);
    377 		break;
    378 	case ARMOR:
    379 		gr_armor(obj);
    380 		break;
    381 	case WAND:
    382 		gr_wand(obj);
    383 		break;
    384 	case FOOD:
    385 		get_food(obj, 0);
    386 		break;
    387 	case RING:
    388 		gr_ring(obj, 1);
    389 		break;
    390 	}
    391 	return(obj);
    392 }
    393 
    394 unsigned short
    395 gr_what_is()
    396 {
    397 	short percent;
    398 	unsigned short what_is;
    399 
    400 	percent = get_rand(1, 91);
    401 
    402 	if (percent <= 30) {
    403 		what_is = SCROL;
    404 	} else if (percent <= 60) {
    405 		what_is = POTION;
    406 	} else if (percent <= 64) {
    407 		what_is = WAND;
    408 	} else if (percent <= 74) {
    409 		what_is = WEAPON;
    410 	} else if (percent <= 83) {
    411 		what_is = ARMOR;
    412 	} else if (percent <= 88) {
    413 		what_is = FOOD;
    414 	} else {
    415 		what_is = RING;
    416 	}
    417 	return(what_is);
    418 }
    419 
    420 void
    421 gr_scroll(obj)
    422 	object *obj;
    423 {
    424 	short percent;
    425 
    426 	percent = get_rand(0, 91);
    427 
    428 	obj->what_is = SCROL;
    429 
    430 	if (percent <= 5) {
    431 		obj->which_kind = PROTECT_ARMOR;
    432 	} else if (percent <= 10) {
    433 		obj->which_kind = HOLD_MONSTER;
    434 	} else if (percent <= 20) {
    435 		obj->which_kind = CREATE_MONSTER;
    436 	} else if (percent <= 35) {
    437 		obj->which_kind = IDENTIFY;
    438 	} else if (percent <= 43) {
    439 		obj->which_kind = TELEPORT;
    440 	} else if (percent <= 50) {
    441 		obj->which_kind = SLEEP;
    442 	} else if (percent <= 55) {
    443 		obj->which_kind = SCARE_MONSTER;
    444 	} else if (percent <= 64) {
    445 		obj->which_kind = REMOVE_CURSE;
    446 	} else if (percent <= 69) {
    447 		obj->which_kind = ENCH_ARMOR;
    448 	} else if (percent <= 74) {
    449 		obj->which_kind = ENCH_WEAPON;
    450 	} else if (percent <= 80) {
    451 		obj->which_kind = AGGRAVATE_MONSTER;
    452 	} else if (percent <= 86) {
    453 		obj->which_kind = CON_MON;
    454 	} else {
    455 		obj->which_kind = MAGIC_MAPPING;
    456 	}
    457 }
    458 
    459 void
    460 gr_potion(obj)
    461 	object *obj;
    462 {
    463 	short percent;
    464 
    465 	percent = get_rand(1, 118);
    466 
    467 	obj->what_is = POTION;
    468 
    469 	if (percent <= 5) {
    470 		obj->which_kind = RAISE_LEVEL;
    471 	} else if (percent <= 15) {
    472 		obj->which_kind = DETECT_OBJECTS;
    473 	} else if (percent <= 25) {
    474 		obj->which_kind = DETECT_MONSTER;
    475 	} else if (percent <= 35) {
    476 		obj->which_kind = INCREASE_STRENGTH;
    477 	} else if (percent <= 45) {
    478 		obj->which_kind = RESTORE_STRENGTH;
    479 	} else if (percent <= 55) {
    480 		obj->which_kind = HEALING;
    481 	} else if (percent <= 65) {
    482 		obj->which_kind = EXTRA_HEALING;
    483 	} else if (percent <= 75) {
    484 		obj->which_kind = BLINDNESS;
    485 	} else if (percent <= 85) {
    486 		obj->which_kind = HALLUCINATION;
    487 	} else if (percent <= 95) {
    488 		obj->which_kind = CONFUSION;
    489 	} else if (percent <= 105) {
    490 		obj->which_kind = POISON;
    491 	} else if (percent <= 110) {
    492 		obj->which_kind = LEVITATION;
    493 	} else if (percent <= 114) {
    494 		obj->which_kind = HASTE_SELF;
    495 	} else {
    496 		obj->which_kind = SEE_INVISIBLE;
    497 	}
    498 }
    499 
    500 void
    501 gr_weapon(obj, assign_wk)
    502 	object *obj;
    503 	int assign_wk;
    504 {
    505 	short percent;
    506 	short i;
    507 	short blessing, increment;
    508 
    509 	obj->what_is = WEAPON;
    510 	if (assign_wk) {
    511 		obj->which_kind = get_rand(0, (WEAPONS - 1));
    512 	}
    513 	if ((obj->which_kind == ARROW) || (obj->which_kind == DAGGER) ||
    514 		(obj->which_kind == SHURIKEN) | (obj->which_kind == DART)) {
    515 		obj->quantity = get_rand(3, 15);
    516 		obj->quiver = get_rand(0, 126);
    517 	} else {
    518 		obj->quantity = 1;
    519 	}
    520 	obj->hit_enchant = obj->d_enchant = 0;
    521 
    522 	percent = get_rand(1, 96);
    523 	blessing = get_rand(1, 3);
    524 
    525 	if (percent <= 32) {
    526 		if (percent <= 16) {
    527 			increment = 1;
    528 		} else {
    529 			increment = -1;
    530 			obj->is_cursed = 1;
    531 		}
    532 		for (i = 0; i < blessing; i++) {
    533 			if (coin_toss()) {
    534 				obj->hit_enchant += increment;
    535 			} else {
    536 				obj->d_enchant += increment;
    537 			}
    538 		}
    539 	}
    540 	switch(obj->which_kind) {
    541 	case BOW:
    542 	case DART:
    543 		obj->damage = "1d1";
    544 		break;
    545 	case ARROW:
    546 		obj->damage = "1d2";
    547 		break;
    548 	case DAGGER:
    549 		obj->damage = "1d3";
    550 		break;
    551 	case SHURIKEN:
    552 		obj->damage = "1d4";
    553 		break;
    554 	case MACE:
    555 		obj->damage = "2d3";
    556 		break;
    557 	case LONG_SWORD:
    558 		obj->damage = "3d4";
    559 		break;
    560 	case TWO_HANDED_SWORD:
    561 		obj->damage = "4d5";
    562 		break;
    563 	}
    564 }
    565 
    566 void
    567 gr_armor(obj)
    568 	object *obj;
    569 {
    570 	short percent;
    571 	short blessing;
    572 
    573 	obj->what_is = ARMOR;
    574 	obj->which_kind = get_rand(0, (ARMORS - 1));
    575 	obj->class = obj->which_kind + 2;
    576 	if ((obj->which_kind == PLATE) || (obj->which_kind == SPLINT)) {
    577 		obj->class--;
    578 	}
    579 	obj->is_protected = 0;
    580 	obj->d_enchant = 0;
    581 
    582 	percent = get_rand(1, 100);
    583 	blessing = get_rand(1, 3);
    584 
    585 	if (percent <= 16) {
    586 		obj->is_cursed = 1;
    587 		obj->d_enchant -= blessing;
    588 	} else if (percent <= 33) {
    589 		obj->d_enchant += blessing;
    590 	}
    591 }
    592 
    593 void
    594 gr_wand(obj)
    595 	object *obj;
    596 {
    597 	obj->what_is = WAND;
    598 	obj->which_kind = get_rand(0, (WANDS - 1));
    599 	obj->class = get_rand(3, 7);
    600 }
    601 
    602 void
    603 get_food(obj, force_ration)
    604 	object *obj;
    605 	boolean force_ration;
    606 {
    607 	obj->what_is = FOOD;
    608 
    609 	if (force_ration || rand_percent(80)) {
    610 		obj->which_kind = RATION;
    611 	} else {
    612 		obj->which_kind = FRUIT;
    613 	}
    614 }
    615 
    616 void
    617 put_stairs()
    618 {
    619 	short row, col;
    620 
    621 	gr_row_col(&row, &col, (FLOOR | TUNNEL));
    622 	dungeon[row][col] |= STAIRS;
    623 }
    624 
    625 int
    626 get_armor_class(obj)
    627 	const object *obj;
    628 {
    629 	if (obj) {
    630 		return(obj->class + obj->d_enchant);
    631 	}
    632 	return(0);
    633 }
    634 
    635 object *
    636 alloc_object()
    637 {
    638 	object *obj;
    639 
    640 	if (free_list) {
    641 		obj = free_list;
    642 		free_list = free_list->next_object;
    643 	} else if (!(obj = (object *) md_malloc(sizeof(object)))) {
    644 			message("cannot allocate object, saving game", 0);
    645 			save_into_file(error_file);
    646 	}
    647 	obj->quantity = 1;
    648 	obj->ichar = 'L';
    649 	obj->picked_up = obj->is_cursed = 0;
    650 	obj->in_use_flags = NOT_USED;
    651 	obj->identified = UNIDENTIFIED;
    652 	obj->damage = "1d1";
    653 	return(obj);
    654 }
    655 
    656 void
    657 free_object(obj)
    658 	object *obj;
    659 {
    660 	obj->next_object = free_list;
    661 	free_list = obj;
    662 }
    663 
    664 void
    665 make_party()
    666 {
    667 	short n;
    668 
    669 	party_room = gr_room();
    670 
    671 	n = rand_percent(99) ? party_objects(party_room) : 11;
    672 	if (rand_percent(99)) {
    673 		party_monsters(party_room, n);
    674 	}
    675 }
    676 
    677 void
    678 show_objects()
    679 {
    680 	object *obj;
    681 	short mc, rc, row, col;
    682 	object *monster;
    683 
    684 	obj = level_objects.next_object;
    685 
    686 	while (obj) {
    687 		row = obj->row;
    688 		col = obj->col;
    689 
    690 		rc = get_mask_char(obj->what_is);
    691 
    692 		if (dungeon[row][col] & MONSTER) {
    693 			if ((monster =
    694 			    object_at(&level_monsters, row, col)) != NULL) {
    695 				monster->trail_char = rc;
    696 			}
    697 		}
    698 		mc = mvinch(row, col);
    699 		if (((mc < 'A') || (mc > 'Z')) &&
    700 			((row != rogue.row) || (col != rogue.col))) {
    701 			mvaddch(row, col, rc);
    702 		}
    703 		obj = obj->next_object;
    704 	}
    705 
    706 	monster = level_monsters.next_object;
    707 
    708 	while (monster) {
    709 		if (monster->m_flags & IMITATES) {
    710 			mvaddch(monster->row, monster->col, (int) monster->disguise);
    711 		}
    712 		monster = monster->next_monster;
    713 	}
    714 }
    715 
    716 void
    717 put_amulet()
    718 {
    719 	object *obj;
    720 
    721 	obj = alloc_object();
    722 	obj->what_is = AMULET;
    723 	rand_place(obj);
    724 }
    725 
    726 void
    727 rand_place(obj)
    728 	object *obj;
    729 {
    730 	short row, col;
    731 
    732 	gr_row_col(&row, &col, (FLOOR | TUNNEL));
    733 	place_at(obj, row, col);
    734 }
    735 
    736 void
    737 c_object_for_wizard()
    738 {
    739 	short ch, max, wk;
    740 	object *obj;
    741 	char buf[80];
    742 
    743 	max = 0;
    744 	if (pack_count((object *) 0) >= MAX_PACK_COUNT) {
    745 		message("pack full", 0);
    746 		return;
    747 	}
    748 	message("type of object?", 0);
    749 
    750 	while (r_index("!?:)]=/,\033", (ch = rgetchar()), 0) == -1) {
    751 		sound_bell();
    752 	}
    753 	check_message();
    754 
    755 	if (ch == '\033') {
    756 		return;
    757 	}
    758 	obj = alloc_object();
    759 
    760 	switch(ch) {
    761 	case '!':
    762 		obj->what_is = POTION;
    763 		max = POTIONS - 1;
    764 		break;
    765 	case '?':
    766 		obj->what_is = SCROL;
    767 		max = SCROLS - 1;
    768 		break;
    769 	case ',':
    770 		obj->what_is = AMULET;
    771 		break;
    772 	case ':':
    773 		get_food(obj, 0);
    774 		break;
    775 	case ')':
    776 		gr_weapon(obj, 0);
    777 		max = WEAPONS - 1;
    778 		break;
    779 	case ']':
    780 		gr_armor(obj);
    781 		max = ARMORS - 1;
    782 		break;
    783 	case '/':
    784 		gr_wand(obj);
    785 		max = WANDS - 1;
    786 		break;
    787 	case '=':
    788 		max = RINGS - 1;
    789 		obj->what_is = RING;
    790 		break;
    791 	}
    792 	if ((ch != ',') && (ch != ':')) {
    793 GIL:
    794 		if (get_input_line("which kind?", "", buf, "", 0, 1)) {
    795 			wk = get_number(buf);
    796 			if ((wk >= 0) && (wk <= max)) {
    797 				obj->which_kind = (unsigned short) wk;
    798 				if (obj->what_is == RING) {
    799 					gr_ring(obj, 0);
    800 				}
    801 			} else {
    802 				sound_bell();
    803 				goto GIL;
    804 			}
    805 		} else {
    806 			free_object(obj);
    807 			return;
    808 		}
    809 	}
    810 	get_desc(obj, buf);
    811 	message(buf, 0);
    812 	(void) add_to_pack(obj, &rogue.pack, 1);
    813 }
    814