/* * 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; }
/* * 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); }