Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Major cleanup of sensing and id-by-use, changing sensing to mean know…

…ing the number of flags on an item.
  • Loading branch information...
commit 5e82e576bc1e34dff004cb3b8e9f6fcb733a1c75 1 parent 34b5d4f
@eddiegrove authored
View
2  src/attack.c
@@ -219,7 +219,7 @@ bool py_attack_real(int y, int x, bool *fear) {
}
/* Learn by use for other equipped items */
- wieldeds_notice_on_attack();
+ wieldeds_notice_offweapon_attack_plusses();
/* Apply the player damage bonuses */
dmg += p_ptr->state.to_d;
View
6 src/cmd1.c
@@ -323,11 +323,7 @@ static void py_pickup_aux(int o_idx, bool domsg)
p_ptr->notice |= PN_SQUELCH;
/* Automatically sense artifacts */
- object_sense_artifact(o_ptr);
-
- /* Log artifacts if found */
- if (o_ptr->artifact)
- history_add_artifact(o_ptr->artifact, object_is_known(o_ptr), TRUE);
+ object_notice_artifact(o_ptr);
/* Optionally, display a message */
if (domsg && !quiver_slot)
View
23 src/cmd3.c
@@ -121,6 +121,8 @@ void textui_cmd_destroy(void)
menu_type *m;
region r;
int selected;
+ byte value;
+ int type;
/* Get an item */
const char *q = "Ignore which item? ";
@@ -158,21 +160,18 @@ void textui_cmd_destroy(void)
}
/* 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);
+ value = squelch_level_of(o_ptr);
+ type = squelch_type_of(o_ptr);
- if (object_is_jewelry(o_ptr) &&
- squelch_level_of(o_ptr) != SQUELCH_BAD)
- value = SQUELCH_MAX;
+ 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);
+ 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);
- }
+ menu_dynamic_add(m, out_val, IGNORE_THIS_QUALITY);
}
/* work out display region */
View
13 src/defines.h
@@ -950,4 +950,17 @@ enum
MON_TMD_MAX
};
+/**
+ * Whether to give the player access to the exact number of object flags
+ * after an object has been pseudoed.
+ */
+#define SENSING_REVEALS_FLAG_COUNT TRUE
+
+/*
+ * Iterators for *_info arrays
+ */
+#define for_each_kind(k) for (k = &k_info[0]; k < &k_info[z_info->k_max]; k++) if (k->alloc_prob)
+#define for_each_ego(e) for (e = &e_info[0]; e < &e_info[z_info->e_max]; e++) if (e->rarity)
+#define for_each_artifact(a) for (a = &a_info[0]; a < &a_info[z_info->a_max]; a++) if (a->alloc_prob)
+
#endif /* !INCLUDED_DEFINES_H */
View
1  src/monster/melee1.c
@@ -75,7 +75,6 @@ bool check_hit(int power, int level)
ac = p_ptr->state.ac + p_ptr->state.to_a;
/* if the monster checks vs ac, the player learns ac bonuses */
- /* XXX Eddie should you only learn +ac on miss, -ac on hit? who knows */
object_notice_on_defend();
/* Check if the player was hit */
View
1  src/monster/monster2.c
@@ -3127,7 +3127,6 @@ void flush_all_monster_messages(void)
size_mon_hist = 0;
}
-/* XXX Eddie This is ghastly. The monster should have known_flags similar to in the object_type structure. */
typedef struct {
int idx;
int flag;
View
1,114 src/object/identify.c
@@ -4,6 +4,7 @@
*
* Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
* Copyright (c) 2009 Brian Bull
+ * Copyright (c) 2011 Edward F. Grove
*
* This work is free software; you can redistribute it and/or modify it
* under the terms of either:
@@ -17,6 +18,19 @@
* are included in all such copies. Other copyrights may also apply.
*/
+/*
+ * Some standard naming conventions for all functions below
+ *
+ * o_ptr is the object being identified
+ * o_flags are the actual flags of the object
+ * k_flags are the flags of a kind, including flags inherited from base tval
+ * o_known are the flags known by the char to be in the object
+ * obvious_mask is the set of flags that would be obvious on the object
+ * curse_mask is the set of flags for curses
+ * pval_mask is the set of flags with pvals
+ */
+
+
#include "angband.h"
#include "cave.h"
#include "game-event.h"
@@ -27,7 +41,9 @@
#include "squelch.h"
/** Time last item was wielded */
-s32b object_last_wield;
+/* EFG evil global, was externed, but not used elsewhere and not put into savefile
+ * save/reload to learn faster, this needs to be excised soon */
+static s32b object_last_wield = 0;
/*** Knowledge accessor functions ***/
@@ -57,8 +73,7 @@ bool object_is_known(const object_type *o_ptr)
*/
bool object_is_known_artifact(const object_type *o_ptr)
{
- return (o_ptr->ident & IDENT_INDESTRUCT) ||
- (o_ptr->artifact && object_was_sensed(o_ptr));
+ return (o_ptr->artifact && (o_ptr->ident & IDENT_NOTICE_ART));
}
/**
@@ -66,14 +81,32 @@ bool object_is_known_artifact(const object_type *o_ptr)
*/
bool object_is_known_cursed(const object_type *o_ptr)
{
- bitflag f[OF_SIZE], f2[OF_SIZE];
+ bitflag o_known[OF_SIZE], curse_mask[OF_SIZE];
+
+ object_flags_known(o_ptr, o_known);
- object_flags_known(o_ptr, f);
+ of_curse_mask(curse_mask);
+
+ return of_is_inter(o_known, curse_mask);
+}
+
+/**
+ * \returns whether the object is known to be cursed
+ */
+bool object_is_known_not_cursed(const object_type *o_ptr)
+{
+ bitflag o_flags[OF_SIZE], curse_mask[OF_SIZE];
/* Gather whatever curse flags there are to know */
- create_mask(f2, FALSE, OFT_CURSE, OFT_MAX);
+ of_curse_mask(curse_mask);
+
+ /* if you don't know a curse flag, might be cursed */
+ if (!of_is_subset(o_ptr->known_flags, curse_mask))
+ return FALSE;
- return of_is_inter(f, f2);
+ object_flags(o_ptr, o_flags);
+
+ return of_is_inter(o_flags, curse_mask) ? FALSE : TRUE;
}
/**
@@ -81,11 +114,11 @@ bool object_is_known_cursed(const object_type *o_ptr)
*/
bool object_is_known_blessed(const object_type *o_ptr)
{
- bitflag f[OF_SIZE];
+ bitflag o_known[OF_SIZE];
- object_flags_known(o_ptr, f);
+ object_flags_known(o_ptr, o_known);
- return (of_has(f, OF_BLESSED)) ? TRUE : FALSE;
+ return of_has(o_known, OF_BLESSED);
}
/**
@@ -93,12 +126,54 @@ bool object_is_known_blessed(const object_type *o_ptr)
*/
bool object_is_known_not_artifact(const object_type *o_ptr)
{
- if (o_ptr->ident & IDENT_NOTART)
- return TRUE;
+ return (o_ptr->ident & IDENT_NOTICE_ART) && !o_ptr->artifact;
+}
- return FALSE;
+/**
+ * \returns whether the object is known to be bad
+ *
+ * currently only checking numeric values
+ *
+ * this calls amulet of inertia bad -- should it be?
+ * negative pval stat rings are bad even though they have a sustain
+ */
+bool object_is_known_bad(const object_type *o_ptr)
+{
+ int i;
+ bool something_bad = FALSE;
+ bool something_good = FALSE;
+
+ for (i = 0; i < o_ptr->num_pvals; i++) {
+ if (object_this_pval_is_visible(o_ptr, i)) {
+ if (o_ptr->pval[i] > 0)
+ something_good = TRUE;
+ else if (o_ptr->pval[i] < 0)
+ something_bad = TRUE;
+ }
+ }
+
+ if (object_attack_plusses_are_visible(o_ptr)) {
+ if (o_ptr->to_h > 0)
+ something_good = TRUE;
+ else if (o_ptr->to_h < 0)
+ something_bad = TRUE;
+ if (o_ptr->to_d > 0)
+ something_good = TRUE;
+ else if (o_ptr->to_d < 0)
+ something_bad = TRUE;
+ }
+
+ if (object_defence_plusses_are_visible(o_ptr)) {
+ if (o_ptr->to_a > 0)
+ something_good = TRUE;
+ else if (o_ptr->to_a < 0)
+ something_bad = TRUE;
+ }
+
+ return something_bad && !something_good ? TRUE : FALSE;
}
+
/**
* \returns whether the object has been worn/wielded
*/
@@ -153,6 +228,31 @@ bool object_effect_is_known(const object_type *o_ptr)
}
/**
+ * \returns whether the effect exists and is known
+ */
+bool object_has_known_effect(const object_type *o_ptr)
+{
+ assert(o_ptr->kind);
+ return o_ptr->kind->effect && object_effect_is_known(o_ptr) ? TRUE : FALSE;
+}
+
+/**
+ * \returns whether the object is neither ego nor artifact
+ */
+bool object_is_not_excellent(const object_type *o_ptr)
+{
+ return !o_ptr->artifact && !o_ptr->ego ? TRUE : FALSE;
+}
+
+/**
+ * \returns whether the object is known to be neither ego nor artifact
+ */
+bool object_is_known_not_excellent(const object_type *o_ptr)
+{
+ return object_name_is_visible(o_ptr) && object_is_not_excellent(o_ptr) ? TRUE : FALSE;
+}
+
+/**
* \returns whether a specific pval is known to the player
*/
bool object_this_pval_is_visible(const object_type *o_ptr, int pval)
@@ -176,7 +276,7 @@ bool object_this_pval_is_visible(const object_type *o_ptr, int pval)
object_pval_flags_known(o_ptr, f);
/* Create the mask for pval-related flags */
- create_mask(f2, FALSE, OFT_STAT, OFT_PVAL, OFT_MAX);
+ of_pval_mask(f2);
if (of_is_inter(f[pval], f2))
return TRUE;
@@ -187,6 +287,8 @@ bool object_this_pval_is_visible(const object_type *o_ptr, int pval)
/**
* \returns whether any ego or artifact name is available to the player
+ *
+ * This can be TRUE for a boring object that is known to be not excellent.
*/
bool object_name_is_visible(const object_type *o_ptr)
{
@@ -194,13 +296,16 @@ bool object_name_is_visible(const object_type *o_ptr)
}
/**
- * \returns whether both the object is both an ego and the player knows it is
+ * \returns whether both the object is an ego and the player knows it is
*/
bool object_ego_is_visible(const object_type *o_ptr)
{
if (!o_ptr->ego)
return FALSE;
+ /* lights cannot be sensed, so ego is obvious */
+ /* EFG this seems broken -- jewelry cannot be sensed but is still learned
+ * Should lights require learning through check_for_ident? */
if (o_ptr->tval == TV_LIGHT)
return TRUE;
@@ -210,22 +315,34 @@ bool object_ego_is_visible(const object_type *o_ptr)
return FALSE;
}
+
/**
* \returns whether the object's attack plusses are known
*/
bool object_attack_plusses_are_visible(const object_type *o_ptr)
{
+ /* bare hands e.g. have visible attack plusses */
+ if (!o_ptr->kind) return TRUE;
+
/* Bonuses have been revealed or for sale */
if ((o_ptr->ident & IDENT_ATTACK) || (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))
- {
+ if (object_is_jewelry(o_ptr) && object_flavor_is_aware(o_ptr)) {
if (!randcalc_varies(o_ptr->kind->to_h) && !randcalc_varies(o_ptr->kind->to_d))
return TRUE;
}
+ /* Defensive items such as shields have fixed attack values unless ego or artifact */
+ else if (object_base_only_defensive(o_ptr)) {
+ if (object_is_known_not_excellent(o_ptr))
+ return TRUE;
+ if (o_ptr->ego && object_ego_is_visible(o_ptr)
+ && !randcalc_varies(o_ptr->ego->to_h) && !randcalc_varies(o_ptr->ego->to_d))
+ return TRUE;
+ }
+
return FALSE;
}
@@ -234,6 +351,8 @@ bool object_attack_plusses_are_visible(const object_type *o_ptr)
*/
bool object_defence_plusses_are_visible(const object_type *o_ptr)
{
+ if (!o_ptr->kind) return TRUE;
+
/* Bonuses have been revealed or for sale */
if ((o_ptr->ident & IDENT_DEFENCE) || (o_ptr->ident & IDENT_STORE))
return TRUE;
@@ -245,14 +364,22 @@ bool object_defence_plusses_are_visible(const object_type *o_ptr)
return TRUE;
}
+ /* Offensive items such as daggers have fixed defense values unless ego or artifact */
+ else if (object_base_only_offensive(o_ptr)) {
+ if (object_is_known_not_excellent(o_ptr))
+ return TRUE;
+ if (o_ptr->ego && object_ego_is_visible(o_ptr) && !randcalc_varies(o_ptr->ego->to_a))
+ return TRUE;
+ }
+
return FALSE;
}
-/*
+/**
* \returns whether the player knows whether an object has a given flag
*/
-bool object_flag_is_known(const object_type *o_ptr, int flag)
+bool object_flag_is_known(const object_type *o_ptr, flag_type flag)
{
if (easy_know(o_ptr) ||
(o_ptr->ident & IDENT_STORE) ||
@@ -263,32 +390,184 @@ bool object_flag_is_known(const object_type *o_ptr, int flag)
}
-/*
+/**
* \returns whether it is possible an object has a high resist given the
* player's current knowledge
*/
bool object_high_resist_is_possible(const object_type *o_ptr)
{
- bitflag flags[OF_SIZE], f2[OF_SIZE];
+ bitflag possible[OF_SIZE], high_resists[OF_SIZE];
/* Actual object flags */
- object_flags(o_ptr, flags);
+ object_flags(o_ptr, possible);
/* Add player's uncertainty */
- of_comp_union(flags, o_ptr->known_flags);
+ of_comp_union(possible, o_ptr->known_flags);
/* Check for possible high resist */
- create_mask(f2, FALSE, OFT_HRES, OFT_MAX);
- if (of_is_inter(flags, f2))
+ create_mask(high_resists, FALSE, OFT_HRES, OFT_MAX);
+ if (of_is_inter(possible, high_resists))
return TRUE;
else
return FALSE;
}
+/**
+ * \returns number of object flags in the list which are learnable
+ */
+static int num_learnable_flags(const bitflag flags[OF_SIZE])
+{
+ bitflag unlearnable[OF_SIZE];
+ flag_type i;
+ int num = 0;
+
+ of_unlearnable_mask(unlearnable);
-/*
- * Sets a some IDENT_ flags on an object.
+ for_each_object_flag(i) {
+ if (of_has(flags, i) && !of_has(unlearnable, i))
+ num++;
+ }
+
+ return num;
+}
+
+
+/**
+ * \returns number of learnable flags in the object that are not known yet
+ */
+int object_num_unlearned_flags(const object_type *o_ptr)
+{
+ bitflag o_flags[OF_SIZE];
+ bitflag o_known[OF_SIZE];
+ bitflag unlearnable[OF_SIZE];
+ int unknown = 0;
+ flag_type i;
+
+ object_flags(o_ptr, o_flags);
+ object_flags_known(o_ptr, o_known);
+ of_unlearnable_mask(unlearnable);
+
+ for_each_object_flag(i)
+ if (of_has(o_flags, i) && !of_has(o_known, i) && !of_has(unlearnable, i)) {
+ unknown++;
+ }
+
+ return unknown;
+}
+
+
+/**
+ * \returns number of learnable flags in the object
+ */
+int object_num_learnable_flags(const object_type *o_ptr)
+{
+ bitflag o_flags[OF_SIZE];
+ object_flags(o_ptr, o_flags);
+
+ return num_learnable_flags(o_flags);
+}
+
+
+/**
+ * Create a list of flags that are obvious on a particular kind.
+ *
+ * This should be allowed to depend upon race and class as well.
+ * If you want SI not to be obvious to high-elves, put that code here.
+ */
+void kind_obvious_mask(const object_kind *kind, bitflag flags[OF_SIZE])
+{
+ if (base_is_ammo(kind->base)) {
+ of_wipe(flags);
+ return;
+ }
+
+ create_mask(flags, TRUE, OFID_WIELD, OFT_MAX);
+
+ /* special case FA, needed at least for mages wielding gloves */
+ if (player_has(PF_CUMBER_GLOVE) && base_wield_slot(kind->base) == INVEN_HANDS)
+ of_on(flags, OF_FREE_ACT);
+
+}
+
+/**
+ * \returns whether the pval of the flag is visible
+ */
+bool object_flag_pval_is_visible(const object_type *o_ptr, flag_type flag)
+{
+ /* currently either all or no pvals are visible, depending upon worn status */
+ return object_was_worn(o_ptr);
+}
+
+/**
+ * \returns whether the player knows the object is splendid
+ */
+bool object_is_known_splendid(const object_type *o_ptr)
+{
+ bitflag o_known[OF_SIZE], k_flags[OF_SIZE], obvious_mask[OF_SIZE], pval_mask[OF_SIZE];
+ flag_type i;
+
+ assert(o_ptr->kind);
+
+ /* possibly cursed items cannot be known to be splendid */
+ if (!object_is_known_not_cursed(o_ptr))
+ return FALSE;
+
+ object_flags_known(o_ptr, o_known);
+ object_kind_flags(o_ptr->kind, k_flags);
+ kind_obvious_mask(o_ptr->kind, obvious_mask);
+ of_pval_mask(pval_mask);
+
+ /* check if any known obvious flags */
+ for_each_object_flag(i) {
+ if (of_has(o_known, i) && of_has(obvious_mask, i)) {
+ /* a pval flag in the kind, such as digging on a pick, is obvious only if the pval is visible */
+ if (of_has(pval_mask, i)) {
+ if (!of_has(k_flags, i))
+ return TRUE;
+ else if (object_flag_pval_is_visible(o_ptr, i) && o_ptr->ego)
+ return TRUE;
+ }
+ else return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ * \returns whether the player knows the object is not splendid
+ */
+bool object_is_known_unsplendid(const object_type *o_ptr)
+{
+ bitflag known_not_in_kind[OF_SIZE], obvious_mask[OF_SIZE];
+ bitflag pval_mask[OF_SIZE], kind_only_pvals[OF_SIZE];
+
+ kind_obvious_mask(o_ptr->kind, obvious_mask);
+ object_flags_known(o_ptr, known_not_in_kind);
+
+ if (o_ptr->ego) {
+ /* collect flags with pvals due to kind not in the ego */
+ of_pval_mask(pval_mask);
+ object_kind_flags(o_ptr->kind, kind_only_pvals);
+ of_inter(kind_only_pvals, pval_mask);
+ of_diff(kind_only_pvals, o_ptr->ego->flags);
+
+ /* removed kind only pval flags before testing for obvious flags */
+ of_diff(known_not_in_kind, kind_only_pvals);
+ }
+
+ /* check if anything known obvious */
+ if (of_is_inter(known_not_in_kind, obvious_mask))
+ return FALSE;
+
+ /* make sure all possible obvious flags are accounted for */
+ return of_is_subset(o_ptr->known_flags, obvious_mask);
+}
+
+
+/**
+ * Sets some IDENT_ flags on an object.
*
* \param o_ptr is the object to check
* \param flags are the ident flags to be added
@@ -306,45 +585,368 @@ static bool object_add_ident_flags(object_type *o_ptr, u32b flags)
return FALSE;
}
-
/*
+ * Set the second param to be those flags known to be in the object with visible pvals
+ *
+ * Currently all pvals or none are visible, depending upon worn status.
+ */
+void object_flags_with_visible_pvals(const object_type *o_ptr, bitflag o_pvals_known[OF_SIZE])
+{
+ if (object_was_worn(o_ptr)) {
+ bitflag pval_mask[OF_SIZE];
+
+ object_flags_known(o_ptr, o_pvals_known);
+ of_pval_mask(pval_mask);
+
+ of_inter(o_pvals_known, pval_mask);
+ }
+ else
+ of_wipe(o_pvals_known);
+}
+
+/**
+ * Counts the number of egos that are consistent with flags known by player.
+ * Count is currently not guaranteed to be exact because of imperfect checks
+ * for random powers.
+ *
+ * \returns an upper bound on the number of egos consistent with knowledge of the object
+ */
+static int num_matching_egos(const object_type *o_ptr)
+{
+ int num = 0;
+ bitflag known_true[OF_SIZE]; /* flags known to be on object */
+ bitflag known_false[OF_SIZE]; /* flags known to be missing from object */
+ bitflag ego_pval_flags_known[OF_SIZE]; /* flags known to be required in the ego */
+ ego_item_type *e_ptr;
+
+ bitflag pval_mask[OF_SIZE];
+ of_pval_mask(pval_mask);
+
+ object_flags_known(o_ptr, known_true);
+ of_copy(known_false, o_ptr->known_flags);
+ of_diff(known_false, known_true);
+
+ if (o_ptr->ego) {
+ of_copy(ego_pval_flags_known, o_ptr->ego->flags);
+ of_inter(ego_pval_flags_known, pval_mask);
+ of_inter(ego_pval_flags_known, o_ptr->known_flags);
+ }
+ else of_wipe(ego_pval_flags_known);
+
+ /* We check each ego to see whether it is a possible match for what is
+ * known about the flags on the object, both positive and negative */
+ for_each_ego(e_ptr)
+ {
+ bitflag possible[OF_SIZE];
+ bitflag required[OF_SIZE];
+ bitflag xtra_flags[OF_SIZE];
+
+ /* restrict to egos that match the object */
+ if (ego_applies(e_ptr, o_ptr->tval, o_ptr->sval))
+ {
+ /* If a base object has a flag like slay undead you cannot differentiate the ego based upon it.
+ * However, for flags with pvals things are clear. */
+ if (o_ptr->ego) {
+ bitflag o_pvals_known[OF_SIZE]; /* flags in the object for which the pval is known */
+ bitflag e_pval_flags[OF_SIZE]; /* flags with pvals in e_ptr that match flags known on the object */
+ bitflag ego_pvals_visible[OF_SIZE]; /* corresponding flags with visible pvals in actual ego */
+
+ /* collect the set of flags in question */
+ object_flags_with_visible_pvals(o_ptr, o_pvals_known);
+
+ /* find matching flags in e_ptr */
+ of_copy(e_pval_flags, e_ptr->flags);
+ of_inter(e_pval_flags, o_pvals_known);
+
+ /* find matching flags in real ego */
+ of_copy(ego_pvals_visible, o_ptr->ego->flags);
+ of_inter(ego_pvals_visible, o_pvals_known);
+
+ /* check that e_ptr matches the actual ego for flags with known pvals */
+ if (!of_is_equal(e_pval_flags, ego_pvals_visible))
+ continue;
+ }
+ /* This ends checking about specific pval values. */
+
+ /* flags either from the object's kind or possible ego are required */
+ object_kind_flags(o_ptr->kind, required);
+ of_union(required, e_ptr->flags);
+
+ /* the possible flags are mainly the required flags */
+ of_copy(possible, required);
+
+ /* egos with an xtra flag increase the range of possible flags */
+ of_wipe(xtra_flags);
+ switch (e_ptr->xtra)
+ {
+ case OBJECT_XTRA_TYPE_NONE:
+ break;
+ case OBJECT_XTRA_TYPE_SUSTAIN:
+ set_ego_xtra_sustain(xtra_flags);
+ break;
+ case OBJECT_XTRA_TYPE_RESIST:
+ set_ego_xtra_resist(xtra_flags);
+ break;
+ case OBJECT_XTRA_TYPE_POWER:
+ set_ego_xtra_power(xtra_flags);
+ break;
+ default:
+ assert(0);
+ }
+ of_union(possible, xtra_flags);
+
+ /* check consistency of object knowledge with flags possible and required */
+ if (!of_is_subset(possible, known_true)) continue;
+ if (of_is_inter(known_false, required)) continue;
+
+ if (SENSING_REVEALS_FLAG_COUNT && object_was_sensed(o_ptr)) {
+ /*
+ * Given the flag count, we can limit to egos producing the same number of flags as the object has.
+ * This section of code is only about the true number of flags matching the ego.
+ * There is no need for any reference to what is known.
+ * However, sensing is only about learnable flags. Stuff like HIDE_TYPE should not be counted.
+ */
+
+ int num_eflags; /* number of flags present in possible ego, including inherited from kind */
+ int num_oflags; /* ditto for object */
+ bitflag e_flags[OF_SIZE]; /* flags in ego, including inherited from kind */
+ bitflag o_flags[OF_SIZE]; /* ditto for object */
+
+ /* get the number of learnable flags in the object */
+ object_flags(o_ptr, o_flags);
+ num_oflags = num_learnable_flags(o_flags);
+
+ /* get the number of learnable flags for ego in question applied to same kind */
+ object_kind_flags(o_ptr->kind, e_flags);
+ of_union(e_flags, e_ptr->flags);
+ num_eflags = num_learnable_flags(e_flags);
+ if (e_ptr->xtra)
+ /* Currently all xtra powers are a single flag guaranteed to be different from given ego and kind properties */
+ num_eflags++;
+
+ if (num_oflags != num_eflags) continue;
+ }
+ num++;
+ }
+ }
+ if ((num == 0) && (o_ptr->ego))
+ /*
+ * We could assert that some ego must match, but in case of an old savefile
+ * that does not quite match, the ident code just reveals the ego in such cases.
+ * This message is so that perhaps someone will make a bug report.
+ */
+ msgt(MSG_GENERIC, "Bug: object's ego seems impossible.");
+
+ return num;
+}
+
+
+/**
+ * \returns the number of flavors that match current knowledge of object
+ */
+static int num_matching_unaware_flavors(const object_type *o_ptr)
+{
+ int num = 0;
+ bitflag known_true[OF_SIZE]; /* flags known to be in the object */
+ bitflag known_false[OF_SIZE]; /* flags known not to be in the object */
+ object_kind *k_ptr;
+
+ object_flags_known(o_ptr, known_true);
+ of_copy(known_false, o_ptr->known_flags);
+ of_diff(known_false, known_true);
+
+ /* simply check each kind to see if it allocatable and matches knowledge */
+ for_each_kind(k_ptr) {
+ bitflag k_flags[OF_SIZE];
+
+ if (k_ptr->aware) continue;
+ if (k_ptr->tval != o_ptr->tval) continue;
+ if (!k_ptr->alloc_prob) continue;
+
+ object_kind_flags(k_ptr, k_flags);
+ if (!of_is_subset(k_flags, known_true)) continue;
+
+ if (of_is_inter(known_false, k_flags)) continue;
+ if (o_ptr->kind->effect && !k_ptr->effect) continue;
+ if (!o_ptr->kind->effect && k_ptr->effect) continue;
+
+ num++;
+ }
+ if ((num == 0) && (!o_ptr->artifact))
+ msgt(MSG_GENERIC, "Bug: object's flavor seems impossible.");
+ return num;
+}
+
+/**
+ * \returns whether all plusses are known on an object
+ *
+ * plusses are values not associated to flags, such as to_h and to_d and to_a,
+ */
+bool object_all_plusses_are_visible(const object_type *o_ptr)
+{
+ return object_attack_plusses_are_visible(o_ptr) && object_defence_plusses_are_visible(o_ptr) ? TRUE : FALSE;
+}
+
+/**
* Checks for additional knowledge implied by what the player already knows.
*
* \param o_ptr is the object to check
*
- * returns whether it calls object_notice_everyting
+ * \returns whether it calls object_notice_everyting
*/
bool object_check_for_ident(object_type *o_ptr)
{
- bitflag flags[OF_SIZE], known_flags[OF_SIZE], f2[OF_SIZE];
-
- object_flags(o_ptr, flags);
+ bitflag o_flags[OF_SIZE], k_flags[OF_SIZE], known_flags[OF_SIZE], unlearnable[OF_SIZE];
+ bitflag o_flags_learnable[OF_SIZE], known_flags_learnable[OF_SIZE];
+ int i;
+
+ bool something_sensed; /* whether you have learned any information about flags being on the object */
+
+ /*
+ * This next variable describes whether any flag was learned to be present on the object.
+ * This does not inlcude flags known to be present in the kind, such as OF_TUNNEL on a digger
+ * It does include flags on unaware jewelry.
+ */
+ bool some_flag_known;
+
+ assert(o_ptr->kind);
+ assert(o_ptr->kind->base);
+
+ if (object_is_known(o_ptr))
+ return FALSE;
+
+ /*
+ * Objects such as wands could be checked for flags such as IGNORE_ELEC,
+ * but for now this function is only about learning about wieldable items and ammo
+ */
+ if (!obj_can_wear(o_ptr) && !object_can_be_sensed(o_ptr))
+ return FALSE;
+
+ if (SENSING_REVEALS_FLAG_COUNT && object_was_sensed(o_ptr)) {
+ /* if you know there are no flags left to learn, know all flags */
+ if (object_num_unlearned_flags(o_ptr) == 0)
+ of_setall(o_ptr->known_flags);
+ }
+
+ object_flags(o_ptr, o_flags);
object_flags_known(o_ptr, known_flags);
+ object_kind_flags(o_ptr->kind, k_flags);
+
+ /* first determine if we know anything about the object's flags */
+ if (object_is_jewelry(o_ptr))
+ /* jewelry learning is about learning kind flags */
+ some_flag_known = object_has_known_effect(o_ptr) || !of_is_subset(o_ptr->kind->base->flags, known_flags);
+ else
+ /* non-jewelry kinds are known, learning is about further flags */
+ some_flag_known = object_has_known_effect(o_ptr) || !of_is_subset(k_flags, known_flags);
+ something_sensed = some_flag_known || object_was_sensed(o_ptr);
- /* Some flags are irrelevant or never learned or too hard to learn */
- create_mask(f2, FALSE, OFT_INT, OFT_IGNORE, OFT_HATES, OFT_MAX);
- of_diff(flags, f2);
- of_diff(known_flags, f2);
+ /*
+ * If nothing is known about flags, give up, unless the item might have magical plusses only.
+ * An object with no possible ego or artifact can continue.
+ * E.g. a wielded digger with no digging bonus is known neither ego nor artifact, so might still ID.
+ */
+ if (!something_sensed && !object_is_jewelry(o_ptr) &&
+ ((num_matching_egos(o_ptr) != 0) || !object_is_known_not_artifact(o_ptr)))
+ return FALSE;
- if (!of_is_equal(flags, known_flags)) return FALSE;
+ /*
+ * See if there is a unique match, flavor or ego, to the object in question.
+ * Then the player can be informed.
+ *
+ * The following tests for <= 1 rather than == 1 give some hope to recover if
+ * there are bugs or an object comes from an earlier version and the
+ * rarity has been changed to 0.
+ */
- /* If we know attack bonuses, and defence bonuses, and effect, then
- * we effectively know everything, so mark as such */
- if ((object_attack_plusses_are_visible(o_ptr) || (object_was_sensed(o_ptr) && o_ptr->to_h == 0 && o_ptr->to_d == 0)) &&
- (object_defence_plusses_are_visible(o_ptr) || (object_was_sensed(o_ptr) && o_ptr->to_a == 0)) &&
- (object_effect_is_known(o_ptr) || !object_effect(o_ptr)))
- {
- object_notice_everything(o_ptr);
- return TRUE;
+ /* unique jewelry flavor */
+ if (!o_ptr->artifact && object_is_jewelry(o_ptr) &&
+ !object_flavor_is_aware(o_ptr) &&
+ (num_matching_unaware_flavors(o_ptr) <= 1)) {
+ object_flavor_aware(o_ptr);
+
+ /* noticing the flavor may mean more flags known */
+ object_flags_known(o_ptr, known_flags);
}
- /* We still know all the flags, so we still know if it's an ego */
- else if (o_ptr->ego)
- {
- /* require worn status so you don't learn launcher of accuracy or gloves of slaying before wield */
- if (object_was_worn(o_ptr))
- object_notice_ego(o_ptr);
+ /* unique ego, or no possible ego */
+ else if (!object_is_jewelry(o_ptr) && !o_ptr->artifact && !object_ego_is_visible(o_ptr)) {
+ int num = num_matching_egos(o_ptr);
+ if (num == 0) {
+ if (o_ptr->ego) {
+ /* requires a bug to get here, but instead of assert failure,
+ * might as well let the player keep playing */
+ num = 1;
+ } else {
+ /* the char knows that no ego could match */
+ object_notice_ego(o_ptr);
+ if (object_all_plusses_are_visible(o_ptr)) {
+ object_notice_everything(o_ptr);
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+ }
+ if (num == 1) { /* not an else-if, see num=1 above */
+ /* it is possible for num of 1 with no ego e.g. boring gloves match ego of slaying */
+ if (o_ptr->ego) {
+ object_notice_ego(o_ptr);
+ /* object_notice_ego recursively calls back to object_check_for_ident
+ * so the recursion already did all ident work possible. */
+ return o_ptr->ident & IDENT_KNOWN ? TRUE : FALSE;
+
+ /* If the recursion is ever removed from object_notice_ego, uncomment the next line */
+ /* noticing the ego may mean more flags known
+ object_flags_known(o_ptr, known_flags);
+ */
+ }
+ }
+
+ }
+
+ /* ID is not finished if you do not know the activation */
+ if (object_effect(o_ptr) && !object_effect_is_known(o_ptr))
+ return FALSE;
+
+ of_copy(o_flags_learnable, o_flags);
+ of_copy(known_flags_learnable, known_flags);
+
+ /* only interested in what's over and above flags inherited from kind */
+ if (object_flavor_is_aware(o_ptr)) {
+ bitflag k_flags[OF_SIZE];
+ object_kind_flags(o_ptr->kind, k_flags);
+
+ of_diff(o_flags_learnable, k_flags);
+ of_diff(known_flags_learnable, k_flags);
+ }
+
+ /* We need to deal with flags that cannot be learned */
+ of_unlearnable_mask(unlearnable);
+ of_diff(o_flags_learnable, unlearnable);
+ of_diff(known_flags_learnable, unlearnable);
+
+
+ /* require full knowledge, positive and negative, of all learnable flags */
+ if (!of_is_equal(o_flags_learnable, known_flags_learnable)) return FALSE;
+
+ /*
+ * In order to get this far, all knowable flags in the object must be known.
+ * To give IDENT_KNOWN status, we also require knowing there are no other flags,
+ * and also require knowledge of all pvals and non-flag plusses.
+ */
+
+ /* In addition to knowing the pval flags, it is necessary to know the pvals */
+ /* EFG this should test knowledge of pvals of individual flags */
+ for (i = 0; i < o_ptr->num_pvals; i++) if (!object_this_pval_is_visible(o_ptr, i)) return FALSE;
+
+ /* require sensing to know if there are unknown flags, except if cannot sense */
+ if (object_was_sensed(o_ptr) || !object_can_be_sensed(o_ptr)) {
+ if (object_all_plusses_are_visible(o_ptr)) {
+ object_notice_everything(o_ptr);
+ return TRUE;
+ }
}
return FALSE;
@@ -407,7 +1009,7 @@ void object_know_all_flags(object_type *o_ptr)
#define IDENTS_SET_BY_IDENTIFY ( IDENT_KNOWN | IDENT_ATTACK | IDENT_DEFENCE | IDENT_SENSE | IDENT_EFFECT | IDENT_WORN | IDENT_FIRED | IDENT_NAME )
/**
- * Check whether an object has IDENT_KNOWN but should not
+ * \returns whether an object has IDENT_KNOWN but should not
*/
bool object_is_not_known_consistently(const object_type *o_ptr)
{
@@ -443,14 +1045,14 @@ void object_notice_everything(object_type *o_ptr)
/* Mark as known */
object_flavor_aware(o_ptr);
- object_add_ident_flags(o_ptr, IDENTS_SET_BY_IDENTIFY);
+ object_notice_artifact(o_ptr);
+ object_notice_ego(o_ptr);
- /* Artifact has now been seen */
- if (o_ptr->artifact && !(o_ptr->ident & IDENT_FAKE))
- {
- o_ptr->artifact->seen = o_ptr->artifact->everseen = TRUE;
- history_add_artifact(o_ptr->artifact, TRUE, TRUE);
- }
+ /* IDENT_NAME is in the next set, but it should be set only by
+ * object_notice_artifact or object_notice_ego for everseen purposes,
+ * among other reasons. What should be changed?
+ */
+ object_add_ident_flags(o_ptr, IDENTS_SET_BY_IDENTIFY);
/* Know all flags there are to be known */
object_know_all_flags(o_ptr);
@@ -458,6 +1060,8 @@ void object_notice_everything(object_type *o_ptr)
+#if 0
+/* EFG the flag IDENT_INDESTRUCT should be eliminated */
/**
* Notice that an object is indestructible.
*/
@@ -465,30 +1069,33 @@ void object_notice_indestructible(object_type *o_ptr)
{
if (object_add_ident_flags(o_ptr, IDENT_INDESTRUCT))
object_check_for_ident(o_ptr);
+ object_notice_artifact(o_ptr);
}
+#endif
-/*
- * Notice the ego on an ego item.
+/**
+ * Notice the ego on an ego item, or that there is no ego
*/
void object_notice_ego(object_type *o_ptr)
{
bitflag learned_flags[OF_SIZE];
bitflag xtra_flags[OF_SIZE];
- if (!o_ptr->ego)
- return;
-
+ /* Things are a bit confused because lights can be egos, but can also be jewelry e.g. The Phial */
+ /* This function might be called on a light, which might be jewelry, leading to bugs elsewhere. */
+ if (object_is_jewelry(o_ptr)) return;
- /* XXX Eddie print a message on notice ego if not already noticed? */
- /* XXX Eddie should we do something about everseen of egos here? */
+ if (!object_add_ident_flags(o_ptr, IDENT_NAME)) return;
- /* Learn ego flags */
- of_union(o_ptr->known_flags, o_ptr->ego->flags);
+ /* all flags are known when an object is known neither ego nor artifact */
+ if (!o_ptr->ego && object_is_known_not_artifact(o_ptr)) {
+ of_setall(o_ptr->known_flags);
+ return;
+ }
/* Learn all flags except random abilities */
of_setall(learned_flags);
-
switch (o_ptr->ego->xtra)
{
case OBJECT_XTRA_TYPE_NONE:
@@ -508,47 +1115,64 @@ void object_notice_ego(object_type *o_ptr)
default:
assert(0);
}
-
of_union(o_ptr->known_flags, learned_flags);
- if (object_add_ident_flags(o_ptr, IDENT_NAME))
- {
- /* if you know the ego, you know which it is of excellent or splendid */
- object_notice_sensing(o_ptr);
+ /*
+ * Learn ego flags, which is not redundant in the case where an ego is
+ * allowed with a guaranteed flag that matches the xtra possibilities.
+ * E.g. gondolin ego has guaranteed flags matching xtra_flags.
+ */
+ of_union(o_ptr->known_flags, o_ptr->ego->flags);
- object_check_for_ident(o_ptr);
- }
+ object_check_for_ident(o_ptr);
}
-/*
+/**
* Mark an object as sensed.
+ *
+ * This now means that the char knows the number of flags on the item,
+ * so it is premature to notice sensing just because you know the item
+ * is splendid or an artifact.
*/
void object_notice_sensing(object_type *o_ptr)
{
- if (object_was_sensed(o_ptr))
- return;
+ if (!object_add_ident_flags(o_ptr, IDENT_SENSE)) return;
- if (o_ptr->artifact) {
- o_ptr->artifact->seen = o_ptr->artifact->everseen = TRUE;
- o_ptr->ident |= IDENT_NAME;
- }
+ object_notice_artifact(o_ptr);
object_notice_curses(o_ptr);
- if (object_add_ident_flags(o_ptr, IDENT_SENSE))
- object_check_for_ident(o_ptr);
+
+ /* note lack of name for boring objects */
+ if (object_is_not_excellent(o_ptr))
+ object_notice_ego(o_ptr);
+
+ object_check_for_ident(o_ptr);
}
-/*
- * Sense artifacts
+/**
+ * Notice whether object is an artifact
*/
-void object_sense_artifact(object_type *o_ptr)
+void object_notice_artifact(object_type *o_ptr)
{
- if (o_ptr->artifact)
- object_notice_sensing(o_ptr);
- else
- o_ptr->ident |= IDENT_NOTART;
+ if (!object_add_ident_flags(o_ptr, IDENT_NOTICE_ART)) return;
+
+ if (o_ptr->artifact) {
+ /* Show the artifact name so you get the correct description. */
+ object_add_ident_flags(o_ptr, IDENT_NAME);
+ /* no need to show flavor when name is known */
+ object_flavor_aware(o_ptr);
+
+ if (!(o_ptr->ident & IDENT_FAKE)) {
+ /* mark seen status */
+ o_ptr->artifact->seen = TRUE;
+ o_ptr->artifact->everseen = TRUE;
+
+ /* Note artifacts when found */
+ history_add_artifact(o_ptr->artifact, object_is_known(o_ptr), TRUE);
+ }
+ }
}
@@ -559,12 +1183,13 @@ void object_sense_artifact(object_type *o_ptr)
*/
void object_notice_effect(object_type *o_ptr)
{
- if (object_add_ident_flags(o_ptr, IDENT_EFFECT))
- object_check_for_ident(o_ptr);
+ if (!object_add_ident_flags(o_ptr, IDENT_EFFECT)) return;
/* noticing an effect gains awareness */
if (!object_flavor_is_aware(o_ptr))
object_flavor_aware(o_ptr);
+
+ object_check_for_ident(o_ptr);
}
@@ -572,11 +1197,9 @@ static void object_notice_defence_plusses(object_type *o_ptr)
{
assert(o_ptr && o_ptr->kind);
- if (object_defence_plusses_are_visible(o_ptr))
- return;
+ if (!object_add_ident_flags(o_ptr, IDENT_DEFENCE)) return;
- if (object_add_ident_flags(o_ptr, IDENT_DEFENCE))
- object_check_for_ident(o_ptr);
+ object_check_for_ident(o_ptr);
if (o_ptr->ac || o_ptr->to_a)
{
@@ -598,11 +1221,9 @@ void object_notice_attack_plusses(object_type *o_ptr)
{
assert(o_ptr && o_ptr->kind);
- if (object_attack_plusses_are_visible(o_ptr))
- return;
+ if (!object_add_ident_flags(o_ptr, IDENT_ATTACK)) return;
- if (object_add_ident_flags(o_ptr, IDENT_ATTACK))
- object_check_for_ident(o_ptr);
+ object_check_for_ident(o_ptr);
if (wield_slot(o_ptr) == INVEN_WIELD)
@@ -629,17 +1250,25 @@ void object_notice_attack_plusses(object_type *o_ptr)
}
-/*
- * Notice a single flag - returns TRUE if anything new was learned
+/**
+ * Notice a single flag
+ *
+ * \returns whether anything new was learned
*/
-bool object_notice_flag(object_type *o_ptr, int flag)
+bool object_notice_flag(object_type *o_ptr, flag_type flag)
{
if (!of_has(o_ptr->known_flags, flag))
{
+ /* message for noticing presence of flag */
+ bitflag o_flags[OF_SIZE];
+ object_flags(o_ptr, o_flags);
+ if (of_has(o_flags, flag)) {
+ char o_name[80];
+ object_desc(o_name, sizeof(o_name), o_ptr, ODESC_BASE);
+ flag_message(flag, o_name);
+ }
+
of_on(o_ptr->known_flags, flag);
- /* XXX Eddie don't want infinite recursion if object_check_for_ident sets more flags,
- * but maybe this will interfere with savefile repair
- */
object_check_for_ident(o_ptr);
event_signal(EVENT_INVENTORY);
event_signal(EVENT_EQUIPMENT);
@@ -651,17 +1280,16 @@ bool object_notice_flag(object_type *o_ptr, int flag)
}
-/*
- * Notice a set of flags - returns TRUE if anything new was learned
+/**
+ * Notice a set of flags
+ *
+ * \returns whether anything new was learned
*/
bool object_notice_flags(object_type *o_ptr, bitflag flags[OF_SIZE])
{
if (!of_is_subset(o_ptr->known_flags, flags))
{
of_union(o_ptr->known_flags, flags);
- /* XXX Eddie don't want infinite recursion if object_check_for_ident sets more flags,
- * but maybe this will interfere with savefile repair
- */
object_check_for_ident(o_ptr);
event_signal(EVENT_INVENTORY);
event_signal(EVENT_EQUIPMENT);
@@ -677,27 +1305,24 @@ bool object_notice_flags(object_type *o_ptr, bitflag flags[OF_SIZE])
* Notice curses on an object.
*
* \param o_ptr is the object to notice curses on
+ *
+ * \returns whether the object is cursed
*/
bool object_notice_curses(object_type *o_ptr)
{
- bitflag f[OF_SIZE], f2[OF_SIZE];
-
- object_flags(o_ptr, f);
-
- /* Gather whatever curse flags there are to know */
- create_mask(f2, FALSE, OFT_CURSE, OFT_MAX);
+ bitflag o_flags[OF_SIZE], curse_mask[OF_SIZE];
- /* Remove everything except the curse flags */
- of_inter(f, f2);
+ object_flags(o_ptr, o_flags);
+ of_curse_mask(curse_mask);
/* give knowledge of which curses are present */
- object_notice_flags(o_ptr, f);
+ object_notice_flags(o_ptr, curse_mask);
object_check_for_ident(o_ptr);
p_ptr->notice |= PN_SQUELCH;
- return !of_is_empty(f);
+ return of_is_inter(o_flags, curse_mask);
}
@@ -717,11 +1342,10 @@ void object_notice_on_defend(void)
}
-/*
+/**
* Notice stuff when firing or throwing objects.
*
*/
-/* XXX Eddie perhaps some stuff from do_cmd_fire and do_cmd_throw should be moved here */
void object_notice_on_firing(object_type *o_ptr)
{
if (object_add_ident_flags(o_ptr, IDENT_FIRED))
@@ -730,36 +1354,31 @@ void object_notice_on_firing(object_type *o_ptr)
-/*
- * Determine whether a weapon or missile weapon is obviously {excellent} when
- * worn.
- *
- * 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
+/**
+ * Notice flags that are apparent when the object is wielded
*/
void object_notice_on_wield(object_type *o_ptr)
{
- bitflag f[OF_SIZE], f2[OF_SIZE], obvious_mask[OF_SIZE];
+ bitflag o_flags[OF_SIZE], obvious_mask[OF_SIZE];
bool obvious = FALSE;
- create_mask(obvious_mask, TRUE, OFID_WIELD, OFT_MAX);
-
/* Save time of wield for later */
object_last_wield = turn;
+ if (!object_add_ident_flags(o_ptr, IDENT_WORN)) {
+ /* In case of bugs, it is nice to run through the
+ * routine even with IDENT_WORN already set
+ return*/;
+ }
+
/* Only deal with un-ID'd items */
if (object_is_known(o_ptr)) return;
+ /* Automatically sense artifacts upon wield */
+ object_notice_artifact(o_ptr);
+
/* Wear it */
object_flavor_tried(o_ptr);
- if (object_add_ident_flags(o_ptr, IDENT_WORN))
- object_check_for_ident(o_ptr);
-
- /* CC: may wish to be more subtle about this once we have ego lights
- * with multiple pvals */
- if (obj_is_light(o_ptr) && o_ptr->ego)
- object_notice_ego(o_ptr);
if (object_flavor_is_aware(o_ptr) && easy_know(o_ptr))
{
@@ -767,25 +1386,16 @@ void object_notice_on_wield(object_type *o_ptr)
return;
}
- /* Automatically sense artifacts upon wield */
- object_sense_artifact(o_ptr);
-
- /* Note artifacts when found */
- if (o_ptr->artifact)
- history_add_artifact(o_ptr->artifact, 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);
+ object_check_for_ident(o_ptr);
/* Extract the flags */
- object_flags(o_ptr, f);
+ object_flags(o_ptr, o_flags);
+
+ kind_obvious_mask(o_ptr->kind, obvious_mask);
- /* Find obvious things (disregarding curses) - why do we remove the curses?? */
- create_mask(f2, FALSE, OFT_CURSE, OFT_MAX);
- of_diff(obvious_mask, f2);
- if (of_is_inter(f, obvious_mask)) obvious = TRUE;
- create_mask(obvious_mask, TRUE, OFID_WIELD, OFT_MAX);
+ /* ability to be activated is obvious, but there is no flag for it any more */
+ if (of_is_inter(o_flags, obvious_mask) || object_effect(o_ptr))
+ obvious = TRUE;
/* Notice any obvious brands or slays */
object_notice_slays(o_ptr, obvious_mask);
@@ -793,71 +1403,52 @@ void object_notice_on_wield(object_type *o_ptr)
/* Learn about obvious flags */
of_union(o_ptr->known_flags, obvious_mask);
- /* 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) && !o_ptr->artifact)
- object_know_all_flags(o_ptr);
- }
-
object_check_for_ident(o_ptr);
if (!obvious) return;
- /* XXX Eddie need to add stealth here, also need to assert/double-check everything is covered */
+ /* EFG need to add stealth here, also need to assert/double-check everything is covered */
/* CC: also need to add FA! */
- if (of_has(f, OF_STR))
+ if (of_has(o_flags, OF_STR))
msg("You feel %s!", o_ptr->pval[which_pval(o_ptr,
OF_STR)] > 0 ? "stronger" : "weaker");
- if (of_has(f, OF_INT))
+ if (of_has(o_flags, OF_INT))
msg("You feel %s!", o_ptr->pval[which_pval(o_ptr,
OF_INT)] > 0 ? "smarter" : "more stupid");
- if (of_has(f, OF_WIS))
+ if (of_has(o_flags, OF_WIS))
msg("You feel %s!", o_ptr->pval[which_pval(o_ptr,
OF_WIS)] > 0 ? "wiser" : "more naive");
- if (of_has(f, OF_DEX))
+ if (of_has(o_flags, OF_DEX))
msg("You feel %s!", o_ptr->pval[which_pval(o_ptr,
OF_DEX)] > 0 ? "more dextrous" : "clumsier");
- if (of_has(f, OF_CON))
+ if (of_has(o_flags, OF_CON))
msg("You feel %s!", o_ptr->pval[which_pval(o_ptr,
OF_CON)] > 0 ? "healthier" : "sicklier");
- if (of_has(f, OF_CHR))
+ if (of_has(o_flags, OF_CHR))
msg("You feel %s!", o_ptr->pval[which_pval(o_ptr,
OF_CHR)] > 0 ? "cuter" : "uglier");
- if (of_has(f, OF_SPEED))
+ if (of_has(o_flags, OF_SPEED))
msg("You feel strangely %s.", o_ptr->pval[which_pval(o_ptr,
OF_SPEED)] > 0 ? "quick" : "sluggish");
- if (of_has(f, OF_BLOWS))
+ if (of_has(o_flags, OF_BLOWS))
msg("Your weapon %s in your hands.",
o_ptr->pval[which_pval(o_ptr, OF_BLOWS)] > 0 ?
"tingles" : "aches");
- if (of_has(f, OF_SHOTS))
+ if (of_has(o_flags, OF_SHOTS))
msg("Your bow %s in your hands.",
o_ptr->pval[which_pval(o_ptr, OF_SHOTS)] > 0 ?
"tingles" : "aches");
- if (of_has(f, OF_INFRA))
+ if (of_has(o_flags, OF_INFRA))
msg("Your eyes tingle.");
- if (of_has(f, OF_LIGHT))
+ if (of_has(o_flags, OF_LIGHT))
msg("It glows!");
- if (of_has(f, OF_TELEPATHY))
+ if (of_has(o_flags, OF_TELEPATHY))
msg("Your mind feels strangely sharper!");
- /* WARNING -- masking f by obvious mask -- this should be at the end of this function */
- /* CC: I think this can safely go, but just in case ... */
-/* flags_mask(f, OF_SIZE, OF_OBVIOUS_MASK, FLAG_END); */
-
- /* Remember the flags */
- object_notice_sensing(o_ptr);
+ /* this used to be a flag, still counts as the same idea */
+ if (object_effect(o_ptr) && !object_effect_is_known(o_ptr))
+ msg("You have something to activate.");
- /* XXX Eddie should we check_for_ident here? */
}
@@ -867,54 +1458,27 @@ void object_notice_on_wield(object_type *o_ptr)
static void object_notice_after_time(void)
{
int i;
- int flag;
+ flag_type flag;
object_type *o_ptr;
- char o_name[80];
- bitflag f[OF_SIZE], timed_mask[OF_SIZE];
+ bitflag timed_mask[OF_SIZE];
create_mask(timed_mask, TRUE, OFID_TIMED, OFT_MAX);
/* Check every item the player is wearing */
- for (i = INVEN_WIELD; i < ALL_INVEN_TOTAL; i++)
+ for (i = INVEN_WIELD; i < INVEN_TOTAL; i++)
{
o_ptr = &p_ptr->inventory[i];
if (!o_ptr->kind || 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))
+ for (flag = of_next(timed_mask, FLAG_START); flag != FLAG_END; flag = of_next(timed_mask, flag + 1))
{
- if (!of_has(o_ptr->known_flags, flag))
- {
- /* Message */
- flag_message(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);
- }
+ /* Learn the flag */
+ object_notice_flag(o_ptr, flag);
}
- /* XXX Is this necessary? */
object_check_for_ident(o_ptr);
}
}
@@ -925,48 +1489,15 @@ static void object_notice_after_time(void)
*
* \param flag is the flag to notice
*/
-void wieldeds_notice_flag(int flag)
+void wieldeds_notice_flag(flag_type 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++)
+ for (i = INVEN_WIELD; i < INVEN_TOTAL; i++)
{
object_type *o_ptr = &p_ptr->inventory[i];
- bitflag f[OF_SIZE];
-
if (!o_ptr->kind) 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 */
- flag_message(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);
-
+ object_notice_flag(o_ptr, flag);
}
return;
@@ -974,10 +1505,10 @@ void wieldeds_notice_flag(int flag)
/**
- * Notice things which happen on attacking.
+ * Notice attack plusses from offweapon slots.
+ * Does not apply to melee weapon or bow.
*/
-void wieldeds_notice_on_attack(void)
-/* Does not apply to weapon or bow which should be done separately */
+void wieldeds_notice_offweapon_attack_plusses(void)
{
int i;
@@ -985,66 +1516,24 @@ void wieldeds_notice_on_attack(void)
if (p_ptr->inventory[i].kind)
object_notice_attack_plusses(&p_ptr->inventory[i]);
- /* XXX Eddie print message? */
- /* XXX Eddie do we need to do more about ammo? */
-
return;
}
-bool object_FA_would_be_obvious(const object_type *o_ptr)
-{
- if (player_has(PF_CUMBER_GLOVE) && wield_slot(o_ptr) == INVEN_HANDS) {
- bitflag flags[OF_SIZE];
- object_flags(o_ptr, flags);
-
- if (!of_has(flags, OF_DEX) && !of_has(flags, OF_SPELLS_OK))
- return TRUE;
- }
-
- return FALSE;
-}
-
/*
* 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)
{
- bitflag flags[OF_SIZE], f2[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);
- create_mask(f2, TRUE, OFID_WIELD, OFT_MAX);
-
- /* 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))
- of_on(f2, OF_FREE_ACT);
-
- /* Now we remove the non-obvious known flags */
- of_inter(flags, f2);
-
- /* Now we remove the cursed flags and the kind flags */
- create_mask(f2, FALSE, OFT_CURSE, OFT_MAX);
- of_diff(flags, f2);
- of_diff(flags, o_ptr->kind->flags);
-
- if (o_ptr->ident & IDENT_INDESTRUCT)
- return INSCRIP_SPECIAL;
- if ((object_was_sensed(o_ptr) || object_was_worn(o_ptr)) && o_ptr->artifact)
+ if (object_is_known_artifact(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))
+ if (object_is_known_splendid(o_ptr))
return INSCRIP_SPLENDID;
if (!object_is_known(o_ptr) && !object_was_sensed(o_ptr))
@@ -1052,9 +1541,12 @@ obj_pseudo_t object_pseudo(const object_type *o_ptr)
if (o_ptr->ego)
{
+ bitflag curse_mask[OF_SIZE];
+ of_curse_mask(curse_mask);
+
/* uncursed bad egos are not excellent */
- if (of_is_inter(o_ptr->ego->flags, f2))
- return INSCRIP_STRANGE; /* XXX Eddie need something worse */
+ if (of_is_inter(o_ptr->ego->flags, curse_mask))
+ return INSCRIP_STRANGE;
else
return INSCRIP_EXCELLENT;
}
View
9 src/object/obj-desc.c
@@ -627,22 +627,27 @@ static size_t obj_desc_inscrip(const object_type *o_ptr, char *buf, size_t max,
u[n++] = quark_str(o_ptr->note);
/* Use special inscription, if any */
- if (!object_is_known(o_ptr) && feel)
+ if (!object_is_known(o_ptr) && object_was_sensed(o_ptr))
{
/* cannot tell excellent vs strange vs splendid until wield */
- if (!object_was_worn(o_ptr) && o_ptr->ego)
+ if (o_ptr->ego &&
+ !(object_is_known_splendid(o_ptr) || object_is_known_unsplendid(o_ptr)))
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_is_jewelry(o_ptr) && object_is_not_excellent(o_ptr) && object_name_is_visible(o_ptr))
+ u[n++] = "not excellent";
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_name_is_visible(o_ptr))
+ u[n++] = "not 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))
View
40 src/object/obj-flag.c
@@ -49,12 +49,18 @@ static const char *flag_names[] =
*
* N.B. OFT_MAX must be the last item in the ... list
*/
-void create_mask(bitflag *f, bool id, ...)
+void create_mask(bitflag f[OF_SIZE], bool id, ...)
{
const struct object_flag *of_ptr;
int i;
va_list args;
+ /* a dummy first flag is assumed below, so make sure it is still there */
+ assert(OF_NONE == 0);
+
+ /* using OFT_MAX as end marker, but OFID are a separate enum */
+ assert (OFID_MAX <= OFT_MAX);
+
of_wipe(f);
va_start(args, id);
@@ -62,8 +68,11 @@ void create_mask(bitflag *f, bool id, ...)
/* Process each type in the va_args */
for (i = va_arg(args, int); i != OFT_MAX; i = va_arg(args, int)) {
for (of_ptr = object_flag_table; of_ptr->index < OF_MAX; of_ptr++)
- if ((id && of_ptr->id == i) || (!id && of_ptr->type == i))
- of_on(f, of_ptr->index);
+ if ((id && of_ptr->id == i) || (!id && of_ptr->type == i)) {
+ /* flag code crashes badly with too small flags */
+ if (of_ptr->index >= FLAG_START)
+ of_on(f, of_ptr->index);
+ }
}
va_end(args);
@@ -72,6 +81,31 @@ void create_mask(bitflag *f, bool id, ...)
}
/**
+ * Create the mask of unlearnable flags.
+ */
+void of_unlearnable_mask(bitflag unlearnable[OF_SIZE])
+{
+ create_mask(unlearnable, TRUE, OFID_NONE, OFT_MAX);
+}
+
+/**
+ * Create the mask of curse flags.
+ */
+void of_curse_mask(bitflag curse_mask[OF_SIZE])
+{
+ create_mask(curse_mask, FALSE, OFT_CURSE, OFT_MAX);
+}
+
+/**
+ * Create the mask of pval flags.
+ */
+void of_pval_mask(bitflag pval_mask[OF_SIZE])
+{
+ create_mask(pval_mask, FALSE, OFT_PVAL, OFT_STAT, OFT_MAX);
+}
+
+
+/**
* Print a message when an object flag is identified by use.
*
* \param flag is the flag being noticed
View
6 src/object/obj-flag.h
@@ -65,7 +65,9 @@ enum object_flag_id {
OFID_NONE = 0, /* never shown */
OFID_NORMAL, /* normal ID on use */
OFID_TIMED, /* obvious after time */
- OFID_WIELD /* obvious on wield */
+ OFID_WIELD, /* obvious on wield */
+
+ OFID_MAX
};
#define OF_SIZE FLAG_SIZE(OF_MAX)
@@ -89,6 +91,8 @@ enum object_flag_id {
#define of_inter(f1, f2) flag_inter(f1, f2, OF_SIZE)
#define of_diff(f1, f2) flag_diff(f1, f2, OF_SIZE)
+#define for_each_object_flag(f) for (f = FLAG_START; f < OF_MAX; f++)
+
/* Hack -- special "xtra" object flag info (type) */
/* Can get rid of these now we have OFT_ flags */
#define OBJECT_XTRA_TYPE_NONE 0
View
39 src/object/obj-info.c
@@ -32,7 +32,7 @@ typedef struct
{
int flag;
const char *name;
-} flag_type;
+} flag_w_name_type;
@@ -61,7 +61,7 @@ static void info_out_list(textblock *tb, const char *list[], size_t count)
/*
*
*/
-static size_t info_collect(textblock *tb, const flag_type list[], size_t max,
+static size_t info_collect(textblock *tb, const flag_w_name_type list[], size_t max,
const bitflag flags[OF_SIZE], const char *recepticle[])
{
size_t i, count = 0;
@@ -78,7 +78,7 @@ static size_t info_collect(textblock *tb, const flag_type list[], size_t max,
/*** Big fat data tables ***/
-static const flag_type pval_flags[] =
+static const flag_w_name_type pval_flags[] =
{
{ OF_STR, "strength" },
{ OF_INT, "intelligence" },
@@ -95,7 +95,7 @@ static const flag_type pval_flags[] =
{ OF_MIGHT, "shooting power" },
};
-static const flag_type immunity_flags[] =
+static const flag_w_name_type immunity_flags[] =
{
{ OF_IM_ACID, "acid" },
{ OF_IM_ELEC, "lightning" },
@@ -103,7 +103,7 @@ static const flag_type immunity_flags[] =
{ OF_IM_COLD, "cold" },
};
-static const flag_type vuln_flags[] =
+static const flag_w_name_type vuln_flags[] =
{
{ OF_VULN_ACID, "acid" },
{ OF_VULN_ELEC, "electricity" },
@@ -111,7 +111,7 @@ static const flag_type vuln_flags[] =
{ OF_VULN_COLD, "cold" },
};
-static const flag_type resist_flags[] =
+static const flag_w_name_type resist_flags[] =
{
{ OF_RES_ACID, "acid" },
{ OF_RES_ELEC, "lightning" },
@@ -128,7 +128,7 @@ static const flag_type resist_flags[] =
{ OF_RES_DISEN, "disenchantment" },
};
-static const flag_type protect_flags[] =
+static const flag_w_name_type protect_flags[] =
{
{ OF_RES_FEAR, "fear" },
{ OF_RES_BLIND, "blindness" },
@@ -136,7 +136,7 @@ static const flag_type protect_flags[] =
{ OF_RES_STUN, "stunning" },
};
-static const flag_type ignore_flags[] =
+static const flag_w_name_type ignore_flags[] =
{
{ OF_IGNORE_ACID, "acid" },
{ OF_IGNORE_ELEC, "electricity" },
@@ -144,7 +144,7 @@ static const flag_type ignore_flags[] =
{ OF_IGNORE_COLD, "cold" },
};
-static const flag_type sustain_flags[] =
+static const flag_w_name_type sustain_flags[] =
{
{ OF_SUST_STR, "strength" },
{ OF_SUST_INT, "intelligence" },
@@ -154,7 +154,7 @@ static const flag_type sustain_flags[] =
{ OF_SUST_CHR, "charisma" },
};
-static const flag_type misc_flags[] =
+static const flag_w_name_type misc_flags[] =
{
{ OF_BLESSED, "Blessed by the gods" },
{ OF_SLOW_DIGEST, "Slows your metabolism" },
@@ -1134,7 +1134,7 @@ static void describe_flavor_text(textblock *tb, const object_type *o_ptr)
{
/* Display the known artifact description */
if (!OPT(birth_randarts) && o_ptr->artifact &&
- object_is_known(o_ptr) && o_ptr->artifact->text)
+ object_name_is_visible(o_ptr) && o_ptr->artifact->text)
textblock_append(tb, "%s\n\n", o_ptr->artifact->text);
/* Display the known object description */
@@ -1209,6 +1209,23 @@ static textblock *object_info_out(const object_type *o_ptr, oinfo_detail_t mode)
if (!full && !known)
{
textblock_append(tb, "You do not know the full extent of this item's powers.\n");
+ if (SENSING_REVEALS_FLAG_COUNT) {
+ if (object_was_sensed(o_ptr)) {
+ int unlearned = object_num_unlearned_flags(o_ptr);
+ switch(unlearned) {
+ case 0:
+ textblock_append(tb, "It has no unknown flags.\n");
+ break;
+ case 1:
+ textblock_append(tb, "It has 1 unknown flag.\n", unlearned);
+ break;
+ default:
+ textblock_append(tb, "It has %d unknown flags.\n", unlearned);
+ break;
+ }
+ }
+ }
+
something = TRUE;
}
View
31 src/object/obj-make.c
@@ -129,11 +129,28 @@ static int get_new_attr(bitflag flags[OF_SIZE], const int attrs[], size_t size)
/**
+ * \returns whether an ego can be applied to an object with a particular tval and sval.
+ */
+bool ego_applies(const ego_item_type *e_ptr, byte tval, byte sval)
+{
+ int i;
+
+ if (!e_ptr->rarity) return FALSE;
+
+ for (i = 0; i < EGO_TVALS_MAX; i++)
+ if ((e_ptr->tval[i] == tval) && (e_ptr->min_sval[i] <= sval) && (e_ptr->max_sval[i] >= sval))
+ return TRUE;
+
+ return FALSE;
+}
+
+
+/**
* Select an ego-item that fits the object's tval and sval.
*/
static struct ego_item *ego_find_random(object_type *o_ptr, int level)
{
- int i, j;
+ int i;
long total = 0L;
/* XXX alloc_ego_table &c should be static to this file */
@@ -154,16 +171,8 @@ static struct ego_item *ego_find_random(object_type *o_ptr, int level)
/* XXX Ignore cursed items for now */
if (cursed_p(ego->flags)) continue;
- /* Test if this is a legal ego-item type for this object */
- for (j = 0; j < EGO_TVALS_MAX; j++) {
- /* Require identical base type */
- if (o_ptr->tval == ego->tval[j] &&
- o_ptr->sval >= ego->min_sval[j] &&
- o_ptr->sval <= ego->max_sval[j]) {
- table[i].prob3 = table[i].prob2;
- break;
- }
- }
+ if (ego_applies(ego, o_ptr->tval, o_ptr->sval))
+ table[i].prob3 = table[i].prob2;
/* Total */
total += table[i].prob3;
View
97 src/object/obj-util.c
@@ -299,7 +299,59 @@ void reset_visuals(bool load_prefs)
}
-/*
+/**
+ * \returns whether an object is of a type that can be pseudoed
+ */
+bool object_can_be_sensed(const object_type *o_ptr)
+{
+ if (!obj_can_wear(o_ptr)) return FALSE;
+
+ return !(object_is_jewelry(o_ptr) || obj_is_light(o_ptr)) ? TRUE : FALSE;
+}
+
+/**
+ * \returns whether wieldable object is only offensive without ego
+ */
+bool object_base_only_offensive(const object_type *o_ptr)
+{
+ if (obj_is_ammo(o_ptr)) return TRUE;
+ switch(wield_slot(o_ptr)) {
+ case INVEN_WIELD:
+ case INVEN_BOW:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+
+/**
+ * \returns whether wieldable object is only defensive without ego
+ */
+bool object_base_only_defensive(const object_type *o_ptr)
+{
+ if (obj_is_ammo(o_ptr)) return FALSE;
+ if (wield_slot(o_ptr) > INVEN_LIGHT)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+
+/**
+ * Obtain the "flags" for an item
+ */
+void object_kind_flags(const object_kind *kind, bitflag flags[OF_SIZE])
+{
+ of_wipe(flags);
+ if (kind) {
+ of_union(flags, kind->base->flags);
+ of_union(flags, kind->flags);
+ }
+}
+
+
+/**
* Obtain the "flags" for an item
*/
void object_flags(const object_type *o_ptr, bitflag flags[OF_SIZE])
@@ -312,8 +364,7 @@ void object_flags(const object_type *o_ptr, bitflag flags[OF_SIZE])
return;
/* Obtain kind flags */
- of_union(flags, o_ptr->kind->base->flags);
- of_union(flags, o_ptr->kind->flags);
+ object_kind_flags(o_ptr->kind, flags);
/* Obtain artifact flags */
if (o_ptr->artifact)
@@ -337,10 +388,23 @@ void object_flags(const object_type *o_ptr, bitflag flags[OF_SIZE])
*/
void object_flags_known(const object_type *o_ptr, bitflag flags[OF_SIZE])
{
+
object_flags(o_ptr, flags);
of_inter(flags, o_ptr->known_flags);
+ if (object_is_known_artifact(o_ptr)) {
+ /* all artifacts have all ignores */
+ bitflag f2[OF_SIZE];
+ create_mask(f2, FALSE, OFT_IGNORE, OFT_MAX);
+
+ /* sanity check */
+ of_inter(f2, o_ptr->artifact->flags);
+
+ of_union(flags, f2);
+ }
+
+ of_union(flags, o_ptr->kind->base->flags);
if (object_flavor_is_aware(o_ptr))
of_union(flags, o_ptr->kind->flags);
@@ -539,6 +603,12 @@ s16b wield_slot_ammo(const object_type *o_ptr)
return open ? open : QUIVER_START;
}
+s16b wield_slot(const object_type *o_ptr)
+{
+ /* ammo requires special casing due to current quiver implementation */
+ if (obj_is_ammo(o_ptr)) return wield_slot_ammo(o_ptr);
+ else return base_wield_slot(o_ptr->kind->base);
+}
/**
* Determine which equipment slot (if any) an item likes. The slot might (or
* might not) be open, but it is a slot which the object could be equipped in.
@@ -547,10 +617,10 @@ s16b wield_slot_ammo(const object_type *o_ptr)
* will try to a return a stackable slot first (only for ammo), then an open
* slot if possible, and finally a used (but valid) slot if necessary.
*/
-s16b wield_slot(const object_type *o_ptr)
+s16b base_wield_slot(const object_base *base)
{
/* Slot for equipment */
- switch (o_ptr->tval)
+ switch (base->tval)
{
case TV_DIGGING:
case TV_HAFTED:
@@ -581,9 +651,10 @@ s16b wield_slot(const object_type *o_ptr)
case TV_BOOTS: return (INVEN_FEET);
+ /* ammo requires an object, not just a base */
case TV_BOLT:
case TV_ARROW:
- case TV_SHOT: return wield_slot_ammo(o_ptr);
+ case TV_SHOT: assert(0);
}
/* No slot available */
@@ -985,7 +1056,7 @@ void delete_object(int y, int x)
next_o_idx = o_ptr->next_o_idx;
/* Preserve unseen artifacts */
- if (o_ptr->artifact && !object_was_sensed(o_ptr))
+ if (o_ptr->artifact && !object_name_is_visible(o_ptr))
o_ptr->artifact->created = FALSE;
/* Wipe the object */
@@ -1240,7 +1311,7 @@ void wipe_o_list(struct cave *c)
/* Preserve artifacts or mark them as lost in the history */
if (o_ptr->artifact) {
/* Preserve if dungeon creation failed, or preserve mode, and only artifacts not seen */
- if ((!character_dungeon || !OPT(birth_no_preserve)) && !object_was_sensed(o_ptr))
+ if ((!character_dungeon || !OPT(birth_no_preserve)) && !object_name_is_visible(o_ptr))
o_ptr->artifact->created = FALSE;
else
history_lose_artifact(o_ptr->artifact);
@@ -4017,14 +4088,20 @@ bool obj_is_light(const object_type *o_ptr) { return o_ptr->tval == TV_LIGHT;
bool obj_is_ring(const object_type *o_ptr) { return o_ptr->tval == TV_RING; }
+bool obj_is_ammo(const object_type *o_ptr)
+{
+ if (!o_ptr->kind) return FALSE;
+
+ return base_is_ammo(o_ptr->kind->base);
+}
/**
* Determine whether an object is ammo
*
* \param o_ptr is the object to check
*/
-bool obj_is_ammo(const object_type *o_ptr)
+bool base_is_ammo(const object_base *base)
{
- switch (o_ptr->tval)
+ switch (base->tval)
{
case TV_SHOT:
case TV_ARROW:
View
38 src/object/object.h
@@ -24,14 +24,11 @@ struct player;
#define IDENT_EFFECT 0x0080 /* Know item activation/effect */
/* xxx */
#define IDENT_INDESTRUCT 0x0200 /* Tried to destroy it and failed */
-#define IDENT_NAME 0x0400 /* Know the name of ego or artifact if there is one */
+#define IDENT_NAME 0x0400 /* Know whether the object has a name [no name means avg or magical] and, if so, what it is */
#define IDENT_FIRED 0x0800 /* Has been used as a missile */
-#define IDENT_NOTART 0x1000 /* Item is known not to be an artifact */
+#define IDENT_NOTICE_ART 0x1000 /* Item is known whether an artifact */
#define IDENT_FAKE 0x2000 /* Item is a fake, for displaying knowledge */
-/* Whether to learn egos and flavors with less than complete information */
-#define EASY_LEARN 1
-
/* Maximum number of scroll titles generated */
#define MAX_TITLES 50
@@ -471,14 +468,21 @@ typedef struct flavor {
/*** Functions ***/
/* identify.c */
+/*
extern s32b object_last_wield;
+*/
bool object_is_known(const object_type *o_ptr);
bool object_is_known_artifact(const object_type *o_ptr);
bool object_is_known_cursed(const object_type *o_ptr);
bool object_is_known_blessed(const object_type *o_ptr);
bool object_is_known_not_artifact(const object_type *o_ptr);
+bool object_is_known_splendid(const object_type *o_ptr);
+bool object_is_known_unsplendid(const object_type *o_ptr);
+bool object_is_known_bad(const object_type *o_ptr);
bool object_is_not_known_consistently(const object_type *o_ptr);
+bool object_is_not_excellent(const object_type *o_ptr);
+bool object_is_known_not_excellent(const object_type *o_ptr);
bool object_was_worn(const object_type *o_ptr);
bool object_was_fired(const object_type *o_ptr);
bool object_was_sensed(const object_type *o_ptr);
@@ -489,7 +493,9 @@ bool object_this_pval_is_visible(const object_type *o_ptr, int pval);
bool object_ego_is_visible(const object_type *o_ptr);
bool object_attack_plusses_are_visible(const object_type *o_ptr);
bool object_defence_plusses_are_visible(const object_type *o_ptr);
-bool object_flag_is_known(const object_type *o_ptr, int flag);
+bool object_flag_is_known(const object_type *o_ptr, flag_type flag);
+int object_number_of_learnable_flags(const object_type *o_ptr);
+int object_num_unlearned_flags(const object_type *o_ptr);
bool object_high_resist_is_possible(const object_type *o_ptr);
void object_flavor_aware(object_type *o_ptr);
void object_flavor_tried(object_type *o_ptr);
@@ -497,17 +503,17 @@ void object_notice_everything(object_type *o_ptr);
void object_notice_indestructible(object_type *o_ptr);
void object_notice_ego(object_type *o_ptr);
void object_notice_sensing(object_type *o_ptr);
-void object_sense_artifact(object_type *o_ptr);
+void object_notice_artifact(object_type *o_ptr);
void object_notice_effect(object_type *o_ptr);
void object_notice_attack_plusses(object_type *o_ptr);
-bool object_notice_flag(object_type *o_ptr, int flag);
+bool object_notice_flag(object_type *o_ptr, flag_type flag);
bool object_notice_flags(object_type *o_ptr, bitflag flags[OF_SIZE]);
bool object_notice_curses(object_type *o_ptr);
void object_notice_on_defend(void);
void object_notice_on_wield(object_type *o_ptr);
void object_notice_on_firing(object_type *o_ptr);
-void wieldeds_notice_flag(int flag);
-void wieldeds_notice_on_attack(void);
+void wieldeds_notice_flag(flag_type flag);
+void wieldeds_notice_offweapon_attack_plusses(void);
void object_repair_knowledge(object_type *o_ptr);
bool object_FA_would_be_obvious(const object_type *o_ptr);
obj_pseudo_t object_pseudo(const object_type *o_ptr);
@@ -523,6 +529,11 @@ void object_kind_name(char *buf, size_t max, const object_kind *kind, bool easy_
size_t object_desc(char *buf, size_t max, const object_type *o_ptr, odesc_detail_t mode);
int which_pval(const object_type *o_ptr, const int flag);
+/* obj-flags.c */
+void of_unlearnable_mask(bitflag unlearnable[OF_SIZE]);
+void of_curse_mask(bitflag unlearnable[OF_SIZE]);
+void of_pval_mask(bitflag unlearnable[OF_SIZE]);
+
/* obj-info.c */
textblock *object_info(const object_type *o_ptr, oinfo_detail_t mode);
textblock *object_info_ego(struct ego_item *ego);
@@ -530,6 +541,7 @@ void object_info_spoil(ang_file *f, const object_type *o_ptr, int wrap);
void object_info_chardump(ang_file *f, const object_type *o_ptr, int indent, int wrap);
/* obj-make.c */
+bool ego_applies(const ego_item_type *e_ptr, byte tval, byte sval);
void free_obj_alloc(void);
bool init_obj_alloc(void);
object_kind *get_obj_num(int level, bool good);
@@ -551,10 +563,14 @@ bool verify_item(const char *prompt, int item);
bool get_item(int *cp, const char *pmt, const char *str, cmd_code cmd, int mode);
/* obj-util.c */
+bool object_can_be_sensed(const object_type *o_ptr);
+bool object_base_only_defensive(const object_type *o_ptr);
+bool object_base_only_offensive(const object_type *o_ptr);
struct object_kind *objkind_get(int tval, int sval);
struct object_kind *objkind_byid(int kidx);
void flavor_init(void);
void reset_visuals(bool load_prefs);
+void object_kind_flags(const object_kind *kind, bitflag flags[OF_SIZE]);
void object_flags(const object_type *o_ptr, bitflag flags[OF_SIZE]);
void object_flags_known(const object_type *o_ptr, bitflag flags[OF_SIZE]);
void object_pval_flags(const object_type *o_ptr, bitflag flags[MAX_PVALS][OF_SIZE]);