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