/* * Return the price of an item including plusses (and charges) * * This function returns the "value" of the given item (qty one) * * Never notice "unknown" bonuses or properties, including "curses", * since that would give the player information he did not have. * * Note that discounted items stay discounted forever, even if * the discount is "forgotten" by the player via memory loss. */ s32b object_value(object_type *o_ptr) { s32b value; /* Known items -- acquire the actual value */ if (object_known_p(o_ptr)) { /* Cursed items -- worthless */ if (cursed_p(o_ptr)) return (0L); /* Real value (see above) */ value = object_value_real(o_ptr); } /* Unknown items -- acquire a base value */ else { /* Hack -- Felt cursed items */ if ((o_ptr->ident & (IDENT_SENSE)) && cursed_p(o_ptr)) return (0L); /* Base value (see above) */ // DGDGDGDG fix me, make a nice way to get base values value = 1; } /* Apply discount (if any) */ if (o_ptr->discount) value -= (value * o_ptr->discount / 100L); /* Return the final value */ return (value); }
/* Destroy an item */ void do_cmd_destroy(cmd_code code, cmd_arg args[]) { object_type *o_ptr; int item = args[0].item; if (!item_is_available(item, NULL, USE_INVEN | USE_EQUIP | USE_FLOOR)) { msg("You do not have that item to ignore it."); return; } o_ptr = object_from_item_idx(item); if ((item >= INVEN_WIELD) && cursed_p(o_ptr->flags)) { msg("You cannot ignore cursed items."); } else { char o_name[80]; object_desc(o_name, sizeof o_name, o_ptr, ODESC_PREFIX | ODESC_FULL); msgt(MSG_DESTROY, "Ignoring %s.", o_name); o_ptr->ignore = TRUE; p_ptr->notice |= PN_SQUELCH; } }
/* * Create the artifact with the specified number */ static void wiz_create_artifact(int a_idx) { object_type *i_ptr; object_type object_type_body; int k_idx; artifact_type *a_ptr = &a_info[a_idx]; /* Ignore "empty" artifacts */ if (!a_ptr->name) return; /* Get local object */ i_ptr = &object_type_body; /* Wipe the object */ object_wipe(i_ptr); /* Acquire the "kind" index */ k_idx = lookup_kind(a_ptr->tval, a_ptr->sval); /* Oops */ if (!k_idx) return; /* Create the artifact */ object_prep(i_ptr, &k_info[k_idx], a_ptr->alloc_min, RANDOMISE); /* Save the name */ i_ptr->name1 = a_idx; /* Extract the fields */ i_ptr->pval = a_ptr->pval; i_ptr->ac = a_ptr->ac; i_ptr->dd = a_ptr->dd; i_ptr->ds = a_ptr->ds; i_ptr->to_a = a_ptr->to_a; i_ptr->to_h = a_ptr->to_h; i_ptr->to_d = a_ptr->to_d; i_ptr->weight = a_ptr->weight; /* Hack -- extract the "cursed" flags */ if (cursed_p(a_ptr)) { bitflag curse_flags[OF_SIZE]; of_copy(curse_flags, a_ptr->flags); flags_mask(curse_flags, OF_SIZE, OF_CURSE_MASK, FLAG_END); of_union(i_ptr->flags, curse_flags); } /* Mark that the artifact has been created. */ a_ptr->created = TRUE; /* Mark as cheat */ i_ptr->origin = ORIGIN_CHEAT; /* Drop the artifact from heaven */ drop_near(i_ptr, 0, p_ptr->py, p_ptr->px, TRUE); /* All done */ msg_print("Allocated."); }
/** * Copy artifact data to a normal object, and set various slightly hacky * globals. */ static void copy_artifact_data(object_type *o_ptr, const artifact_type *a_ptr) { /* Extract the other fields */ o_ptr->pval = a_ptr->pval; o_ptr->ac = a_ptr->ac; o_ptr->dd = a_ptr->dd; o_ptr->ds = a_ptr->ds; o_ptr->to_a = a_ptr->to_a; o_ptr->to_h = a_ptr->to_h; o_ptr->to_d = a_ptr->to_d; o_ptr->weight = a_ptr->weight; /* Hack -- extract the "cursed" flags */ if (cursed_p(a_ptr)) { bitflag curse_flags[OF_SIZE]; of_copy(curse_flags, a_ptr->flags); flags_mask(curse_flags, OF_SIZE, OF_CURSE_MASK, FLAG_END); of_union(o_ptr->flags, curse_flags); } /* Mega-Hack -- increase the rating */ rating += 10; /* Mega-Hack -- increase the rating again */ if (a_ptr->cost > 50000L) rating += 10; /* Set the good item flag */ good_item_flag = TRUE; /* Cheat -- peek at the item */ if (OPT(cheat_peek)) object_mention(o_ptr); }
/* Holy Orb -- destroys cursed non-artifacts */ static void project_object_handler_HOLY_ORB(project_object_handler_context_t *context) { if (cursed_p(context->obj->flags)) { context->do_kill = true; context->note_kill = VERB_AGREEMENT(context->obj->number, "is destroyed", "are destroyed"); } }
/** * Copy artifact data to a normal object, and set various slightly hacky * globals. */ static void copy_artifact_data(object_type *o_ptr, const artifact_type *a_ptr) { /* Extract the other fields */ o_ptr->pval = a_ptr->pval; o_ptr->ac = a_ptr->ac; o_ptr->dd = a_ptr->dd; o_ptr->ds = a_ptr->ds; o_ptr->to_a = a_ptr->to_a; o_ptr->to_h = a_ptr->to_h; o_ptr->to_d = a_ptr->to_d; o_ptr->weight = a_ptr->weight; /* Hack -- extract the "cursed" flags */ if (cursed_p(a_ptr)) { bitflag curse_flags[OF_SIZE]; of_copy(curse_flags, a_ptr->flags); flags_mask(curse_flags, OF_SIZE, OF_CURSE_MASK, FLAG_END); of_union(o_ptr->flags, curse_flags); } /* Mega-Hack -- increase the level rating * - a sizeable increase for any artifact (c.f. up to 30 for ego items) * - a bigger increase for more powerful artifacts */ rating += 30; rating += object_power(o_ptr, FALSE, NULL, TRUE) / 25; /* Set the good item flag */ good_item_flag = TRUE; /* Cheat -- peek at the item */ if (OPT(cheat_peek)) object_mention(o_ptr); }
/* * Take off an item */ void do_cmd_takeoff(void) { int item; object_type *o_ptr; cptr q, s; /* Get an item */ #ifdef JP q = "どれを装備からはずしますか? "; s = "はずせる装備がない。"; #else q = "Take off which item? "; s = "You are not wearing anything to take off."; #endif if (!get_item(&item, q, s, (USE_EQUIP))) return; /* Get the item (in the pack) */ if (item >= 0) { o_ptr = &inventory[item]; } /* Get the item (on the floor) */ else { o_ptr = &o_list[0 - item]; } /* Item is cursed */ if (cursed_p(o_ptr)) { /* Oops */ #ifdef JP msg_print("ふーむ、どうやら呪われているようだ。"); #else msg_print("Hmmm, it seems to be cursed."); #endif /* Nope */ return; } /* Take a partial turn */ energy_use = 50; /* Take off the item */ (void)inven_takeoff(item, 255); /* Swap hands wielding sub weapon */ if (item == INVEN_WIELD) swap_wielding_hands(); p_ptr->redraw |= (PR_EQUIPPY); }
/** * Select an ego-item that fits the object's tval and sval. */ static struct ego_item *ego_find_random(struct object *obj, int level) { int i, ood_chance; long total = 0L; alloc_entry *table = alloc_ego_table; struct ego_item *ego; struct ego_poss_item *poss; /* Go through all possible ego items and find ones which fit this item */ for (i = 0; i < alloc_ego_size; i++) { /* Reset any previous probability of this type being picked */ table[i].prob3 = 0; if (level < table[i].level) continue; /* Access the ego item */ ego = &e_info[table[i].index]; /* enforce maximum */ if (level > ego->alloc_max) continue; /* roll for Out of Depth (ood) */ if (level < ego->alloc_min){ ood_chance = MAX(2, (ego->alloc_min - level) / 3); if (!one_in_(ood_chance)) continue; } /* XXX Ignore cursed items for now */ if (cursed_p(ego->flags)) continue; for (poss = ego->poss_items; poss; poss = poss->next) if (poss->kidx == obj->kind->kidx) { table[i].prob3 = table[i].prob2; break; } /* Total */ total += table[i].prob3; } if (total) { long value = randint0(total); for (i = 0; i < alloc_ego_size; i++) { /* Found the entry */ if (value < table[i].prob3) break; /* Decrement */ value = value - table[i].prob3; } return &e_info[table[i].index]; } return NULL; }
/** * Attempt to make an object * * \param c is the current dungeon level. * \param j_ptr is the object struct to be populated. * \param lev is the creation level of the object (not necessarily == depth). * \param good is whether the object is to be good * \param great is whether the object is to be great * \param value is the value to be returned to the calling function * * Returns the whether or not creation worked. */ bool make_object(struct cave *c, object_type *j_ptr, int lev, bool good, bool great, s32b *value) { int base, art, div; object_kind *kind; /* Base level and artifact chance for the object */ if (great) { art = ART_GREAT; base = lev + 10 + m_bonus(5, lev); } else if (good) { art = ART_GOOD; base = lev + 5 + m_bonus(5, lev); } else { art = ART_NORMAL; base = lev; } /* Small hack to bring artifact frequencies at low depths in line with V */ div = 9 - p_ptr->depth; if (div < 1) div = 1; /* Try to make an artifact */ if (one_in_(art * div)) { if (make_artifact(j_ptr, lev)) { if (value) *value = object_value_real(j_ptr, 1, FALSE, TRUE); return TRUE; } } /* Get the object, prep it and apply magic */ kind = get_obj_num(base, good || great); if (!kind) return FALSE; object_prep(j_ptr, kind, base, RANDOMISE); apply_magic(j_ptr, base, FALSE, good, great); /* Generate multiple items */ if (kind->gen_mult_prob >= randint1(100)) j_ptr->number = randcalc(kind->stack_size, lev, RANDOMISE); if (j_ptr->number >= MAX_STACK_SIZE) j_ptr->number = MAX_STACK_SIZE - 1; /* Return value, increased for uncursed out-of-depth objects */ if (value) *value = object_value_real(j_ptr, j_ptr->number, FALSE, TRUE); if (!cursed_p(j_ptr->flags) && (kind->alloc_min > c->depth)) { if (value) *value = (kind->alloc_min - c->depth) * (*value / 5); } return TRUE; }
/** * 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; long total = 0L; /* XXX alloc_ego_table &c should be static to this file */ alloc_entry *table = alloc_ego_table; ego_item_type *ego; /* Go through all possible ego items and find oens which fit this item */ for (i = 0; i < alloc_ego_size; i++) { /* Reset any previous probability of this type being picked */ table[i].prob3 = 0; if (level < table[i].level) continue; /* Access the ego item */ ego = &e_info[table[i].index]; /* 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; } } /* Total */ total += table[i].prob3; } if (total) { long value = randint0(total); for (i = 0; i < alloc_ego_size; i++) { /* Found the entry */ if (value < table[i].prob3) break; /* Decrement */ value = value - table[i].prob3; } return &e_info[table[i].index]; } return NULL; }
/** * Attempt to make an object * * \param c is the current dungeon level. * \param lev is the creation level of the object (not necessarily == depth). * \param good is whether the object is to be good * \param great is whether the object is to be great * \param extra_roll is whether we get an extra roll in apply_magic() * \param value is the value to be returned to the calling function * \param tval is the desired tval, or 0 if we allow any tval * * \return a pointer to the newly allocated object, or NULL on failure. */ struct object *make_object(struct chunk *c, int lev, bool good, bool great, bool extra_roll, s32b *value, int tval) { int base; object_kind *kind; struct object *new_obj; /* Try to make a special artifact */ if (one_in_(good ? 10 : 1000)) { new_obj = make_artifact_special(lev); if (new_obj) { if (value) *value = object_value_real(new_obj, 1, FALSE, TRUE); return new_obj; } /* If we failed to make an artifact, the player gets a good item */ good = TRUE; } /* Base level for the object */ base = (good ? (lev + 10) : lev); /* Try to choose an object kind */ kind = get_obj_num(base, good || great, tval); if (!kind) return NULL; /* Make the object, prep it and apply magic */ new_obj = object_new(); object_prep(new_obj, kind, lev, RANDOMISE); apply_magic(new_obj, lev, TRUE, good, great, extra_roll); /* Generate multiple items */ if (kind->gen_mult_prob >= randint1(100)) new_obj->number = randcalc(kind->stack_size, lev, RANDOMISE); if (new_obj->number > z_info->stack_size) new_obj->number = z_info->stack_size; /* Return value, increased for uncursed out-of-depth objects */ if (value) *value = object_value_real(new_obj, new_obj->number, FALSE, TRUE); /* This seems to imply objects get less value from being > 1 but < 5 * levels out of depth - should it be *value +=... - NRM */ if (!cursed_p(new_obj->flags) && (kind->alloc_min > c->depth)) { if (value) *value = (kind->alloc_min - c->depth) * (*value / 5); } return new_obj; }
/** * Attempt to make an object * * \param c is the current dungeon level. * \param lev is the creation level of the object (not necessarily == depth). * \param good is whether the object is to be good * \param great is whether the object is to be great * \param extra_roll is whether we get an extra roll in apply_magic() * \param value is the value to be returned to the calling function * \param tval is the desired tval, or 0 if we allow any tval * * \return a pointer to the newly allocated object, or NULL on failure. */ struct object *make_object(struct chunk *c, int lev, bool good, bool great, bool extra_roll, s32b *value, int tval) { int base; struct object_kind *kind; struct object *new_obj; /* Try to make a special artifact */ if (one_in_(good ? 10 : 1000)) { new_obj = make_artifact_special(lev); if (new_obj) { if (value) *value = object_value_real(new_obj, 1, false); return new_obj; } /* If we failed to make an artifact, the player gets a good item */ good = true; } /* Base level for the object */ base = (good ? (lev + 10) : lev); /* Try to choose an object kind */ kind = get_obj_num(base, good || great, tval); if (!kind) return NULL; /* Make the object, prep it and apply magic */ new_obj = object_new(); object_prep(new_obj, kind, lev, RANDOMISE); apply_magic(new_obj, lev, true, good, great, extra_roll); /* Generate multiple items */ if (kind->gen_mult_prob >= randint1(100)) new_obj->number = randcalc(kind->stack_size, lev, RANDOMISE); if (new_obj->number > z_info->stack_size) new_obj->number = z_info->stack_size; /* Get the value */ if (value) *value = object_value_real(new_obj, new_obj->number, false); /* Boost of 20% per level OOD for uncursed objects */ if (!cursed_p(new_obj->flags) && (kind->alloc_min > c->depth)) { if (value) *value += (kind->alloc_min - c->depth) * (*value / 5); } return new_obj; }
/** * Return the price of an item including plusses (and charges). * * This function returns the "value" of the given item (qty one). * * Never notice unknown bonuses or properties, including curses, * since that would give the player information they did not have. */ s32b object_value(const object_type *obj, int qty, int verbose) { s32b value; /* Known items use the actual value */ if (object_is_known(obj)) { if (cursed_p((bitflag *)obj->flags)) return (0L); value = object_value_real(obj, qty, verbose, TRUE); } else if (tval_has_variable_power(obj)) { /* Variable power items are assessed by what is known about them */ object_type object_type_body; object_type *j_ptr = &object_type_body; /* Hack -- Felt cursed items */ if (object_was_sensed(obj) && cursed_p((bitflag *)obj->flags)) return (0L); memcpy(j_ptr, obj, sizeof(object_type)); /* give j_ptr only the flags known to be in obj */ object_flags_known(obj, j_ptr->flags); if (!object_attack_plusses_are_visible(obj)) j_ptr->to_h = j_ptr->to_d = 0; if (!object_defence_plusses_are_visible(obj)) j_ptr->to_a = 0; value = object_value_real(j_ptr, qty, verbose, FALSE); } else /* Unknown constant-price items just get a base value */ value = object_value_base(obj) * qty; /* Return the final value */ return (value); }
/* * Return a "feeling" (or NULL) about an item. Method 1 (Heavy). */ static int value_check_aux1(object_type *o_ptr) { /* Artifacts */ if (artifact_p(o_ptr)) { /* Cursed/Broken */ if (cursed_p(o_ptr) || broken_p(o_ptr)) return (FEEL_TERRIBLE); /* Normal */ return (FEEL_SPECIAL); } /* Ego-Items */ if (ego_item_p(o_ptr)) { /* Cursed/Broken */ if (cursed_p(o_ptr) || broken_p(o_ptr)) return (FEEL_WORTHLESS); /* Normal */ return (FEEL_EXCELLENT); } /* Cursed items */ if (cursed_p(o_ptr)) return (FEEL_CURSED); /* Broken items */ if (broken_p(o_ptr)) return (FEEL_BROKEN); /* Good "armor" bonus */ if (o_ptr->to_a > 0) return (FEEL_GOOD); /* Good "weapon" bonus */ if (o_ptr->to_h + o_ptr->to_d > 0) return (FEEL_GOOD); /* Default to "average" */ return (FEEL_AVERAGE); }
/* * Attempt to make an object (normal or good/great) * * This routine plays nasty games to generate the "special artifacts". * * We assume that the given object has been "wiped". */ bool make_object(object_type *j_ptr, int lev, bool good, bool great) { int k_idx, base; object_kind *k_ptr; /* Try to make a special artifact */ if (one_in_(good ? 10 : 1000)) { if (make_artifact_special(j_ptr, lev)) return TRUE; /* If we failed to make an artifact, the player gets a great item */ good = great = TRUE; } /* Base level for the object */ base = (good ? (lev + 10) : lev); /* Get the object */ k_idx = get_obj_num(base, good || great); if (!k_idx) return FALSE; /* Prepare the object */ object_prep(j_ptr, &k_info[k_idx], lev, RANDOMISE); /* Apply magic (allow artifacts) */ apply_magic(j_ptr, lev, TRUE, good, great); /* Generate multiple items */ k_ptr = &k_info[j_ptr->k_idx]; if (k_ptr->gen_mult_prob >= 100 || k_ptr->gen_mult_prob >= randint1(100)) { j_ptr->number = randcalc(k_ptr->stack_size, lev, RANDOMISE); } /* Notice "okay" out-of-depth objects */ if (!cursed_p(j_ptr) && (k_info[j_ptr->k_idx].level > p_ptr->depth)) { /* Rating increase */ rating += (k_info[j_ptr->k_idx].alloc_min - p_ptr->depth); /* Cheat -- peek at items */ if (OPT(cheat_peek)) object_mention(j_ptr); } return TRUE; }
/** * Tweak the cursed status of an object. * * \param o_ptr is the object to curse or decurse */ static void wiz_tweak_curse(object_type *o_ptr) { if (cursed_p(o_ptr)) { msg_print("Resetting existing curses."); flags_clear(o_ptr->flags, OF_SIZE, OF_CURSE_MASK, FLAG_END); } if (get_check("Set light curse? ")) flags_set(o_ptr->flags, OF_SIZE, OF_LIGHT_CURSE, FLAG_END); else if (get_check("Set heavy curse? ")) flags_set(o_ptr->flags, OF_SIZE, OF_LIGHT_CURSE, OF_HEAVY_CURSE, FLAG_END); else if (get_check("Set permanent curse? ")) flags_set(o_ptr->flags, OF_SIZE, OF_LIGHT_CURSE, OF_HEAVY_CURSE, OF_PERMA_CURSE, FLAG_END); }
/* * Drop an item */ void do_cmd_drop(void) { int item, amt; object_type *o_ptr; cptr q, s; /* Get an item */ q = "Drop which item? "; s = "You have nothing to drop."; if (!get_item(&item, q, s, (USE_EQUIP | USE_INVEN))) return; /* Get the item (in the pack) */ if (item >= 0) { o_ptr = &inventory[item]; } /* Get the item (on the floor) */ else { o_ptr = &o_list[0 - item]; } /* Get a quantity */ amt = get_quantity(NULL, o_ptr->number); /* Allow user abort */ if (amt <= 0) return; /* Hack -- Cannot remove cursed items */ if ((item >= INVEN_WIELD) && cursed_p(o_ptr)) { /* Oops */ msg_print("Hmmm, it seems to be cursed."); /* Nope */ return; } /* Take a partial turn */ p_ptr->energy_use = 50; /* Drop (some of) the item */ inven_drop(item, amt); }
/** * Tweak the cursed status of an object. * * \param o_ptr is the object to curse or decurse */ static void wiz_tweak_curse(object_type *o_ptr) { if (cursed_p(o_ptr->flags)) { bitflag f[OF_SIZE]; msg("Resetting existing curses."); create_mask(f, FALSE, OFT_CURSE, OFT_MAX); of_diff(o_ptr->flags, f); } if (get_check("Set light curse? ")) flags_set(o_ptr->flags, OF_SIZE, OF_LIGHT_CURSE, FLAG_END); else if (get_check("Set heavy curse? ")) flags_set(o_ptr->flags, OF_SIZE, OF_LIGHT_CURSE, OF_HEAVY_CURSE, FLAG_END); else if (get_check("Set permanent curse? ")) flags_set(o_ptr->flags, OF_SIZE, OF_LIGHT_CURSE, OF_HEAVY_CURSE, OF_PERMA_CURSE, FLAG_END); }
/* * Take off an item */ void do_cmd_takeoff(void) { int item; object_type *o_ptr; cptr q, s; /* Get an item */ q = "Take off which item? "; s = "You are not wearing anything to take off."; if (!get_item(&item, q, s, (USE_EQUIP))) return; /* Get the item (in the pack) */ if (item >= 0) { o_ptr = &inventory[item]; } /* Get the item (on the floor) */ else { o_ptr = &o_list[0 - item]; } /* Item is cursed */ if (cursed_p(o_ptr)) { /* Oops */ msg_print("Hmmm, it seems to be cursed."); /* Nope */ return; } /* Take a partial turn */ p_ptr->energy_use = 50; /* Take off the item */ (void)inven_takeoff(item, 255); }
/** * Attempt to make an object * * \param c is the current dungeon level. * \param j_ptr is the object struct to be populated. * \param lev is the creation level of the object (not necessarily == depth). * \param good is whether the object is to be good * \param great is whether the object is to be great * \param value is the value to be returned to the calling function * \param tval is the desired tval, or 0 if we allow any tval * * Returns the whether or not creation worked. */ bool make_object(struct cave *c, object_type *j_ptr, int lev, bool good, bool great, bool extra_roll, s32b *value, int tval) { int base; object_kind *kind; /* Try to make a special artifact */ if (one_in_(good ? 10 : 1000)) { if (make_artifact_special(j_ptr, lev)) { if (value) *value = object_value_real(j_ptr, 1, FALSE, TRUE); return TRUE; } /* If we failed to make an artifact, the player gets a good item */ good = TRUE; } /* Base level for the object */ base = (good ? (lev + 10) : lev); /* Get the object, prep it and apply magic */ kind = get_obj_num(base, good || great, tval); if (!kind) return FALSE; object_prep(j_ptr, kind, lev, RANDOMISE); apply_magic(j_ptr, lev, TRUE, good, great, extra_roll); /* Generate multiple items */ if (kind->gen_mult_prob >= randint1(100)) j_ptr->number = randcalc(kind->stack_size, lev, RANDOMISE); if (j_ptr->number >= MAX_STACK_SIZE) j_ptr->number = MAX_STACK_SIZE - 1; /* Return value, increased for uncursed out-of-depth objects */ if (value) *value = object_value_real(j_ptr, j_ptr->number, FALSE, TRUE); if (!cursed_p(j_ptr->flags) && (kind->alloc_min > c->depth)) { if (value) *value = (kind->alloc_min - c->depth) * (*value / 5); } return TRUE; }
/* Drop an item */ void do_cmd_drop(cmd_code code, cmd_arg args[]) { int item = args[0].item; object_type *o_ptr = object_from_item_idx(item); int amt = args[1].number; if (!item_is_available(item, NULL, USE_INVEN | USE_EQUIP)) { msg("You do not have that item to drop it."); return; } /* Hack -- Cannot remove cursed items */ if ((item >= INVEN_WIELD) && cursed_p(o_ptr->flags)) { msg("Hmmm, it seems to be cursed."); return; } inven_drop(item, amt); p_ptr->energy_use = 50; }
/** * Test an item for any negative qualities */ bool item_dubious(const object_type * o_ptr, bool unknown) { int i; object_kind *k_ptr = &k_info[o_ptr->k_idx]; /* Resists, bonuses, multiples */ for (i = 0; i < MAX_P_RES; i++) if (o_ptr->percent_res[i] > RES_LEVEL_BASE) return TRUE; for (i = 0; i < A_MAX; i++) if (o_ptr->bonus_stat[i] < BONUS_BASE) return TRUE; for (i = 0; i < MAX_P_BONUS; i++) if (o_ptr->bonus_other[i] < BONUS_BASE) return TRUE; for (i = 0; i < MAX_P_SLAY; i++) if (o_ptr->multiple_slay[i] < MULTIPLE_BASE) return TRUE; for (i = 0; i < MAX_P_BRAND; i++) if (o_ptr->multiple_brand[i] < MULTIPLE_BASE) return TRUE; /* To skill, to deadliness, to AC */ if (o_ptr->to_h + o_ptr->to_d < k_ptr->to_h.base) return TRUE; if (o_ptr->to_a < 0) return TRUE; /* Only check curses if NOT known, so we can infer dubious items with no * other bad properties must be cursed */ if (unknown) { /* Cursed */ if (cursed_p(o_ptr)) return TRUE; } /* Must be OK */ return FALSE; }
static size_t obj_desc_inscrip(const object_type *o_ptr, char *buf, size_t max, size_t end) { const char *u[6] = { 0, 0, 0, 0, 0, 0}; int n = 0; /* See if the object is "known" */ bool known = (object_known_p(o_ptr) ? TRUE : FALSE); bool aware = (object_aware_p(o_ptr) ? TRUE : FALSE); u32b f1, f2, f3, fn; object_flags(o_ptr, &f1, &f2, &f3, &fn); /* Get inscription, pdeudo-id, or store discount */ if (o_ptr->obj_note) u[n++] = quark_str(o_ptr->obj_note); if (o_ptr->discount >= INSCRIP_NULL) { u[n++] = inscrip_text[o_ptr->discount - INSCRIP_NULL]; } else if (cursed_p(o_ptr) && known) { u[n++] = "cursed"; } else if ((o_ptr->ident & IDENT_EMPTY) && (!known)) { u[n++] = "empty"; } else if ((!aware) && object_tried_p(o_ptr)) { u[n++] = "tried"; } else if (o_ptr->discount > 0) { char buf[80]; my_strcpy(buf, format("%d%% off", o_ptr->discount), sizeof(buf)); u[n++] = buf; } /* Use the "unknown" inscription */ else if (!known && can_be_pseudo_ided(o_ptr) && (o_ptr->discount < INSCRIP_NULL)) { u[n++] = "unknown"; } 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; }
/** * Complete object creation by applying magic to it. * * Magic includes rolling for random bonuses, applying flags to ego-items, * charging charged items, fuelling lights, and trapping chests. * * The `good` argument forces the item to be at least `good`, and the `great` * argument does likewise. Setting `allow_artifacts` to TRUE allows artifacts * to be created here. * * If `good` or `great` are not set, then the `lev` argument controls the * quality of item. See the function itself for the specifics of the * calculations involved. */ void apply_magic(object_type *o_ptr, int lev, bool allow_artifacts, bool good, bool great) { int power = 0; /*u32b xtra = 0;*/ /*bool new = FALSE;*/ /* Chance of being `good` and `great` */ int good_chance = (lev+2) * 3; int great_chance = MIN(lev/4 + lev, 50); /* Limit depth */ if (lev > MAX_DEPTH - 1) lev = MAX_DEPTH - 1; /* Roll for "good" */ if (good || (randint0(100) < good_chance)) { /* Assume "good" */ power = 1; /* Roll for "great" */ if (great || (randint0(100) < great_chance)) power = 2; } /* Roll for "cursed" */ else if (randint0(100) < good_chance) { /* Assume "cursed" */ power = -1; /* Roll for "broken" */ if (randint0(100) < great_chance) power = -2; } /* Roll for artifact creation */ if (allow_artifacts) { int i; int rolls = 0; /* Get one roll if excellent */ if (power >= 2) rolls = 1; /* Get four rolls if forced great */ if (great) rolls = 4; /* Roll for artifacts if allowed */ for (i = 0; i < rolls; i++) { if (make_artifact(o_ptr)) return; } } /* Apply magic */ switch (o_ptr->tval) { case TV_DIGGING: case TV_HAFTED: case TV_POLEARM: case TV_SWORD: case TV_BOW: case TV_SHOT: case TV_ARROW: case TV_BOLT: { if (power == 2 || power == -2) { int ego_power; ego_power = make_ego_item(o_ptr, lev, (bool)(power > 0)); if (ego_power) power = ego_power; } if (power) a_m_aux_1(o_ptr, lev, power); break; } case TV_DRAG_ARMOR: case TV_HARD_ARMOR: case TV_SOFT_ARMOR: case TV_SHIELD: case TV_HELM: case TV_CROWN: case TV_CLOAK: case TV_GLOVES: case TV_BOOTS: { if (power == 2 || power == -2) { int ego_power; ego_power = make_ego_item(o_ptr, lev, (bool)(power > 0)); if (ego_power) power = ego_power; } if (power) a_m_aux_2(o_ptr, lev, power); break; } case TV_RING: case TV_AMULET: { if (!power && (randint0(100) < 50)) power = -1; a_m_aux_3(o_ptr, lev, power); break; } case TV_LIGHT: { if (power == 2 || power == -2) make_ego_item(o_ptr, lev, (bool)(power > 0)); /* Fuel it */ a_m_aux_4(o_ptr, lev, power); break; } default: { a_m_aux_4(o_ptr, lev, power); break; } } /* Hack -- analyze ego-items */ if (o_ptr->name2) { ego_item_type *e_ptr = &e_info[o_ptr->name2]; bitflag flags[OF_SIZE]; object_flags(o_ptr, flags); /* Extra powers */ if (e_ptr->xtra == OBJECT_XTRA_TYPE_SUSTAIN) of_on(o_ptr->flags, get_new_attr(flags, ego_sustains, N_ELEMENTS(ego_sustains))); else if (e_ptr->xtra == OBJECT_XTRA_TYPE_RESIST) of_on(o_ptr->flags, get_new_attr(flags, ego_resists, N_ELEMENTS(ego_resists))); else if (e_ptr->xtra == OBJECT_XTRA_TYPE_POWER) of_on(o_ptr->flags, get_new_attr(flags, ego_powers, N_ELEMENTS(ego_powers))); /* Hack -- acquire "cursed" flags */ if (cursed_p(e_ptr)) { bitflag curse_flags[OF_SIZE]; of_copy(curse_flags, e_ptr->flags); flags_mask(curse_flags, OF_SIZE, OF_CURSE_MASK, FLAG_END); of_union(o_ptr->flags, curse_flags); } /* Hack -- apply extra penalties if needed */ if (cursed_p(o_ptr)) { /* Apply extra ego bonuses */ o_ptr->to_h -= randcalc(e_ptr->to_h, lev, RANDOMISE); o_ptr->to_d -= randcalc(e_ptr->to_d, lev, RANDOMISE); o_ptr->to_a -= randcalc(e_ptr->to_a, lev, RANDOMISE); /* Apply ego pval */ o_ptr->pval -= randcalc(e_ptr->pval, lev, RANDOMISE); /* Apply minimums */ if (o_ptr->to_h > -1 * e_ptr->min_to_h) o_ptr->to_h = -1 * e_ptr->min_to_h; if (o_ptr->to_d > -1 * e_ptr->min_to_d) o_ptr->to_d = -1 * e_ptr->min_to_d; if (o_ptr->to_a > -1 * e_ptr->min_to_a) o_ptr->to_a = -1 * e_ptr->min_to_a; if (o_ptr->pval > -1 * e_ptr->min_pval) o_ptr->pval = -1 * e_ptr->min_pval; } /* Hack -- apply extra bonuses if needed */ else { /* Apply extra ego bonuses */ o_ptr->to_h += randcalc(e_ptr->to_h, lev, RANDOMISE); o_ptr->to_d += randcalc(e_ptr->to_d, lev, RANDOMISE); o_ptr->to_a += randcalc(e_ptr->to_a, lev, RANDOMISE); /* Apply ego pval */ o_ptr->pval += randcalc(e_ptr->pval, lev, RANDOMISE); /* Apply minimums */ if (o_ptr->to_h < e_ptr->min_to_h) o_ptr->to_h = e_ptr->min_to_h; if (o_ptr->to_d < e_ptr->min_to_d) o_ptr->to_d = e_ptr->min_to_d; if (o_ptr->to_a < e_ptr->min_to_a) o_ptr->to_a = e_ptr->min_to_a; if (o_ptr->pval < e_ptr->min_pval) o_ptr->pval = e_ptr->min_pval; } /* Hack -- apply rating bonus */ rating += e_ptr->rating; /* Cheat -- describe the item */ if (OPT(cheat_peek)) object_mention(o_ptr); /* Done */ return; } /* Examine real objects */ if (o_ptr->k_idx) { object_kind *k_ptr = &k_info[o_ptr->k_idx]; /* Hack -- acquire "cursed" flag */ if (cursed_p(k_ptr)) { bitflag curse_flags[OF_SIZE]; of_copy(curse_flags, k_ptr->flags); flags_mask(curse_flags, OF_SIZE, OF_CURSE_MASK, FLAG_END); of_union(o_ptr->flags, curse_flags); } } }
/* * Creates a description of the item "o_ptr", and stores it in "out_val". * * One can choose the "verbosity" of the description, including whether * or not the "number" of items should be described, and how much detail * should be used when describing the item. * * The given "buf" must be 80 chars long to hold the longest possible * description, which can get pretty long, including incriptions, such as: * "no more Maces of Disruption (Defender) (+10,+10) [+5] (+3 to stealth)". * Note that the inscription will be clipped to keep the total description * under 79 chars (plus a terminator). * * Note the use of "object_desc_num()" and "object_desc_int()" as * hyper-efficient, portable, versions of some common "sprintf()" commands. * * Note that all ego-items (when known) append an "Ego-Item Name", unless * the item is also an artifact, which should NEVER happen. * * Note that all artifacts (when known) append an "Artifact Name", so we * have special processing for "Specials" (artifact Lites, Rings, Amulets). * The "Specials" never use "modifiers" if they are "known", since they * have special "descriptions", such as "The Necklace of the Dwarves". * * Special Lite's use the "k_info" base-name (Phial, Star, or Arkenstone), * plus the artifact name, just like any other artifact, if known. * * Special Ring's and Amulet's, if not "aware", use the same code as normal * rings and amulets, and if "aware", use the "k_info" base-name (Ring or * Amulet or Necklace). They will NEVER "append" the "k_info" name. But, * they will append the artifact name, just like any artifact, if known. * * None of the Special Rings/Amulets are "EASY_KNOW", though they could be, * at least, those which have no "pluses", such as the three artifact lites. * * Hack -- Display "The One Ring" as "a Plain Gold Ring" until aware. * * If "pref" then a "numeric" prefix will be pre-pended. * * Mode: * 0 -- The Cloak of Death * 1 -- The Cloak of Death [1,+3] * 2 -- The Cloak of Death [1,+3] (+2 to Stealth) * 3 -- The Cloak of Death [1,+3] (+2 to Stealth) {nifty} */ void object_desc(char *buf, const object_type *o_ptr, int pref, int mode) { cptr basenm, modstr; int power, indexx, durable; bool aware = FALSE; bool known = FALSE; bool append_name = FALSE; bool show_weapon = FALSE; bool show_armour = FALSE; cptr s, u; char *t; char p1 = '(', p2 = ')'; char b1 = '[', b2 = ']'; char c1 = '{', c2 = '}'; char pv1 = '<', pv2 = '>'; char tmp_val[160]; char tmp_val2[90]; u32b f1, f2, f3, f4, f5, f6; object_type *bow_ptr; /* damage dice, damage sides, damage bonus, energy */ int dd, ds, db, energy_use; int tmul; long avgdam; object_kind *k_ptr = &k_info[o_ptr->k_idx]; monster_race *r_ptr = &r_info[o_ptr->pval]; /* Extract some flags */ object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &f6); /***** NEEDS REWORKING *****/ durable = 0; /* See if the object is "aware" */ if (object_aware_p(o_ptr)) aware = TRUE; /* See if the object is "known" */ if (object_known_p(o_ptr)) known = TRUE; /* Hack -- Extract the sub-type "indexx" */ indexx = o_ptr->sval; /* Extract default "base" string */ basenm = get_object_name(o_ptr); /* Assume no "modifier" string */ modstr = ""; /* Analyze the object */ switch (o_ptr->tval) { /* Some objects are easy to describe */ case TV_SKELETON: case TV_BOTTLE: case TV_JUNK: case TV_SPIKE: case TV_FLASK: case TV_CHEST: { break; } /* Figurines/Statues */ case TV_FIGURINE: case TV_STATUE: { cptr tmp = r_name + r_ptr->name; if (!(r_ptr->flags1 & RF1_UNIQUE)) { sprintf(tmp_val2, "%s%s", (is_a_vowel(*tmp) ? "an " : "a "), tmp); modstr = tmp_val2; } else { modstr = tmp; } break; } /* Missiles/ Bows/ Weapons */ case TV_SHOT: case TV_BOLT: case TV_ARROW: case TV_BOW: case TV_HAFTED: case TV_POLEARM: case TV_SWORD: case TV_DIGGING: { show_weapon = TRUE; break; } /* Armour */ case TV_BOOTS: case TV_GLOVES: case TV_CLOAK: case TV_CROWN: case TV_HELM: case TV_SHIELD: case TV_SOFT_ARMOR: case TV_HARD_ARMOR: case TV_DRAG_ARMOR: { show_armour = TRUE; break; } /* Lites (including a few "Specials") */ case TV_LITE: { break; } /* Amulets (including a few "Specials") */ case TV_AMULET: { /* Known artifacts */ if ((o_ptr->flags3 & TR3_INSTA_ART) && aware) break; /* Color the object */ modstr = amulet_adj[indexx]; break; } /* Rings (including a few "Specials") */ case TV_RING: { /* Known artifacts */ if ((o_ptr->flags3 & TR3_INSTA_ART) && aware) break; /* Color the object */ modstr = ring_adj[indexx]; /* Hack -- The One Ring */ /*if (!aware && (o_ptr->sval == SV_RING_POWER)) modstr = "Plain Gold";*/ break; } case TV_STAFF: { /* Color the object */ modstr = staff_adj[indexx]; break; } case TV_WAND: { /* Color the object */ modstr = wand_adj[indexx]; break; } case TV_ROD: { /* Color the object */ modstr = rod_adj[indexx]; break; } case TV_SCROLL: { /* Color the object */ modstr = scroll_adj[indexx]; break; } case TV_POTION: { /* Color the object */ modstr = potion_adj[indexx]; break; } case TV_FOOD: { /* Ordinary food is "boring" */ if (o_ptr->sval >= SV_FOOD_MIN_FOOD) break; /* Color the object */ modstr = food_adj[indexx]; break; } /* Magic Books */ case TV_SPELL_BOOK: { modstr = basenm; break; } /* Hack -- Gold/Gems */ case TV_GOLD: { strcpy(buf, basenm); return; } /* Used in the "inventory" routine */ default: { strcpy(buf, "(nothing)"); return; } } /* Start dumping the result */ t = tmp_val; /* Durability Check */ durable = (o_ptr->C_Durability / (o_ptr->weight * 3)); if (durable > 7) durable = 7; if (durable == 0) t = object_desc_str(t, "(J) "); if (durable == 1) t = object_desc_str(t, "(B) "); if (durable == 2) t = object_desc_str(t, "(P) "); if (durable == 3) t = object_desc_str(t, "(N) "); if (durable == 4) t = object_desc_str(t, "(G) "); if (durable == 5) t = object_desc_str(t, "(E) "); if (durable == 6) t = object_desc_str(t, "(W) "); if (durable == 7) t = object_desc_str(t, "(M) "); /* The object "expects" a "number" */ if (basenm[0] == '&') { /* Skip the ampersand (and space) */ s = basenm + 2; /* No prefix */ if (!pref) { /* Nothing */ } /* Hack -- None left */ else if (o_ptr->number <= 0) { t = object_desc_str(t, "no more "); } /* Extract the number */ else if (o_ptr->number > 1) { t = object_desc_num(t, o_ptr->number); t = object_desc_chr(t, ' '); } /* Hack -- The only one of its kind */ else if (known && (o_ptr->flags3 & TR3_INSTA_ART)) { t = object_desc_str(t, "The "); } /* A single one, with a vowel in the modifier */ else if ((*s == '#') && (is_a_vowel(modstr[0]))) { t = object_desc_str(t, "an "); } /* A single one, with a vowel */ else if (is_a_vowel(*s)) { t = object_desc_str(t, "an "); } /* A single one, without a vowel */ else { t = object_desc_str(t, "a "); } } /* Hack -- objects that "never" take an article */ else { /* No ampersand */ s = basenm; /* No pref */ if (!pref) { /* Nothing */ } /* Hack -- all gone */ else if (o_ptr->number <= 0) { t = object_desc_str(t, "no more "); } /* Prefix a number if required */ else if (o_ptr->number > 1) { t = object_desc_num(t, o_ptr->number); t = object_desc_chr(t, ' '); } /* Hack -- The only one of its kind */ else if (known && (o_ptr->flags3 & TR3_INSTA_ART)) { t = object_desc_str(t, "The "); } /* Hack -- single items get no prefix */ else { /* Nothing */ } } /* Paranoia -- skip illegal tildes */ /* while (*s == '~') s++; */ /* Copy the string */ for (; *s; s++) { /* Pluralizer */ if (*s == '~') { /* Add a plural if needed */ if (o_ptr->number != 1) { char k = t[-1]; /* XXX XXX XXX Mega-Hack */ /* Hack -- "Cutlass-es" and "Torch-es" */ if ((k == 's') || (k == 'h')) *t++ = 'e'; /* Add an 's' */ *t++ = 's'; } } /* Modifier */ else if (*s == '#') { /* Insert the modifier */ for (u = modstr; *u; u++) *t++ = *u; } /* Normal */ else { /* Copy */ *t++ = *s; } } /* Terminate */ *t = '\0'; /* Append the "kind name" to the "base name" */ if (append_name) { t = object_desc_str(t, " of "); t = object_desc_str(t, get_object_name(o_ptr)); } /* Hack -- Append "Artifact" or "Special" names */ if (known) { if (o_ptr->inscription && strchr(quark_str(o_ptr->inscription), '#')) { /* Find the '#' */ cptr str = strchr(quark_str(o_ptr->inscription), '#'); /* Add the false name */ t = object_desc_chr(t, ' '); t = object_desc_str(t, &str[1]); } /* Is it a new artifact or ego item? */ else if (o_ptr->xtra_name) { t = object_desc_chr(t, ' '); t = object_desc_str(t, quark_str(o_ptr->xtra_name)); } } /* No more details wanted */ if (mode < 1) goto copyback; /* Hack -- Chests must be described in detail */ if (o_ptr->tval == TV_CHEST) { /* Not searched yet */ if (!known) { /* Nothing */ } /* May be "empty" */ else if (!o_ptr->pval) { t = object_desc_str(t, " (empty)"); } /* May be "disarmed" */ else if (o_ptr->pval < 0) { if (chest_traps[0 - o_ptr->pval]) { t = object_desc_str(t, " (disarmed)"); } else { t = object_desc_str(t, " (unlocked)"); } } /* Describe the traps, if any */ else { /* Describe the traps */ switch (chest_traps[o_ptr->pval]) { case 0: { t = object_desc_str(t, " (Locked)"); break; } case CHEST_LOSE_STR: { t = object_desc_str(t, " (Poison Needle)"); break; } case CHEST_LOSE_CON: { t = object_desc_str(t, " (Poison Needle)"); break; } case CHEST_POISON: { t = object_desc_str(t, " (Gas Trap)"); break; } case CHEST_PARALYZE: { t = object_desc_str(t, " (Gas Trap)"); break; } case CHEST_EXPLODE: { t = object_desc_str(t, " (Explosion Device)"); break; } case CHEST_SUMMON: { t = object_desc_str(t, " (Summoning Runes)"); break; } default: { t = object_desc_str(t, " (Multiple Traps)"); break; } } } } /* Display the item like a weapon */ if (f3 & (TR3_SHOW_MODS)) show_weapon = TRUE; /* Display the item like a weapon */ if (o_ptr->to_h && o_ptr->to_d) show_weapon = TRUE; /* Display the item like armour */ if ((o_ptr->ac) && (o_ptr->tval != TV_WAND)) show_armour = TRUE; /* Dump base weapon info */ switch (o_ptr->tval) { /* Missiles and Weapons */ case TV_SHOT: case TV_BOLT: case TV_ARROW: case TV_HAFTED: case TV_POLEARM: case TV_SWORD: case TV_DIGGING: /* Append a "damage" string */ t = object_desc_chr(t, ' '); t = object_desc_chr(t, p1); t = object_desc_num(t, o_ptr->dd); t = object_desc_chr(t, 'd'); t = object_desc_num(t, o_ptr->ds); t = object_desc_chr(t, p2); /* All done */ break; /* Bows get a special "damage string" */ case TV_BOW: /* Extract the "base power" */ switch (o_ptr->sval) { case SV_SLING: power = 2; break; case SV_SHORT_BOW: power = 2; break; case SV_LONG_BOW: if (p_ptr->stat_use[A_STR] >= 16) { power = 3; } else { /* hack- weak players cannot use a longbow well */ power = 2; } break; case SV_LIGHT_XBOW: power = 4; break; case SV_HEAVY_XBOW: power = 5; break; default: msg_print("Unknown firing multiplier."); power = 0; } /* Apply the "Extra Might" flag */ if (f3 & (TR3_XTRA_MIGHT)) power++; /* Append a special "damage" string */ t = object_desc_chr(t, ' '); t = object_desc_chr(t, p1); t = object_desc_chr(t, 'x'); t = object_desc_num(t, power); t = object_desc_chr(t, p2); /* All done */ break; } /* Add the weapon bonuses */ if (known) { /* Show the tohit/todam on request */ if (show_weapon) { t = object_desc_chr(t, ' '); t = object_desc_chr(t, p1); t = object_desc_int(t, o_ptr->to_h); t = object_desc_chr(t, ','); t = object_desc_int(t, o_ptr->to_d); t = object_desc_chr(t, p2); } /* Show the tohit if needed */ else if (o_ptr->to_h) { t = object_desc_chr(t, ' '); t = object_desc_chr(t, p1); t = object_desc_int(t, o_ptr->to_h); t = object_desc_chr(t, p2); } /* Show the todam if needed */ else if (o_ptr->to_d) { t = object_desc_chr(t, ' '); t = object_desc_chr(t, p1); t = object_desc_int(t, o_ptr->to_d); t = object_desc_chr(t, p2); } } bow_ptr = &inventory[INVEN_BOW]; /* if have a firing weapon + ammo matches bow */ if (bow_ptr->k_idx && (p_ptr->ammo_tval == o_ptr->tval)) { /* See if the bow is "known" - then set damage bonus */ if (object_known_p(bow_ptr)) { db = bow_ptr->to_d; } else { db = 0; } /* effect of player */ db += p_ptr->dis_to_d; /* effect of ammo */ if (known) db += o_ptr->to_d; dd = o_ptr->dd; ds = o_ptr->ds; /* avgdam = deadliness_calc(db);*/ /* effect of damage dice x2 */ avgdam = dd * (ds + 1); avgdam += db; /* Bow properties */ energy_use = p_ptr->bow_energy; tmul = p_ptr->ammo_mult; /* Get extra "power" from "extra might" */ if (p_ptr->xtra_might) tmul++; /* launcher multiplier */ avgdam *= tmul; /* display (shot damage/ avg damage) */ t = object_desc_chr(t, ' '); t = object_desc_chr(t, p1); t = object_desc_num(t, avgdam / 2/*00*/); t = object_desc_chr(t, '/'); tmul = p_ptr->num_fire; if (tmul == 0) { t = object_desc_chr(t, '-'); } else { /* calc effects of energy x2 */ avgdam *= (1 + p_ptr->num_fire); /* rescale */ avgdam /= ((int)(4 * (int)(energy_use / 100.0))); t = object_desc_num(t, avgdam); } t = object_desc_chr(t, p2); } /* Add the armor bonuses */ if (known) { /* Show the armor class info */ if (show_armour) { t = object_desc_chr(t, ' '); t = object_desc_chr(t, b1); t = object_desc_num(t, o_ptr->ac); t = object_desc_chr(t, ','); t = object_desc_int(t, o_ptr->to_a); t = object_desc_chr(t, b2); } /* No base armor, but does increase armor */ else if (o_ptr->to_a) { t = object_desc_chr(t, ' '); t = object_desc_chr(t, b1); t = object_desc_int(t, o_ptr->to_a); t = object_desc_chr(t, b2); } } /* Hack -- always show base armor */ else if (show_armour) { t = object_desc_chr(t, ' '); t = object_desc_chr(t, b1); t = object_desc_num(t, o_ptr->ac); t = object_desc_chr(t, b2); } /* No more details wanted */ if (mode < 2) goto copyback; /* * Hack -- Wands and Staffs have charges. Make certain how many charges * a stack of staffs really has is clear. -LM- */ if (known && ((o_ptr->tval == TV_STAFF) || (o_ptr->tval == TV_WAND))) { /* Dump " (N charges)" */ t = object_desc_chr(t, ' '); t = object_desc_chr(t, p1); /* Clear explaination for staffs. */ if ((o_ptr->tval == TV_STAFF) && (o_ptr->number > 1)) { t = object_desc_num(t, o_ptr->number); t = object_desc_str(t, "x "); } t = object_desc_num(t, o_ptr->pval); t = object_desc_str(t, " charge"); if (o_ptr->pval != 1) { t = object_desc_chr(t, 's'); } t = object_desc_chr(t, p2); } /* Hack -- Rods have a "charging" indicator. Now that stacks of rods may * be in any state of charge or discharge, this now includes a number. -LM- */ else if (known && (o_ptr->tval == TV_ROD)) { /* Hack -- Dump " (# charging)" if relevant */ if ((o_ptr->timeout) && (o_ptr->tval != TV_LITE)) { /* Stacks of rods display an exact count of charging rods. */ if (o_ptr->number > 1) { /* Paranoia. */ if (k_ptr->pval == 0) k_ptr->pval = 1; /* Find out how many rods are charging, by dividing * current timeout by each rod's maximum timeout. * Ensure that any remainder is rounded up. Display * very discharged stacks as merely fully discharged. */ power = (o_ptr->timeout + (k_ptr->pval - 1)) / k_ptr->pval; if (power > o_ptr->number) power = o_ptr->number; /* Display prettily. */ t = object_desc_str(t, " ("); t = object_desc_num(t, power); t = object_desc_str(t, " charging)"); } /* "one Rod of Perception (1 charging)" would look tacky. */ else { t = object_desc_str(t, " (charging)"); } } } /* Hack -- Process Lanterns/Torches */ else if ((o_ptr->tval == TV_LITE) && (!(o_ptr->flags3 & TR3_LITE))) { /* Hack -- Turns of light for normal lites */ t = object_desc_str(t, " (with "); t = object_desc_num(t, o_ptr->timeout); t = object_desc_str(t, " turns of light)"); } /* Dump "pval" flags for wearable items */ if (known && (f1 & (TR1_PVAL_MASK))) { if (o_ptr->tval != TV_STAFF && o_ptr->tval != TV_ROD && o_ptr->tval != TV_POTION && o_ptr->tval != TV_FOOD && o_ptr->tval != TV_WAND && o_ptr->tval != TV_SCROLL) { /* Start the display */ t = object_desc_chr(t, ' '); t = object_desc_chr(t, p1); /* Dump the "pval" itself */ t = object_desc_int(t, o_ptr->pval); /* Do not display the "pval" flags */ if (f3 & (TR3_HIDE_TYPE)) { /* Nothing */ } /* Speed */ else if (f1 & (TR1_SPEED)) { /* Dump " to speed" */ t = object_desc_str(t, " to speed"); } /* Attack speed */ else if (f1 & (TR1_BLOWS)) { /* Add " attack" */ t = object_desc_str(t, " attack"); /* Add "attacks" */ if (ABS(o_ptr->pval) != 1) t = object_desc_chr(t, 's'); } /* Stealth */ else if (f1 & (TR1_STEALTH)) { /* Dump " to stealth" */ t = object_desc_str(t, " to stealth"); } /* Search */ else if (f1 & (TR1_SEARCH)) { /* Dump " to searching" */ t = object_desc_str(t, " to searching"); } /* Infravision */ else if (f1 & (TR1_INFRA)) { /* Dump " to infravision" */ t = object_desc_str(t, " to infravision"); } /* Finish the display */ t = object_desc_chr(t, p2); } } if (known && o_ptr->pval2) { t = object_desc_chr(t, ' '); t = object_desc_chr(t, pv1); t = object_desc_num(t, o_ptr->pval2); t = object_desc_chr(t, pv2); } /* Indicate charging objects, but not rods. */ if (known && o_ptr->timeout && o_ptr->tval != TV_ROD && o_ptr->tval != TV_LITE) { /* Hack -- Dump " (charging)" if relevant */ t = object_desc_str(t, " (charging)"); } /* No more details wanted */ if (mode < 3) goto copyback; /* No inscription yet */ tmp_val2[0] = '\0'; /* Use the standard inscription if available */ if (o_ptr->inscription) { char *tmp = tmp_val2; strcpy(tmp_val2, quark_str(o_ptr->inscription)); for (; *tmp && (*tmp != '#'); tmp++); *tmp = '\0'; } /* Use the game-generated "feeling" otherwise, if available */ else if (o_ptr->feeling) { strcpy(tmp_val2, game_inscriptions[o_ptr->feeling]); } /* Note "cursed" if the item is known to be cursed */ else if (cursed_p(o_ptr) && (known || (o_ptr->ident & (IDENT_SENSE)))) { strcpy(tmp_val2, "cursed"); } /* Mega-Hack -- note empty wands/staffs */ else if (!known && (o_ptr->ident & (IDENT_EMPTY))) { strcpy(tmp_val2, "empty"); } /* Note "tried" if the object has been tested unsuccessfully */ else if (!aware && object_tried_p(o_ptr)) { strcpy(tmp_val2, "tried"); } /* Note the discount, if any */ else if (o_ptr->discount) { (void)object_desc_num(tmp_val2, o_ptr->discount); strcat(tmp_val2, "% off"); } /* Append the inscription, if any */ if (tmp_val2[0]) { int n; /* Hack -- How much so far */ n = (t - tmp_val); /* Paranoia -- do not be stupid */ if (n > 75) n = 75; /* Hack -- shrink the inscription */ tmp_val2[75 - n] = '\0'; /* Append the inscription */ t = object_desc_chr(t, ' '); t = object_desc_chr(t, c1); t = object_desc_str(t, tmp_val2); t = object_desc_chr(t, c2); } copyback: /* Here's where we dump the built string into buf. */ tmp_val[79] = '\0'; t = tmp_val; while ((*(buf++) = *(t++))); /* copy the string over */ }
/* * Destroy an item */ void do_cmd_destroy(void) { int item, amt; int old_number; object_type *o_ptr; char o_name[80]; char out_val[160]; cptr q, s; /* Get an item */ q = "Destroy which item? "; s = "You have nothing to destroy."; if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return; /* Get the item (in the pack) */ if (item >= 0) { o_ptr = &inventory[item]; } /* Get the item (on the floor) */ else { o_ptr = &o_list[0 - item]; } /* Get a quantity */ amt = get_quantity(NULL, o_ptr->number); /* Allow user abort */ if (amt <= 0) return; /* Describe the object */ old_number = o_ptr->number; o_ptr->number = amt; object_desc(o_name, o_ptr, TRUE, 3); o_ptr->number = old_number; /* Verify destruction */ if (verify_destroy) { sprintf(out_val, "Really destroy %s? ", o_name); if (!get_check(out_val)) return; } /* Take a turn */ p_ptr->energy_use = 100; /* Artifacts cannot be destroyed */ if (artifact_p(o_ptr)) { /* Message */ msg_format("You cannot destroy %s.", o_name); /* Don't mark id'ed objects */ if (object_known_p(o_ptr)) return; /* It has already been sensed */ if (o_ptr->ident & (IDENT_SENSE)) { /* Already sensed objects always get improved feelings */ if (cursed_p(o_ptr) || broken_p(o_ptr)) o_ptr->discount = INSCRIP_TERRIBLE; else o_ptr->discount = INSCRIP_SPECIAL; } else { /* Mark the object as indestructible */ o_ptr->discount = INSCRIP_INDESTRUCTIBLE; } /* Combine the pack */ p_ptr->notice |= (PN_COMBINE); /* Window stuff */ p_ptr->window |= (PW_INVEN | PW_EQUIP); p_ptr->redraw |= (PR_EQUIPPY); /* Done */ return; } /* Message */ msg_format("You destroy %s.", o_name); /* Eliminate the item (from the pack) */ if (item >= 0) { inven_item_increase(item, -amt); inven_item_describe(item); inven_item_optimize(item); } /* Eliminate the item (from the floor) */ else { floor_item_increase(0 - item, -amt); floor_item_describe(0 - item); floor_item_optimize(0 - item); } }
/* * Wield or wear a single item from the pack or floor */ void wield_item(object_type *o_ptr, int item, int slot) { object_type object_type_body; object_type *i_ptr = &object_type_body; const char *fmt; char o_name[80]; bool combined_ammo = FALSE; bool track_wielded_item = FALSE; int num = 1; /* If we are stacking ammo in the quiver */ if (obj_is_ammo(o_ptr)) { num = o_ptr->number; combined_ammo = object_similar(o_ptr, &p_ptr->inventory[slot], OSTACK_QUIVER); } /* Take a turn */ p_ptr->energy_use = 100; /* Obtain local object */ object_copy(i_ptr, o_ptr); /* Modify quantity */ i_ptr->number = num; /* Update object_idx if necessary, once object is in slot */ if (p_ptr->object_idx == item) { track_wielded_item = TRUE; } /* Decrease the item (from the pack) */ if (item >= 0) { inven_item_increase(item, -num); inven_item_optimize(item); } /* Decrease the item (from the floor) */ else { floor_item_increase(0 - item, -num); floor_item_optimize(0 - item); } /* Get the wield slot */ o_ptr = &p_ptr->inventory[slot]; if (combined_ammo) { /* Add the new ammo to the already-quiver-ed ammo */ object_absorb(o_ptr, i_ptr); } else { /* Take off existing item */ if (o_ptr->kind) (void)inven_takeoff(slot, 255); /* If we are wielding ammo we may need to "open" the slot by shifting * later ammo up the quiver; this is because we already called the * inven_item_optimize() function. */ if (slot >= QUIVER_START) open_quiver_slot(slot); /* Wear the new stuff */ object_copy(o_ptr, i_ptr); /* Increment the equip counter by hand */ p_ptr->equip_cnt++; } /* Increase the weight */ p_ptr->total_weight += i_ptr->weight * num; /* Track object if necessary */ if (track_wielded_item) { track_object(slot); } /* Do any ID-on-wield */ object_notice_on_wield(o_ptr); /* Where is the item now */ if (slot == INVEN_WIELD) fmt = "You are wielding %s (%c)."; else if (slot == INVEN_BOW) fmt = "You are shooting with %s (%c)."; else if (slot == INVEN_LIGHT) fmt = "Your light source is %s (%c)."; else if (combined_ammo) fmt = "You combine %s in your quiver (%c)."; else if (slot >= QUIVER_START && slot < QUIVER_END) fmt = "You add %s to your quiver (%c)."; else fmt = "You are wearing %s (%c)."; /* Describe the result */ object_desc(o_name, sizeof(o_name), o_ptr, ODESC_PREFIX | ODESC_FULL); /* Message */ msgt(MSG_WIELD, fmt, o_name, index_to_label(slot)); /* Cursed! */ if (cursed_p(o_ptr->flags)) { /* Warn the player */ msgt(MSG_CURSED, "Oops! It feels deathly cold!"); /* Sense the object */ object_notice_curses(o_ptr); } /* Save quiver size */ save_quiver_size(p_ptr); /* See if we have to overflow the pack */ pack_overflow(); /* Recalculate bonuses, torch, mana */ p_ptr->notice |= PN_SORT_QUIVER; p_ptr->update |= (PU_BONUS | PU_TORCH | PU_MANA); p_ptr->redraw |= (PR_INVEN | PR_EQUIP); }
/* Wield or wear an item */ void do_cmd_wield(cmd_code code, cmd_arg args[]) { object_type *equip_o_ptr; char o_name[80]; unsigned n; int item = args[0].item; int slot = args[1].number; object_type *o_ptr = object_from_item_idx(item); if (!item_is_available(item, NULL, USE_INVEN | USE_FLOOR)) { msg("You do not have that item to wield."); return; } /* Check the slot */ if (!slot_can_wield_item(slot, o_ptr)) { msg("You cannot wield that item there."); return; } equip_o_ptr = &p_ptr->inventory[slot]; /* If the slot is open, wield and be done */ if (!equip_o_ptr->kind) { wield_item(o_ptr, item, slot); return; } /* If the slot is in the quiver and objects can be combined */ if (obj_is_ammo(equip_o_ptr) && object_similar(equip_o_ptr, o_ptr, OSTACK_QUIVER)) { wield_item(o_ptr, item, slot); return; } /* Prevent wielding into a cursed slot */ if (cursed_p(equip_o_ptr->flags)) { object_desc(o_name, sizeof(o_name), equip_o_ptr, ODESC_BASE); msg("The %s you are %s appears to be cursed.", o_name, describe_use(slot)); return; } /* "!t" checks for taking off */ n = check_for_inscrip(equip_o_ptr, "!t"); while (n--) { /* Prompt */ object_desc(o_name, sizeof(o_name), equip_o_ptr, ODESC_PREFIX | ODESC_FULL); /* Forget it */ if (!get_check(format("Really take off %s? ", o_name))) return; } wield_item(o_ptr, item, slot); }
/* * Wield or wear a single item from the pack or floor */ void do_cmd_wield(void) { int item, slot; object_type *o_ptr; object_type *i_ptr; object_type object_type_body; cptr act; cptr q, s; char o_name[80]; /* Restrict the choices */ item_tester_hook = item_tester_hook_wear; /* Get an item */ q = "Wear/Wield which item? "; s = "You have nothing you can wear or wield."; if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return; /* Get the item (in the pack) */ if (item >= 0) { o_ptr = &inventory[item]; } /* Get the item (on the floor) */ else { o_ptr = &o_list[0 - item]; } /* Check the slot */ slot = wield_slot(o_ptr); /* Prevent wielding into a cursed slot */ if (cursed_p(&inventory[slot])) { /* Describe it */ object_desc(o_name, &inventory[slot], FALSE, 0); /* Message */ msg_format("The %s you are %s appears to be cursed.", o_name, describe_use(slot)); /* Cancel the command */ return; } /* Take a turn */ p_ptr->energy_use = 100; /* Get local object */ i_ptr = &object_type_body; /* Obtain local object */ object_copy(i_ptr, o_ptr); /* Modify quantity */ i_ptr->number = 1; /* Decrease the item (from the pack) */ if (item >= 0) { inven_item_increase(item, -1); inven_item_optimize(item); } /* Decrease the item (from the floor) */ else { floor_item_increase(0 - item, -1); floor_item_optimize(0 - item); } /* Get the wield slot */ o_ptr = &inventory[slot]; /* Take off existing item */ if (o_ptr->k_idx) { /* Take off existing item */ (void)inven_takeoff(slot, 255); } /* Wear the new stuff */ object_copy(o_ptr, i_ptr); /* Increase the weight */ p_ptr->total_weight += i_ptr->weight; /* Increment the equip counter by hand */ p_ptr->equip_cnt++; /* Where is the item now */ if (slot == INVEN_WIELD) { act = "You are wielding"; } else if (slot == INVEN_BOW) { act = "You are shooting with"; } else if (slot == INVEN_LIGHT) { act = "Your light source is"; } else { act = "You are wearing"; } /* Describe the result */ object_desc(o_name, o_ptr, TRUE, 3); /* Message */ msg_format("%s %s (%c).", act, o_name, index_to_label(slot)); /* Cursed! */ if (cursed_p(o_ptr)) { /* Warn the player */ msg_print("Oops! It feels deathly cold!"); /* Remove special inscription, if any */ if (o_ptr->discount >= INSCRIP_NULL) o_ptr->discount = 0; /* Sense the object if allowed */ if (o_ptr->discount == 0) o_ptr->discount = INSCRIP_CURSED; /* The object has been "sensed" */ o_ptr->ident |= (IDENT_SENSE); } /* Recalculate bonuses */ p_ptr->update |= (PU_BONUS); /* Recalculate torch */ p_ptr->update |= (PU_TORCH); /* Recalculate mana */ p_ptr->update |= (PU_MANA); /* Window stuff */ p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER_0 | PW_PLAYER_1); p_ptr->redraw |= (PR_EQUIPPY); }
/* * Creates a description of the item "o_ptr", and stores it in "out_val". * * One can choose the "verbosity" of the description, including whether * or not the "number" of items should be described, and how much detail * should be used when describing the item. * * The given "buf" must be 80 chars long to hold the longest possible * description, which can get pretty long, including incriptions, such as: * "no more Maces of Disruption (Defender) (+10,+10) [+5] (+3 to stealth)". * Note that the inscription will be clipped to keep the total description * under size - 1 chars (plus a terminator). * * Note the use of "object_desc_num()" and "object_desc_int()" as * hyper-efficient, portable, versions of some common "sprintf()" commands. * * Note that all ego-items (when known) append an "Ego-Item Name", unless * the item is also an artifact, which should NEVER happen. * * Note that all artifacts (when known) append an "Artifact Name", so we * have special processing for "Specials" (artifact Lites, Rings, Amulets). * The "Specials" never use "modifiers" if they are "known", since they * have special "descriptions", such as "The Necklace of the Dwarves". * * Special Lite's use the "k_info" base-name (Phial, Star, or Arkenstone), * plus the artifact name, just like any other artifact, if known. * * Special Ring's and Amulet's, if not "aware", use the same code as normal * rings and amulets, and if "aware", use the "k_info" base-name (Ring or * Amulet or Necklace). They will NEVER "append" the "k_info" name. But, * they will append the artifact name, just like any artifact, if known. * * None of the Special Rings/Amulets are "EASY_KNOW", though they could be, * at least, those which have no "pluses", such as the three artifact lites. * * Hack -- Display "The One Ring" as "a Plain Gold Ring" until aware. * * If "pref" then a "numeric" prefix will be pre-pended. * * Mode: * 0 -- The Cloak of Death * 1 -- The Cloak of Death [1,+3] * 2 -- The Cloak of Death [1,+3] (+2 to Stealth) * 3 -- The Cloak of Death [1,+3] (+2 to Stealth) {nifty} */ void object_desc(char *buf, const object_type *o_ptr, int pref, int mode, int max) { cptr basenm, modstr; int power; bool aware = FALSE; bool known = FALSE; bool append_name = FALSE; bool show_weapon = FALSE; bool show_armour = FALSE; cptr s; object_type *bow_ptr; /* damage dice, damage sides, damage bonus, energy */ int dd, ds, db, energy_use; int tmul; long avgdam; int len = 0; object_kind *k_ptr = &k_info[o_ptr->k_idx]; monster_race *r_ptr = &r_info[o_ptr->pval]; /* See if the object is "aware" */ if (object_aware_p(o_ptr)) aware = TRUE; /* See if the object is "known" */ if (object_known_p(o_ptr)) known = TRUE; /* Artifacts are not "aware' unless "known" */ if ((FLAG(o_ptr, TR_INSTA_ART)) && !known) aware = FALSE; /* Extract default "base" string */ basenm = get_object_name(o_ptr); /* Assume no "modifier" string */ modstr = ""; /* Empty description */ buf[0] = '\0'; /* Analyze the object */ switch (o_ptr->tval) { case TV_SKELETON: case TV_BOTTLE: case TV_JUNK: case TV_SPIKE: case TV_FLASK: case TV_CHEST: { /* Some objects are easy to describe */ break; } case TV_FIGURINE: case TV_STATUE: { /* Figurines/Statues */ cptr tmp = mon_race_name(r_ptr); char idol_name[512]; if (!FLAG(r_ptr, RF_UNIQUE)) { strnfmt(idol_name, 512, "%s%s", (is_a_vowel(*tmp) ? "an " : "a "), tmp); modstr = idol_name; } else { modstr = tmp; } break; } case TV_SHOT: case TV_BOLT: case TV_ARROW: case TV_BOW: case TV_HAFTED: case TV_POLEARM: case TV_SWORD: case TV_DIGGING: { /* Missiles/ Bows/ Weapons */ show_weapon = TRUE; break; } case TV_BOOTS: case TV_GLOVES: case TV_CLOAK: case TV_CROWN: case TV_HELM: case TV_SHIELD: case TV_SOFT_ARMOR: case TV_HARD_ARMOR: case TV_DRAG_ARMOR: { /* Armour */ show_armour = TRUE; break; } case TV_LITE: { /* Lites (including a few "Specials") */ break; } case TV_AMULET: { /* Amulets (including a few "Specials") */ /* Known artifacts */ if ((FLAG(k_ptr, TR_INSTA_ART)) && aware) break; /* Color the object */ modstr = amulet_adj[o_ptr->sval]; if (aware) append_name = TRUE; if (((plain_descriptions) && (aware)) || (o_ptr->info & OB_STOREB)) basenm = "& Amulet~"; else basenm = "& # Amulet~"; break; } case TV_RING: { /* Rings (including a few "Specials") */ /* Known artifacts */ if ((FLAG(k_ptr, TR_INSTA_ART)) && aware) break; /* Color the object */ modstr = ring_adj[o_ptr->sval]; if (aware) append_name = TRUE; if (((plain_descriptions) && (aware)) || (o_ptr->info & OB_STOREB)) basenm = "& Ring~"; else basenm = "& # Ring~"; /* Hack -- The One Ring */ if (!aware && (o_ptr->sval == SV_RING_POWER)) modstr = "Plain Gold"; break; } case TV_STAFF: { /* Color the object */ modstr = staff_adj[o_ptr->sval]; if (aware) append_name = TRUE; if (((plain_descriptions) && (aware)) || (o_ptr->info & OB_STOREB)) basenm = "& Staff~"; else basenm = "& # Staff~"; break; } case TV_WAND: { /* Color the object */ modstr = wand_adj[o_ptr->sval]; if (aware) append_name = TRUE; if (((plain_descriptions) && (aware)) || (o_ptr->info & OB_STOREB)) basenm = "& Wand~"; else basenm = "& # Wand~"; break; } case TV_ROD: { /* Color the object */ modstr = rod_adj[o_ptr->sval]; if (aware) append_name = TRUE; if (((plain_descriptions) && (aware)) || (o_ptr->info & OB_STOREB)) basenm = "& Rod~"; else basenm = "& # Rod~"; break; } case TV_SCROLL: { /* Color the object */ modstr = scroll_adj[o_ptr->sval]; if (aware) append_name = TRUE; if (((plain_descriptions) && (aware)) || (o_ptr->info & OB_STOREB)) basenm = "& Scroll~"; else basenm = "& Scroll~ titled \"#\""; break; } case TV_POTION: { /* Color the object */ modstr = potion_adj[o_ptr->sval]; if (aware) append_name = TRUE; if (((plain_descriptions) && (aware)) || (o_ptr->info & OB_STOREB)) basenm = "& Potion~"; else basenm = "& # Potion~"; break; } case TV_FOOD: { /* Ordinary food is "boring" */ if (o_ptr->sval >= SV_FOOD_MIN_FOOD) break; /* Color the object */ modstr = food_adj[o_ptr->sval]; if (aware) append_name = TRUE; if (((plain_descriptions) && (aware)) || (o_ptr->info & OB_STOREB)) basenm = "& Mushroom~"; else basenm = "& # Mushroom~"; break; } /*** Magic Books ***/ case TV_LIFE_BOOK: { modstr = basenm; if (mp_ptr->spell_book == TV_LIFE_BOOK) basenm = "& Book~ of Life Magic #"; else basenm = "& Life Spellbook~ #"; break; } case TV_SORCERY_BOOK: { modstr = basenm; if (mp_ptr->spell_book == TV_LIFE_BOOK) basenm = "& Book~ of Sorcery #"; else basenm = "& Sorcery Spellbook~ #"; break; } case TV_NATURE_BOOK: { modstr = basenm; if (mp_ptr->spell_book == TV_LIFE_BOOK) basenm = "& Book~ of Nature Magic #"; else basenm = "& Nature Spellbook~ #"; break; } case TV_CHAOS_BOOK: { modstr = basenm; if (mp_ptr->spell_book == TV_LIFE_BOOK) basenm = "& Book~ of Chaos Magic #"; else basenm = "& Chaos Spellbook~ #"; break; } case TV_DEATH_BOOK: { modstr = basenm; if (mp_ptr->spell_book == TV_LIFE_BOOK) basenm = "& Book~ of Death Magic #"; else basenm = "& Death Spellbook~ #"; break; } case TV_TRUMP_BOOK: { modstr = basenm; if (mp_ptr->spell_book == TV_LIFE_BOOK) basenm = "& Book~ of Trump Magic #"; else basenm = "& Trump Spellbook~ #"; break; } case TV_ARCANE_BOOK: { modstr = basenm; if (mp_ptr->spell_book == TV_LIFE_BOOK) basenm = "& Book~ of Arcane Magic #"; else basenm = "& Arcane Spellbook~ #"; break; } case TV_GOLD: { /* Hack -- Gold/Gems */ strcpy(buf, basenm); return; } default: { /* Used in the "inventory" routine */ strcpy(buf, "(nothing)"); return; } } /* The object "expects" a "number" */ if (basenm[0] == '&') { /* Skip the ampersand (and space) */ s = basenm + 2; /* No prefix */ if (!pref) { /* Nothing */ } /* Hack -- None left */ else if (o_ptr->number <= 0) { strnfcat(buf, max, &len, "no more "); } /* Extract the number */ else if (o_ptr->number > 1) { strnfcat(buf, max, &len, "%d ", o_ptr->number); } /* Hack -- The only one of its kind */ else if (known && (FLAG(o_ptr, TR_INSTA_ART))) { strnfcat(buf, max, &len, "The "); } /* A single one, with a vowel in the modifier */ else if ((*s == '#') && (is_a_vowel(modstr[0]))) { strnfcat(buf, max, &len, "an "); } /* A single one, with a vowel */ else if (is_a_vowel(*s)) { strnfcat(buf, max, &len, "an "); } /* A single one, without a vowel */ else { strnfcat(buf, max, &len, "a "); } } /* Hack -- objects that "never" take an article */ else { /* No ampersand */ s = basenm; /* No pref */ if (!pref) { /* Nothing */ } /* Hack -- all gone */ else if (o_ptr->number <= 0) { strnfcat(buf, max, &len, "no more "); } /* Prefix a number if required */ else if (o_ptr->number > 1) { strnfcat(buf, max, &len, "%d ", o_ptr->number); } /* Hack -- The only one of its kind */ else if (known && (FLAG(o_ptr, TR_INSTA_ART))) { strnfcat(buf, max, &len, "The "); } /* Hack -- single items get no prefix */ else { /* Nothing */ } } /* Copy the string */ while (*s) { /* Pluralizer */ if (*s == '~') { /* Add a plural if needed */ if (o_ptr->number != 1) { /* Get previous character */ char k = s[-1]; /* XXX XXX XXX Mega-Hack */ /* Hack -- "Cutlass-es" and "Torch-es" */ if ((k == 's') || (k == 'h')) { strnfcat(buf, max, &len, "es"); } else { /* Add an 's' */ strnfcat(buf, max, &len, "s"); } } } /* Modifier */ else if (*s == '#') { /* Insert the modifier */ strnfcat(buf, max, &len, "%s", modstr); } /* Normal */ else { /* Copy character */ strnfcat(buf, max, &len, "%c", *s); } s++; } /* Append the "kind name" to the "base name" */ if (append_name) { strnfcat(buf, max, &len, " of %s", get_object_name(o_ptr)); } /* Hack -- Append "Artifact" or "Special" names */ if (known) { if (o_ptr->inscription && strchr(quark_str(o_ptr->inscription), '#')) { /* Find the '#' */ cptr str = strchr(quark_str(o_ptr->inscription), '#'); /* Add the false name */ strnfcat(buf, max, &len, " %s" CLR_DEFAULT, &str[1]); } /* Is it a new artifact or ego item? */ else if (o_ptr->xtra_name) { strnfcat(buf, max, &len, " %s", quark_str(o_ptr->xtra_name)); } } /* No more details wanted */ if (mode < 1) return; /* Hack -- Chests must be described in detail */ if (o_ptr->tval == TV_CHEST) { /* Not searched yet */ if (!known) { /* Nothing */ } /* May be "empty" */ else if (!o_ptr->pval) { strnfcat(buf, max, &len, " (empty)"); } /* May be "disarmed" */ else if (o_ptr->pval < 0) { if (chest_traps[0 - o_ptr->pval]) { strnfcat(buf, max, &len, " (disarmed)"); } else { strnfcat(buf, max, &len, " (unlocked)"); } } /* Describe the traps, if any */ else { /* Describe the traps */ switch (chest_traps[o_ptr->pval]) { case 0: { strnfcat(buf, max, &len, " (Locked)"); break; } case CHEST_LOSE_STR: { strnfcat(buf, max, &len, " (Poison Needle)"); break; } case CHEST_LOSE_CON: { strnfcat(buf, max, &len, " (Poison Needle)"); break; } case CHEST_POISON: { strnfcat(buf, max, &len, " (Gas Trap)"); break; } case CHEST_PARALYZE: { strnfcat(buf, max, &len, " (Gas Trap)"); break; } case CHEST_EXPLODE: { strnfcat(buf, max, &len, " (Explosion Device)"); break; } case CHEST_SUMMON: { strnfcat(buf, max, &len, " (Summoning Runes)"); break; } default: { strnfcat(buf, max, &len, " (Multiple Traps)"); break; } } } } /* Display the item like a weapon */ if (FLAG(o_ptr, TR_SHOW_MODS)) show_weapon = TRUE; /* Display the item like a weapon */ if (o_ptr->to_h && o_ptr->to_d) show_weapon = TRUE; /* Display the item like armour */ if ((o_ptr->ac) && (o_ptr->tval != TV_WAND)) show_armour = TRUE; /* Dump base weapon info */ switch (o_ptr->tval) { case TV_SHOT: case TV_BOLT: case TV_ARROW: case TV_HAFTED: case TV_POLEARM: case TV_SWORD: case TV_DIGGING: { /* Missiles and Weapons */ /* Append a "damage" string */ strnfcat(buf, max, &len, " (%dd%d)", o_ptr->dd, o_ptr->ds); /* All done */ break; } case TV_BOW: { /* Bows get a special "damage string" */ /* Extract the "base power" */ switch (o_ptr->sval) { case SV_SLING: { power = 2; break; } case SV_SHORT_BOW: { power = 2; break; } case SV_LONG_BOW: { if (p_ptr->stat[A_STR].use >= 160) { power = 3; } else { /* hack- weak players cannot use a longbow well */ power = 2; } break; } case SV_LIGHT_XBOW: { power = 4; break; } case SV_HEAVY_XBOW: { power = 5; break; } default: { msgf("Unknown firing multiplier."); power = 0; } } /* Apply the "Extra Might" flag */ if (FLAG(o_ptr, TR_XTRA_MIGHT)) power++; /* Append a special "damage" string */ strnfcat(buf, max, &len, " (x%d)", power); /* All done */ break; } } /* Add the weapon bonuses */ if (known) { /* Show the tohit/todam on request */ if (show_weapon) { strnfcat(buf, max, &len, " (%+d,%+d%%)", o_ptr->to_h, deadliness_calc(o_ptr->to_d) - 100); } /* Show the tohit if needed */ else if (o_ptr->to_h) { strnfcat(buf, max, &len, " (%+d)", o_ptr->to_h); } /* Show the todam if needed */ else if (o_ptr->to_d) { strnfcat(buf, max, &len, " (%+d%%)", o_ptr->to_d * 5); } } bow_ptr = &p_ptr->equipment[EQUIP_BOW]; /* if have a firing weapon + ammo matches bow */ if (bow_ptr->k_idx && (p_ptr->ammo_tval == o_ptr->tval)) { /* See if the bow is "known" - then set damage bonus */ if (object_known_p(bow_ptr)) { db = bow_ptr->to_d; } else { db = 0; } /* effect of player */ db += p_ptr->dis_to_d; /* effect of ammo */ if (known) db += o_ptr->to_d; dd = o_ptr->dd; ds = o_ptr->ds; /* effect of damage dice x2 */ avgdam = avg_dam(db, dd, ds); /* Bow properties */ energy_use = p_ptr->bow_energy; tmul = p_ptr->ammo_mult; /* Get extra "power" from "extra might" */ if (FLAG(p_ptr, TR_XTRA_MIGHT)) tmul++; /* launcher multiplier */ avgdam *= tmul; /* display (shot damage/ avg damage) */ strnfcat(buf, max, &len, " (%d/", avgdam / 200); tmul = p_ptr->num_fire; if (tmul == 0) { strnfcat(buf, max, &len, "0)"); } else { /* calc effects of energy x2 */ avgdam *= (1 + p_ptr->num_fire); /* rescale */ avgdam /= 4 * energy_use; strnfcat(buf, max, &len, "%d)", avgdam); } } /* Add the armor bonuses */ if (known) { /* Show the armor class info */ if (show_armour) { strnfcat(buf, max, &len, " [%d,%+d]", o_ptr->ac, o_ptr->to_a); } /* No base armor, but does increase armor */ else if (o_ptr->to_a) { strnfcat(buf, max, &len, " [%+d]", o_ptr->to_a); } } /* Hack -- always show base armor */ else if (show_armour) { strnfcat(buf, max, &len, " [%d]", o_ptr->ac); } /* No more details wanted */ if (mode < 2) return; /* * Hack -- Wands and Staffs have charges. Make certain how many charges * a stack of staffs really has is clear. -LM- */ if (known && ((o_ptr->tval == TV_STAFF) || (o_ptr->tval == TV_WAND))) { /* Dump " (N charges)" */ strnfcat(buf, max, &len, " ("); /* Clear explaination for staffs. */ if ((o_ptr->tval == TV_STAFF) && (o_ptr->number > 1)) { strnfcat(buf, max, &len, "%dx ", o_ptr->number); } if (o_ptr->pval == 1) { strnfcat(buf, max, &len, "%d charge)", o_ptr->pval); } else { strnfcat(buf, max, &len, "%d charges)", o_ptr->pval); } } /* Hack -- Rods have a "charging" indicator. Now that stacks of rods may * be in any state of charge or discharge, this now includes a number. -LM- */ else if (o_ptr->tval == TV_ROD) { /* Hack -- Dump " (# charging)" if relevant */ if (o_ptr->timeout) { /* Stacks of rods display an exact count of charging rods. */ if (o_ptr->number > 1) { /* Paranoia. */ if (k_ptr->pval == 0) k_ptr->pval = 1; /* * Find out how many rods are charging, by dividing * current timeout by each rod's maximum timeout. * Ensure that any remainder is rounded up. Display * very discharged stacks as merely fully discharged. */ power = (o_ptr->timeout + (k_ptr->pval - 1)) / k_ptr->pval; if (power > o_ptr->number) power = o_ptr->number; /* Display prettily. */ strnfcat(buf, max, &len, " (%d charging)", power); } /* "one Rod of Perception (1 charging)" would look tacky. */ else { strnfcat(buf, max, &len, " (charging)"); } } } /* Hack -- Process Lanterns/Torches */ else if (o_ptr->tval == TV_LITE) { if (FLAG(o_ptr, TR_LITE)) { /* Hack - tell us when lites of everburning are "empty" */ if ((o_ptr->sval <= SV_LITE_LANTERN) && !o_ptr->timeout) { strnfcat(buf, max, &len, " (empty)"); } } else { /* Hack -- Turns of light for normal lites */ strnfcat(buf, max, &len, " (with %d turns of light)", o_ptr->timeout); } } /* Dump "pval" flags for wearable items */ if (known && (FLAG(o_ptr, TR_PVAL_MASK))) { /* Start the display */ strnfcat(buf, max, &len, " (%+d", o_ptr->pval); /* Do not display the "pval" flags */ if (FLAG(o_ptr, TR_HIDE_TYPE)) { /* Nothing */ } /* Speed */ else if (FLAG(o_ptr, TR_SPEED)) { /* Dump " to speed" */ strnfcat(buf, max, &len, " to speed"); } /* Attack speed */ else if (FLAG(o_ptr, TR_BLOWS)) { if (ABS(o_ptr->pval) == 1) { /* Add " attack" */ strnfcat(buf, max, &len, " attack"); } else { /* Add "attacks" */ strnfcat(buf, max, &len, " attacks"); } } /* Finish the display */ strnfcat(buf, max, &len, ")"); } /* Indicate charging objects, but not rods. */ if (known && o_ptr->timeout && (o_ptr->tval != TV_ROD) && (o_ptr->tval != TV_LITE)) { /* Hack -- Dump " (charging)" if relevant */ strnfcat(buf, max, &len, " (charging)"); } /* No more details wanted */ if (mode < 3) return; /* Use the standard inscription if available */ if (o_ptr->inscription) { cptr tmp = quark_str(o_ptr->inscription); /* Append the inscription */ strnfcat(buf, max, &len, " {"); /* Scan for the '#' character which marks a fake name. */ while(*tmp && (*tmp != '#')) { strnfcat(buf, max, &len, "%c", *tmp); tmp++; } /* Finish the inscription */ strnfcat(buf, max, &len, CLR_DEFAULT "}"); } /* Use the game-generated "feeling" otherwise, if available */ else if (o_ptr->feeling) { /* Append the inscription */ strnfcat(buf, max, &len, " {%s" CLR_DEFAULT "}", game_inscriptions[o_ptr->feeling]); } /* Note "cursed" if the item is known to be cursed */ else if (cursed_p(o_ptr) && (known || (o_ptr->info & (OB_SENSE)))) { /* Append the inscription */ strnfcat(buf, max, &len, " {cursed}"); } /* Mega-Hack -- note empty wands/staffs */ else if (!known && (o_ptr->info & (OB_EMPTY))) { /* Append the inscription */ strnfcat(buf, max, &len, " {empty}"); } /* Note "tried" if the object has been tested unsuccessfully */ else if (!aware && object_tried_p(o_ptr)) { /* Append the inscription */ strnfcat(buf, max, &len, " {tried}"); } /* Note the discount, if any */ else if (o_ptr->discount) { /* Append the inscription */ strnfcat(buf, max, &len, " {%d%% off}", o_ptr->discount); } }