static size_t obj_desc_pval(const object_type *o_ptr, char *buf, size_t max, size_t end, bool spoil) { bitflag f[OF_SIZE], f2[OF_SIZE]; int i; bool any = FALSE; object_flags(o_ptr, f); create_mask(f2, FALSE, OFT_PVAL, OFT_STAT, OFT_MAX); if (!of_is_inter(f, f2)) return end; strnfcat(buf, max, &end, " <"); for (i = 0; i < o_ptr->num_pvals; i++) { if (spoil || object_this_pval_is_visible(o_ptr, i)) { if (any) strnfcat(buf, max, &end, ", "); strnfcat(buf, max, &end, "%+d", o_ptr->pval[i]); any = TRUE; } } strnfcat(buf, max, &end, ">"); return end; }
/** * Add player-defined inscriptions or game-defined descriptions */ static size_t obj_desc_inscrip(const struct object *obj, char *buf, size_t max, size_t end) { const char *u[4] = { 0, 0, 0, 0 }; int n = 0; int feel = object_pseudo(obj); bitflag flags_known[OF_SIZE], f2[OF_SIZE]; object_flags_known(obj, flags_known); /* Get inscription */ if (obj->note) u[n++] = quark_str(obj->note); /* Use special inscription, if any */ if (!object_is_known(obj)) { if (feel) { /* cannot tell excellent vs strange vs splendid until wield */ if (!object_was_worn(obj) && obj->ego) u[n++] = "ego"; else u[n++] = inscrip_text[feel]; } else if (tval_can_have_charges(obj) && (obj->pval == 0)) u[n++] = "empty"; else if (object_was_worn(obj)) u[n++] = (tval_is_weapon(obj)) ? "wielded" : "worn"; else if (!object_flavor_is_aware(obj) && object_flavor_was_tried(obj)) u[n++] = "tried"; } /* Note curses */ create_mask(f2, FALSE, OFT_CURSE, OFT_MAX); if (of_is_inter(flags_known, f2)) u[n++] = "cursed"; /* Note ignore */ if (ignore_item_ok(obj)) u[n++] = "ignore"; if (n) { int i; for (i = 0; i < n; i++) { if (i == 0) strnfcat(buf, max, &end, " {"); strnfcat(buf, max, &end, "%s", u[i]); if (i < n-1) strnfcat(buf, max, &end, ", "); } strnfcat(buf, max, &end, "}"); } return end; }
/** * Determine whether a flagset includes any curse flags. */ bool cursed_p(bitflag *f) { bitflag f2[OF_SIZE]; of_wipe(f2); create_mask(f2, FALSE, OFT_CURSE, OFT_MAX); return of_is_inter(f, f2); }
/** * \returns whether the object is known to be cursed */ bool object_is_known_cursed(const object_type *o_ptr) { bitflag f[OF_SIZE], f2[OF_SIZE]; object_flags_known(o_ptr, f); /* Gather whatever curse flags there are to know */ create_mask(f2, false, OFT_CURSE, OFT_MAX); return of_is_inter(f, f2); }
/** * Determine if an item has the properties to be an ego item */ bool has_ego_properties(const object_type * o_ptr) { ego_item_type *e_ptr = &e_info[o_ptr->name2]; /* Has to be an ego item */ if (!(o_ptr->name2)) return FALSE; /* ID'd items are known */ if (o_ptr->ident & IDENT_KNOWN) return TRUE; /* This ego type has to have been seen */ if (!e_ptr->everseen) return FALSE; /* Rings and amulets have to be worn */ if ((o_ptr->tval == TV_RING) && (o_ptr->tval == TV_RING) && (!(o_ptr->ident & IDENT_WORN))) return FALSE; /* A curse matches */ if (cf_is_inter(e_ptr->id_curse, o_ptr->id_curse)) return TRUE; /* An object flag matches */ if (of_is_inter(e_ptr->id_obj, o_ptr->id_obj)) return TRUE; /* Another property matches */ if (if_is_inter(e_ptr->id_other, o_ptr->id_other)) return TRUE; /* Nothing */ 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; }
static size_t obj_desc_inscrip(const object_type *o_ptr, char *buf, size_t max, size_t end) { const char *u[4] = { 0, 0, 0, 0 }; int n = 0; int feel = object_pseudo(o_ptr); bitflag flags_known[OF_SIZE], f2[OF_SIZE]; object_flags_known(o_ptr, flags_known); /* Get inscription */ if (o_ptr->note) u[n++] = quark_str(o_ptr->note); /* Use special inscription, if any */ if (!object_is_known(o_ptr) && feel) { /* cannot tell excellent vs strange vs splendid until wield */ if (!object_was_worn(o_ptr) && o_ptr->ego) u[n++] = "ego"; else u[n++] = inscrip_text[feel]; } else if ((o_ptr->ident & IDENT_EMPTY) && !object_is_known(o_ptr)) u[n++] = "empty"; else if (!object_is_known(o_ptr) && object_was_worn(o_ptr)) { if (wield_slot(o_ptr) == INVEN_WIELD || wield_slot(o_ptr) == INVEN_BOW) u[n++] = "wielded"; else u[n++] = "worn"; } else if (!object_is_known(o_ptr) && object_was_fired(o_ptr)) u[n++] = "fired"; else if (!object_flavor_is_aware(o_ptr) && object_flavor_was_tried(o_ptr)) u[n++] = "tried"; /* Note curses */ create_mask(f2, FALSE, OFT_CURSE, OFT_MAX); if (of_is_inter(flags_known, f2)) u[n++] = "cursed"; /* Note squelch */ if (squelch_item_ok(o_ptr)) u[n++] = "squelch"; if (n) { int i; for (i = 0; i < n; i++) { if (i == 0) strnfcat(buf, max, &end, " {"); strnfcat(buf, max, &end, "%s", u[i]); if (i < n-1) strnfcat(buf, max, &end, ", "); } strnfcat(buf, max, &end, "}"); } return end; }
/** * 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; }
/** * Calculate the rating for a given slay combination */ static s32b slay_power(const object_type *o_ptr, int verbose, ang_file* log_file, bool known) { bitflag s_index[OF_SIZE], f[OF_SIZE], f2[OF_SIZE]; u32b sv = 0; int i, j; int mult; const struct slay *best_s_ptr = NULL; monster_race *r_ptr; monster_type *m_ptr; monster_type monster_type_body; const char *desc[SL_MAX] = { 0 }, *brand[SL_MAX] = { 0 }; int s_mult[SL_MAX] = { 0 }; if (known) object_flags(o_ptr, f); else object_flags_known(o_ptr, f); /* Combine the slay bytes into an index value, return if there are none */ of_copy(s_index, f); create_mask(f2, FALSE, OFT_SLAY, OFT_KILL, OFT_BRAND, OFT_MAX); if (!of_is_inter(s_index, f2)) return tot_mon_power; else of_inter(s_index, f2); /* Look in the cache to see if we know this one yet */ sv = check_slay_cache(s_index); /* If it's cached (or there are no slays), return the value */ if (sv) { file_putf(log_file, "Slay cache hit\n"); return sv; } /* * Otherwise we need to calculate the expected average multiplier * for this combination (multiplied by the total number of * monsters, which we'll divide out later). */ for (i = 0; i < z_info->r_max; i++) { best_s_ptr = NULL; mult = 1; r_ptr = &r_info[i]; m_ptr = &monster_type_body; m_ptr->r_idx = i; /* Find the best multiplier against this monster */ improve_attack_modifier((object_type *)o_ptr, m_ptr, &best_s_ptr, FALSE, !known); if (best_s_ptr) mult = best_s_ptr->mult; /* Add the multiple to sv */ sv += mult * r_ptr->scaled_power; } /* * To get the expected damage for this weapon, multiply the * average damage from base dice by sv, and divide by the * total number of monsters. */ if (verbose) { /* Write info about the slay combination and multiplier */ file_putf(log_file, "Slay multiplier for: "); j = list_slays(s_index, s_index, desc, brand, s_mult, FALSE); for (i = 0; i < j; i++) { if (brand[i]) { file_putf(log_file, brand[i]); } else { file_putf(log_file, desc[i]); } file_putf(log_file, "x%d ", s_mult[i]); } file_putf(log_file, "\nsv is: %d\n", sv); file_putf(log_file, " and t_m_p is: %d \n", tot_mon_power); file_putf(log_file, "times 1000 is: %d\n", (1000 * sv) / tot_mon_power); } /* Add to the cache */ if (fill_slay_cache(s_index, sv)) file_putf(log_file, "Added to slay cache\n"); return sv; }
/* 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? */ }