Exemplo n.º 1
0
/*
 * Checks for additional knowledge implied by what the player already knows.
 *
 * \param o_ptr is the object to check
 *
 * returns whether it calls object_notice_everyting
 */
bool object_check_for_ident(object_type *o_ptr)
{
	bitflag flags[OF_SIZE], known_flags[OF_SIZE];
	
	object_flags(o_ptr, flags);
	object_flags_known(o_ptr, known_flags);

	/* Some flags are irrelevant or never learned or too hard to learn */
	flags_clear(flags, OF_SIZE, OF_OBJ_ONLY_MASK, FLAG_END);
	flags_clear(known_flags, OF_SIZE, OF_OBJ_ONLY_MASK, FLAG_END);

	if (!of_is_equal(flags, known_flags)) return FALSE;

	/* If we know attack bonuses, and defence bonuses, and effect, then
	 * we effectively know everything, so mark as such */
	if ((object_attack_plusses_are_visible(o_ptr) || (object_was_sensed(o_ptr) && o_ptr->to_h == 0 && o_ptr->to_d == 0)) &&
	    (object_defence_plusses_are_visible(o_ptr) || (object_was_sensed(o_ptr) && o_ptr->to_a == 0)) &&
	    (object_effect_is_known(o_ptr) || !object_effect(o_ptr)))
	{
		object_notice_everything(o_ptr);
		return TRUE;
	}

	/* We still know all the flags, so we still know if it's an ego */
	else if (ego_item_p(o_ptr))
	{
		/* require worn status so you don't learn launcher of accuracy or gloves of slaying before wield */
		if (object_was_worn(o_ptr))
			object_notice_ego(o_ptr);
	}

	return FALSE;
}
Exemplo n.º 2
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);
	}
}
Exemplo n.º 3
0
/**
 * Gives the known effects of using the given item.
 *
 * Fills in:
 *  - the effect
 *  - whether the effect can be aimed
 *  -  the minimum and maximum time in game turns for the item to recharge 
 *     (or zero if it does not recharge)
 *  - the percentage chance of the effect failing when used
 *
 * Return false if the object has no effect.
 */
static bool obj_known_effect(const struct object *obj, struct effect **effect,
								 bool *aimed, int *min_recharge,
								 int *max_recharge, int *failure_chance)
{
	random_value timeout = {0, 0, 0, 0};

	*effect = 0;
	*min_recharge = 0;
	*max_recharge = 0;
	*failure_chance = 0;
	*aimed = false;

	if (object_effect_is_known(obj)) {
		*effect = object_effect(obj);
		timeout = obj->time;
		if (effect_aim(*effect))
			*aimed = true;;
	} else if (object_effect(obj)) {
		/* Don't know much - be vague */
		*effect = NULL;

		if (!obj->artifact && effect_aim(object_effect(obj)))
			*aimed = true;

		return true;
	} else {
		/* No effect - no info */
		return false;
	}

	if (randcalc(timeout, 0, MAXIMISE) > 0)	{
		*min_recharge = randcalc(timeout, 0, MINIMISE);
		*max_recharge = randcalc(timeout, 0, MAXIMISE);
	}

	if (tval_is_edible(obj) || tval_is_potion(obj) || tval_is_scroll(obj)) {
		*failure_chance = 0;
	} else {
		*failure_chance = get_use_device_chance(obj);
	}

	return true;
}
Exemplo n.º 4
0
/**
 * Add power for effect
 */
static int effects_power(const object_type *obj, int p, bool known)
{
	int q = 0;

	if (known || object_effect_is_known(obj))	{
		if (obj->artifact && obj->artifact->activation &&
			obj->artifact->activation->power) {
			q = obj->artifact->activation->power;
		} else if (obj->kind->power) {
			q = obj->kind->power;
		}

		if (q) {
			p += q;
			log_obj(format("Add %d power for item activation, total is %d\n",
						   q, p));
		}
	}
	return p;
}
Exemplo n.º 5
0
/**
 * Gives the known effects of using the given item.
 *
 * Fills in:
 *  - the effect id, or OBJ_KNOWN_PRESENT if there is an effect but details
 *    are unknown
 *  - whether the effect can be aimed
 *  -  the minimum and maximum time in game turns for the item to recharge 
 *     (or zero if it does not recharge)
 *  - the percentage chance of the effect failing when used
 *
 * Return FALSE if the object has no effect.
 */
static bool obj_known_effect(const struct object *obj, int *effect, bool *aimed, int *min_recharge, int *max_recharge, int *failure_chance)
{
	random_value timeout = {0, 0, 0, 0};

	*effect = 0;
	*min_recharge = 0;
	*max_recharge = 0;
	*failure_chance = 0;
	*aimed = FALSE;

	if (object_effect_is_known(obj)) {
		*effect = object_effect(obj);
		timeout = obj->time;
	} else if (object_effect(obj)) {
		/* Don't know much - be vague */
		*effect = OBJ_KNOWN_PRESENT;

		if (!obj->artifact && effect_aim(obj->effect))
			*aimed = TRUE;
					
		return TRUE;
	} else {
		/* No effect - no info */
		return FALSE;
	}
	
	if (randcalc(timeout, 0, MAXIMISE) > 0)	{
		*min_recharge = randcalc(timeout, 0, MINIMISE);
		*max_recharge = randcalc(timeout, 0, MAXIMISE);
	}

	if (tval_is_food(obj) || tval_is_potion(obj) || tval_is_scroll(obj)) {
		*failure_chance = 0;
	} else {
		*failure_chance = get_use_device_chance(obj);
	}

	return TRUE;
}
Exemplo n.º 6
0
/*
 * Describe an object's effect, if any.
 */
static bool describe_effect(textblock *tb, const object_type *o_ptr, bool full,
		bool only_artifacts, bool subjective)
{
	const char *desc;
	random_value timeout = {0, 0, 0, 0};

	int effect = 0, fail;

	if (o_ptr->artifact)
	{
		if (object_effect_is_known(o_ptr) || full)
		{
			effect = o_ptr->artifact->effect;
			timeout = o_ptr->artifact->time;
		}
		else if (object_effect(o_ptr))
		{
			textblock_append(tb, "It can be activated.\n");
			return TRUE;
		}
	}
	else
	{
		/* Sometimes only print artifact activation info */
		if (only_artifacts == TRUE) return FALSE;

		if (object_effect_is_known(o_ptr) || full)
		{
			effect = o_ptr->kind->effect;
			timeout = o_ptr->kind->time;
		}
		else if (object_effect(o_ptr) != 0)
		{
			if (effect_aim(o_ptr->kind->effect))
				textblock_append(tb, "It can be aimed.\n");
			else if (o_ptr->tval == TV_FOOD)
				textblock_append(tb, "It can be eaten.\n");
			else if (o_ptr->tval == TV_POTION)
				textblock_append(tb, "It can be drunk.\n");
			else if (o_ptr->tval == TV_SCROLL)
				textblock_append(tb, "It can be read.\n");
			else textblock_append(tb, "It can be activated.\n");

			return TRUE;
		}
	}

	/* Forget it without an effect */
	if (!effect) return FALSE;

	/* Obtain the description */
	desc = effect_desc(effect);
	if (!desc) return FALSE;

	if (effect_aim(effect))
		textblock_append(tb, "When aimed, it ");
	else if (o_ptr->tval == TV_FOOD)
		textblock_append(tb, "When eaten, it ");
	else if (o_ptr->tval == TV_POTION)
		textblock_append(tb, "When drunk, it ");
	else if (o_ptr->tval == TV_SCROLL)
	    textblock_append(tb, "When read, it ");
	else
	    textblock_append(tb, "When activated, it ");

	/* Print a colourised description */
	do
	{
		if (isdigit((unsigned char) *desc))
			textblock_append_c(tb, TERM_L_GREEN, "%c", *desc);
		else
			textblock_append(tb, "%c", *desc);
	} while (*desc++);

	textblock_append(tb, ".\n");

	if (randcalc(timeout, 0, MAXIMISE) > 0)
	{
		int min_time, max_time;

		/* Sometimes adjust for player speed */
		int multiplier = extract_energy[p_ptr->state.speed];
		if (!subjective) multiplier = 10;

		textblock_append(tb, "Takes ");

		/* Correct for player speed */
		min_time = randcalc(timeout, 0, MINIMISE) * multiplier / 10;
		max_time = randcalc(timeout, 0, MAXIMISE) * multiplier / 10;

		textblock_append_c(tb, TERM_L_GREEN, "%d", min_time);

		if (min_time != max_time)
		{
			textblock_append(tb, " to ");
			textblock_append_c(tb, TERM_L_GREEN, "%d", max_time);
		}

		textblock_append(tb, " turns to recharge");
		if (subjective && p_ptr->state.speed != 110)
			textblock_append(tb, " at your current speed");

		textblock_append(tb, ".\n");
	}

	if (!subjective || o_ptr->tval == TV_FOOD || o_ptr->tval == TV_POTION ||
		o_ptr->tval == TV_SCROLL)
	{
		return TRUE;
	}
	else
	{
		fail = get_use_device_chance(o_ptr);
		textblock_append(tb, "Your chance of success is %d.%d%%\n", (1000 - fail) /
			10, (1000 - fail) % 10);
	}

	return TRUE;
}
Exemplo n.º 7
0
/*
 * Display a list of objects.  Each object may be prefixed with a label.
 * Used by show_inven(), show_equip(), and show_floor().  Mode flags are
 * documented in object.h
 */
static void show_obj_list(int num_obj, int num_head, char labels[50][80],
	object_type *objects[50], olist_detail_t mode)
{
	int i, row = 0, col = 0;
	int attr;
	size_t max_len = 0;
	int ex_width = 0, ex_offset, ex_offset_ctr;

	object_type *o_ptr;
	char o_name[50][80];
	char tmp_val[80];
	
	bool in_term = (mode & OLIST_WINDOW) ? TRUE : FALSE;
	bool terse = FALSE;

	if (in_term) max_len = 40;
	if (in_term && Term->wid < 40) mode &= ~(OLIST_WEIGHT);

	if (Term->wid < 50) terse = TRUE;

	/* Calculate name offset and max name length */
	for (i = 0; i < num_obj; i++)
	{
		o_ptr = objects[i];

		/* Null objects are used to skip lines, or display only a label */		
		if (!o_ptr || !o_ptr->kind)
		{
			if (i < num_head)
				strnfmt(o_name[i], sizeof(o_name[i]), "");
			else
				strnfmt(o_name[i], sizeof(o_name[i]), "(nothing)");
		}
		else
			object_desc(o_name[i], sizeof(o_name[i]), o_ptr, ODESC_PREFIX | ODESC_FULL |
				(terse ? ODESC_TERSE : 0));

		/* Max length of label + object name */
		max_len = MAX(max_len, strlen(labels[i]) + strlen(o_name[i]));
	}

	/* Take the quiver message into consideration */
	if (mode & OLIST_QUIVER && p_ptr->quiver_slots > 0)
		max_len = MAX(max_len, 24);

	/* Width of extra fields */
	if (mode & OLIST_WEIGHT) ex_width += 9;
	if (mode & OLIST_PRICE) ex_width += 9;
	if (mode & OLIST_FAIL) ex_width += 10;

	/* Determine beginning row and column */
	if (in_term)
	{
		/* Term window */
		row = 0;
		col = 0;
	}
	else
	{
		/* Main window */
		row = 1;
		col = Term->wid - 1 - max_len - ex_width;

		if (col < 3) col = 0;
	}

	/* Column offset of the first extra field */
	ex_offset = MIN(max_len, (size_t)(Term->wid - 1 - ex_width - col));

	/* Output the list */
	for (i = 0; i < num_obj; i++)
	{
		o_ptr = objects[i];
		
		/* Clear the line */
		prt("", row + i, MAX(col - 2, 0));

		/* If we have no label then we won't display anything */
		if (!strlen(labels[i])) continue;

		/* Print the label */
		put_str(labels[i], row + i, col);

		/* Limit object name */
		if (strlen(labels[i]) + strlen(o_name[i]) > (size_t)ex_offset)
		{
			int truncate = ex_offset - strlen(labels[i]);
			
			if (truncate < 0) truncate = 0;
			if ((size_t)truncate > sizeof(o_name[i]) - 1) truncate = sizeof(o_name[i]) - 1;

			o_name[i][truncate] = '\0';
		}
		
		/* Item kind determines the color of the output */
		if (o_ptr && o_ptr->kind)
			attr = tval_to_attr[o_ptr->tval % N_ELEMENTS(tval_to_attr)];
		else
			attr = TERM_SLATE;

		/* Object name */
		c_put_str(attr, o_name[i], row + i, col + strlen(labels[i]));

		/* If we don't have an object, we can skip the rest of the output */
		if (!(o_ptr && o_ptr->kind)) continue;

		/* Extra fields */
		ex_offset_ctr = ex_offset;
		
		if (mode & OLIST_PRICE)
		{
			int price = price_item(o_ptr, TRUE, o_ptr->number);
			strnfmt(tmp_val, sizeof(tmp_val), "%6d au", price);
			put_str(tmp_val, row + i, col + ex_offset_ctr);
			ex_offset_ctr += 9;
		}

		if (mode & OLIST_FAIL && obj_can_fail(o_ptr))
		{
			int fail = (9 + get_use_device_chance(o_ptr)) / 10;
			if (object_effect_is_known(o_ptr))
				strnfmt(tmp_val, sizeof(tmp_val), "%4d%% fail", fail);
			else
				my_strcpy(tmp_val, "    ? fail", sizeof(tmp_val));
			put_str(tmp_val, row + i, col + ex_offset_ctr);
			ex_offset_ctr += 10;
		}

		if (mode & OLIST_WEIGHT)
		{
			int weight = o_ptr->weight * o_ptr->number;
			strnfmt(tmp_val, sizeof(tmp_val), "%4d.%1d lb", weight / 10, weight % 10);
			put_str(tmp_val, row + i, col + ex_offset_ctr);
			ex_offset_ctr += 9;
		}
	}

	/* For the inventory: print the quiver count */
	if (mode & OLIST_QUIVER)
	{
		int count, j;

		/* Quiver may take multiple lines */
		for(j = 0; j < p_ptr->quiver_slots; j++, i++)
		{
			const char *fmt = "in Quiver: %d missile%s";
			char letter = index_to_label(in_term ? i - 1 : i);

			/* Number of missiles in this "slot" */
			if (j == p_ptr->quiver_slots - 1 && p_ptr->quiver_remainder > 0)
				count = p_ptr->quiver_remainder;
			else
				count = MAX_STACK_SIZE-1;

			/* Clear the line */
			prt("", row + i, MAX(col - 2, 0));

			/* Print the (disabled) label */
			strnfmt(tmp_val, sizeof(tmp_val), "%c) ", letter);
			c_put_str(TERM_SLATE, tmp_val, row + i, col);

			/* Print the count */
			strnfmt(tmp_val, sizeof(tmp_val), fmt, count, count == 1 ? "" : "s");
			c_put_str(TERM_L_UMBER, tmp_val, row + i, col + 3);
		}
	}

	/* Clear term windows */
	if (in_term)
	{
		for (; i < Term->hgt; i++)
		{
			prt("", row + i, MAX(col - 2, 0));
		}
	}
	
	/* Print a drop shadow for the main window if necessary */
	else if (i > 0 && row + i < 24)
	{
		prt("", row + i, MAX(col - 2, 0));
	}
}
Exemplo n.º 8
0
/*
 * Display a list of objects.  Each object may be prefixed with a label.
 * Used by show_inven(), show_equip(), and show_floor().  Mode flags are
 * documented in object.h
 */
static void show_obj_list(int num_obj, char labels[50][80], object_type *objects[50], olist_detail_t mode)
{
	int i, row = 0, col = 0;
	size_t max_len = 0;
	int ex_width = 0, ex_offset, ex_offset_ctr;

	object_type *o_ptr;
	char o_name[50][80];
	char tmp_val[80];
	
	bool in_term;
	
	in_term = (mode & OLIST_WINDOW) ? TRUE : FALSE;

	if (in_term) max_len = 40;

	/* Calculate name offset and max name length */
	for (i = 0; i < num_obj; i++)
	{
		o_ptr = objects[i];

		/* Null objects are used to skip lines, or display only a label */		
		if (o_ptr == NULL) continue;

		/* Max length of label + object name */
		object_desc(o_name[i], sizeof(o_name[i]), o_ptr, ODESC_PREFIX | ODESC_FULL);
		max_len = MAX(max_len, strlen(labels[i]) + strlen(o_name[i]));
	}

	/* Width of extra fields */
	if (mode & OLIST_WEIGHT) ex_width += 9;
	if (mode & OLIST_PRICE) ex_width += 9;
	if (mode & OLIST_FAIL) ex_width += 10;

	/* Determine beginning row and column */
	if (in_term)
	{
		/* Term window */
		row = 0;
		col = 0;
	}
	else
	{
		/* Main window */
		row = 1;
		col = Term->wid - 1 - max_len - ex_width;

		if (col < 3) col = 0;
	}

	/* Column offset of the first extra field */
	ex_offset = MIN(max_len, (size_t)(Term->wid - 1 - ex_width - col));

	/* Output the list */
	for (i = 0; i < num_obj; i++)
	{
		o_ptr = objects[i];
		
		/* Clear the line */
		prt("", row + i, MAX(col - 2, 0));

		/* Print the label */
		put_str(labels[i], row + i, col);

		/* Print the object */
		if (o_ptr != NULL)
		{
			/* Limit object name */
			if (strlen(labels[i]) + strlen(o_name[i]) > (size_t)ex_offset)
			{
				int truncate = ex_offset - strlen(labels[i]);
				
				if (truncate < 0) truncate = 0;
				if ((size_t)truncate > sizeof(o_name[i]) - 1) truncate = sizeof(o_name[i]) - 1;

				o_name[i][truncate] = '\0';
			}

			/* Object name */
			c_put_str(tval_to_attr[o_ptr->tval % N_ELEMENTS(tval_to_attr)], o_name[i],
			          row + i, col + strlen(labels[i]));

			/* Extra fields */
			ex_offset_ctr = ex_offset;
			
			if (mode & OLIST_PRICE)
			{
				int price = price_item(o_ptr, TRUE, o_ptr->number);
				strnfmt(tmp_val, sizeof(tmp_val), "%6d au", price);
				put_str(tmp_val, row + i, col + ex_offset_ctr);
				ex_offset_ctr += 9;
			}

			if (mode & OLIST_FAIL)
			{
				int fail = (9 + get_use_device_chance(o_ptr)) / 10;
				if (object_effect_is_known(o_ptr))
					strnfmt(tmp_val, sizeof(tmp_val), "%4d%% fail", fail);
				else
					my_strcpy(tmp_val, "    ? fail", sizeof(tmp_val));
				put_str(tmp_val, row + i, col + ex_offset_ctr);
				ex_offset_ctr += 10;
			}

			if (mode & OLIST_WEIGHT)
			{
				int weight = o_ptr->weight * o_ptr->number;
				strnfmt(tmp_val, sizeof(tmp_val), "%4d.%1d lb", weight / 10, weight % 10);
				put_str(tmp_val, row + i, col + ex_offset_ctr);
				ex_offset_ctr += 9;
			}
		}
	}

	/* For the inventory: print the quiver count */
	if (mode & OLIST_QUIVER)
	{
		int count, j;

		/* Quiver may take multiple lines */
		for(j = 0; j < p_ptr->quiver_slots; j++, i++)
		{
			/* Number of missiles in this "slot" */
			if (j == p_ptr->quiver_slots - 1 && p_ptr->quiver_remainder > 0)
				count = p_ptr->quiver_remainder;
			else
				count = 99;

			/* Clear the line */
			prt("", row + i, MAX(col - 2, 0));

			/* Print the (disabled) label */
			strnfmt(tmp_val, sizeof(tmp_val), "%c) ", index_to_label(i));
			c_put_str(TERM_SLATE, tmp_val, row + i, col);

			/* Print the count */
			strnfmt(tmp_val, sizeof(tmp_val), "in Quiver: %d missile%s", count,
					count == 1 ? "" : "s");
			c_put_str(TERM_L_UMBER, tmp_val, row + i, col + 3);
		}
	}

	/* Clear term windows */
	if (in_term)
	{
		for (; i < Term->hgt; i++)
		{
			prt("", row + i, MAX(col - 2, 0));
		}
	}
	
	/* Print a drop shadow for the main window if necessary */
	else if (i > 0 && row + i < 24)
	{
		prt("", row + i, MAX(col - 2, 0));
	}
}
Exemplo n.º 9
0
/**
 * Display an object.  Each object may be prefixed with a label.
 * Used by show_inven(), show_equip(), show_quiver() and show_floor().
 * Mode flags are documented in object.h
 */
static void show_obj(int obj_num, int row, int col, bool cursor,
					 olist_detail_t mode)
{
	int attr;
	int label_attr = cursor ? COLOUR_L_BLUE : COLOUR_WHITE;
	int ex_offset_ctr;
	char buf[80];
	struct object *obj = items[obj_num].object;
	bool show_label = mode & (OLIST_WINDOW | OLIST_DEATH) ? true : false;
	int label_size = show_label ? strlen(items[obj_num].label) : 0;
	int equip_label_size = strlen(items[obj_num].equip_label);

	/* Clear the line */
	prt("", row + obj_num, MAX(col - 1, 0));

	/* If we have no label then we won't display anything */
	if (!strlen(items[obj_num].label)) return;

	/* Print the label */
	if (show_label)
		c_put_str(label_attr, items[obj_num].label, row + obj_num, col);

	/* Print the equipment label */
	c_put_str(label_attr, items[obj_num].equip_label, row + obj_num,
			  col + label_size);

	/* Limit object name */
	if (label_size + equip_label_size + strlen(items[obj_num].o_name) >
		(size_t)ex_offset) {
		int truncate = ex_offset - label_size - equip_label_size;

		if (truncate < 0) truncate = 0;
		if ((size_t)truncate > sizeof(items[obj_num].o_name) - 1)
			truncate = sizeof(items[obj_num].o_name) - 1;

		items[obj_num].o_name[truncate] = '\0';
	}

	/* Item kind determines the color of the output */
	if (obj) {
		attr = obj->kind->base->attr;

		/* Unreadable books are a special case */
		if (tval_is_book_k(obj->kind) &&
			(player_object_to_book(player, obj) == NULL)) {
			attr = COLOUR_SLATE;
		}
	} else {
		attr = COLOUR_SLATE;
	}

	/* Object name */
	c_put_str(attr, items[obj_num].o_name, row + obj_num,
			  col + label_size + equip_label_size);

	/* If we don't have an object, we can skip the rest of the output */
	if (!obj) return;

	/* Extra fields */
	ex_offset_ctr = ex_offset;

	/* Price */
	if (mode & OLIST_PRICE) {
		struct store *store = store_at(cave, player->grid);
		if (store) {
			int price = price_item(store, obj, true, obj->number);

			strnfmt(buf, sizeof(buf), "%6d au", price);
			put_str(buf, row + obj_num, col + ex_offset_ctr);
			ex_offset_ctr += 9;
		}
	}

	/* Failure chance for magic devices and activations */
	if (mode & OLIST_FAIL && obj_can_fail(obj)) {
		int fail = (9 + get_use_device_chance(obj)) / 10;
		if (object_effect_is_known(obj))
			strnfmt(buf, sizeof(buf), "%4d%% fail", fail);
		else
			my_strcpy(buf, "    ? fail", sizeof(buf));
		put_str(buf, row + obj_num, col + ex_offset_ctr);
		ex_offset_ctr += 10;
	}

	/* Failure chances for recharging an item; see effect_handler_RECHARGE */
	if (mode & OLIST_RECHARGE) {
		int fail = 1000 / recharge_failure_chance(obj, player->upkeep->recharge_pow);
		if (object_effect_is_known(obj))
			strnfmt(buf, sizeof(buf), "%2d.%1d%% fail", fail / 10, fail % 10);
		else
			my_strcpy(buf, "    ? fail", sizeof(buf));
		put_str(buf, row + obj_num, col + ex_offset_ctr);
		ex_offset_ctr += 10;
	}

	/* Weight */
	if (mode & OLIST_WEIGHT) {
		int weight = obj->weight * obj->number;
		strnfmt(buf, sizeof(buf), "%4d.%1d lb", weight / 10, weight % 10);
		put_str(buf, row + obj_num, col + ex_offset_ctr);
		ex_offset_ctr += 9;
	}
}
Exemplo n.º 10
0
/*
 * Evaluate the object's overall power level.
 */
s32b object_power(const object_type* o_ptr, int verbose, ang_file *log_file,
	bool known)
{
	s32b p = 0, q = 0, slay_pwr = 0;
	unsigned int i, j;
	int extra_stat_bonus = 0, mult = 1, num_slays = 0, k = 1;
	bitflag flags[OF_SIZE], mask[OF_SIZE];

	/* Zero the flag counts */
	for (i = 0; i < N_ELEMENTS(sets); i++)
		sets[i].count = 0;

	/* Extract the flags */
	if (known) {
		file_putf(log_file, "Object is deemed known\n");
		object_flags(o_ptr, flags);
	} else {
		file_putf(log_file, "Object may not be fully known\n");
		object_flags_known(o_ptr, flags);
	}

	/* Log the flags in human-readable form */
	if (verbose)
		log_flags(flags, log_file);

	/* Get the slay power and number of slay/brand types */
	create_mask(mask, FALSE, OFT_SLAY, OFT_KILL, OFT_BRAND, OFT_MAX);
	num_slays = list_slays(flags, mask, NULL, NULL, NULL, TRUE);
	if (num_slays)
		slay_pwr = slay_power(o_ptr, verbose, log_file, known);

	/* Start with any damage boost from the item itself */
	p += (o_ptr->to_d * DAMAGE_POWER / 2);
	file_putf(log_file, "Adding power from to_dam, total is %d\n", p);

	/* Add damage from dice for any wieldable weapon or ammo */
	if (wield_slot(o_ptr) == INVEN_WIELD || obj_is_ammo(o_ptr)) {
		p += (o_ptr->dd * (o_ptr->ds + 1) * DAMAGE_POWER / 4);
		file_putf(log_file, "Adding power for dam dice, total is %d\n", p);
	/* Add 2nd lot of damage power for nonweapons */
	} else if (wield_slot(o_ptr) != INVEN_BOW) {
		p += (o_ptr->to_d * DAMAGE_POWER);
		file_putf(log_file, "Adding power from nonweap to_dam, total is %d\n", p);
		/* Add power boost for nonweapons with combat flags */
		if (num_slays || of_has(flags, OF_BLOWS) || of_has(flags, OF_SHOTS) ||
				of_has(flags, OF_MIGHT)) {
			p += (WEAP_DAMAGE * DAMAGE_POWER);
			file_putf(log_file, "Adding power for nonweap combat flags, total is %d\n", p);
		}
	}

	/* Add ammo damage for launchers, get multiplier and rescale */
	if (wield_slot(o_ptr) == INVEN_BOW) {
		p += (archery[o_ptr->sval / 10].ammo_dam * DAMAGE_POWER / 2);
		file_putf(log_file, "Adding power from ammo, total is %d\n", p);

		mult = bow_multiplier(o_ptr->sval);
		file_putf(log_file, "Base mult for this weapon is %d\n", mult);
	}

	/* Add launcher bonus for ego ammo, multiply for launcher and rescale */
	if (obj_is_ammo(o_ptr)) {
		if (o_ptr->ego)
			p += (archery[o_ptr->tval - TV_SHOT].launch_dam * DAMAGE_POWER / 2);
		p = p * archery[o_ptr->tval - TV_SHOT].launch_mult / (2 * MAX_BLOWS);
		file_putf(log_file, "After multiplying ammo and rescaling, power is %d\n", p);
	}

	/* Add power for extra blows */
	if (of_has(flags, OF_BLOWS)) {
		j = which_pval(o_ptr, OF_BLOWS);
		if (known || object_this_pval_is_visible(o_ptr, j)) {
			if (o_ptr->pval[j] >= INHIBIT_BLOWS) {
				p += INHIBIT_POWER;
				file_putf(log_file, "INHIBITING - too many extra blows\n");
			} else {
				p = p * (MAX_BLOWS + o_ptr->pval[j]) / MAX_BLOWS;
				/* Add boost for assumed off-weapon damage */
				p += (NONWEAP_DAMAGE * o_ptr->pval[j] * DAMAGE_POWER / 2);
				file_putf(log_file, "Adding power for extra blows, total is %d\n", p);
			}
		}
	}

	/* Add power for extra shots - note that we cannot handle negative shots */
	if (of_has(flags, OF_SHOTS)) {
		j = which_pval(o_ptr, OF_SHOTS);
		if (known || object_this_pval_is_visible(o_ptr, j)) {
			if (o_ptr->pval[j] >= INHIBIT_SHOTS) {
				p += INHIBIT_POWER;
				file_putf(log_file, "INHIBITING - too many extra shots\n");
			} else if (o_ptr->pval[j] > 0) {
				p = (p * (1 + o_ptr->pval[j]));
				file_putf(log_file, "Extra shots: multiplying power by 1 + %d, total is %d\n", o_ptr->pval[j], p);
			}
		}
	}

	/* Add power for extra might */
	if (of_has(flags, OF_MIGHT)) {
		j = which_pval(o_ptr, OF_MIGHT);
		if (known || object_this_pval_is_visible(o_ptr, j)) {
			if (o_ptr->pval[j] >= INHIBIT_MIGHT) {
				p += INHIBIT_POWER;
				mult = 1;	/* don't overflow */
				file_putf(log_file, "INHIBITING - too much extra might\n");
			} else
				mult += o_ptr->pval[j];
			file_putf(log_file, "Mult after extra might is %d\n", mult);
		}
	}
	p *= mult;
	file_putf(log_file, "After multiplying power for might, total is %d\n", p);

	/* Apply the correct slay multiplier */
	if (slay_pwr) {
		p = (p * (slay_pwr / 10)) / (tot_mon_power / 10);
		file_putf(log_file, "Adjusted for slay power, total is %d\n", p);
	}

	/* Melee weapons assume MAX_BLOWS per turn, so we must divide by MAX_BLOWS
     * to get equal ratings for launchers. */
	if (wield_slot(o_ptr) == INVEN_BOW) {
		p /= MAX_BLOWS;
		file_putf(log_file, "Rescaling bow power, total is %d\n", p);
	}

	/* Add power for +to_hit */
	p += (o_ptr->to_h * TO_HIT_POWER / 2);
	file_putf(log_file, "Adding power for to hit, total is %d\n", p);

	/* Add power for base AC and adjust for weight */
	if (o_ptr->ac) {
		q += BASE_ARMOUR_POWER;
		q += (o_ptr->ac * BASE_AC_POWER / 2);
		file_putf(log_file, "Adding %d power for base AC value\n", q);

		/* Add power for AC per unit weight */
		if (o_ptr->weight > 0) {
			i = 800 * (o_ptr->ac + o_ptr->to_a) / o_ptr->weight;

			/* Avoid overpricing Elven Cloaks */
			if (i > 450) i = 450;

			q *= i;
			q /= 100;

		/* Weightless (ethereal) armour items get fixed boost */
		} else
			q *= 5;
		p += q;
		file_putf(log_file, "Adding power for AC per unit weight, now %d\n", p);
	}
	/* Add power for +to_ac */
	p += (o_ptr->to_a * TO_AC_POWER / 2);
	file_putf(log_file, "Adding power for to_ac of %d, total is %d\n", o_ptr->to_a, p);
	if (o_ptr->to_a > HIGH_TO_AC) {
		p += ((o_ptr->to_a - (HIGH_TO_AC - 1)) * TO_AC_POWER);
		file_putf(log_file, "Adding power for high to_ac value, total is %d\n", p);
	}
	if (o_ptr->to_a > VERYHIGH_TO_AC) {
		p += ((o_ptr->to_a - (VERYHIGH_TO_AC -1)) * TO_AC_POWER * 2);
		file_putf(log_file, "Adding power for very high to_ac value, total is %d\n", p);
	}
	if (o_ptr->to_a >= INHIBIT_AC) {
		p += INHIBIT_POWER;
		file_putf(log_file, "INHIBITING: AC bonus too high\n");
	}


	/* Add power for light sources by radius XXX Hack - rewrite calc_torch! */
	if (wield_slot(o_ptr) == INVEN_LIGHT) {
		p += BASE_LIGHT_POWER;

		/* Artifact lights have larger radius so add more */
		if (o_ptr->artifact)
			p += BASE_LIGHT_POWER;

		file_putf(log_file, "Adding power for light radius, total is %d\n", p);
	}

	/* Add base power for jewelry */
	if (object_is_jewelry(o_ptr)) {
		p += BASE_JEWELRY_POWER;
		file_putf(log_file, "Adding power for jewelry, total is %d\n", p);
	}

	/* Add power for non-derived flags (derived flags have flag_power 0) */
	for (i = 0; i < OF_MAX; i++) {
		if (of_has(flags, i)) {
			if (flag_uses_pval(i)) {
				j = which_pval(o_ptr, i);
				if (known || object_this_pval_is_visible(o_ptr, j)) {
					k = o_ptr->pval[j];
					extra_stat_bonus += (k * pval_mult(i));
				}
			} else
				k = 1;

			if (flag_power(i)) {
				p += (k * flag_power(i) * slot_mult(i, wield_slot(o_ptr)));
				file_putf(log_file, "Adding power for %s, total is %d\n", flag_name(i), p);
			}

			/* Track combinations of flag types - note we ignore SUST_CHR */
			for (j = 0; j < N_ELEMENTS(sets); j++)
				if ((sets[j].type == obj_flag_type(i)) && (i != OF_SUST_CHR))
					sets[j].count++;
		}
	}

	/* Add extra power term if there are a lot of ability bonuses */
	if (extra_stat_bonus > 249) {
		file_putf(log_file, "Inhibiting!  (Total ability bonus of %d is too high)\n", extra_stat_bonus);
		p += INHIBIT_POWER;
	} else {
		p += ability_power[extra_stat_bonus / 10];
		file_putf(log_file, "Adding power for pval total of %d, total is %d\n", extra_stat_bonus, p);
	}

	/* Add extra power for multiple flags of the same type */
	for (i = 0; i < N_ELEMENTS(sets); i++) {
		if (sets[i].count > 1) {
			p += (sets[i].factor * sets[i].count * sets[i].count);
			file_putf(log_file, "Adding power for multiple flags of type %d, total is %d\n", i, p);
		}

		/* Add bonus if item has a full set of these flags */
		if (sets[i].count == sets[i].size) {
			p += sets[i].bonus;
			file_putf(log_file, "Adding power for full set of type %d, total is %d\n", i, p);
		}
	}

	/* add power for effect */
	if (known || object_effect_is_known(o_ptr))	{
		if (o_ptr->artifact && o_ptr->artifact->effect) {
			p += effect_power(o_ptr->artifact->effect);
			file_putf(log_file, "Adding power for artifact activation, total is %d\n", p);
		} else {
			p += effect_power(o_ptr->kind->effect);
			file_putf(log_file, "Adding power for item activation, total is %d\n", p);
		}
	}

	file_putf(log_file, "FINAL POWER IS %d\n", p);

	return p;
}
Exemplo n.º 11
0
/*
 * Evaluate the object's overall power level.
 */
s32b object_power(const object_type* o_ptr, int verbose, ang_file *log_file,
	bool known)
{
	s32b p = 0;
	object_kind *k_ptr;
	int immunities = 0;
	int misc = 0;
	int lowres = 0;
	int highres = 0;
	int sustains = 0;
	int extra_stat_bonus = 0;
	int i;
	bitflag flags[OF_SIZE];
	const slay_t *s_ptr;

	/* Extract the flags */
	if (known)
	{
		LOG_PRINT("Object is known\n");
		object_flags(o_ptr, flags);
	}
	else
	{
		LOG_PRINT("Object is not fully known\n");
		object_flags_known(o_ptr, flags);
	}

	if (verbose)
	{
		LOG_PRINT("Object flags =");
		for (i = 0; i < (int)OF_SIZE; i++)
			LOG_PRINT1(" %02x", flags[i]);
		LOG_PRINT("\n");
	}

	k_ptr = &k_info[o_ptr->k_idx];

	/* Evaluate certain abilities based on type of object. */
	switch (o_ptr->tval)
	{
		case TV_BOW:
		{
			int mult;

			/*
			 * Damage multiplier for bows should be weighted less than that
			 * for melee weapons, since players typically get fewer shots
			 * than hits (note, however, that the multipliers are applied
			 * afterwards in the bow calculation, not before as for melee
			 * weapons, which tends to bring these numbers back into line).
			 * ToDo: rework evaluation of negative pvals
			 */

			p += (o_ptr->to_d * DAMAGE_POWER / 2);
			LOG_PRINT1("Adding power from to_dam, total is %d\n", p);

			/*
			 * Add the average damage of fully enchanted (good) ammo for this
			 * weapon.  Could make this dynamic based on k_info if desired.
			 * ToDo: precisely that.
			 */

			if (o_ptr->sval == SV_SLING)
			{
				p += (AVG_SLING_AMMO_DAMAGE * DAMAGE_POWER / 2);
			}
			else if (o_ptr->sval == SV_SHORT_BOW ||
				o_ptr->sval == SV_LONG_BOW)
			{
				p += (AVG_BOW_AMMO_DAMAGE * DAMAGE_POWER / 2);
			}
			else if (o_ptr->sval == SV_LIGHT_XBOW ||
				o_ptr->sval == SV_HEAVY_XBOW)
			{
				p += (AVG_XBOW_AMMO_DAMAGE * DAMAGE_POWER / 2);
			}

			LOG_PRINT1("Adding power from ammo, total is %d\n", p);

			mult = bow_multiplier(o_ptr->sval);

			LOG_PRINT1("Base multiplier for this weapon is %d\n", mult);

			if (of_has(flags, OF_MIGHT) &&
			    (known || object_pval_is_visible(o_ptr)))
			{
				if (o_ptr->pval >= INHIBIT_MIGHT || o_ptr->pval < 0)
				{
					p += INHIBIT_POWER;	/* inhibit */
					mult = 1;	/* don't overflow */
					LOG_PRINT("INHIBITING - too much extra might\n");
				}
				else
				{
					mult += o_ptr->pval;
				}
				LOG_PRINT1("Extra might multiple is %d\n", mult);
			}
			p *= mult;
			LOG_PRINT2("Multiplying power by %d, total is %d\n", mult, p);

			if (of_has(flags, OF_SHOTS) &&
			    (known || object_pval_is_visible(o_ptr)))
			{
				LOG_PRINT1("Extra shots: %d\n", o_ptr->pval);

				if (o_ptr->pval >= INHIBIT_SHOTS || o_ptr->pval < 0)
				{
					p += INHIBIT_POWER;	/* inhibit */
					LOG_PRINT("INHIBITING - too many extra shots\n");
				}
				else if (o_ptr->pval > 0)
				{
					p = (p * (1 + o_ptr->pval));
					LOG_PRINT2("Multiplying power by 1 + %d, total is %d\n",
						o_ptr->pval, p);
				}
			}

			/* Apply the correct slay multiplier */
			p = (p * slay_power(o_ptr, verbose, log_file, flags)) / tot_mon_power;
			LOG_PRINT1("Adjusted for slay power, total is %d\n", p);

			if (o_ptr->weight < k_ptr->weight)
			{
				p++;
				LOG_PRINT("Incrementing power by one for low weight\n");
			}

			/*
			 * Correction to match ratings to melee damage ratings.
			 * We multiply all missile weapons by 1.5 in order to compare damage.
			 * (CR 11/20/01 - changed this to 1.25).
			 * (CC 25/07/10 - changed this back to 1.5).
			 * Melee weapons assume MAX_BLOWS per turn, so we must
			 * also divide by MAX_BLOWS to get equal ratings.
			 */
			p = sign(p) * (ABS(p) * BOW_RESCALER / (10 * MAX_BLOWS));
			LOG_PRINT1("Rescaling bow power, total is %d\n", p);

			p += sign(o_ptr->to_h) * (ABS(o_ptr->to_h) * TO_HIT_POWER / 2);
			LOG_PRINT1("Adding power from to_hit, total is %d\n", p);

			break;
		}
		case TV_SHOT:
		case TV_ARROW:
		case TV_BOLT:
		case TV_DIGGING:
		case TV_HAFTED:
		case TV_POLEARM:
		case TV_SWORD:
		{
			p += (o_ptr->dd * (o_ptr->ds + 1) * DAMAGE_POWER / 4);
			LOG_PRINT1("Adding power for dam dice, total is %d\n", p);

			/* Apply the correct slay multiplier */
			p = (p * slay_power(o_ptr, verbose, log_file, flags)) / tot_mon_power;
			LOG_PRINT1("Adjusted for slay power, total is %d\n", p);

			p += (o_ptr->to_d * DAMAGE_POWER / 2);
			LOG_PRINT1("Adding power for to_dam, total is %d\n", p);

			if (of_has(flags, OF_BLOWS) &&
			    (known || object_pval_is_visible(o_ptr)))
			{
				LOG_PRINT1("Extra blows: %d\n", o_ptr->pval);
				if (o_ptr->pval >= INHIBIT_BLOWS || o_ptr->pval < 0)
				{
					p += INHIBIT_POWER;	/* inhibit */
					LOG_PRINT("INHIBITING, too many extra blows or a negative number\n");
				}
				else if (o_ptr->pval > 0)
				{
					p = sign(p) * ((ABS(p) * (MAX_BLOWS + o_ptr->pval)) 
						/ MAX_BLOWS);
					/* Add an extra amount per extra blow to account for damage/branding rings */
					p += ((MELEE_DAMAGE_BOOST + RING_BRAND_DMG) * o_ptr->pval * DAMAGE_POWER / (2 * MAX_BLOWS));
					LOG_PRINT1("Adding power for blows, total is %d\n", p);
				}
			}

			/*
			 * add extra power for multiple slays/brands, as these
			 * add diminishing amounts to average damage
			 */
			i = 0;

			for (s_ptr = slay_table; s_ptr->slay_flag; s_ptr++)
			{
				if (!of_has(flags, s_ptr->slay_flag)) continue;

				i++;
				if (i > 1) p += (i * 3);
			}
			LOG_PRINT1("Adding power for multiple slays/brands, total is %d\n", p);

			/* add launcher bonus for ego ammo, and multiply */
			if (o_ptr->tval == TV_SHOT)
			{
				if (o_ptr->name2) p += (AVG_LAUNCHER_DMG * DAMAGE_POWER / 2);
				p = p * AVG_SLING_MULT * BOW_RESCALER / (20 * MAX_BLOWS);
			}
			if (o_ptr->tval == TV_ARROW)
			{
				if (o_ptr->name2) p += (AVG_LAUNCHER_DMG * DAMAGE_POWER / 2);
				p = p * AVG_BOW_MULT * BOW_RESCALER / (20 * MAX_BLOWS);
			}
			if (o_ptr->tval == TV_BOLT)
			{
				if (o_ptr->name2) p += (AVG_LAUNCHER_DMG * DAMAGE_POWER / 2);
				p = p * AVG_XBOW_MULT * BOW_RESCALER / (20 * MAX_BLOWS);
			}
			LOG_PRINT1("After multiplying ammo and rescaling, power is %d\n", p);

			p += sign(o_ptr->to_h) * (ABS(o_ptr->to_h) * TO_HIT_POWER / 2);
			LOG_PRINT1("Adding power for to hit, total is %d\n", p);

			/* Remember, weight is in 0.1 lb. units. */
			if (o_ptr->weight < k_ptr->weight)
			{
				p += (k_ptr->weight - o_ptr->weight) / 20;
				LOG_PRINT1("Adding power for low weight, total is %d\n", p);
			}

			break;
		}
		case TV_BOOTS:
		case TV_GLOVES:
		case TV_HELM:
		case TV_CROWN:
		case TV_SHIELD:
		case TV_CLOAK:
		case TV_SOFT_ARMOR:
		case TV_HARD_ARMOR:
		case TV_DRAG_ARMOR:
		{
			p += BASE_ARMOUR_POWER;
			LOG_PRINT1("Armour item, base power is %d\n", p);

			p += sign(o_ptr->ac) * ((ABS(o_ptr->ac) * BASE_AC_POWER) / 2);
			LOG_PRINT1("Adding power for base AC value, total is %d\n", p);

			/* Add power for AC per unit weight */
			if (o_ptr->weight > 0)
			{
				i = 1000 * (o_ptr->ac + o_ptr->to_a) /
					o_ptr->weight;

				/* Stop overpricing Elven Cloaks */
				if (i > 400) i = 400;

				/* Adjust power */
				p *= i;
				p /= 100;
			}
			/* Weightless (ethereal) items get fixed boost */
			else p *= 5;

			/* Add power for +hit and +dam */
			p += sign(o_ptr->to_h) * (ABS(o_ptr->to_h) * TO_HIT_POWER);
			LOG_PRINT1("Adding power for to_hit, total is %d\n", p);

			p += o_ptr->to_d * DAMAGE_POWER;
			LOG_PRINT1("Adding power for to_dam, total is %d\n", p);

			/* Apply the correct brand/slay multiplier */
			p += (((2 * (o_ptr->to_d + RING_BRAND_DMG)
				* slay_power(o_ptr, verbose, log_file, flags))
				/ tot_mon_power) - (2 * (o_ptr->to_d + RING_BRAND_DMG)));
			LOG_PRINT1("Adjusted for brand/slay power, total is %d\n", p);

			/* Add power for extra blows */
			if (of_has(flags, OF_BLOWS) &&
			    (known || object_pval_is_visible(o_ptr)))
			{
				LOG_PRINT1("Extra blows: %d\n", o_ptr->pval);
				if (o_ptr->pval >= INHIBIT_BLOWS || o_ptr->pval < 0)
				{
					p += INHIBIT_POWER;	/* inhibit */
					LOG_PRINT("INHIBITING, too many extra blows or a negative number\n");
				}
				else if (o_ptr->pval > 0)
				{
					p += ((MELEE_DAMAGE_BOOST + RING_BRAND_DMG + o_ptr->to_d) * o_ptr->pval * DAMAGE_POWER / MAX_BLOWS);
					LOG_PRINT1("Adding power for extra blows, total is %d\n", p);
				}
			}

			/* Add power for extra shots */
			if (of_has(flags, OF_SHOTS) &&
			    (known || object_pval_is_visible(o_ptr)))
			{
				LOG_PRINT1("Extra shots: %d\n", o_ptr->pval);
				if (o_ptr->pval >= INHIBIT_SHOTS || o_ptr->pval < 0)
				{
					p += INHIBIT_POWER;	/* inhibit */
					LOG_PRINT("INHIBITING - too many extra shots\n");
				}
				else if (o_ptr->pval > 0)
				{
					p += ((AVG_XBOW_AMMO_DAMAGE + AVG_LAUNCHER_DMG) * AVG_XBOW_MULT * o_ptr->pval * DAMAGE_POWER * BOW_RESCALER / (20 * MAX_BLOWS));
					LOG_PRINT1("Adding power for extra shots - total is %d\n", p);
				}
			}

			break;
		}
		case TV_LIGHT:
		{
			p += BASE_LIGHT_POWER;
			LOG_PRINT("Light source, adding base power\n");

			p += sign(o_ptr->to_h) * (ABS(o_ptr->to_h) * TO_HIT_POWER);
			LOG_PRINT1("Adding power for to_hit, total is %d\n", p);

			p += o_ptr->to_d * DAMAGE_POWER;
			LOG_PRINT1("Adding power for to_dam, total is %d\n", p);

			/* Apply the correct brand/slay multiplier */
			p += (((2 * (o_ptr->to_d + RING_BRAND_DMG)
				* slay_power(o_ptr, verbose, log_file, flags))
				/ tot_mon_power) - (2 * (o_ptr->to_d + RING_BRAND_DMG)));
			LOG_PRINT1("Adjusted for brand/slay power, total is %d\n", p);

			/* Add power for extra blows */
			if (of_has(flags, OF_BLOWS) &&
			    (known || object_pval_is_visible(o_ptr)))
			{
				LOG_PRINT1("Extra blows: %d\n", o_ptr->pval);
				if (o_ptr->pval >= INHIBIT_BLOWS || o_ptr->pval < 0)
				{
					p += INHIBIT_POWER;	/* inhibit */
					LOG_PRINT("INHIBITING, too many extra blows or a negative number\n");
				}
				else if (o_ptr->pval > 0)
				{
					p += ((MELEE_DAMAGE_BOOST + RING_BRAND_DMG + o_ptr->to_d) * o_ptr->pval * DAMAGE_POWER / MAX_BLOWS);
					LOG_PRINT1("Adding power for extra blows, total is %d\n", p);
				}
			}

			/* Add power for extra shots */
			if (of_has(flags, OF_SHOTS) &&
			    (known || object_pval_is_visible(o_ptr)))
			{
				LOG_PRINT1("Extra shots: %d\n", o_ptr->pval);
				if (o_ptr->pval >= INHIBIT_SHOTS || o_ptr->pval < 0)
				{
					p += INHIBIT_POWER;	/* inhibit */
					LOG_PRINT("INHIBITING - too many extra shots\n");
				}
				else if (o_ptr->pval > 0)
				{
					p += ((AVG_XBOW_AMMO_DAMAGE + AVG_LAUNCHER_DMG) * AVG_XBOW_MULT * o_ptr->pval * DAMAGE_POWER * BOW_RESCALER / (20 * MAX_BLOWS));
					LOG_PRINT1("Adding power for extra shots - total is %d\n", p);
				}
			}

			/*
			 * Big boost for extra light radius
			 * n.b. Another few points are added below
			 */
			if (of_has(flags, OF_LIGHT)) p += 30;

			break;
		}
		case TV_RING:
		case TV_AMULET:
		{
			p += BASE_JEWELRY_POWER;
			LOG_PRINT("Jewellery - adding base power\n");

			p += sign(o_ptr->to_h) * (ABS(o_ptr->to_h) * TO_HIT_POWER);
			LOG_PRINT1("Adding power for to_hit, total is %d\n", p);

			p += o_ptr->to_d * DAMAGE_POWER;
			LOG_PRINT1("Adding power for to_dam, total is %d\n", p);

			/* Apply the correct brand/slay multiplier */
			p += (((2 * (o_ptr->to_d + RING_BRAND_DMG)
				* slay_power(o_ptr, verbose, log_file, flags))
				/ tot_mon_power) - (2 * (o_ptr->to_d + RING_BRAND_DMG)));
			LOG_PRINT1("Adjusted for brand/slay power, total is %d\n", p);

			/* Add power for extra blows */
			if (of_has(flags, OF_BLOWS) &&
			    (known || object_pval_is_visible(o_ptr)))
			{
				LOG_PRINT1("Extra blows: %d\n", o_ptr->pval);
				if (o_ptr->pval >= INHIBIT_BLOWS || o_ptr->pval < 0)
				{
					p += INHIBIT_POWER;	/* inhibit */
					LOG_PRINT("INHIBITING, too many extra blows or a negative number\n");
				}
				else if (o_ptr->pval > 0)
				{
					p += ((MELEE_DAMAGE_BOOST + RING_BRAND_DMG + o_ptr->to_d) * o_ptr->pval * DAMAGE_POWER / MAX_BLOWS);
					LOG_PRINT1("Adding power for extra blows, total is %d\n", p);
				}
			}

			/* Add power for extra shots */
			if (of_has(flags, OF_SHOTS) &&
			    (known || object_pval_is_visible(o_ptr)))
			{
				LOG_PRINT1("Extra shots: %d\n", o_ptr->pval);
				if (o_ptr->pval >= INHIBIT_SHOTS || o_ptr->pval < 0)
				{
					p += INHIBIT_POWER;	/* inhibit */
					LOG_PRINT("INHIBITING - too many extra shots\n");
				}
				else if (o_ptr->pval > 0)
				{
					p += ((AVG_XBOW_AMMO_DAMAGE + AVG_LAUNCHER_DMG) * AVG_XBOW_MULT * o_ptr->pval * DAMAGE_POWER * BOW_RESCALER / (20 * MAX_BLOWS));
					LOG_PRINT1("Adding power for extra shots - total is %d\n", p);
				}
			}

			break;
		}
	}

	/* Other abilities are evaluated independent of the object type. */
	p += sign(o_ptr->to_a) * (ABS(o_ptr->to_a) * TO_AC_POWER / 2);
	LOG_PRINT2("Adding power for to_ac of %d, total is %d\n", o_ptr->to_a, p);

	if (o_ptr->to_a > HIGH_TO_AC)
	{
		p += ((o_ptr->to_a - (HIGH_TO_AC - 1)) * TO_AC_POWER / 2);
		LOG_PRINT1("Adding power for high to_ac value, total is %d\n", p);
	}
	if (o_ptr->to_a > VERYHIGH_TO_AC)
	{
		p += ((o_ptr->to_a - (VERYHIGH_TO_AC -1)) * TO_AC_POWER / 2);
		LOG_PRINT1("Adding power for very high to_ac value, total is %d\n", p);
	}
	if (o_ptr->to_a >= INHIBIT_AC)
	{
		p += INHIBIT_POWER;	/* inhibit */
		LOG_PRINT("INHIBITING: AC bonus too high\n");
	}

	if ((o_ptr->pval > 0) && (known || object_pval_is_visible(o_ptr)))
	{
		if (of_has(flags, OF_STR))
		{
			p += STR_POWER * o_ptr->pval;
			LOG_PRINT2("Adding power for STR bonus %d, total is %d\n", o_ptr->pval, p);
		}
		if (of_has(flags, OF_INT))
		{
			p += INT_POWER * o_ptr->pval;
			LOG_PRINT2("Adding power for INT bonus %d, total is %d\n", o_ptr->pval, p);
		}
		if (of_has(flags, OF_WIS))
		{
			p += WIS_POWER * o_ptr->pval;
			LOG_PRINT2("Adding power for WIS bonus %d, total is %d\n", o_ptr->pval, p);
		}
		if (of_has(flags, OF_DEX))
		{
			p += DEX_POWER * o_ptr->pval;
			LOG_PRINT2("Adding power for DEX bonus %d, total is %d\n", o_ptr->pval, p);
		}
		if (of_has(flags, OF_CON))
		{
			p += CON_POWER * o_ptr->pval;
			LOG_PRINT2("Adding power for CON bonus %d, total is %d\n", o_ptr->pval, p);
		}
		if (of_has(flags, OF_STEALTH))
		{
			p += STEALTH_POWER * o_ptr->pval;
			LOG_PRINT2("Adding power for Stealth bonus %d, total is %d\n", o_ptr->pval, p);
		}
		if (of_has(flags, OF_SEARCH))
		{
			p += SEARCH_POWER * o_ptr->pval;
			LOG_PRINT2("Adding power for searching bonus %d, total is %d\n", o_ptr->pval , p);
		}
		/* Add extra power term if there are a lot of ability bonuses */
		if (o_ptr->pval > 0)
		{
			extra_stat_bonus += (of_has(flags, OF_STR) ? 1 * o_ptr->pval : 0);
			extra_stat_bonus += (of_has(flags, OF_INT) ? 1 * o_ptr->pval : 0);
			extra_stat_bonus += (of_has(flags, OF_WIS) ? 1 * o_ptr->pval : 0);
			extra_stat_bonus += (of_has(flags, OF_DEX) ? 1 * o_ptr->pval : 0);
			extra_stat_bonus += (of_has(flags, OF_CON) ? 1 * o_ptr->pval : 0);
			extra_stat_bonus += (of_has(flags, OF_CHR) ? 0 * o_ptr->pval : 0);
			extra_stat_bonus += (of_has(flags, OF_STEALTH) ? 1 * o_ptr->pval : 0);
			extra_stat_bonus += (of_has(flags, OF_INFRA) ? 0 * o_ptr->pval : 0);
			extra_stat_bonus += (of_has(flags, OF_TUNNEL) ? 0 * o_ptr->pval : 0);
			extra_stat_bonus += (of_has(flags, OF_SEARCH) ? 0 * o_ptr->pval : 0);
			extra_stat_bonus += (of_has(flags, OF_SPEED) ? 0 * o_ptr->pval : 0);

			if (o_ptr->tval == TV_BOW)
			{
				extra_stat_bonus += (of_has(flags, OF_MIGHT) ? 5 * o_ptr->pval / 2 : 0);
				extra_stat_bonus += (of_has(flags, OF_SHOTS) ? 3 * o_ptr->pval : 0);
			}
			else if ( (o_ptr->tval == TV_DIGGING) || (o_ptr->tval == TV_HAFTED) ||
			          (o_ptr->tval == TV_POLEARM) || (o_ptr->tval == TV_SWORD) )
			{
				extra_stat_bonus += (of_has(flags, OF_BLOWS) ? 3 * o_ptr->pval : 0);
			}

			if (extra_stat_bonus > 24)
			{
				/* Inhibit */
				LOG_PRINT1("Inhibiting!  (Total ability bonus of %d is too high)\n", extra_stat_bonus);
				p += INHIBIT_POWER;
			}
			else
			{
				p += ability_power[extra_stat_bonus];
				LOG_PRINT2("Adding power for combination of %d, total is %d\n", ability_power[extra_stat_bonus], p);
			}
		}

	}
	else if ((o_ptr->pval < 0) && (known || object_pval_is_visible(o_ptr)))
	{
		if (of_has(flags, OF_STR)) p += 4 * o_ptr->pval;
		if (of_has(flags, OF_INT)) p += 2 * o_ptr->pval;
		if (of_has(flags, OF_WIS)) p += 2 * o_ptr->pval;
		if (of_has(flags, OF_DEX)) p += 3 * o_ptr->pval;
		if (of_has(flags, OF_CON)) p += 4 * o_ptr->pval;
		if (of_has(flags, OF_STEALTH)) p += o_ptr->pval;
		LOG_PRINT1("Subtracting power for negative ability values, total is %d\n", p);
	}

	if (known || object_pval_is_visible(o_ptr))
	{
		if (of_has(flags, OF_CHR))
		{
			p += CHR_POWER * o_ptr->pval;
			LOG_PRINT2("Adding power for CHR bonus/penalty %d, total is %d\n", o_ptr->pval, p);
		}
		if (of_has(flags, OF_INFRA))
		{
			p += INFRA_POWER * o_ptr->pval;
			LOG_PRINT2("Adding power for infra bonus/penalty %d, total is %d\n", o_ptr->pval, p);
		}
		if (of_has(flags, OF_TUNNEL))
		{
			p += TUNN_POWER * o_ptr->pval;
			LOG_PRINT2("Adding power for tunnelling bonus/penalty %d, total is %d\n", o_ptr->pval, p);
		}
		if (of_has(flags, OF_SPEED))
		{
			p += sign(o_ptr->pval) * speed_power[ABS(o_ptr->pval)];
			LOG_PRINT2("Adding power for speed bonus/penalty %d, total is %d\n", o_ptr->pval, p);
		}
	}

#define ADD_POWER1(string, val, flag) \
	if (of_has(flags, flag)) { \
		p += (val); \
		LOG_PRINT1("Adding power for " string ", total is %d\n", p); \
	}

#define ADD_POWER2(string, val, flag, extra) \
	if (of_has(flags, flag)) { \
		p += (val); \
		extra; \
		LOG_PRINT1("Adding power for " string ", total is %d\n", p); \
	}

	ADD_POWER2("sustain STR",         9, OF_SUST_STR, sustains++);
	ADD_POWER2("sustain INT",         4, OF_SUST_INT, sustains++);
	ADD_POWER2("sustain WIS",         4, OF_SUST_WIS, sustains++);
	ADD_POWER2("sustain DEX",         7, OF_SUST_DEX, sustains++);
	ADD_POWER2("sustain CON",         8, OF_SUST_CON, sustains++);
	ADD_POWER1("sustain CHR",         1, OF_SUST_CHR);

	for (i = 2; i <= sustains; i++)
	{
		p += i;
		LOG_PRINT1("Adding power for multiple sustains, total is %d\n", p);
		if (i == 5)
		{
			p += SUST_POWER;
			LOG_PRINT1("Adding power for full set of sustains, total is %d\n", p);
		}
	}

	ADD_POWER2("acid immunity",      38, OF_IM_ACID, immunities++);
	ADD_POWER2("elec immunity",      35, OF_IM_ELEC, immunities++);
	ADD_POWER2("fire immunity",      40, OF_IM_FIRE, immunities++);
	ADD_POWER2("cold immunity",      37, OF_IM_COLD, immunities++);

	for (i = 2; i <= immunities; i++)
	{
		p += IMMUNITY_POWER;
		LOG_PRINT1("Adding power for multiple immunities, total is %d\n", p);
		if (i >= INHIBIT_IMMUNITIES)
		{
			p += INHIBIT_POWER;             /* inhibit */
			LOG_PRINT("INHIBITING: Too many immunities\n");
		}
	}

	ADD_POWER2("free action",           14, OF_FREE_ACT,    misc++);
	ADD_POWER2("hold life",             12, OF_HOLD_LIFE,   misc++);
	ADD_POWER1("feather fall",           1, OF_FEATHER);
	ADD_POWER2("permanent light",        3, OF_LIGHT,       misc++);
	ADD_POWER2("see invisible",         10, OF_SEE_INVIS,   misc++);
	ADD_POWER2("telepathy",             70, OF_TELEPATHY,   misc++);
	ADD_POWER2("slow digestion",         2, OF_SLOW_DIGEST, misc++);
	ADD_POWER2("resist acid",            5, OF_RES_ACID,    lowres++);
	ADD_POWER2("resist elec",            6, OF_RES_ELEC,    lowres++);
	ADD_POWER2("resist fire",            6, OF_RES_FIRE,    lowres++);
	ADD_POWER2("resist cold",            6, OF_RES_COLD,    lowres++);
	ADD_POWER2("resist poison",         28, OF_RES_POIS,    highres++);
	ADD_POWER2("resist fear",            6, OF_RES_FEAR,    highres++);
	ADD_POWER2("resist light",           6, OF_RES_LIGHT,   highres++);
	ADD_POWER2("resist dark",           16, OF_RES_DARK,    highres++);
	ADD_POWER2("resist blindness",      16, OF_RES_BLIND,   highres++);
	ADD_POWER2("resist confusion",      24, OF_RES_CONFU,   highres++);
	ADD_POWER2("resist sound",          14, OF_RES_SOUND,   highres++);
	ADD_POWER2("resist shards",          8, OF_RES_SHARD,   highres++);
	ADD_POWER2("resist nexus",          15, OF_RES_NEXUS,   highres++);
	ADD_POWER2("resist nether",         20, OF_RES_NETHR,   highres++);
	ADD_POWER2("resist chaos",          20, OF_RES_CHAOS,   highres++);
	ADD_POWER2("resist disenchantment", 20, OF_RES_DISEN,   highres++);
	ADD_POWER2("regeneration",           9, OF_REGEN,       misc++);
	ADD_POWER1("blessed",                1, OF_BLESSED);
	ADD_POWER1("no fuel",                5, OF_NO_FUEL);

	for (i = 2; i <= misc; i++)
	{
		p += i;
		LOG_PRINT1("Adding power for multiple misc abilities, total is %d\n", p);
	}

	for (i = 2; i <= lowres; i++)
	{
		p += i;
		LOG_PRINT1("Adding power for multiple low resists, total is %d\n", p);
		if (i == 4)
		{
			p += RBASE_POWER;
			LOG_PRINT1("Adding power for full rbase set, total is %d\n", p);
		}
	}

	for (i = 2; i <= highres; i++)
	{
		p += (i * 2);
		LOG_PRINT1("Adding power for multiple high resists, total is %d\n", p);
	}

	/* Note: the following code is irrelevant until curses are reworked */
	if (of_has(flags, OF_TELEPORT))
	{
		p -= 1;
		LOG_PRINT1("Subtracting power for teleportation, total is %d\n", p);
	}
	if (of_has(flags, OF_DRAIN_EXP))
	{
		p -= 1;
		LOG_PRINT1("Subtracting power for drain experience, total is %d\n", p);
	}
	if (of_has(flags, OF_AGGRAVATE))
	{
		p -= 1;
		LOG_PRINT1("Subtracting power for aggravation, total is %d\n", p);
	}
	if (of_has(flags, OF_LIGHT_CURSE))
	{
		p -= 1;
		LOG_PRINT1("Subtracting power for light curse, total is %d\n", p);
	}
	if (of_has(flags, OF_HEAVY_CURSE))
	{
		p -= 1;
		LOG_PRINT1("Subtracting power for heavy curse, total is %d\n", p);
	}

	/*	if (of_has(flags, OF_PERMA_CURSE)) p -= 40; */

	/* add power for effect */
	if (known || object_effect_is_known(o_ptr))
	{
		if (o_ptr->name1 && a_info[o_ptr->name1].effect)
		{
			p += effect_power(a_info[o_ptr->name1].effect);
			LOG_PRINT1("Adding power for artifact activation, total is %d\n", p);
		}
		else
		{
			p += effect_power(k_info[o_ptr->k_idx].effect);
			LOG_PRINT1("Adding power for item activation, total is %d\n", p);
		}
	}

	/* add tiny amounts for ignore flags */
	if (of_has(flags, OF_IGNORE_ACID)) p++;
	if (of_has(flags, OF_IGNORE_FIRE)) p++;
	if (of_has(flags, OF_IGNORE_COLD)) p++;
	if (of_has(flags, OF_IGNORE_ELEC)) p++;

	LOG_PRINT1("After ignore flags, FINAL POWER IS %d\n", p);

	return (p);
}