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