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