/* * Inquire whether the player wishes to squelch items similar to an object * * Returns whether the item is now squelched. */ bool squelch_interactive(const object_type *o_ptr) { char out_val[70]; if (squelch_tval(o_ptr->tval)) { char sval_name[50]; /* Obtain plural form without a quantity */ object_desc(sval_name, sizeof sval_name, o_ptr, ODESC_BASE | ODESC_PLURAL); /* XXX Eddie while correct in a sense, to squelch all torches on torch of brightness you get the message "Ignore Wooden Torches of Brightness in future? " */ strnfmt(out_val, sizeof out_val, "Ignore %s in future? ", sval_name); if (!artifact_p(o_ptr) || !object_flavor_is_aware(o_ptr)) { if (get_check(out_val)) { object_squelch_flavor_of(o_ptr); msg_format("Ignoring %s from now on.", sval_name); return TRUE; } } /* XXX Eddie need to add generalized squelching, e.g. con rings with pval < 3 */ if (!object_is_jewelry(o_ptr) || (squelch_level_of(o_ptr) != SQUELCH_BAD)) return FALSE; } if (object_was_sensed(o_ptr) || object_was_worn(o_ptr) || object_is_known_not_artifact(o_ptr)) { byte value = squelch_level_of(o_ptr); int type = squelch_type_of(o_ptr); /* XXX Eddie on pseudoed cursed artifact, only showed {cursed}, asked to ignore artifacts */ if ((value != SQUELCH_MAX) && ((value == SQUELCH_BAD) || !object_is_jewelry(o_ptr))) { strnfmt(out_val, sizeof out_val, "Ignore all %s that are %s in future? ", quality_choices[type].name, quality_values[value].name); if (get_check(out_val)) { squelch_level[type] = value; return TRUE; } } } return FALSE; }
/** * \returns whether the object's pval is known to the player */ bool object_pval_is_visible(const object_type *o_ptr) { bitflag f[OF_SIZE]; if (o_ptr->ident & IDENT_STORE) return TRUE; /* Aware jewelry with non-variable pvals */ if (object_is_jewelry(o_ptr) && object_flavor_is_aware(o_ptr)) { const object_kind *k_ptr = &k_info[o_ptr->k_idx]; if (!randcalc_varies(k_ptr->pval)) return TRUE; } if (object_was_worn(o_ptr)) { object_flags_known(o_ptr, f); if (flags_test(f, OF_SIZE, OF_PVAL_MASK, FLAG_END)) return TRUE; } return FALSE; }
/** * 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); } }
/** * Notice a given special flag on wielded items. * * \param flag is the flag to notice */ void wieldeds_notice_flag(int flag) { int i; /* XXX Eddie need different naming conventions for starting wieldeds at INVEN_WIELD vs INVEN_WIELD+2 */ for (i = INVEN_WIELD; i < ALL_INVEN_TOTAL; i++) { object_type *o_ptr = &p_ptr->inventory[i]; bitflag f[OF_SIZE]; if (!o_ptr->k_idx) continue; object_flags(o_ptr, f); if (of_has(f, flag) && !of_has(o_ptr->known_flags, flag)) { char o_name[80]; object_desc(o_name, sizeof(o_name), o_ptr, ODESC_BASE); /* Notice the flag */ object_notice_flag(o_ptr, flag); /* XXX Eddie should this go before noticing the flag to avoid learning twice? */ if (EASY_LEARN && object_is_jewelry(o_ptr)) { /* XXX Eddie EASY_LEARN Possible concern: gets =teleportation just from +2 speed */ object_flavor_aware(o_ptr); object_check_for_ident(o_ptr); } /* Message */ if (!streq(msgs[flag], "")) msg_format(msgs[flag], o_name); } else { /* Notice that flag is absent */ object_notice_flag(o_ptr, flag); } /* XXX Eddie should not need this, should be done in noticing, but will remove later */ object_check_for_ident(o_ptr); } return; }
/** * \returns whether the object's defence bonuses are known */ bool object_defence_plusses_are_visible(const object_type *o_ptr) { /* Bonuses have been revealed or for sale */ if ((o_ptr->ident & IDENT_DEFENCE) || (o_ptr->ident & IDENT_STORE)) return TRUE; /* Aware jewelry with non-variable bonuses */ if (object_is_jewelry(o_ptr) && object_flavor_is_aware(o_ptr)) { const object_kind *k_ptr = &k_info[o_ptr->k_idx]; if (!randcalc_varies(k_ptr->to_a)) return TRUE; } return FALSE; }
/* * Determine the squelch 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 squelch_level_of(const object_type *o_ptr) { byte value; bitflag f[OF_SIZE], f2[OF_SIZE]; int i; object_flags_known(o_ptr, f); /* Deal with jewelry specially. */ if (object_is_jewelry(o_ptr)) { /* CC: average jewelry has at least one known positive pval */ for (i = 0; i < o_ptr->num_pvals; i++) if ((object_this_pval_is_visible(o_ptr, i)) && (o_ptr->pval[i] > 0)) return SQUELCH_AVERAGE; if ((o_ptr->to_h > 0) || (o_ptr->to_d > 0) || (o_ptr->to_a > 0)) return SQUELCH_AVERAGE; if ((object_attack_plusses_are_visible(o_ptr) && ((o_ptr->to_h < 0) || (o_ptr->to_d < 0))) || (object_defence_plusses_are_visible(o_ptr) && o_ptr->to_a < 0)) return SQUELCH_BAD; return SQUELCH_AVERAGE; } /* And lights */ if (o_ptr->tval == TV_LIGHT) { create_mask(f2, TRUE, OFID_WIELD, OFT_MAX); if (of_is_inter(f, f2)) return SQUELCH_ALL; if ((o_ptr->to_h > 0) || (o_ptr->to_d > 0) || (o_ptr->to_a > 0)) return SQUELCH_GOOD; if ((o_ptr->to_h < 0) || (o_ptr->to_d < 0) || (o_ptr->to_a < 0)) return SQUELCH_BAD; return SQUELCH_AVERAGE; } /* CC: we need to redefine "bad" with multiple pvals * At the moment we use "all pvals known and negative" */ for (i = 0; i < o_ptr->num_pvals; i++) { if (!object_this_pval_is_visible(o_ptr, i) || (o_ptr->pval[i] > 0)) break; if (i == (o_ptr->num_pvals - 1)) return SQUELCH_BAD; } if (object_was_sensed(o_ptr)) { obj_pseudo_t pseudo = object_pseudo(o_ptr); switch (pseudo) { case INSCRIP_AVERAGE: { value = SQUELCH_AVERAGE; break; } case INSCRIP_EXCELLENT: { /* have to assume splendid until you have tested it */ if (object_was_worn(o_ptr)) { if (object_high_resist_is_possible(o_ptr)) value = SQUELCH_EXCELLENT_NO_SPL; else value = SQUELCH_EXCELLENT_NO_HI; } else { value = SQUELCH_ALL; } break; } case INSCRIP_SPLENDID: value = SQUELCH_ALL; break; case INSCRIP_NULL: case INSCRIP_SPECIAL: value = SQUELCH_MAX; break; /* This is the interesting case */ case INSCRIP_STRANGE: case INSCRIP_MAGICAL: { value = SQUELCH_GOOD; if ((object_attack_plusses_are_visible(o_ptr) || randcalc_valid(o_ptr->kind->to_h, o_ptr->to_h) || randcalc_valid(o_ptr->kind->to_d, o_ptr->to_d)) && (object_defence_plusses_are_visible(o_ptr) || randcalc_valid(o_ptr->kind->to_a, o_ptr->to_a))) { int isgood = is_object_good(o_ptr); if (isgood > 0) { value = SQUELCH_GOOD; } else if (isgood < 0) { value = SQUELCH_BAD; } else { value = SQUELCH_AVERAGE; } } break; } default: /* do not handle any other possible pseudo values */ assert(0); } } else { if (object_was_worn(o_ptr)) value = SQUELCH_EXCELLENT_NO_SPL; /* object would be sensed if it were splendid */ else if (object_is_known_not_artifact(o_ptr)) value = SQUELCH_ALL; else value = SQUELCH_MAX; } return value; }
/* * Destroy an item */ void do_cmd_destroy(void) { int item, amt = 1; int old_number; bool force = FALSE; object_type *o_ptr; object_type forge; object_type *q_ptr = &forge; bool is_equipped = FALSE; char o_name[MAX_NLEN]; char out_val[MAX_NLEN+40]; cptr q, s; int mode = USE_INVEN | USE_FLOOR; if (p_ptr->pclass == CLASS_RUNE_KNIGHT) mode |= USE_EQUIP; if (p_ptr->special_defense & KATA_MUSOU) { set_action(ACTION_NONE); } /* Hack -- force destruction */ if (command_arg > 0) force = TRUE; /* Get an item */ q = "Destroy which item? "; s = "You have nothing to destroy."; if (!get_item(&item, q, s, mode)) return; /* Get the item (in the pack) */ if (item >= 0) { o_ptr = &inventory[item]; is_equipped = equip_is_valid_slot(item); } /* Get the item (on the floor) */ else { o_ptr = &o_list[0 - item]; } /* Hack for Rune Knight: They can destroy worn equipment, but only if it has the Sacrifice rune. get_item() is not smart enough to handle this restriction ... */ if (is_equipped && o_ptr->rune != RUNE_SACRIFICE) { msg_print("You must first remove that item before destroying it."); return; } /* Verify unless quantity given beforehand */ if (!force && (confirm_destroy || (object_value(o_ptr) > 0))) { object_desc(o_name, o_ptr, OD_OMIT_PREFIX); /* Make a verification */ sprintf(out_val, "Really destroy %s? [y/n/Auto]", o_name); msg_print(NULL); /* HACK : Add the line to message buffer */ message_add(out_val); p_ptr->window |= (PW_MESSAGE); window_stuff(); /* Get an acceptable answer */ while (TRUE) { char i; /* Prompt */ prt(out_val, 0, 0); i = inkey(); /* Erase the prompt */ prt("", 0, 0); if (i == 'y' || i == 'Y') { break; } if (i == ESCAPE || i == 'n' || i == 'N') { /* Cancel */ return; } if (i == 'A') { /* Add an auto-destroy preference line */ if (autopick_autoregister(o_ptr)) { /* Auto-destroy it */ autopick_alter_item(item, TRUE); } /* The object is already destroyed. */ return; } } /* while (TRUE) */ } /* See how many items */ if (o_ptr->number > 1) { /* Get a quantity */ amt = get_quantity(NULL, o_ptr->number); /* Allow user abort */ if (amt <= 0) return; } /* Describe the object */ old_number = o_ptr->number; o_ptr->number = amt; object_desc(o_name, o_ptr, 0); o_ptr->number = old_number; /* Take a turn */ energy_use = 100; /* Artifacts cannot be destroyed */ if (!can_player_destroy_object(o_ptr)) { energy_use = 0; /* Message */ msg_format("You cannot destroy %s.", o_name); /* Done */ return; } object_copy(q_ptr, o_ptr); stats_on_p_destroy(o_ptr, amt); if (prace_is_(RACE_MON_JELLY)) jelly_eat_object(o_ptr); else if (prace_is_(RACE_MON_SWORD) && object_is_melee_weapon(o_ptr)) sword_absorb_object(o_ptr); else if (prace_is_(RACE_MON_RING) && object_is_jewelry(o_ptr)) ring_absorb_object(o_ptr); else msg_format("You destroy %s.", o_name); if (o_ptr->rune == RUNE_SACRIFICE) { int add_hp = is_equipped ? p_ptr->mhp : p_ptr->mhp/3; int add_sp = is_equipped ? p_ptr->msp : p_ptr->msp/3; msg_print("You feel a surge of wondrous power enter your body."); p_ptr->chp = MIN(p_ptr->mhp, p_ptr->chp + add_hp); p_ptr->chp_frac = 0; p_ptr->csp = MIN(p_ptr->msp, p_ptr->csp + add_sp); p_ptr->csp_frac = 0; p_ptr->redraw |= (PR_MANA); p_ptr->window |= (PW_PLAYER); p_ptr->window |= (PW_SPELL); p_ptr->redraw |= (PR_HP); if (is_equipped) { blast_object(o_ptr); o_ptr->curse_flags = TRC_HEAVY_CURSE; } } else if (is_equipped) blast_object(o_ptr); sound(SOUND_DESTITEM); /* Reduce the charges of rods/wands */ reduce_charges(o_ptr, amt); /* Eliminate the item (from the pack) */ if (item >= 0) { if (!is_equipped) { inven_item_increase(item, -amt); inven_item_describe(item); inven_item_optimize(item); } } /* Eliminate the item (from the floor) */ else { floor_item_increase(0 - item, -amt); floor_item_describe(0 - item); floor_item_optimize(0 - item); } if ( p_ptr->pclass == CLASS_NECROMANCER && (q_ptr->tval == TV_LIFE_BOOK || q_ptr->tval == TV_CRUSADE_BOOK) ) { int sp = 0; int osp = p_ptr->csp; switch (q_ptr->sval) { case 0: sp = 10; break; case 1: sp = 25; break; case 2: sp = 100; break; case 3: sp = 666; break; } p_ptr->csp += sp; if (p_ptr->csp >= p_ptr->msp) { p_ptr->csp = p_ptr->msp; p_ptr->csp_frac = 0; } if (p_ptr->csp > osp) msg_print("You feel your head clear."); p_ptr->redraw |= (PR_MANA); } if (high_level_book(q_ptr)) { bool gain_expr = FALSE; if (p_ptr->prace == RACE_ANDROID) { } else if ((p_ptr->pclass == CLASS_WARRIOR) || (p_ptr->pclass == CLASS_BERSERKER)) { gain_expr = TRUE; } else if (p_ptr->pclass == CLASS_PALADIN) { if (is_good_realm(p_ptr->realm1)) { if (!is_good_realm(tval2realm(q_ptr->tval))) gain_expr = TRUE; } else { if (is_good_realm(tval2realm(q_ptr->tval))) gain_expr = TRUE; } } if (gain_expr && (p_ptr->exp < PY_MAX_EXP)) { s32b tester_exp = p_ptr->max_exp / 20; if (tester_exp > 10000) tester_exp = 10000; if (q_ptr->sval < 3) tester_exp /= 4; if (tester_exp<1) tester_exp = 1; msg_print("You feel more experienced."); gain_exp(tester_exp * amt); } } if (high_level_book(q_ptr) && q_ptr->tval == TV_LIFE_BOOK) { virtue_add(VIRTUE_UNLIFE, 1); virtue_add(VIRTUE_VITALITY, -1); } else if ( high_level_book(q_ptr) && (q_ptr->tval == TV_DEATH_BOOK || q_ptr->tval == TV_NECROMANCY_BOOK) ) { virtue_add(VIRTUE_UNLIFE, -1); virtue_add(VIRTUE_VITALITY, 1); } if (q_ptr->to_a || q_ptr->to_h || q_ptr->to_d) virtue_add(VIRTUE_ENCHANTMENT, -1); if (object_value_real(q_ptr) > 30000) virtue_add(VIRTUE_SACRIFICE, 2); else if (object_value_real(q_ptr) > 10000) virtue_add(VIRTUE_SACRIFICE, 1); if (q_ptr->to_a != 0 || q_ptr->to_d != 0 || q_ptr->to_h != 0) virtue_add(VIRTUE_HARMONY, 1); if (equip_is_valid_slot(item)) calc_android_exp(); }
/* * 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; }
/* XXX Eddie should messages be adhoc all over the place? perhaps the main * loop should check for change in inventory/wieldeds and all messages be * printed from one place */ void object_notice_on_wield(object_type *o_ptr) { bitflag f[OF_SIZE], obvious_mask[OF_SIZE]; bool obvious = FALSE; const slay_t *s_ptr; flags_init(obvious_mask, OF_SIZE, OF_OBVIOUS_MASK, FLAG_END); /* Save time of wield for later */ object_last_wield = turn; /* Only deal with un-ID'd items */ if (object_is_known(o_ptr)) return; /* Wear it */ object_flavor_tried(o_ptr); if (object_add_ident_flags(o_ptr, IDENT_WORN)) object_check_for_ident(o_ptr); if (obj_is_light(o_ptr) && ego_item_p(o_ptr)) object_notice_ego(o_ptr); if (object_flavor_is_aware(o_ptr) && easy_know(o_ptr)) { object_notice_everything(o_ptr); return; } /* Automatically sense artifacts upon wield */ object_sense_artifact(o_ptr); /* Note artifacts when found */ if (artifact_p(o_ptr)) history_add_artifact(o_ptr->name1, object_is_known(o_ptr), TRUE); /* special case FA, needed at least for mages wielding gloves */ if (object_FA_would_be_obvious(o_ptr)) of_on(obvious_mask, OF_FREE_ACT); /* Learn about obvious flags */ of_union(o_ptr->known_flags, obvious_mask); /* Extract the flags */ object_flags(o_ptr, f); /* Find obvious things (disregarding curses) */ flags_clear(obvious_mask, OF_SIZE, OF_CURSE_MASK, FLAG_END); if (of_is_inter(f, obvious_mask)) obvious = TRUE; flags_init(obvious_mask, OF_SIZE, OF_OBVIOUS_MASK, FLAG_END); /* XXX Eddie should these next NOT call object_check_for_ident due to worries about repairing? */ /* XXX Eddie this is a small hack, but jewelry with anything noticeable really is obvious */ /* XXX Eddie learn =soulkeeping vs =bodykeeping when notice sustain_str */ if (object_is_jewelry(o_ptr)) { /* Learn the flavor of jewelry with obvious flags */ if (EASY_LEARN && obvious) object_flavor_aware(o_ptr); /* Learn all flags on any aware non-artifact jewelry */ if (object_flavor_is_aware(o_ptr) && !artifact_p(o_ptr)) object_know_all_flags(o_ptr); } object_check_for_ident(o_ptr); if (!obvious) return; /* Messages */ for (s_ptr = slay_table; s_ptr->slay_flag; s_ptr++) { if (of_has(f, s_ptr->slay_flag) && s_ptr->brand) { char o_name[40]; object_desc(o_name, sizeof(o_name), o_ptr, ODESC_BASE); msg_format("Your %s %s!", o_name, s_ptr->active_verb); } } /* XXX Eddie need to add stealth here, also need to assert/double-check everything is covered */ if (of_has(f, OF_STR)) msg_format("You feel %s!", o_ptr->pval > 0 ? "stronger" : "weaker"); if (of_has(f, OF_INT)) msg_format("You feel %s!", o_ptr->pval > 0 ? "smarter" : "more stupid"); if (of_has(f, OF_WIS)) msg_format("You feel %s!", o_ptr->pval > 0 ? "wiser" : "more naive"); if (of_has(f, OF_DEX)) msg_format("You feel %s!", o_ptr->pval > 0 ? "more dextrous" : "clumsier"); if (of_has(f, OF_CON)) msg_format("You feel %s!", o_ptr->pval > 0 ? "healthier" : "sicklier"); if (of_has(f, OF_CHR)) msg_format("You feel %s!", o_ptr->pval > 0 ? "cuter" : "uglier"); if (of_has(f, OF_SPEED)) msg_format("You feel strangely %s.", o_ptr->pval > 0 ? "quick" : "sluggish"); if (flags_test(f, OF_SIZE, OF_BLOWS, OF_SHOTS, FLAG_END)) msg_format("Your hands %s", o_ptr->pval > 0 ? "tingle!" : "ache."); if (of_has(f, OF_INFRA)) msg_format("Your eyes tingle."); if (of_has(f, OF_LIGHT)) msg_print("It glows!"); if (of_has(f, OF_TELEPATHY)) msg_print("Your mind feels strangely sharper!"); /* WARNING -- masking f by obvious mask -- this should be at the end of this function */ flags_mask(f, OF_SIZE, OF_OBVIOUS_MASK, FLAG_END); /* learn the ego on any obvious brand or slay */ if (EASY_LEARN && ego_item_p(o_ptr) && obvious && flags_test(f, OF_SIZE, OF_ALL_SLAY_MASK, FLAG_END)) object_notice_ego(o_ptr); /* Remember the flags */ object_notice_sensing(o_ptr); /* XXX Eddie should we check_for_ident here? */ }
/* * Given an object, return a short identifier which gives some idea of what * the item is. */ obj_pseudo_t object_pseudo(const object_type *o_ptr) { object_kind *k_ptr = &k_info[o_ptr->k_idx]; bitflag flags[OF_SIZE]; /* Get the known and obvious flags on the object, * not including curses or properties of the kind */ object_flags_known(o_ptr, flags); /* MEGA-hack : there needs to be a table of what is obvious in each slot perhaps for each class */ /* FA on gloves is obvious to mage casters */ if (object_FA_would_be_obvious(o_ptr)) flags_mask(flags, OF_SIZE, OF_OBVIOUS_MASK, OF_FREE_ACT, FLAG_END); else flags_mask(flags, OF_SIZE, OF_OBVIOUS_MASK, FLAG_END); flags_clear(flags, OF_SIZE, OF_CURSE_MASK, FLAG_END); of_diff(flags, k_ptr->flags); if (o_ptr->ident & IDENT_INDESTRUCT) return INSCRIP_SPECIAL; if ((object_was_sensed(o_ptr) || object_was_worn(o_ptr)) && artifact_p(o_ptr)) return INSCRIP_SPECIAL; /* jewelry does not pseudo */ if (object_is_jewelry(o_ptr)) return INSCRIP_NULL; /* XXX Eddie should also check for flags with pvals where the pval exceeds * the base pval for things like picks of digging, though for now acid brand gets those */ if (!of_is_empty(flags)) return INSCRIP_SPLENDID; if (!object_is_known(o_ptr) && !object_was_sensed(o_ptr)) return INSCRIP_NULL; if (ego_item_p(o_ptr)) { /* uncursed bad egos are not excellent */ if (flags_test(e_info[o_ptr->name2].flags, OF_SIZE, OF_CURSE_MASK, FLAG_END)) return INSCRIP_STRANGE; /* XXX Eddie need something worse */ else return INSCRIP_EXCELLENT; } if (o_ptr->to_a == randcalc(k_ptr->to_a, 0, MINIMISE) && o_ptr->to_h == randcalc(k_ptr->to_h, 0, MINIMISE) && o_ptr->to_d == randcalc(k_ptr->to_d, 0, MINIMISE)) return INSCRIP_AVERAGE; if (o_ptr->to_a >= randcalc(k_ptr->to_a, 0, MINIMISE) && o_ptr->to_h >= randcalc(k_ptr->to_h, 0, MINIMISE) && o_ptr->to_d >= randcalc(k_ptr->to_d, 0, MINIMISE)) return INSCRIP_MAGICAL; if (o_ptr->to_a <= randcalc(k_ptr->to_a, 0, MINIMISE) && o_ptr->to_h <= randcalc(k_ptr->to_h, 0, MINIMISE) && o_ptr->to_d <= randcalc(k_ptr->to_d, 0, MINIMISE)) return INSCRIP_MAGICAL; return INSCRIP_STRANGE; }
/* * Determine the squelch 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. */ static byte squelch_level_of(const object_type *o_ptr) { object_kind *k_ptr = &k_info[o_ptr->k_idx]; byte value; bitflag f[OF_SIZE]; object_flags_known(o_ptr, f); if ((object_pval_is_visible(o_ptr)) && (o_ptr->pval < 0)) return SQUELCH_BAD; /* Deal with jewelry specially. */ if (object_is_jewelry(o_ptr)) { if ((object_pval_is_visible(o_ptr)) && (o_ptr->pval > 0)) return SQUELCH_AVERAGE; if ((o_ptr->to_h > 0) || (o_ptr->to_d > 0) || (o_ptr->to_a > 0)) return SQUELCH_AVERAGE; if ((o_ptr->to_h < 0) || (o_ptr->to_d < 0) || (o_ptr->to_a < 0)) return SQUELCH_BAD; return SQUELCH_AVERAGE; } /* And lights */ if (o_ptr->tval == TV_LIGHT) { if (flags_test(f, OF_SIZE, OF_OBVIOUS_MASK, FLAG_END)) return SQUELCH_ALL; if ((o_ptr->to_h > 0) || (o_ptr->to_d > 0) || (o_ptr->to_a > 0)) return SQUELCH_GOOD; if ((o_ptr->to_h < 0) || (o_ptr->to_d < 0) || (o_ptr->to_a < 0)) return SQUELCH_BAD; return SQUELCH_AVERAGE; } if (object_was_sensed(o_ptr)) { obj_pseudo_t pseudo = object_pseudo(o_ptr); switch (pseudo) { case INSCRIP_AVERAGE: value = SQUELCH_AVERAGE; break; case INSCRIP_EXCELLENT: /* have to assume splendid until you have tested it */ if (object_was_worn(o_ptr)) { if (object_high_resist_is_possible(o_ptr)) value = SQUELCH_EXCELLENT_NO_SPL; else value = SQUELCH_EXCELLENT_NO_HI; } else { value = SQUELCH_ALL; } break; case INSCRIP_STRANGE: /* XXX Eddie perhaps some strange count as something else */ case INSCRIP_SPLENDID: value = SQUELCH_ALL; break; case INSCRIP_NULL: case INSCRIP_SPECIAL: value = SQUELCH_MAX; break; /* This is the interesting case */ case INSCRIP_MAGICAL: value = SQUELCH_GOOD; if ((object_attack_plusses_are_visible(o_ptr) || (randcalc_valid(k_ptr->to_h, o_ptr->to_h) && randcalc_valid(k_ptr->to_d, o_ptr->to_d))) && (object_defence_plusses_are_visible(o_ptr) || (randcalc_valid(k_ptr->to_a, o_ptr->to_a))) && (o_ptr->to_h <= randcalc(k_ptr->to_h, 0, MINIMISE)) && (o_ptr->to_d <= randcalc(k_ptr->to_d, 0, MINIMISE)) && (o_ptr->to_a <= randcalc(k_ptr->to_a, 0, MINIMISE))) value = SQUELCH_BAD; break; default: /* do not handle any other possible pseudo values */ assert(0); } } else { if (object_was_worn(o_ptr)) value = SQUELCH_EXCELLENT_NO_SPL; /* object would be sensed if it were splendid */ else if (object_is_known_not_artifact(o_ptr)) value = SQUELCH_ALL; else value = SQUELCH_MAX; } return value; }
void textui_cmd_destroy(void) { int item; object_type *o_ptr; char out_val[160]; menu_type *m; region r; int selected; /* Get an item */ const char *q = "Ignore which item? "; const char *s = "You have nothing to ignore."; if (!get_item(&item, q, s, CMD_DESTROY, USE_INVEN | USE_EQUIP | USE_FLOOR)) return; o_ptr = object_from_item_idx(item); m = menu_dynamic_new(); m->selections = lower_case; /* Basic ignore option */ if (!o_ptr->ignore) { menu_dynamic_add(m, "This item only", IGNORE_THIS_ITEM); } else { menu_dynamic_add(m, "Unignore this item", UNIGNORE_THIS_ITEM); } /* Flavour-aware squelch */ if (squelch_tval(o_ptr->tval) && (!o_ptr->artifact || !object_flavor_is_aware(o_ptr))) { bool squelched = kind_is_squelched_aware(o_ptr->kind) || kind_is_squelched_unaware(o_ptr->kind); char tmp[70]; object_desc(tmp, sizeof(tmp), o_ptr, ODESC_BASE | ODESC_PLURAL); if (!squelched) { strnfmt(out_val, sizeof out_val, "All %s", tmp); menu_dynamic_add(m, out_val, IGNORE_THIS_FLAVOR); } else { strnfmt(out_val, sizeof out_val, "Unignore all %s", tmp); menu_dynamic_add(m, out_val, UNIGNORE_THIS_FLAVOR); } } /* Quality squelching */ if (object_was_sensed(o_ptr) || object_was_worn(o_ptr) || object_is_known_not_artifact(o_ptr)) { byte value = squelch_level_of(o_ptr); int type = squelch_type_of(o_ptr); if (object_is_jewelry(o_ptr) && squelch_level_of(o_ptr) != SQUELCH_BAD) value = SQUELCH_MAX; if (value != SQUELCH_MAX && type != TYPE_MAX) { strnfmt(out_val, sizeof out_val, "All %s %s", quality_values[value].name, quality_choices[type].name); menu_dynamic_add(m, out_val, IGNORE_THIS_QUALITY); } } /* work out display region */ r.width = menu_dynamic_longest_entry(m) + 3 + 2; /* +3 for tag, 2 for pad */ r.col = 80 - r.width; r.row = 1; r.page_rows = m->count; screen_save(); menu_layout(m, &r); region_erase_bordered(&r); prt("(Enter to select, ESC) Ignore:", 0, 0); selected = menu_dynamic_select(m); screen_load(); if (selected == IGNORE_THIS_ITEM) { cmd_insert(CMD_DESTROY); cmd_set_arg_item(cmd_get_top(), 0, item); } else if (selected == UNIGNORE_THIS_ITEM) { o_ptr->ignore = FALSE; } else if (selected == IGNORE_THIS_FLAVOR) { object_squelch_flavor_of(o_ptr); } else if (selected == UNIGNORE_THIS_FLAVOR) { kind_squelch_clear(o_ptr->kind); } else if (selected == IGNORE_THIS_QUALITY) { byte value = squelch_level_of(o_ptr); int type = squelch_type_of(o_ptr); squelch_level[type] = value; } p_ptr->notice |= PN_SQUELCH; menu_dynamic_free(m); }