Esempio n. 1
0
/*
 * Know inventory and home items upon death
 */
static void death_knowledge(void)
{
	store_type *st_ptr = &store[STORE_HOME];
	object_type *o_ptr;

	int i;

	for (i = 0; i < ALL_INVEN_TOTAL; i++)
	{
		o_ptr = &p_ptr->inventory[i];
		if (!o_ptr->kind) continue;

		object_flavor_aware(o_ptr);
		object_notice_everything(o_ptr);
	}

	for (i = 0; i < st_ptr->stock_num; i++)
	{
		o_ptr = &st_ptr->stock[i];
		if (!o_ptr->kind) continue;

		object_flavor_aware(o_ptr);
		object_notice_everything(o_ptr);
	}

	history_unmask_unknown();

	/* Hack -- Recalculate bonuses */
	p_ptr->update |= (PU_BONUS);
	handle_stuff(p_ptr);
}
Esempio n. 2
0
/*
 * Become aware of a lot of objects
 */
static void do_cmd_wiz_learn(void)
{
	int i;

	object_type *i_ptr;
	object_type object_type_body;

	/* Scan every object */
	for (i = 1; i < z_info->k_max; i++)
	{
		object_kind *k_ptr = &k_info[i];

		if (!k_ptr || !k_ptr->name) continue;

		/* Induce awareness */
		if (k_ptr->level <= p_ptr->command_arg)
		{
			/* Get local object */
			i_ptr = &object_type_body;

			/* Prepare object */
			object_prep(i_ptr, k_ptr, 0, MAXIMISE);

			/* Awareness */
			object_flavor_aware(i_ptr);
		}
	}
	
	msg("You now know about many items!");
}
Esempio n. 3
0
/**
 * Notice the "effect" from activating an object.
 *
 * \param o_ptr is the object to become aware of
 */
void object_notice_effect(object_type *o_ptr)
{
	if (object_add_ident_flags(o_ptr, IDENT_EFFECT))
		object_check_for_ident(o_ptr);

	/* noticing an effect gains awareness */
	if (!object_flavor_is_aware(o_ptr))
		object_flavor_aware(o_ptr);
}
Esempio n. 4
0
/**
 * Notice things about an object that would be noticed in time.
 */
static void object_notice_after_time(void)
{
	int i;
	int flag;

	object_type *o_ptr;
	char o_name[80];

	bitflag f[OF_SIZE], timed_mask[OF_SIZE];

	flags_init(timed_mask, OF_SIZE, OF_NOTICE_TIMED_MASK, FLAG_END);

	/* Check every item the player is wearing */
	for (i = INVEN_WIELD; i < ALL_INVEN_TOTAL; i++)
	{
		o_ptr = &p_ptr->inventory[i];

		if (!o_ptr->k_idx || object_is_known(o_ptr)) continue;

		/* Check for timed notice flags */
		object_desc(o_name, sizeof(o_name), o_ptr, ODESC_BASE);
		object_flags(o_ptr, f);
		of_inter(f, timed_mask);

		for (flag = of_next(f, FLAG_START); flag != FLAG_END; flag = of_next(f, flag + 1))
		{
			if (!of_has(o_ptr->known_flags, flag))
			{
				/* Message */
				if (!streq(msgs[flag], ""))
					msg_format(msgs[flag], o_name);

				/* Notice the flag */
				object_notice_flag(o_ptr, flag);

				if (object_is_jewelry(o_ptr) &&
					 (!object_effect(o_ptr) || object_effect_is_known(o_ptr)))
				{
					/* XXX this is a small hack, but jewelry with anything noticeable really is obvious */
					/* XXX except, wait until learn activation if that is only clue */
					object_flavor_aware(o_ptr);
					object_check_for_ident(o_ptr);
				}
			}
			else
			{
				/* Notice the flag is absent */
				object_notice_flag(o_ptr, flag);
			}
		}

		/* XXX Is this necessary? */
		object_check_for_ident(o_ptr);
	}
}
Esempio n. 5
0
/**
 * Notice a given special flag on wielded items.
 *
 * \param flag is the flag to notice
 */
void wieldeds_notice_flag(int flag)
{
	int i;

	/* XXX Eddie need different naming conventions for starting wieldeds at INVEN_WIELD vs INVEN_WIELD+2 */
	for (i = INVEN_WIELD; i < ALL_INVEN_TOTAL; i++)
	{
		object_type *o_ptr = &p_ptr->inventory[i];
		bitflag f[OF_SIZE];

		if (!o_ptr->k_idx) continue;

		object_flags(o_ptr, f);

		if (of_has(f, flag) && !of_has(o_ptr->known_flags, flag))
		{
			char o_name[80];
			object_desc(o_name, sizeof(o_name), o_ptr, ODESC_BASE);

			/* Notice the flag */
			object_notice_flag(o_ptr, flag);

			/* XXX Eddie should this go before noticing the flag to avoid learning twice? */
			if (EASY_LEARN && object_is_jewelry(o_ptr))
			{
				/* XXX Eddie EASY_LEARN Possible concern: gets =teleportation just from +2 speed */
				object_flavor_aware(o_ptr);
				object_check_for_ident(o_ptr);
			}

			/* Message */
			if (!streq(msgs[flag], ""))
				msg_format(msgs[flag], o_name);
		}
		else
		{
			/* Notice that flag is absent */
			object_notice_flag(o_ptr, flag);
		}

		/* XXX Eddie should not need this, should be done in noticing, but will remove later */
		object_check_for_ident(o_ptr);

	}

	return;
}
Esempio n. 6
0
/**
 * Mark as object as fully known, a.k.a identified. 
 * Mark as object as fully known, a.k.a identified.
 *
 * \param o_ptr is the object to mark as identified
 */
void object_notice_everything(object_type *o_ptr)
{
	artifact_type *a_ptr = artifact_of(o_ptr);

	/* The object is "empty" */
	o_ptr->ident &= ~(IDENT_EMPTY);

	/* Mark as known */
	object_flavor_aware(o_ptr);
	object_add_ident_flags(o_ptr, IDENTS_SET_BY_IDENTIFY);

	/* Artifact has now been seen */
	if (a_ptr && !(o_ptr->ident & IDENT_FAKE))
	{
		a_ptr->seen = a_ptr->everseen = TRUE;
		history_add_artifact(o_ptr->name1, TRUE, TRUE);
	}

	/* Know all flags there are to be known */
	object_know_all_flags(o_ptr);
}
Esempio n. 7
0
/**
 * Add an item to the players inventory.
 *
 * If the new item can combine with an existing item in the inventory,
 * it will do so, using object_similar() and object_absorb(), else,
 * the item will be placed into the first available gear array index.
 *
 * This function can be used to "over-fill" the player's pack, but only
 * once, and such an action must trigger the "overflow" code immediately.
 * Note that when the pack is being "over-filled", the new item must be
 * placed into the "overflow" slot, and the "overflow" must take place
 * before the pack is reordered, but (optionally) after the pack is
 * combined.  This may be tricky.  See "dungeon.c" for info.
 *
 * Note that this code removes any location information from the object once
 * it is placed into the inventory, but takes no responsibility for removing
 * the object from any other pile it was in.
 */
void inven_carry(struct player *p, struct object *obj, bool absorb,
				 bool message)
{
	struct object *gear_obj;
	char o_name[80];

	/* Check for combining, if appropriate */
	if (absorb) {
		for (gear_obj = p->gear; gear_obj; gear_obj = gear_obj->next) {
			/* Can't stack equipment */
			if (object_is_equipped(p->body, gear_obj))
				continue;

			/* Check if the two items can be combined */
			if (object_similar(gear_obj, obj, OSTACK_PACK)) {
				/* Increase the weight */
				p->upkeep->total_weight += (obj->number * obj->weight);

				/* Combine the items, and their known versions */
				object_absorb(gear_obj->known, obj->known);
				obj->known = NULL;
				object_absorb(gear_obj, obj);

				/* Describe the combined object */
				object_desc(o_name, sizeof(o_name), gear_obj,
							ODESC_PREFIX | ODESC_FULL);

				/* Recalculate bonuses */
				p->upkeep->update |= (PU_BONUS | PU_INVEN);

				/* Redraw stuff */
				p->upkeep->redraw |= (PR_INVEN);

				/* Inventory will need updating */
				update_stuff(player);

				/* Optionally, display a message */
				if (message)
					msg("You have %s (%c).", o_name, gear_to_label(gear_obj));

				/* Sound for quiver objects */
				if (object_is_in_quiver(p, gear_obj))
					sound(MSG_QUIVER);

				/* Success */
				return;
			}
		}
	}

	/* Paranoia */
	assert(pack_slots_used(p) <= z_info->pack_size);

	/* Add to the end of the list */
	gear_insert_end(obj);

	/* Apply an autoinscription */
	apply_autoinscription(obj);

	/* Remove cave object details */
	obj->held_m_idx = 0;
	obj->iy = obj->ix = 0;
	obj->known->iy = obj->known->ix = 0;

	/* Update the inventory */
	p->upkeep->total_weight += (obj->number * obj->weight);
	p->upkeep->update |= (PU_BONUS | PU_INVEN);
	p->upkeep->notice |= (PN_COMBINE);
	p->upkeep->redraw |= (PR_INVEN);

	/* Inventory will need updating */
	update_stuff(player);

	/* Hobbits ID mushrooms on pickup, gnomes ID wands and staffs on pickup */
	if (!object_flavor_is_aware(obj)) {
		if (player_has(player, PF_KNOW_MUSHROOM) && tval_is_mushroom(obj)) {
			object_flavor_aware(obj);
			msg("Mushrooms for breakfast!");
		} else if (player_has(player, PF_KNOW_ZAPPER) && tval_is_zapper(obj))
			object_flavor_aware(obj);
	}

	/* Optionally, display a message */
	if (message) {
		/* Describe the object */
		object_desc(o_name, sizeof(o_name), obj, ODESC_PREFIX | ODESC_FULL);

		/* Message */
		msg("You have %s (%c).", o_name, gear_to_label(obj));
	}

	/* Sound for quiver objects */
	if (object_is_in_quiver(p, obj))
		sound(MSG_QUIVER);
}
Esempio n. 8
0
/*
 * Use an object the right way.
 *
 * There may be a BIG problem with any "effect" that can cause "changes"
 * to the inventory.  For example, a "scroll of recharging" can cause
 * a wand/staff to "disappear", moving the inventory up.  Luckily, the
 * scrolls all appear BEFORE the staffs/wands, so this is not a problem.
 * But, for example, a "staff of recharging" could cause MAJOR problems.
 * In such a case, it will be best to either (1) "postpone" the effect
 * until the end of the function, or (2) "change" the effect, say, into
 * giving a staff "negative" charges, or "turning a staff into a stick".
 * It seems as though a "rod of recharging" might in fact cause problems.
 * The basic problem is that the act of recharging (and destroying) an
 * item causes the inducer of that action to "move", causing "o_ptr" to
 * no longer point at the correct item, with horrifying results.
 */
void do_cmd_use(cmd_code code, cmd_arg args[])
{
	int item = args[0].item;
	object_type *o_ptr = object_from_item_idx(item);
	int effect;
	bool ident = FALSE, used = FALSE;
	bool was_aware = object_flavor_is_aware(o_ptr);
	int dir = 5;
	int px = p_ptr->px, py = p_ptr->py;
	int snd, boost, level;
	use_type use;
	int items_allowed = 0;

	/* Determine how this item is used. */
	if (obj_is_rod(o_ptr))
	{
		if (!obj_can_zap(o_ptr))
		{
			msg("That rod is still charging.");
			return;
		}

		use = USE_TIMEOUT;
		snd = MSG_ZAP_ROD;
		items_allowed = USE_INVEN | USE_FLOOR;
	}
	else if (obj_is_wand(o_ptr))
	{
		if (!obj_has_charges(o_ptr))
		{
			msg("That wand has no charges.");
			return;
		}

		use = USE_CHARGE;
		snd = MSG_ZAP_ROD;
		items_allowed = USE_INVEN | USE_FLOOR;
	}
	else if (obj_is_staff(o_ptr))
	{
		if (!obj_has_charges(o_ptr))
		{
			msg("That staff has no charges.");
			return;
		}

		use = USE_CHARGE;
		snd = MSG_USE_STAFF;
		items_allowed = USE_INVEN | USE_FLOOR;
	}
	else if (obj_is_food(o_ptr))
	{
		use = USE_SINGLE;
		snd = MSG_EAT;
		items_allowed = USE_INVEN | USE_FLOOR;
	}
	else if (obj_is_potion(o_ptr))
	{
		use = USE_SINGLE;
		snd = MSG_QUAFF;
		items_allowed = USE_INVEN | USE_FLOOR;
	}
	else if (obj_is_scroll(o_ptr))
	{
		/* Check player can use scroll */
		if (!player_can_read())
			return;

		use = USE_SINGLE;
		snd = MSG_GENERIC;
		items_allowed = USE_INVEN | USE_FLOOR;
	}
	else if (obj_is_activatable(o_ptr))
	{
		if (!obj_can_activate(o_ptr))
		{
			msg("That item is still charging.");
			return;
		}

		use = USE_TIMEOUT;
		snd = MSG_ACT_ARTIFACT;
		items_allowed = USE_EQUIP;
	}
	else
	{
		msg("The item cannot be used at the moment");
	}

	/* Check if item is within player's reach. */
	if (items_allowed == 0 || !item_is_available(item, NULL, items_allowed))
	{
		msg("You cannot use that item from its current location.");
		return;
	}

	/* track the object used */
	track_object(item);

	/* Figure out effect to use */
	effect = object_effect(o_ptr);

	/* If the item requires a direction, get one (allow cancelling) */
	if (obj_needs_aim(o_ptr))
		dir = args[1].direction;

	/* Check for use if necessary, and execute the effect */
	if ((use != USE_CHARGE && use != USE_TIMEOUT) || check_devices(o_ptr))
	{
		int beam = beam_chance(o_ptr->tval);

		/* Special message for artifacts */
		if (o_ptr->artifact)
		{
			msgt(snd, "You activate it.");
			if (o_ptr->artifact->effect_msg)
				activation_message(o_ptr, o_ptr->artifact->effect_msg);
			level = o_ptr->artifact->level;
		}
		else
		{
			/* Make a noise! */
			sound(snd);
			level = o_ptr->kind->level;
		}

		/* A bit of a hack to make ID work better.
			-- Check for "obvious" effects beforehand. */
		if (effect_obvious(effect)) object_flavor_aware(o_ptr);

		/* Boost damage effects if skill > difficulty */
		boost = MAX(p_ptr->state.skills[SKILL_DEVICE] - level, 0);

		/* Do effect */
		used = effect_do(effect, &ident, was_aware, dir, beam, boost);

		/* Quit if the item wasn't used and no knowledge was gained */
		if (!used && (was_aware || !ident)) return;
	}

	/* If the item is a null pointer or has been wiped, be done now */
	if (!o_ptr || !o_ptr->kind) return;

	if (ident) object_notice_effect(o_ptr);

	/* Food feeds the player */
	if (o_ptr->tval == TV_FOOD || o_ptr->tval == TV_POTION)
		(void)set_food(p_ptr->food + o_ptr->pval[DEFAULT_PVAL]);

	/* Use the turn */
	p_ptr->energy_use = 100;

	/* Mark as tried and redisplay */
	p_ptr->notice |= (PN_COMBINE | PN_REORDER);
	p_ptr->redraw |= (PR_INVEN | PR_EQUIP | PR_OBJECT);

	/*
	 * If the player becomes aware of the item's function, then mark it as
	 * aware and reward the player with some experience.  Otherwise, mark
	 * it as "tried".
	 */
	if (ident && !was_aware)
	{
		/* Object level */
		int lev = o_ptr->kind->level;

		object_flavor_aware(o_ptr);
		if (o_ptr->tval == TV_ROD) object_notice_everything(o_ptr);
		player_exp_gain(p_ptr, (lev + (p_ptr->lev / 2)) / p_ptr->lev);
		p_ptr->notice |= PN_SQUELCH;
	}
	else if (used)
	{
		object_flavor_tried(o_ptr);
	}

	/* If there are no more of the item left, then we're done. */
	if (!o_ptr->number) return;

	/* Chargeables act differently to single-used items when not used up */
	if (used && use == USE_CHARGE)
	{
		/* Use a single charge */
		o_ptr->pval[DEFAULT_PVAL]--;

		/* Describe charges */
		if (item >= 0)
			inven_item_charges(item);
		else
			floor_item_charges(0 - item);
	}
	else if (used && use == USE_TIMEOUT)
	{
		/* Artifacts use their own special field */
		if (o_ptr->artifact)
			o_ptr->timeout = randcalc(o_ptr->artifact->time, 0, RANDOMISE);
		else
			o_ptr->timeout += randcalc(o_ptr->kind->time, 0, RANDOMISE);
	}
	else if (used && use == USE_SINGLE)
	{
		/* Destroy a potion in the pack */
		if (item >= 0)
		{
			inven_item_increase(item, -1);
			inven_item_describe(item);
			inven_item_optimize(item);
		}

		/* Destroy a potion on the floor */
		else
		{
			floor_item_increase(0 - item, -1);
			floor_item_describe(0 - item);
			floor_item_optimize(0 - item);
		}
	}
	
	/* Hack to make Glyph of Warding work properly */
	if (cave->feat[py][px] == FEAT_GLYPH)
	{
		/* Push objects off the grid */
		if (cave->o_idx[py][px]) push_object(py, px);
	}


}
Esempio n. 9
0
/* XXX Eddie should messages be adhoc all over the place?  perhaps the main
 * loop should check for change in inventory/wieldeds and all messages be
 * printed from one place
 */
void object_notice_on_wield(object_type *o_ptr)
{
	bitflag f[OF_SIZE], obvious_mask[OF_SIZE];
	bool obvious = FALSE;
	const slay_t *s_ptr;

	flags_init(obvious_mask, OF_SIZE, OF_OBVIOUS_MASK, FLAG_END);

	/* Save time of wield for later */
	object_last_wield = turn;

	/* Only deal with un-ID'd items */
	if (object_is_known(o_ptr)) return;

	/* Wear it */
	object_flavor_tried(o_ptr);
	if (object_add_ident_flags(o_ptr, IDENT_WORN))
		object_check_for_ident(o_ptr);

	if (obj_is_light(o_ptr) && ego_item_p(o_ptr))
		object_notice_ego(o_ptr);

	if (object_flavor_is_aware(o_ptr) && easy_know(o_ptr))
	{
		object_notice_everything(o_ptr);
		return;
	}

	/* Automatically sense artifacts upon wield */
	object_sense_artifact(o_ptr);

	/* Note artifacts when found */
	if (artifact_p(o_ptr))
		history_add_artifact(o_ptr->name1, object_is_known(o_ptr), TRUE);

	/* special case FA, needed at least for mages wielding gloves */
	if (object_FA_would_be_obvious(o_ptr))
		of_on(obvious_mask, OF_FREE_ACT);

	/* Learn about obvious flags */
	of_union(o_ptr->known_flags, obvious_mask);

	/* Extract the flags */
	object_flags(o_ptr, f);

	/* Find obvious things (disregarding curses) */
	flags_clear(obvious_mask, OF_SIZE, OF_CURSE_MASK, FLAG_END);
	if (of_is_inter(f, obvious_mask)) obvious = TRUE;
	flags_init(obvious_mask, OF_SIZE, OF_OBVIOUS_MASK, FLAG_END);

	/* XXX Eddie should these next NOT call object_check_for_ident due to worries about repairing? */


	/* XXX Eddie this is a small hack, but jewelry with anything noticeable really is obvious */
	/* XXX Eddie learn =soulkeeping vs =bodykeeping when notice sustain_str */
	if (object_is_jewelry(o_ptr))
	{
		/* Learn the flavor of jewelry with obvious flags */
		if (EASY_LEARN && obvious)
			object_flavor_aware(o_ptr);

		/* Learn all flags on any aware non-artifact jewelry */
		if (object_flavor_is_aware(o_ptr) && !artifact_p(o_ptr))
			object_know_all_flags(o_ptr);
	}

	object_check_for_ident(o_ptr);

	if (!obvious) return;

	/* Messages */
	for (s_ptr = slay_table; s_ptr->slay_flag; s_ptr++)
	{
		if (of_has(f, s_ptr->slay_flag) && s_ptr->brand)
		{
			char o_name[40];
			object_desc(o_name, sizeof(o_name), o_ptr, ODESC_BASE);
			msg_format("Your %s %s!", o_name, s_ptr->active_verb);
		}
	}

	/* XXX Eddie need to add stealth here, also need to assert/double-check everything is covered */
	if (of_has(f, OF_STR))
		msg_format("You feel %s!", o_ptr->pval > 0 ? "stronger" : "weaker");
	if (of_has(f, OF_INT))
		msg_format("You feel %s!", o_ptr->pval > 0 ? "smarter" : "more stupid");
	if (of_has(f, OF_WIS))
		msg_format("You feel %s!", o_ptr->pval > 0 ? "wiser" : "more naive");
	if (of_has(f, OF_DEX))
		msg_format("You feel %s!", o_ptr->pval > 0 ? "more dextrous" : "clumsier");
	if (of_has(f, OF_CON))
		msg_format("You feel %s!", o_ptr->pval > 0 ? "healthier" : "sicklier");
	if (of_has(f, OF_CHR))
		msg_format("You feel %s!", o_ptr->pval > 0 ? "cuter" : "uglier");
	if (of_has(f, OF_SPEED))
		msg_format("You feel strangely %s.", o_ptr->pval > 0 ? "quick" : "sluggish");
	if (flags_test(f, OF_SIZE, OF_BLOWS, OF_SHOTS, FLAG_END))
		msg_format("Your hands %s", o_ptr->pval > 0 ? "tingle!" : "ache.");
	if (of_has(f, OF_INFRA))
		msg_format("Your eyes tingle.");
	if (of_has(f, OF_LIGHT))
		msg_print("It glows!");
	if (of_has(f, OF_TELEPATHY))
		msg_print("Your mind feels strangely sharper!");

	/* WARNING -- masking f by obvious mask -- this should be at the end of this function */
	flags_mask(f, OF_SIZE, OF_OBVIOUS_MASK, FLAG_END);

	/* learn the ego on any obvious brand or slay */
	if (EASY_LEARN && ego_item_p(o_ptr) && obvious &&
	    flags_test(f, OF_SIZE, OF_ALL_SLAY_MASK, FLAG_END))
		object_notice_ego(o_ptr);

	/* Remember the flags */
	object_notice_sensing(o_ptr);

	/* XXX Eddie should we check_for_ident here? */
}
Esempio n. 10
0
/**
 * Add an item to the players inventory.
 *
 * If the new item can combine with an existing item in the inventory,
 * it will do so, using object_similar() and object_absorb(), else,
 * the item will be placed into the first available gear array index.
 *
 * This function can be used to "over-fill" the player's pack, but only
 * once, and such an action must trigger the "overflow" code immediately.
 * Note that when the pack is being "over-filled", the new item must be
 * placed into the "overflow" slot, and the "overflow" must take place
 * before the pack is reordered, but (optionally) after the pack is
 * combined.  This may be tricky.  See "dungeon.c" for info.
 *
 * Note that this code removes any location information from the object once
 * it is placed into the inventory, but takes no responsibility for removing
 * the object from any other pile it was in.
 */
void inven_carry(struct player *p, struct object *obj, bool absorb,
				 bool message)
{
	bool combining = false;

	/* Check for combining, if appropriate */
	if (absorb) {
		struct object *combine_item = NULL;

		struct object *gear_obj = p->gear;
		while (combine_item == false && gear_obj) {
			if (!object_is_equipped(p->body, gear_obj) &&
					object_similar(gear_obj, obj, OSTACK_PACK)) {
				combine_item = gear_obj;
			}

			gear_obj = gear_obj->next;
		}

		if (combine_item) {
			/* Increase the weight */
			p->upkeep->total_weight += (obj->number * obj->weight);

			/* Combine the items, and their known versions */
			object_absorb(combine_item->known, obj->known);
			obj->known = NULL;
			object_absorb(combine_item, obj);

			obj = combine_item;
			combining = true;
		}
	}

	/* We didn't manage the find an object to combine with */
	if (!combining) {
		/* Paranoia */
		assert(pack_slots_used(p) <= z_info->pack_size);

		gear_insert_end(obj);
		apply_autoinscription(obj);

		/* Remove cave object details */
		obj->held_m_idx = 0;
		obj->grid = loc(0, 0);
		obj->known->grid = loc(0, 0);

		/* Update the inventory */
		p->upkeep->total_weight += (obj->number * obj->weight);
		p->upkeep->notice |= (PN_COMBINE);

		/* Hobbits ID mushrooms on pickup, gnomes ID wands and staffs on pickup */
		if (!object_flavor_is_aware(obj)) {
			if (player_has(player, PF_KNOW_MUSHROOM) && tval_is_mushroom(obj)) {
				object_flavor_aware(obj);
				msg("Mushrooms for breakfast!");
			} else if (player_has(player, PF_KNOW_ZAPPER) && tval_is_zapper(obj))
				object_flavor_aware(obj);
		}
	}

	p->upkeep->update |= (PU_BONUS | PU_INVEN);
	p->upkeep->redraw |= (PR_INVEN);
	update_stuff(player);

	if (message) {
		char o_name[80];
		object_desc(o_name, sizeof(o_name), obj, ODESC_PREFIX | ODESC_FULL);
		msg("You have %s (%c).", o_name, gear_to_label(obj));
	}

	if (object_is_in_quiver(p, obj))
		sound(MSG_QUIVER);
}