/** * 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; int i; if (!obj->known) return IGNORE_MAX; /* Deal with jewelry specially - only bad or average */ if (tval_is_jewelry(obj)) { /* One positive modifier means not bad*/ for (i = 0; i < OBJ_MOD_MAX; i++) if (obj->known->modifiers[i] > 0) return IGNORE_AVERAGE; /* One positive combat value means not bad, one negative means bad */ if ((obj->known->to_h > 0) || (obj->known->to_d > 0) || (obj->known->to_a > 0)) return IGNORE_AVERAGE; if ((obj->known->to_h < 0) || (obj->known->to_d < 0) || (obj->known->to_a < 0)) return IGNORE_BAD; return IGNORE_AVERAGE; } /* Now just do bad, average, good, ego */ if (object_fully_known(obj)) { int isgood = is_object_good(obj); /* Values for items not egos or artifacts, may be updated */ if (isgood > 0) { value = IGNORE_GOOD; } else if (isgood < 0) { value = IGNORE_BAD; } else { value = IGNORE_AVERAGE; } if (obj->ego) value = IGNORE_ALL; else if (obj->artifact) value = IGNORE_MAX; } else { if ((obj->known->notice & OBJ_NOTICE_ASSESSED) && !obj->artifact) value = IGNORE_ALL; else value = IGNORE_MAX; } return value; }
/** * Determine if an item can "absorb" a second item * * See "object_absorb()" for the actual "absorption" code. * * If permitted, we allow weapons/armor to stack, if "known". * * Missiles will combine if both stacks have the same "known" status. * This is done to make unidentified stacks of missiles useful. * * Food, potions, scrolls, and "easy know" items always stack. * * Chests, and activatable items, except rods, never stack (for various * reasons). */ bool object_stackable(const struct object *obj1, const struct object *obj2, object_stack_t mode) { int i; /* Equipment items don't stack */ if (object_is_equipped(player->body, obj1)) return false; if (object_is_equipped(player->body, obj2)) return false; /* If either item is unknown, do not stack */ if (mode & OSTACK_LIST && obj1->kind != obj1->known->kind) return false; if (mode & OSTACK_LIST && obj2->kind != obj2->known->kind) return false; /* Hack -- identical items cannot be stacked */ if (obj1 == obj2) return false; /* Require identical object kinds */ if (obj1->kind != obj2->kind) return false; /* Different flags don't stack */ if (!of_is_equal(obj1->flags, obj2->flags)) return false; /* Different elements don't stack */ for (i = 0; i < ELEM_MAX; i++) { if (obj1->el_info[i].res_level != obj2->el_info[i].res_level) return false; if ((obj1->el_info[i].flags & (EL_INFO_HATES | EL_INFO_IGNORE)) != (obj2->el_info[i].flags & (EL_INFO_HATES | EL_INFO_IGNORE))) return false; } /* Artifacts never stack */ if (obj1->artifact || obj2->artifact) return false; /* Analyze the items */ if (tval_is_chest(obj1)) { /* Chests never stack */ return false; } else if (tval_is_edible(obj1) || tval_is_potion(obj1) || tval_is_scroll(obj1) || tval_is_rod(obj1)) { /* Food, potions, scrolls and rods all stack nicely, since the kinds are identical, either both will be aware or both will be unaware */ } else if (tval_can_have_charges(obj1) || tval_is_money(obj1)) { /* Gold, staves and wands stack most of the time */ /* Too much gold or too many charges */ if (obj1->pval + obj2->pval > MAX_PVAL) return false; /* ... otherwise ok */ } else if (tval_is_weapon(obj1) || tval_is_armor(obj1) || tval_is_jewelry(obj1) || tval_is_light(obj1)) { bool obj1_is_known = object_fully_known((struct object *)obj1); bool obj2_is_known = object_fully_known((struct object *)obj2); /* Require identical values */ if (obj1->ac != obj2->ac) return false; if (obj1->dd != obj2->dd) return false; if (obj1->ds != obj2->ds) return false; /* Require identical bonuses */ if (obj1->to_h != obj2->to_h) return false; if (obj1->to_d != obj2->to_d) return false; if (obj1->to_a != obj2->to_a) return false; /* Require all identical modifiers */ for (i = 0; i < OBJ_MOD_MAX; i++) if (obj1->modifiers[i] != obj2->modifiers[i]) return (false); /* Require identical ego-item types */ if (obj1->ego != obj2->ego) return false; /* Require identical curses */ if (!curses_are_equal(obj1->curses, obj2->curses)) return false; /* Hack - Never stack recharging wearables ... */ if ((obj1->timeout || obj2->timeout) && !tval_is_light(obj1)) return false; /* ... and lights must have same amount of fuel */ else if ((obj1->timeout != obj2->timeout) && tval_is_light(obj1)) return false; /* Prevent unIDd items stacking with IDd items in the object list */ if (mode & OSTACK_LIST && (obj1_is_known != obj2_is_known)) return false; } else { /* Anything else probably okay */ } /* Require compatible inscriptions */ if (obj1->note && obj2->note && (obj1->note != obj2->note)) return false; /* They must be similar enough */ return true; }
/** * Output object information */ static textblock *object_info_out(const struct object *obj, int mode) { bitflag flags[OF_SIZE]; struct element_info el_info[ELEM_MAX]; bool something = false; bool terse = mode & OINFO_TERSE ? true : false; bool subjective = mode & OINFO_SUBJ ? true : false; bool ego = mode & OINFO_EGO ? true : false; textblock *tb = textblock_new(); assert(obj->known); /* Unaware objects get simple descriptions */ if (obj->kind != obj->known->kind) { textblock_append(tb, "\n\nYou do not know what this is.\n"); return tb; } /* Grab the object flags */ get_known_flags(obj, mode, flags); /* Grab the element info */ get_known_elements(obj, mode, el_info); if (subjective) describe_origin(tb, obj, terse); if (!terse) describe_flavor_text(tb, obj, ego); if (!object_fully_known(obj) && (obj->known->notice & OBJ_NOTICE_ASSESSED) && !tval_is_useable(obj)) { textblock_append(tb, "You do not know the full extent of this item's powers.\n"); something = true; } if (describe_curses(tb, obj, flags)) something = true; if (describe_stats(tb, obj, mode)) something = true; if (describe_slays(tb, obj)) something = true; if (describe_brands(tb, obj)) something = true; if (describe_elements(tb, el_info)) something = true; if (describe_protects(tb, flags)) something = true; if (describe_ignores(tb, el_info)) something = true; if (describe_hates(tb, el_info)) something = true; if (describe_sustains(tb, flags)) something = true; if (describe_misc_magic(tb, flags)) something = true; if (describe_light(tb, obj, mode)) something = true; if (ego && describe_ego(tb, obj->ego)) something = true; if (something) textblock_append(tb, "\n"); /* Skip all the very specific information where we are giving general ego knowledge rather than for a single item - abilities can vary */ if (!ego) { if (describe_effect(tb, obj, terse, subjective)) { something = true; textblock_append(tb, "\n"); } if (subjective && describe_combat(tb, obj)) { something = true; textblock_append(tb, "\n"); } if (!terse && subjective && describe_digger(tb, obj)) something = true; } /* Don't append anything in terse (for chararacter dump) */ if (!something && !terse) textblock_append(tb, "\n\nThis item does not seem to possess any special abilities."); return tb; }