Exemple #1
0
/**
 * Add power for modifiers
 */
static int modifier_power(const object_type *obj, int p, bool known)
{
	int i, k = 1, extra_stat_bonus = 0, q;

	for (i = 0; i < OBJ_MOD_MAX; i++) {
		if (known || object_this_mod_is_visible(obj, i)) {
			k = obj->modifiers[i];
			extra_stat_bonus += (k * mod_mult(i));
		}
		else continue;

		if (mod_power(i)) {
			q = (k * mod_power(i) * mod_slot_mult(i, wield_slot(obj)));
			p += q;
			if (q) log_obj(format("Add %d power for %d %s, total is %d\n", 
								  q, k, mod_name(i), p));
		}
	}

	/* Add extra power term if there are a lot of ability bonuses */
	if (extra_stat_bonus > 249) {
		log_obj(format("Inhibiting - Total ability bonus of %d is too high\n", 
					   extra_stat_bonus));
		p += INHIBIT_POWER;
	} else if (extra_stat_bonus > 0) {
		q = ability_power[extra_stat_bonus / 10];
		if (!q) return p;
		p += q;
		log_obj(format("Add %d power for modifier total of %d, total is %d\n", 
					   q, extra_stat_bonus, p));
	}
	return p;
}
/**
 * Describe combat properties of an item - damage dice, to-hit, to-dam, armor
 * class, missile multipler
 */
static size_t obj_desc_combat(const struct object *obj, char *buf, size_t max, 
		size_t end, bool spoil)
{
	bitflag flags_known[OF_SIZE];

	object_flags_known(obj, flags_known);

	if (kf_has(obj->kind->kind_flags, KF_SHOW_DICE)) {
		/* Only display the real damage dice if the combat stats are known */
		if (spoil || object_attack_plusses_are_visible(obj))
			strnfcat(buf, max, &end, " (%dd%d)", obj->dd, obj->ds);
		else
			strnfcat(buf, max, &end, " (%dd%d)", obj->kind->dd,
					 obj->kind->ds);
	}

	if (kf_has(obj->kind->kind_flags, KF_SHOW_MULT)) {
		/* Display shooting power as part of the multiplier */
		if ((obj->modifiers[OBJ_MOD_MIGHT] > 0) &&
		    (spoil || object_this_mod_is_visible(obj, OBJ_MOD_MIGHT)))
			strnfcat(buf, max, &end, " (x%d)",
					 obj->pval + obj->modifiers[OBJ_MOD_MIGHT]);
		else
			strnfcat(buf, max, &end, " (x%d)", obj->pval);
	}

	/* Show weapon bonuses */
	if (spoil || object_attack_plusses_are_visible(obj)) {
		if (tval_is_weapon(obj) || obj->to_d || obj->to_h) {
			/* Make an exception for body armor with only a to-hit penalty */
			if (obj->to_h < 0 && obj->to_d == 0 &&
				tval_is_body_armor(obj))
				strnfcat(buf, max, &end, " (%+d)", obj->to_h);

			/* Otherwise, always use the full tuple */
			else
				strnfcat(buf, max, &end, " (%+d,%+d)", obj->to_h,
						 obj->to_d);
		}
	}


	/* Show armor bonuses */
	if (spoil || object_defence_plusses_are_visible(obj)) {
		if (obj_desc_show_armor(obj))
			strnfcat(buf, max, &end, " [%d,%+d]", obj->ac, obj->to_a);
		else if (obj->to_a)
			strnfcat(buf, max, &end, " [%+d]", obj->to_a);
	}
	else if (obj_desc_show_armor(obj))
		strnfcat(buf, max, &end, " [%d]",
				 object_was_sensed(obj) ? obj->ac : obj->kind->ac);

	return end;
}
Exemple #3
0
/**
 * Add power for extra might
 */
static int extra_might_power(const object_type *obj, int p, int mult,
							 bool known)
{
	if (known || object_this_mod_is_visible(obj, OBJ_MOD_MIGHT)) {
		if (obj->modifiers[OBJ_MOD_MIGHT] >= INHIBIT_MIGHT) {
			p += INHIBIT_POWER;
			log_obj("INHIBITING - too much extra might - quitting\n");
			return p;
		} else {
			mult += obj->modifiers[OBJ_MOD_MIGHT];
		}
		log_obj(format("Mult after extra might is %d\n", mult));
	}
	p *= mult;
	log_obj(format("After multiplying power for might, total is %d\n", p));
	return p;
}
Exemple #4
0
/**
 * Add power for extra shots - note that we cannot handle negative shots
 */
static int extra_shots_power(const object_type *obj, int p, bool known)
{
	if (obj->modifiers[OBJ_MOD_SHOTS] == 0)
		return p;

	if (known || object_this_mod_is_visible(obj, OBJ_MOD_SHOTS)) {
		if (obj->modifiers[OBJ_MOD_SHOTS] >= INHIBIT_SHOTS) {
			p += INHIBIT_POWER;
			log_obj("INHIBITING - too many extra shots - quitting\n");
			return p;
		} else if (obj->modifiers[OBJ_MOD_SHOTS] > 0) {
			int q = obj->modifiers[OBJ_MOD_SHOTS];
			p = p * (1 + q);
			log_obj(format("Multiplying power by %d for extra shots, total is %d\n", 1 + q, p));
		}
	}
	return p;
}
Exemple #5
0
/**
 * Describe stat modifications.
 */
static bool describe_stats(textblock *tb, const struct object *obj,
						   oinfo_detail_t mode)
{
	size_t count = 0, i;
	bool detail = false;

	/* Don't give exact plusses for faked ego items as each real one will
	 * be different */
	bool suppress_details = mode & OINFO_EGO ? true : false;

	/* Fact of but not size of mods is known for egos and flavoured items
	 * the player is aware of */
	bool known_effect = false;
	if (object_ego_is_visible(obj))
		known_effect = true;
	if (tval_can_have_flavor_k(obj->kind) && object_flavor_is_aware(obj))
		known_effect = true;

	/* See what we've got */
	for (i = 0; i < N_ELEMENTS(mod_flags); i++)
		if (obj->modifiers[mod_flags[i].flag] != 0 && mod_flags[i].name[0]) {
			count++;
			/* Either all mods are visible, or none are */
			if (object_this_mod_is_visible(obj, mod_flags[i].flag))
				detail = true;
		}

	if (!count)
		return false;

	for (i = 0; i < N_ELEMENTS(mod_flags); i++) {
		const char *desc = mod_flags[i].name;
		int val = obj->modifiers[mod_flags[i].flag];
		if (!val) continue;
		if (!mod_flags[i].name[0]) continue;
		if (detail && !suppress_details) {
			int attr = (val > 0) ? COLOUR_L_GREEN : COLOUR_RED;
			textblock_append_c(tb, attr, "%+i %s.\n", val, desc);
		} else if (known_effect)
			textblock_append(tb, "Affects your %s\n", desc);
	}

	return true;
}
/**
 * Describe numerical modifiers to stats and other player qualities which
 * allow numerical bonuses - speed, stealth, etc
 */
static size_t obj_desc_mods(const struct object *obj, char *buf, size_t max,
	size_t end, bool spoil)
{
	int i, j, num_mods = 0;
	int mods[OBJ_MOD_MAX] = { 0 };

	/* Run through possible modifiers and store distinct ones */
	for (i = 0; i < OBJ_MOD_MAX; i++) {
		/* Check for known non-zero mods */
		if ((spoil || object_this_mod_is_visible(obj, i))
			&& (obj->modifiers[i] != 0)) {
			/* If no mods stored yet, store and move on */
			if (!num_mods) {
				mods[num_mods++] = obj->modifiers[i];
				continue;
			}

			/* Run through the existing mods, quit on duplicates */
			for (j = 0; j < num_mods; j++)
				if (mods[j] == obj->modifiers[i]) break;

			/* Add another mod if needed */
			if (j == num_mods)
				mods[num_mods++] = obj->modifiers[i];
		}
	}

	if (!num_mods) return end;

	/* Print the modifiers */
	strnfcat(buf, max, &end, " <");
	for (j = 0; j < num_mods; j++) {
		if (j) strnfcat(buf, max, &end, ", ");
		strnfcat(buf, max, &end, "%+d", mods[j]);
	}
	strnfcat(buf, max, &end, ">");

	return end;
}
Exemple #7
0
/**
 * Add power for extra blows
 */
static int extra_blows_power(const object_type *obj, int p, bool known)
{
	int q = p;

	if (obj->modifiers[OBJ_MOD_BLOWS] == 0)
		return p;

	if (known || object_this_mod_is_visible(obj, OBJ_MOD_BLOWS)) {
		if (obj->modifiers[OBJ_MOD_BLOWS] >= INHIBIT_BLOWS) {
			p += INHIBIT_POWER;
			log_obj("INHIBITING - too many extra blows - quitting\n");
			return p;
		} else {
			p = p * (MAX_BLOWS + obj->modifiers[OBJ_MOD_BLOWS]) / MAX_BLOWS;
			/* Add boost for assumed off-weapon damage */
			p += (NONWEAP_DAMAGE * obj->modifiers[OBJ_MOD_BLOWS]
				  * DAMAGE_POWER / 2);
			log_obj(format("Add %d power for extra blows, total is %d\n", 
								p - q, p));
		}
	}
	return p;
}
Exemple #8
0
/**
 * Describe stat modifications.
 */
static bool describe_stats(textblock *tb, const struct object *obj,
						   oinfo_detail_t mode)
{
	size_t count = 0, i;
	bool detail = FALSE;

	/* Don't give exact pluses for faked ego items as each real one 
	   will be different */
	bool suppress_details = mode & OINFO_EGO ? TRUE : FALSE;

	/* See what we've got */
	for (i = 0; i < N_ELEMENTS(mod_flags); i++)
		if (obj->modifiers[mod_flags[i].flag] != 0 &&	mod_flags[i].name[0]) {
			count++;
			/* Either all mods are visible, or none are */
			if (object_this_mod_is_visible(obj, i))
				detail = TRUE;
		}
	
	if (!count)
		return FALSE;
	
	for (i = 0; i < N_ELEMENTS(mod_flags); i++) {
		const char *desc = mod_flags[i].name;
		int val = obj->modifiers[mod_flags[i].flag];
		if (!val) continue;
		if (!mod_flags[i].name[0]) continue;
		if (detail && !suppress_details) {
			int attr = (val > 0) ? COLOUR_L_GREEN : COLOUR_RED;
			textblock_append_c(tb, attr, "%+i %s.\n", val, desc);
		} 
		else
			textblock_append(tb, "Affects your %s\n", desc);
	}

	return TRUE;
}
Exemple #9
0
/**
 * Returns information about objects that can be used for digging.
 *
 * `deciturns` will be filled in with the avg number of deciturns it will
 * take to dig through each type of diggable terrain, and must be at least 
 * [DIGGING_MAX].
 *
 * Returns false if the object has no effect on digging, or if the specifics
 * are meaningless (i.e. the object is an ego template, not a real item).
 */
static bool obj_known_digging(struct object *obj, int deciturns[])
{
	struct player_state state;
	int i;
	int chances[DIGGING_MAX];
	int slot = wield_slot(obj);
	struct object *current = slot_object(player, slot);

	/* Doesn't remotely resemble a digger */
	if (!tval_is_wearable(obj) ||
		(!tval_is_melee_weapon(obj) && (obj->modifiers[OBJ_MOD_TUNNEL] <= 0)))
		return false;

	/* Player has no digging info */
	if (!object_this_mod_is_visible(obj, OBJ_MOD_TUNNEL))
		return false;

	/* Pretend we're wielding the object */
	player->body.slots[slot].obj = obj;

	/* Calculate the player's hypothetical state */
	calc_bonuses(player, &state, true, false);

	/* Stop pretending */
	player->body.slots[slot].obj = current;

	calc_digging_chances(&state, chances);

	/* Digging chance is out of 1600 */
	for (i = DIGGING_RUBBLE; i < DIGGING_MAX; i++) {
		int chance = MIN(1600, chances[i]);
		deciturns[i] = chance ? (16000 / chance) : 0;
	}

	return true;
}
Exemple #10
0
/**
 * Gets information about the number of blows possible for the player with
 * the given object.
 *
 * Fills in whether the object is too_heavy to wield effectively,
 * and the possible_blows[] information of .str_plus and .dex_plus needed
 * to achieve the approximate number of blows in centiblows. 
 *
 * `max_blows` must be at least 1 to hold the current number of blows
 * `possible_blows` must be at least [`max_blows`] in size, and will be limited
 * to that number of entries.  The theoretical maximum is STAT_RANGE * 2 if
 * an extra blow/speed boost was given for each combination of STR and DEX.
 *
 * Returns the number of entries made in the possible_blows[] table, or 0
 * if the object is not a weapon.
 *
 * Note that the results are meaningless if called on a fake ego object as
 * the actual ego may have different properties.
 */
static int obj_known_blows(const struct object *obj, int max_num,
						   struct blow_info possible_blows[])
{
	int str_plus, dex_plus, old_blows = 0, new_blows, extra_blows;
	int str_faster = -1, str_done = -1;
	int dex_plus_bound;
	int str_plus_bound;
	int i;

	struct player_state state;

	int weapon_slot = slot_by_name(player, "weapon");
	struct object *current_weapon = slot_object(player, weapon_slot);
	int num = 0;

	/* Not a weapon - no blows! */
	if (!tval_is_melee_weapon(obj)) return 0;

	/* Pretend we're wielding the object */
	player->body.slots[weapon_slot].obj = (struct object *) obj;

	/* Calculate the player's hypothetical state */
	calc_bonuses(player, &state, true, false);

	/* Stop pretending */
	player->body.slots[weapon_slot].obj = current_weapon;

	/* First entry is always the current num of blows. */
	possible_blows[num].str_plus = 0;
	possible_blows[num].dex_plus = 0;
	possible_blows[num].centiblows = state.num_blows;
	num++;

	/* Check to see if extra STR or DEX would yield extra blows */
	old_blows = state.num_blows;
	extra_blows = 0;

	/* Start with blows from the weapon being examined */
	if (object_this_mod_is_visible(obj, OBJ_MOD_BLOWS))
		extra_blows += obj->modifiers[OBJ_MOD_BLOWS];

	/* Then we need to look for extra blows on other items, as
	 * state does not track these */
	for (i = 0; i < player->body.count; i++) {
		struct object *helper = slot_object(player, i);

		if ((i == slot_by_name(player, "weapon")) || !helper || !helper->kind)
			continue;

		if (object_this_mod_is_visible(helper, OBJ_MOD_BLOWS))
			extra_blows += helper->modifiers[OBJ_MOD_BLOWS];
	}

	dex_plus_bound = STAT_RANGE - state.stat_ind[STAT_DEX];
	str_plus_bound = STAT_RANGE - state.stat_ind[STAT_STR];

	/* Then we check for extra "real" blows */
	for (dex_plus = 0; dex_plus < dex_plus_bound; dex_plus++) {
		for (str_plus = 0; str_plus < str_plus_bound; str_plus++) {
			if (num == max_num)
				return num;

			state.stat_ind[STAT_STR] += str_plus;
			state.stat_ind[STAT_DEX] += dex_plus;
			new_blows = calc_blows(player, obj, &state, extra_blows);
			state.stat_ind[STAT_STR] -= str_plus;
			state.stat_ind[STAT_DEX] -= dex_plus;

			/* Test to make sure that this extra blow is a
			 * new str/dex combination, not a repeat */
			if (((new_blows - new_blows % 10) > (old_blows - old_blows % 10)) &&
				(str_plus < str_done || str_done == -1)) {
				possible_blows[num].str_plus = str_plus;
				possible_blows[num].dex_plus = dex_plus;
				possible_blows[num].centiblows = new_blows / 10;
				possible_blows[num].centiblows *= 10;
				num++;

				str_done = str_plus;
				break;
			}

			/* If the combination doesn't increment
			 * the displayed blows number, it might still
			 * take a little less energy */
			if ((new_blows > old_blows) &&
				(str_plus < str_faster || str_faster == -1) &&
				(str_plus < str_done || str_done == -1)) {
				possible_blows[num].str_plus = str_plus;
				possible_blows[num].dex_plus = dex_plus;
				possible_blows[num].centiblows = new_blows;
				num++;

				str_faster = str_plus;
			}
		}
	}

	return num;
}
Exemple #11
0
/**
 * Determine the ignore level of an object, which is similar to its pseudo.
 *
 * The main point is when the value is undetermined given current info,
 * return the maximum possible value.
 */
byte ignore_level_of(const struct object *obj)
{
	byte value = 0;
	bitflag f[OF_SIZE], f2[OF_SIZE];
	int i;
	bool negative_mod = FALSE;

	object_flags_known(obj, f);

	/* Deal with jewelry specially. */
	if (tval_is_jewelry(obj))
	{
		/* CC: average jewelry has at least one known positive modifier */
		for (i = 0; i < OBJ_MOD_MAX; i++)
			if ((object_this_mod_is_visible(obj, i)) && 
				(obj->modifiers[i] > 0))
				return IGNORE_AVERAGE;

		if ((obj->to_h > 0) || (obj->to_d > 0) || (obj->to_a > 0))
			return IGNORE_AVERAGE;
		if ((object_attack_plusses_are_visible(obj) &&
				((obj->to_h < 0) || (obj->to_d < 0))) ||
		    	(object_defence_plusses_are_visible(obj) && obj->to_a < 0))
			return IGNORE_BAD;

		return IGNORE_AVERAGE;
	}

	/* And lights */
	if (tval_is_light(obj))
	{
		create_mask(f2, TRUE, OFID_WIELD, OFT_MAX);
		if (of_is_inter(f, f2))
			return IGNORE_ALL;
		if ((obj->to_h > 0) || (obj->to_d > 0) || (obj->to_a > 0))
			return IGNORE_GOOD;
		if ((obj->to_h < 0) || (obj->to_d < 0) || (obj->to_a < 0))
			return IGNORE_BAD;

		return IGNORE_AVERAGE;
	}

	/* We need to redefine "bad" 
	 * At the moment we use "all modifiers known and negative" */
	for (i = 0; i < OBJ_MOD_MAX; i++) {
		if (!object_this_mod_is_visible(obj, i) ||
			(obj->modifiers[i] > 0))
			break;

		if (obj->modifiers[i] < 0)
			negative_mod = TRUE;
	}

	if ((i == OBJ_MOD_MAX) && negative_mod)
		return IGNORE_BAD;

	if (object_was_sensed(obj)) {
		obj_pseudo_t pseudo = object_pseudo(obj);

		switch (pseudo) {
			case INSCRIP_AVERAGE: {
				value = IGNORE_AVERAGE;
				break;
			}

			case INSCRIP_EXCELLENT: {
				/* have to assume splendid until you have tested it */
				if (object_was_worn(obj)) {
					if (object_high_resist_is_possible(obj))
						value = IGNORE_EXCELLENT_NO_SPL;
					else
						value = IGNORE_EXCELLENT_NO_HI;
				} else {
					value = IGNORE_ALL;
				}
				break;
			}

			case INSCRIP_SPLENDID:
				value = IGNORE_ALL;
				break;
			case INSCRIP_NULL:
			case INSCRIP_SPECIAL:
				value = IGNORE_MAX;
				break;

			/* This is the interesting case */
			case INSCRIP_STRANGE:
			case INSCRIP_MAGICAL: {
				value = IGNORE_GOOD;

				if ((object_attack_plusses_are_visible(obj) ||
						randcalc_valid(obj->kind->to_h, obj->to_h) ||
						randcalc_valid(obj->kind->to_d, obj->to_d)) &&
				    	(object_defence_plusses_are_visible(obj) ||
						randcalc_valid(obj->kind->to_a, obj->to_a))) {
					int isgood = is_object_good(obj);
					if (isgood > 0) {
						value = IGNORE_GOOD;
					} else if (isgood < 0) {
						value = IGNORE_BAD;
					} else {
						value = IGNORE_AVERAGE;
					}
				}
				break;
			}

			default:
				/* do not handle any other possible pseudo values */
				assert(0);
		}
	}
	else
	{
		if (object_was_worn(obj))
			value = IGNORE_EXCELLENT_NO_SPL; /* object would be sensed if it were splendid */
		else if (object_is_known_not_artifact(obj))
			value = IGNORE_ALL;
		else
			value = IGNORE_MAX;
	}

	return value;
}