static void describe_flavor_text(textblock * tb, const object_type * o_ptr) { /* Display the known artifact description */ if (o_ptr->name1 && object_known_p(o_ptr) && a_info[o_ptr->name1].text) { textblock_append(tb, "%s\n\n", a_info[o_ptr->name1].text); } /* Display the known object description */ else if (object_aware_p(o_ptr) || object_known_p(o_ptr)) { bool did_desc = FALSE; if (k_info[o_ptr->k_idx].text) { textblock_append(tb, "%s", k_info[o_ptr->k_idx].text); did_desc = TRUE; } /* Display an additional ego-item description */ if (has_ego_properties(o_ptr) && e_info[o_ptr->name2].text) { if (did_desc) textblock_append(tb, " "); textblock_append(tb, "%s\n\n", e_info[o_ptr->name2].text); } else if (did_desc) { textblock_append(tb, "\n\n"); } } }
/* * Header for additional information when printing to screen. * * Header for additional information when printing to screen. */ static bool screen_out_head(const object_type *o_ptr) { char *o_name; int name_size = Term->wid; bool has_description = FALSE; /* Allocate memory to the size of the screen */ o_name = C_RNEW(name_size, char); /* Description */ object_desc(o_name, name_size, o_ptr, TRUE, 3); /* Print, in colour */ text_out_c(TERM_YELLOW, format("%^s", o_name)); /* Free up the memory */ FREE(o_name); /* Display the known artefact description */ if (!adult_rand_artefacts && o_ptr->name1 && object_known_p(o_ptr) && a_info[o_ptr->name1].text) { p_text_out("\n\n "); p_text_out(a_text + a_info[o_ptr->name1].text); has_description = TRUE; } /* Display the known object description */ else if (object_aware_p(o_ptr) || object_known_p(o_ptr)) { if (k_info[o_ptr->k_idx].text) { p_text_out("\n\n "); p_text_out(k_text + k_info[o_ptr->k_idx].text); has_description = TRUE; } /* Display an additional special item description */ if (o_ptr->name2 && object_known_p(o_ptr) && e_info[o_ptr->name2].text) { p_text_out("\n\n "); p_text_out(e_text + e_info[o_ptr->name2].text); has_description = TRUE; } } return (has_description); }
/* * Allow one item to "absorb" another, assuming they are similar */ void object_absorb(object_type *o_ptr, object_type *j_ptr) { s32b total = o_ptr->number + j_ptr->number; /* Add together the item counts */ o_ptr->number = ((total < MAX_STACK_SIZE) ? total : (MAX_STACK_SIZE - 1)); /* Probably move most or indeed all of this to ToME code instead of T-engine code */ /* Hack -- blend "known" status */ if (object_known_p(j_ptr)) object_known(o_ptr); /* Hack -- clear "storebought" if only one has it */ if (((o_ptr->ident & IDENT_STOREB) || (j_ptr->ident & IDENT_STOREB)) && (!((o_ptr->ident & IDENT_STOREB) && (j_ptr->ident & IDENT_STOREB)))) { if (j_ptr->ident & IDENT_STOREB) j_ptr->ident &= 0xEF; if (o_ptr->ident & IDENT_STOREB) o_ptr->ident &= 0xEF; } /* Hack -- blend "mental" status */ if (j_ptr->ident & (IDENT_MENTAL)) o_ptr->ident |= (IDENT_MENTAL); /* Hack -- blend "inscriptions" */ if (j_ptr->note) o_ptr->note = j_ptr->note; /* Hack -- could average discounts XXX XXX XXX */ /* Hack -- save largest discount XXX XXX XXX */ if (o_ptr->discount < j_ptr->discount) o_ptr->discount = j_ptr->discount; process_hooks(HOOK_OBJECT_ABSORB,"(O,O)",o_ptr,j_ptr); }
static bool describe_food(textblock * tb, const object_type * o_ptr, bool subjective, bool full) { /* Describe boring bits */ if ((o_ptr->tval == TV_FOOD || o_ptr->tval == TV_POTION) && o_ptr->pval) { /* Sometimes adjust for player speed */ int multiplier = extract_energy[p_ptr->state.pspeed]; if (!subjective) multiplier = 10; if (object_known_p(o_ptr) || full) { textblock_append(tb, "Nourishes for around "); textblock_append_c(tb, TERM_L_GREEN, "%d", (o_ptr->pval / 2) * multiplier / 10); textblock_append(tb, " turns.\n"); } else { textblock_append(tb, "Provides some nourishment.\n"); } return TRUE; } return FALSE; }
bool describe_set(textblock * tb, const object_type * o_ptr, oinfo_detail_t mode) { bool full = mode & OINFO_FULL; if (!full && !object_known_p(o_ptr)) return FALSE; if (!o_ptr->name1) return FALSE; else { artifact_type *a_ptr = &a_info[o_ptr->name1]; /* Is it a set item? */ if (a_ptr->set_no) { set_type *set_ptr = &set_info[a_ptr->set_no]; /* Description */ textblock_append(tb, "\n"); textblock_append_c(tb, TERM_BLUE, set_ptr->text); /* End sentence */ textblock_append_c(tb, TERM_BLUE, "."); } else return FALSE; } return TRUE; }
/** * Determines if an object is eligable for squelching. */ extern bool squelch_item_ok(const object_type * o_ptr) { size_t i; int num = -1; object_kind *k_ptr = &k_info[o_ptr->k_idx]; bool fullid = object_known_p(o_ptr); bool sensed = (o_ptr->ident & IDENT_SENSE) || fullid; byte feel = fullid ? value_check_aux1((object_type *) o_ptr) : o_ptr->feel; int quality_squelch = SQUELCH_NONE; /* Don't squelch artifacts */ if (artifact_p(o_ptr)) return FALSE; /* Don't squelch stuff inscribed not to be destroyed (!k) */ if (check_for_inscrip(o_ptr, "!k") || check_for_inscrip(o_ptr, "!*")) { return FALSE; } /* Auto-squelch dead chests */ if (o_ptr->tval == TV_CHEST && o_ptr->pval == 0) return TRUE; /* Do squelching by sval, if we 'know' the flavour. */ if (k_ptr->squelch && (k_ptr->flavor == 0 || k_ptr->aware)) { if (squelch_tval(k_info[o_ptr->k_idx].tval)) return TRUE; } /* Squelch some ego items if known */ if (has_ego_properties(o_ptr) && (e_info[o_ptr->name2].squelch)) { return TRUE; } /* Don't check pseudo-ID for nonsensed things */ if (!sensed) return FALSE; /* Find the appropriate squelch group */ for (i = 0; i < N_ELEMENTS(quality_choices); i++) { if (quality_choices[i].tval == o_ptr->tval) { num = i; break; } } /* Never squelched */ if (num == -1) return FALSE; /* Get result based on the feeling and the squelch_profile */ quality_squelch = feel_to_squelch_level(feel); if (quality_squelch == SQUELCH_NONE) return FALSE; else return squelch_profile[num][quality_squelch]; }
/* * 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); }
/** * Display the damage done with a multiplier */ static void output_dam(textblock * tb, player_state * state, const object_type * o_ptr, int mult, const char *against, bool * first, oinfo_detail_t mode) { int dam, die_average, add = 0, i, deadliness, crit, chance; bool full = mode & OINFO_FULL; /* Average damage for one standard side (x10) */ die_average = (10 * (o_ptr->ds + 1)) / 2; /* Multiply by slay or brand (x10) */ die_average *= mult; /* Record the addend */ if (mult > MULTIPLE_BASE) add = (mult - MULTIPLE_BASE); /* Multiply by deadliness (x100) */ deadliness = state->dis_to_d; if (if_has(o_ptr->id_other, IF_TO_D) || full) deadliness += o_ptr->to_d; if (deadliness > 150) deadliness = 150; if (deadliness < -150) deadliness = -150; if (deadliness >= 0) die_average *= (100 + deadliness_conversion[deadliness]); else { i = deadliness_conversion[ABS(deadliness)]; if (i >= 100) die_average = 0; else die_average *= (100 - i); } /* Factor in criticals (x 10) */ chance = state->skills[SKILL_TO_HIT_MELEE] + state->dis_to_h; if (object_known_p(o_ptr)) chance += o_ptr->to_h; chance = (100 * chance) / (chance + 240); if (player_has(PF_ARMSMAN)) chance = 100 - (83 * (100 - chance)) / 100; crit = 259 * chance; crit /= 1000; /* Multiply by number of sides */ dam = die_average * (o_ptr->dd * 10 + crit); CHECK_FIRST("", *first); if ((dam > 50000) || (add > 0)) textblock_append_c(tb, TERM_L_GREEN, "%d", add + dam / 100000); else textblock_append_c(tb, TERM_L_RED, "0"); textblock_append(tb, " against %s", against); }
/** * Describes item `o_ptr` into buffer `buf` of size `max`. * * ODESC_PREFIX prepends a 'the', 'a' or number * ODESC_BASE results in a base description. * ODESC_COMBAT will add to-hit, to-dam and AC info. * ODESC_EXTRA will add pval/charge/inscription/squelch info. * ODESC_PLURAL will pluralise regardless of the number in the stack. * ODESC_SPOIL treats the object as fully identified. * * Setting 'prefix' to TRUE prepends a 'the', 'a' or the number in the stack, * respectively. * * \returns The number of bytes used of the buffer. */ size_t object_desc(char *buf, size_t max, const object_type * o_ptr, odesc_detail_t mode) { object_kind *k_ptr = &k_info[o_ptr->k_idx]; bool prefix = mode & ODESC_PREFIX; bool spoil = (mode & ODESC_SPOIL); bool known = object_known_p(o_ptr) || spoil; size_t end = 0; /* We've seen it at least once now we're aware of it */ if (known && o_ptr->name2) e_info[o_ptr->name2].everseen = TRUE; /*** Some things get really simple descriptions ***/ if (o_ptr->tval == TV_GOLD) return strnfmt(buf, max, "%d gold pieces worth of %s", o_ptr->pval, k_ptr->name); else if (!o_ptr->tval) return strnfmt(buf, max, "(nothing)"); /** Construct the name **/ /* Copy the base name to the buffer */ end = obj_desc_name(buf, max, end, o_ptr, prefix, mode, spoil); if (mode & ODESC_COMBAT) { if (o_ptr->tval == TV_CHEST) end = obj_desc_chest(o_ptr, buf, max, end); else if (o_ptr->tval == TV_LIGHT) end = obj_desc_light(o_ptr, buf, max, end); end = obj_desc_combat(o_ptr, buf, max, end, spoil); } if (mode & ODESC_EXTRA) { if (spoil || (o_ptr->ident & IDENT_WORN)) end = obj_desc_pval(o_ptr, buf, max, end); end = obj_desc_charges(o_ptr, buf, max, end); end = obj_desc_inscrip(o_ptr, buf, max, end); } return end; }
/* * Hook to determine if an object is activatable */ static bool item_tester_hook_activate(const object_type *o_ptr) { u32b f1, f2, f3; /* Not known */ if (!object_known_p(o_ptr)) return (FALSE); /* Extract the flags */ object_flags(o_ptr, &f1, &f2, &f3); /* Check activation flag */ if (f3 & (TR3_ACTIVATE)) return (TRUE); /* Assume not */ return (FALSE); }
/* * Return the number of chests around (or under) the character. -TNB- * If requested, count only trapped chests. */ static int count_chests(int *y, int *x, bool trapped) { int d, count, o_idx; object_type *o_ptr; /* Count how many matches */ count = 0; /* Check around (and under) the character */ for (d = 0; d < 9; d++) { /* Extract adjacent (legal) location */ int yy = p_ptr->py + ddy_ddd[d]; int xx = p_ptr->px + ddx_ddd[d]; /* No (visible) chest is there */ if ((o_idx = chest_check(yy, xx)) == 0) continue; /* Grab the object */ o_ptr = &o_list[o_idx]; /* Already open */ if (o_ptr->pval == 0) continue; /* No (known) traps here */ if (trapped && (!object_known_p(o_ptr) || (o_ptr->pval < 0) || !chest_traps[o_ptr->pval])) continue; /* OK */ ++count; /* Remember the location of the last chest found */ *y = yy; *x = xx; } /* All done */ return count; }
static size_t obj_desc_inscrip(const object_type * o_ptr, char *buf, size_t max, size_t end) { const char *u[4] = { 0, 0, 0, 0 }; int n = 0; /* Get inscription */ if (o_ptr->note) u[n++] = quark_str(o_ptr->note); /* Use special inscription, if any */ if (o_ptr->feel) { u[n++] = feel_text[o_ptr->feel]; } else if ((o_ptr->ident & IDENT_EMPTY) && !object_known_p(o_ptr)) u[n++] = "empty"; else if (!object_aware_p(o_ptr) && object_tried_p(o_ptr)) u[n++] = "tried"; /* Use the discount, if any. No annoying inscription for homemade * branded items. */ if ((o_ptr->discount > 0) && (o_ptr->discount != 80)) u[n++] = format("%d%% off", o_ptr->discount); /* Note squelch */ if (squelch_item_ok(o_ptr)) u[n++] = "squelch"; if (n) { int i; for (i = 0; i < n; i++) { if (i == 0) strnfcat(buf, max, &end, " {"); strnfcat(buf, max, &end, "%s", u[i]); if (i < n - 1) strnfcat(buf, max, &end, ", "); } strnfcat(buf, max, &end, "}"); } return end; }
/* * Place an item description on the screen. */ void object_info_screen(const object_type *o_ptr) { bool has_description, has_info; /* Redirect output to the screen */ text_out_hook = text_out_to_screen; /* Save the screen */ screen_save(); has_description = screen_out_head(o_ptr); object_info_out_flags = object_flags_known; /* Dump the info */ new_paragraph = TRUE; has_info = object_info_out(o_ptr); new_paragraph = FALSE; if (!object_known_p(o_ptr)) { p_text_out("\n\n This item has not been identified."); } else if ((!has_description) && (!has_info)) { p_text_out("\n\n This item does not seem to possess any special abilities."); } text_out_c(TERM_L_BLUE, "\n\n(press any key)\n"); /* Wait for input */ (void)inkey(); /* Load the screen */ screen_load(); return; }
/* Preserve arts if needed */ void preserve_artifacts_in_inven(flags_type *inven) { if (p_ptr->preserve) { for_inventory_slot_ro(inven, o_ptr); { /* Hack -- Preserve unknown artifacts */ if (artifact_p(o_ptr) && !object_known_p(o_ptr)) { /* Mega-Hack -- Preserve the artifact */ if (has_flag(&k_info[o_ptr->k_idx], FLAG_NORM_ART)) { k_info[o_ptr->k_idx].artifact = FALSE; } else { a_info[o_ptr->artifact_id].cur_num = 0; } } } end_inventory(); } }
/* * Describe abilities granted by an object. */ static bool describe_abilities(const object_type *o_ptr) { cptr ability[8]; int ac = 0; ability_type *b_ptr; int i; // only describe when identified if (!object_known_p(o_ptr) && !(o_ptr->ident & (IDENT_SPOIL))) return (FALSE); // check its abilities for (i = 0; i < o_ptr->abilities; i++) { b_ptr = &b_info[ability_index(o_ptr->skilltype[i], o_ptr->abilitynum[i])]; ability[ac++] = b_name + b_ptr->name; } /* Describe */ if (ac) { /* Output intro */ if (ac == 1) p_text_out("It grants you the ability: "); else p_text_out("It grants you the abilities: "); /* Output list */ output_list(ability, ac); /* Output end (if needed) */ p_text_out(". "); /* It granted abilities */ return (TRUE); } /* No abilities granted */ return (FALSE); }
static size_t obj_desc_combat(const object_type *o_ptr, char *buf, size_t max, size_t end, bool spoil) { object_kind *k_ptr = &k_info[o_ptr->k_idx]; u32b f1, f2, f3, fn, knownf1, knownf2, knownf3, knownfn; object_flags(o_ptr, &f1, &f2, &f3, &fn); object_flags_known(o_ptr, &knownf1, &knownf2, &knownf3, &knownfn); /* Dump base weapon info */ switch (o_ptr->tval) { /* Weapons */ case TV_SHOT: case TV_BOLT: case TV_ARROW: case TV_HAFTED: case TV_POLEARM: case TV_SWORD: case TV_DIGGING: { /* Only display the real damage dice if the combat stats are known */ if ((spoil) || (object_known_p(o_ptr))) strnfcat(buf, max, &end, " (%dd%d)", o_ptr->dd, o_ptr->ds); else strnfcat(buf, max, &end, " (%dd%d)", k_ptr->dd, k_ptr->ds); break; } /* Missile launchers */ case TV_BOW: { /* Display shooting power as part of the multiplier */ if ((f1 & TR1_MIGHT) && (spoil || (knownf1 & TR1_MIGHT))) strnfcat(buf, max, &end, " (x%d)", (o_ptr->sval % 10) + o_ptr->pval); else strnfcat(buf, max, &end, " (x%d)", o_ptr->sval % 10); break; } } /* Show weapon bonuses */ if (spoil || object_known_p(o_ptr)) { if (obj_desc_show_weapon(o_ptr) || o_ptr->to_d || o_ptr->to_h) { /* Make an exception for body armor with only a to-hit penalty */ if (o_ptr->to_h < 0 && o_ptr->to_d == 0 && (o_ptr->tval == TV_SOFT_ARMOR || o_ptr->tval == TV_HARD_ARMOR || o_ptr->tval == TV_DRAG_ARMOR || o_ptr->tval == TV_DRAG_SHIELD)) strnfcat(buf, max, &end, " (%+d)", o_ptr->to_h); /* Otherwise, always use the full tuple */ else strnfcat(buf, max, &end, " (%+d,%+d)", o_ptr->to_h, o_ptr->to_d); } } /* Show armor bonuses */ if (spoil || object_known_p(o_ptr)) { if (obj_desc_show_armor(o_ptr)) strnfcat(buf, max, &end, " [%d,%+d]", o_ptr->ac, o_ptr->to_a); else if (o_ptr->to_a) strnfcat(buf, max, &end, " [%+d]", o_ptr->to_a); } else if (obj_desc_show_armor(o_ptr)) { strnfcat(buf, max, &end, " [%d]", o_ptr->ac); } return end; }
/* * 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); } }
/* * 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); } }
/* * 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 */ }
/** * Determines if an object is eligable for squelching. */ extern bool squelch_item_ok(const object_type * o_ptr) { size_t i; int num = -1; object_kind *k_ptr = &k_info[o_ptr->k_idx]; bool fullid = object_known_p(o_ptr); bool sensed = (o_ptr->ident & IDENT_SENSE) || fullid; byte feel = fullid ? value_check_aux1((object_type *) o_ptr) : o_ptr->feel; /* Don't squelch artifacts */ if (artifact_p(o_ptr)) return FALSE; /* Don't squelch stuff inscribed not to be destroyed (!k) */ if (check_for_inscrip(o_ptr, "!k") || check_for_inscrip(o_ptr, "!*")) { return FALSE; } /* Auto-squelch dead chests */ if (o_ptr->tval == TV_CHEST && o_ptr->pval == 0) return TRUE; /* Do squelching by sval, if we 'know' the flavour. */ if (k_ptr->squelch && (k_ptr->flavor == 0 || k_ptr->aware)) { if (squelch_tval(k_info[o_ptr->k_idx].tval)) return TRUE; } /* Squelch some ego items if known */ if (has_ego_properties(o_ptr) && (e_info[o_ptr->name2].squelch)) { return TRUE; } /* Don't check pseudo-ID for nonsensed things */ if (!sensed) return FALSE; /* Find the appropriate squelch group */ for (i = 0; i < N_ELEMENTS(quality_choices); i++) { if (quality_choices[i].enum_val == o_ptr->tval) { num = i; break; } } /* Never squelched */ if (num == -1) return FALSE; /* Get result based on the feeling and the squelch_level */ switch (squelch_level[num]) { case SQUELCH_CURSED: { if (o_ptr->ident & IDENT_CURSED) { return TRUE; } break; } case SQUELCH_DUBIOUS: { if ((feel == FEEL_DUBIOUS_WEAK) || (feel == FEEL_PERILOUS) || (feel == FEEL_DUBIOUS_STRONG)) { return TRUE; } break; } case SQUELCH_DUBIOUS_NON: { if (feel == FEEL_DUBIOUS_STRONG) { return TRUE; } break; } case SQUELCH_NON_EGO: { if ((feel == FEEL_DUBIOUS_STRONG) || (feel == FEEL_AVERAGE) || (feel == FEEL_GOOD_STRONG)) { return TRUE; } break; } case SQUELCH_AVERAGE: { if ((feel == FEEL_DUBIOUS_WEAK) || (feel == FEEL_PERILOUS) || (feel == FEEL_DUBIOUS_STRONG) || (feel == FEEL_AVERAGE)) { return TRUE; } break; } case SQUELCH_GOOD_STRONG: { if ((feel == FEEL_PERILOUS) || (feel == FEEL_DUBIOUS_STRONG) || (feel == FEEL_AVERAGE) || (feel == FEEL_GOOD_STRONG)) { return TRUE; } break; } case SQUELCH_GOOD_WEAK: { if ((feel == FEEL_PERILOUS) || (feel == FEEL_DUBIOUS_STRONG) || (feel == FEEL_AVERAGE) || (feel == FEEL_GOOD_WEAK) || (feel == FEEL_GOOD_STRONG)) { return TRUE; } break; } case SQUELCH_ALL: { return TRUE; break; } } /* Failure */ return FALSE; }
/* * Describe miscellaneous powers such as see invisible, free action, * permanent light, etc; also note curses and penalties. */ static bool describe_misc_magic(const object_type *o_ptr, u32b f2, u32b f3) { cptr good[7], bad[6]; int gc = 0, bc = 0; bool something = FALSE; /* Throwing weapons. */ if (f3 & (TR3_THROWING)) { good[gc++] = (format("can be thrown effectively (%d squares)",throwing_range(o_ptr))); } /* Collect stuff which can't be categorized */ if (((o_ptr->tval == TV_LIGHT) && artefact_p(o_ptr)) || ((o_ptr->tval != TV_LIGHT) && (f2 & (TR2_LIGHT)))) good[gc++] = "lights the dungeon around you"; if ((f2 & (TR2_LIGHT)) && (o_ptr->tval == TV_LIGHT)) good[gc++] = "burns brightly, increasing your light radius by an additional square"; if (f2 & (TR2_SLOW_DIGEST)) good[gc++] = "reduces your need for food"; if ((f2 & (TR2_RADIANCE)) && (o_ptr->tval == TV_BOW)) good[gc++] = "fires shining arrows"; if ((f2 & (TR2_RADIANCE)) && (o_ptr->tval == TV_BOOTS)) good[gc++] = "lights your path behind you"; if (f2 & (TR2_REGEN)) good[gc++] = "speeds your regeneration (which increases your hunger while active)"; /* Describe */ output_desc_list("It ", good, gc); /* Set "something" */ if (gc) something = TRUE; /* Collect granted powers */ gc = 0; if (f2 & (TR2_SPEED)) good[gc++] = "great speed"; if (f2 & (TR2_FREE_ACT)) good[gc++] = "freedom of movement"; if (f2 & (TR2_SEE_INVIS)) good[gc++] = "the ability to see invisible creatures"; /* Collect penalties */ if (f2 & (TR2_DANGER)) bad[bc++] = "makes you encounter more dangerous creatures (even when not worn)"; if (f2 & (TR2_FEAR)) bad[bc++] = "causes you to panic in combat"; if (f2 & (TR2_HUNGER)) bad[bc++] = "increases your hunger"; if (f2 & (TR2_DARKNESS)) bad[bc++] = "creates an unnatural darkness"; if (f2 & (TR2_SLOWNESS)) bad[bc++] = "slows your movement"; if (f2 & (TR2_AGGRAVATE)) bad[bc++] = "enrages nearby creatures"; if (f2 & (TR2_HAUNTED)) bad[bc++] = "draws wraiths to your level"; /* Deal with cursed stuff */ if (cursed_p(o_ptr)) { if (f3 & (TR3_PERMA_CURSE)) bad[bc++] = "is permanently cursed"; else if (f3 & (TR3_HEAVY_CURSE)) bad[bc++] = "is heavily cursed"; else if (object_known_p(o_ptr)) bad[bc++] = "is cursed"; } /* Describe */ if (gc) { /* Output intro */ p_text_out("It grants you "); /* Output list */ output_list(good, gc); /* Output end (if needed) */ if (!bc) p_text_out(". "); } if (bc) { /* Output intro */ if (gc) p_text_out(", but it also "); else p_text_out("It "); /* Output list */ output_list(bad, bc); /* Output end */ p_text_out(". "); } /* Set "something" */ if (gc || bc) something = TRUE; /* Return "something" */ return (something); }
/* * Attempt to disarm the chest at the given location * * Assume there is no monster blocking the destination * * Returns TRUE if repeated commands may continue */ static bool do_cmd_disarm_chest(int y, int x, s16b o_idx) { int i, j; bool more = FALSE; object_type *o_ptr = &o_list[o_idx]; /* Get the "disarm" factor */ i = p_ptr->skill_dis; /* Penalize some conditions */ if (p_ptr->blind || no_lite()) i = i / 10; if (p_ptr->confused || p_ptr->image) i = i / 10; /* Difficulty rating. */ j = i - (5 + o_ptr->pval / 2); /* Always have a small chance of success */ if (j < 2) j = 2; /* Must find the trap first. */ if (!object_known_p(o_ptr)) { msg_print("I don't see any traps."); } /* Already disarmed/unlocked */ else if (o_ptr->pval <= 0) { msg_print("The chest is not trapped."); } /* No traps to find. */ else if (!chest_traps[o_ptr->pval]) { msg_print("The chest is not trapped."); } /* Success (get a fair amount of experience) */ else if (randint0(100) < j) { msg_print("You have disarmed the chest."); gain_exp(o_ptr->pval * o_ptr->pval / 10); o_ptr->pval = (0 - o_ptr->pval); } /* Failure -- Keep trying */ else if ((i > 5) && (randint1(i) > 5)) { /* We may keep trying */ more = TRUE; if (flush_failure) flush(); msg_print("You failed to disarm the chest."); } /* Failure -- Set off the trap */ else { msg_print("You set off a trap!"); chest_trap(y, x, o_idx); } /* Result */ return (more); }
/* * Creates a description of the item "o_ptr", and stores it in "buf". * * The given "buf" should be at least 80 chars long to hold the longest * possible description, which can get pretty long, including inscriptions, * such as: * "no more Maces of Disruption (Defender) (+10,+10) [+5] (+3 to stealth)". * * Describes item `o_ptr` into buffer `buf` of size `max`. * * ODESC_PREFIX prepends a 'the', 'a' or number * ODESC_BASE results in a base description. * ODESC_COMBAT will add to-hit, to-dam and AC info. * ODESC_EXTRA will add pval/charge/inscription/squelch info. * ODESC_PLURAL will pluralise regardless of the number in the stack. * ODESC_STORE turns off squelch markers, for in-store display. * ODESC_SPOIL treats the object as fully identified. * * Setting 'prefix' to TRUE prepends a 'the', 'a' or the number in the stack, * respectively. * * \returns The number of bytes used of the buffer. */ size_t object_desc(char *buf, size_t max, const object_type *o_ptr, byte mode) { bool prefix = mode & ODESC_PREFIX; bool spoil = (mode & ODESC_SPOIL); size_t end = 0; bool aware; bool known; u32b f1, f2, f3, fn; object_kind *k_ptr = &k_info[o_ptr->k_idx]; /* Extract some flags */ object_flags(o_ptr, &f1, &f2, &f3, &fn); /* See if the object is "aware" */ aware = (object_aware_p(o_ptr) ? TRUE : FALSE); /* See if the object is "known" */ known = (object_known_p(o_ptr) ? TRUE : FALSE); /* Object is in the inventory of a store */ if (o_ptr->ident & IDENT_STORE) { /* Pretend known and aware */ aware = TRUE; known = TRUE; } /* Player has now seen the item * * This code must be exactly here to properly handle objects in * stores (fake assignment to "aware", see above) and unaware objects * in the dungeon. */ if (aware) k_ptr->everseen = TRUE; /* We've seen it at least once now we're aware of it */ if (known && o_ptr->ego_num) e_info[o_ptr->ego_num].everseen = TRUE; /*** Some things get really simple descriptions ***/ if (o_ptr->tval == TV_GOLD) { return strnfmt(buf, max, "%d gold pieces worth of %s", o_ptr->pval, k_name + k_ptr->name); } else if (!o_ptr->tval) { return strnfmt(buf, max, "(nothing)"); } /* Copy the base name to the buffer */ end = obj_desc_name(buf, max, end, o_ptr, prefix, mode, spoil); if (mode & ODESC_COMBAT) { if (o_ptr->tval == TV_CHEST) end = obj_desc_chest(o_ptr, buf, max, end); else if (o_ptr->tval == TV_LIGHT) end = obj_desc_light(o_ptr, buf, max, end); end = obj_desc_combat(o_ptr, buf, max, end, spoil); } if (mode & ODESC_EXTRA) { if (spoil || known) end = obj_desc_pval(o_ptr, buf, max, end); end = obj_desc_charges(o_ptr, buf, max, end); end = obj_desc_inscrip(o_ptr, buf, max, end); } return end; }
static size_t obj_desc_charges(const object_type *o_ptr, char *buf, size_t max, size_t end) { object_kind *k_ptr = &k_info[o_ptr->k_idx]; bool aware = object_flavor_is_aware(o_ptr) || (o_ptr->ident & IDENT_STORE); /* See if the object is "known" */ bool known = (object_known_p(o_ptr) ? TRUE : FALSE); /* Wands and Staffs have charges */ if (aware && known && (o_ptr->tval == TV_STAFF || o_ptr->tval == TV_WAND)) strnfcat(buf, max, &end, " (%d charge%s)", o_ptr->pval, PLURAL(o_ptr->pval)); /* Charging things */ else if (o_ptr->timeout > 0) { /* Hack -- Rods have a "charging" indicator */ if (known && (o_ptr->tval == TV_ROD)) { /* Hack -- Dump " (# charging)" if relevant */ if (o_ptr->timeout >= 1) { /* Stacks of rods display an exact count of charging rods. */ if (o_ptr->number > 1) { int power; /* 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, &end, " (%d charging)", power); } /* Display prettily */ else strnfcat(buf, max, &end, " (charging)"); } } /* Indicate "charging" objects, but not rods or lites */ if (known && o_ptr->timeout && o_ptr->tval != TV_ROD && !fuelable_lite_p(o_ptr)) { /* Hack -- Dump " (charging)" if relevant */ strnfcat(buf, max, &end, " (charging)"); } } return end; }
/* * Copy 'src' into 'buf, replacing '#' with 'modstr' (if found), putting a plural * in the place indicated by '~' if required, or using alterate... */ static size_t obj_desc_name(char *buf, size_t max, size_t end, const object_type * o_ptr, bool prefix, odesc_detail_t mode, bool spoil) { object_kind *k_ptr = &k_info[o_ptr->k_idx]; bool known = object_known_p(o_ptr) || spoil; bool aware = object_aware_p(o_ptr) || spoil; const char *basename = obj_desc_get_basename(o_ptr, aware); const char *modstr = obj_desc_get_modstr(o_ptr); bool pluralise = (mode & ODESC_PLURAL) ? TRUE : FALSE; if (aware && !k_ptr->everseen) k_ptr->everseen = TRUE; if (o_ptr->number > 1) pluralise = TRUE; if (mode & ODESC_SINGULAR) pluralise = FALSE; /* Add a pseudo-numerical prefix if desired */ if (prefix) { if (o_ptr->number <= 0) { strnfcat(buf, max, &end, "no more "); /* Pluralise for grammatical correctness */ pluralise = TRUE; } else if (o_ptr->number > 1) strnfcat(buf, max, &end, "%d ", o_ptr->number); else if ((known) && artifact_p(o_ptr)) strnfcat(buf, max, &end, "The "); else if (*basename == '&') { bool an = FALSE; const char *lookahead = basename + 1; while (*lookahead == ' ') lookahead++; if (*lookahead == '#') { if (modstr && is_a_vowel(*modstr)) an = TRUE; } else if (is_a_vowel(*lookahead)) { an = TRUE; } if (an) strnfcat(buf, max, &end, "an "); else strnfcat(buf, max, &end, "a "); } } /* * Names have the following elements: * * '~' indicates where to place an 's' or an 'es'. Other plural forms should * be handled with the syntax '|singular|plural|', e.g. "kni|fe|ves|". * * '#' indicates the position of the "modifier", e.g. the flavour or spellbook * name. */ /* Copy the string */ while (*basename) { if (*basename == '&') { while (*basename == ' ' || *basename == '&') basename++; continue; } /* Pluralizer (regular English plurals) */ else if (*basename == '~') { char prev = *(basename - 1); if (!pluralise) { basename++; continue; } /* e.g. cutlass-e-s, torch-e-s, box-e-s */ if (prev == 's' || prev == 'h' || prev == 'x') strnfcat(buf, max, &end, "es"); else strnfcat(buf, max, &end, "s"); } /* Special plurals */ else if (*basename == '|') { /* e.g. & Wooden T|o|e|rch~ ^ ^^ */ const char *singular = basename + 1; const char *plural = strchr(singular, '|'); const char *endmark = NULL; if (plural) { plural++; endmark = strchr(plural, '|'); } if (!singular || !plural || !endmark) return end; if (!pluralise) strnfcat(buf, max, &end, "%.*s", plural - singular - 1, singular); else strnfcat(buf, max, &end, "%.*s", endmark - plural, plural); basename = endmark; } /* Handle pluralisation in the modifier XXX */ else if (*basename == '#') { const char *basename = modstr; while (basename && *basename && (end < max - 1)) { /* Special plurals */ if (*basename == '|') { /* e.g. & Wooden T|o|e|rch~ ^ ^^ */ const char *singular = basename + 1; const char *plural = strchr(singular, '|'); const char *endmark = NULL; if (plural) { plural++; endmark = strchr(plural, '|'); } if (!singular || !plural || !endmark) return end; if (!pluralise) strnfcat(buf, max, &end, "%.*s", plural - singular - 1, singular); else strnfcat(buf, max, &end, "%.*s", endmark - plural, plural); basename = endmark; } else buf[end++] = *basename; basename++; } } else buf[end++] = *basename; basename++; } /* 0-terminate, just in case XXX */ buf[end] = 0; /** Append extra names of various kinds **/ if ((known) && o_ptr->name1) strnfcat(buf, max, &end, " %s", a_info[o_ptr->name1].name); else if ((spoil && o_ptr->name2) || has_ego_properties(o_ptr)) strnfcat(buf, max, &end, " %s", e_info[o_ptr->name2].name); else if (aware && !artifact_p(o_ptr) && (k_ptr->flavor || k_ptr->tval == TV_SCROLL) && ((k_ptr->tval != TV_FOOD) || (k_ptr->sval < SV_FOOD_MIN_FOOD))) strnfcat(buf, max, &end, " of %s", k_ptr->name); return end; }
static size_t obj_desc_chest(const object_type * o_ptr, char *buf, size_t max, size_t end) { bool known = object_known_p(o_ptr); if (o_ptr->tval != TV_CHEST) return end; if (!known) return end; /* May be "empty" */ if (!o_ptr->pval) strnfcat(buf, max, &end, " (empty)"); /* May be "disarmed" */ else if (o_ptr->pval < 0) { if (chest_traps[0 - o_ptr->pval]) strnfcat(buf, max, &end, " (disarmed)"); else strnfcat(buf, max, &end, " (unlocked)"); } /* Describe the traps, if any */ else { /* Describe the traps */ /* Describe the traps */ switch (chest_traps[o_ptr->pval]) { case 0: { strnfcat(buf, max, &end, " (Locked)"); break; } case CHEST_LOSE_STR: case CHEST_LOSE_CON: { strnfcat(buf, max, &end, " (Poison Needle)"); break; } case CHEST_POISON: case CHEST_PARALYZE: { strnfcat(buf, max, &end, " (Gas Trap)"); break; } case CHEST_SCATTER: { strnfcat(buf, max, &end, " (A Strange Rune)"); break; } case CHEST_EXPLODE: { strnfcat(buf, max, &end, " (Explosion Device)"); break; } case CHEST_SUMMON: case CHEST_E_SUMMON: case CHEST_H_SUMMON: case CHEST_BIRD_STORM: { strnfcat(buf, max, &end, " (Summoning Runes)"); break; } case CHEST_RUNES_OF_EVIL: { strnfcat(buf, max, &end, " (Gleaming Black Runes)"); break; } default: { strnfcat(buf, max, &end, " (Multiple Traps)"); break; } } } return end; }
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; }
/** * Carry an object and delete it. */ extern void py_pickup_aux(int o_idx, bool msg) { int slot, quiver_slot = 0; char o_name[120]; object_type *o_ptr = &o_list[o_idx]; object_type *i_ptr = &p_ptr->inventory[INVEN_LIGHT]; bitflag f[OF_SIZE], obvious_mask[OF_SIZE]; flags_init(obvious_mask, OF_SIZE, OF_OBVIOUS_MASK, FLAG_END); of_copy(f, o_ptr->flags_obj); /* Carry the object */ slot = inven_carry(p_ptr, o_ptr); /* Handle errors (paranoia) */ if (slot < 0) return; /* If we have picked up ammo which matches something in the quiver, note * that it so that we can wield it later (and suppress pick up message) */ if (obj_is_quiver_obj(o_ptr)) { int i; for (i = QUIVER_START; i < QUIVER_END; i++) { if (!p_ptr->inventory[i].k_idx) continue; if (!object_similar(&p_ptr->inventory[i], o_ptr, OSTACK_QUIVER)) continue; quiver_slot = i; break; } } /* Get the object again */ o_ptr = &p_ptr->inventory[slot]; /* Set squelch status */ p_ptr->notice |= PN_SQUELCH; /* Stone of Lore gives id on pickup */ if (!object_known_p(o_ptr)) { if (i_ptr->sval == SV_STONE_LORE) identify_object(o_ptr); /* Otherwise pseudo-ID */ else { bool heavy = FALSE; int feel; /* Heavy sensing */ heavy = (player_has(PF_PSEUDO_ID_HEAVY)); /* Type of feeling */ feel = (heavy ? value_check_aux1(o_ptr) : value_check_aux2(o_ptr)); /* We have "felt" it */ o_ptr->ident |= (IDENT_SENSE); /* Inscribe it textually */ o_ptr->feel = feel; /* Set squelch flag as appropriate */ p_ptr->notice |= PN_SQUELCH; } } /* Log artifacts if found */ if (artifact_p(o_ptr)) history_add_artifact(o_ptr->name1, object_is_known(o_ptr), TRUE); /* Notice dice and other obvious stuff */ notice_other(IF_DD_DS, slot + 1); (void) of_inter(f, obvious_mask); of_union(o_ptr->id_obj, f); /* Average things are average */ if ((o_ptr->feel == FEEL_AVERAGE) && (is_weapon(o_ptr) || is_armour(o_ptr))){ notice_other(IF_AC, slot + 1); notice_other(IF_TO_A, slot + 1); notice_other(IF_TO_H, slot + 1); notice_other(IF_TO_D, slot + 1); } /* Recalculate the bonuses */ p_ptr->update |= (PU_BONUS); /* Optionally, display a message */ if (msg && !quiver_slot) { /* Describe the object */ object_desc(o_name, sizeof(o_name), o_ptr, ODESC_PREFIX | ODESC_FULL); /* Message */ msg_format("You have %s (%c).", o_name, index_to_label(slot)); } /* Delete the object */ delete_object_idx(o_idx); /* If we have a quiver slot that this item matches, use it */ if (quiver_slot) wield_item(o_ptr, slot, quiver_slot); }
int context_menu_cave(int cy, int cx, int adjacent, int mx, int my) { menu_type *m; rect_region r; int selected; char *labels; cave_type *c_ptr = area(cx,cy); pcave_type *pc_ptr = parea(cx,cy); feature_type *feat; object_type *o_ptr; /* paranoia */ if (!in_boundsp(cx,cy)) return 0; m = menu_dynamic_new(); if (!m) { return 0; } labels = (char*)string_make(lower_case); m->selections = labels; feat = &(f_info[c_ptr->feat]); menu_dynamic_add_label(m, "Look At", 'l', 1, labels); if (c_ptr->m_idx) { menu_dynamic_add_label(m, "Recall Info", '/', 18, labels); } menu_dynamic_add_label(m, "Use Item On", 'u', 2, labels); if (player_can_cast()) { menu_dynamic_add_label(m, "Cast On", 'm', 3, labels); } if (adjacent) { if (c_ptr->m_idx && m_list[c_ptr->m_idx].ml) { menu_dynamic_add_label(m, "Attack", '+', 4, labels); } else { menu_dynamic_add_label(m, "Alter", '+', 4, labels); } if (c_ptr->o_idx) { o_ptr = chest_check(cx,cy); if (o_ptr && o_ptr->pval) { //if (!squelch_item_ok(o_ptr)) { if (object_known_p(o_ptr)) { if (chest_traps[o_ptr->pval]) { menu_dynamic_add_label(m, "Disarm Chest", 'D', 5, labels); menu_dynamic_add_label(m, "Open Chest", 'o', 8, labels); } else { menu_dynamic_add_label(m, "Open Disarmed Chest", 'o', 8, labels); } } else { menu_dynamic_add_label(m, "Open Chest", 'o', 8, labels); } //} } } if (is_visible_trap(c_ptr)) { menu_dynamic_add_label(m, "Disarm", 'D', 5, labels); menu_dynamic_add_label(m, "Jump Onto", 'W', 6, labels); } if (pc_ptr->feat) { if ((feat->flags & FF_CLOSEABLE) || ((feat->flags & FF_BROKEN) && (feat->flags & FF_DOOR))) { menu_dynamic_add_label(m, "Close", 'c', 7, labels); } if (feat->flags & FF_CLOSED) { menu_dynamic_add_label(m, "Open", 'o', 8, labels); menu_dynamic_add_label(m, "Bash Open", 'B', 9, labels); menu_dynamic_add_label(m, "Lock", 'D', 5, labels); menu_dynamic_add_label(m, "Jam", 'j', 10, labels); } if (feat->flags & FF_DIG) { menu_dynamic_add_label(m, "Tunnel", 'T', 11, labels); } } menu_dynamic_add_label(m, "Search", 's', 12, labels); menu_dynamic_add_label(m, "Walk Towards", ';', 14, labels); } else { menu_dynamic_add_label(m, "Pathfind To", ',', 13, labels); menu_dynamic_add_label(m, "Walk Towards", ';', 14, labels); menu_dynamic_add_label(m, "Run Towards", '.', 15, labels); } if (player_can_fire()) { menu_dynamic_add_label(m, "Fire On", 'f', 16, labels); } if (c_ptr->m_idx && m_list[c_ptr->m_idx].ml) { if (is_pet(&(m_list[c_ptr->m_idx]))) { menu_dynamic_add_label(m, "Pet Commands", 'p', 19, labels); } } menu_dynamic_add_label(m, "Throw To", 'v', 17, labels); /* work out display region */ r.width = menu_dynamic_longest_entry(m) + 3 + 2; /* +3 for tag, 2 for pad */ if (mx > Term->wid - r.width - 1) { r.col = Term->wid - r.width - 1; } else { r.col = mx + 1; } r.page_rows = m->count; if (my > Term->hgt - r.page_rows - 1) { if (my - r.page_rows - 1 <= 0) { /* menu has too many items, so put in upper right corner */ r.row = 1; r.col = Term->wid - r.width - 1; } else { r.row = Term->hgt - r.page_rows - 1; } } else { r.row = my + 1; } /* Hack -- no flush needed */ msg_flag = FALSE; screen_save(); button_backup_all(TRUE); /* if there is a monster, draw a target path, which will be erased by the * screen load below */ if (c_ptr->m_idx && m_list[c_ptr->m_idx].ml) { sint path_n; coord path_g[2*MAX_RANGE+1]; /* Find the path. */ path_n = project_path(path_g, p_ptr->px, p_ptr->py, cx, cy, PROJECT_THRU); /* Draw the path. */ draw_path(path_n, path_g, NULL, NULL, p_ptr->px, p_ptr->py); } menu_layout(m, &r); rect_region_erase_bordered(&r); /* display the prompt for the context menu */ target_look_grid_prompt(0, 0, cx, cy, format("($UEnter to select command$Y\n$V, $UESC$ to cancel$Y%c$V) You see", ESCAPE)); /* Hack - redraw stuff to show the target health bar */ health_redraw(); /* show the menu and pick from it */ selected = menu_dynamic_select(m); menu_dynamic_free(m); string_free(labels); button_restore(); screen_load(); if (selected == 1) { /* look at the spot */ if (target_set_interactive(TARGET_LOOK, cx, cy)) { msgf("Target Selected."); } } else if (selected == 2) { /* use an item on the spot */ p_ptr->cmd.dir = 5; p_ptr->cmd.cmd = 'u'; repeat_check(); do_cmd_use(); /*cmd_insert(CMD_USE_AIMED); cmd_set_arg_target(cmd_get_top(), 1, DIR_TARGET);*/ } else if (selected == 3) { /* cast a spell on the spot */ p_ptr->cmd.dir = 5; p_ptr->cmd.cmd = 'm'; repeat_check(); do_cmd_cast_wrapper(); /*if (textui_obj_cast_ret() >= 0) { cmd_set_arg_target(cmd_get_top(), 1, DIR_TARGET); }*/ } else if (selected == 4) { /* attack a spot adjacent to the player */ p_ptr->cmd.dir = coords_to_dir(cx, cy); p_ptr->cmd.arg = 16; p_ptr->cmd.cmd = '+'; repeat_check(); do_cmd_alter(); /*cmd_insert(CMD_ALTER); cmd_set_arg_direction(cmd_get_top(), 0, coords_to_dir(cy,cx));*/ } else if (selected == 5) { /* disarm an adjacent trap or chest */ p_ptr->cmd.dir = coords_to_dir(cx, cy); p_ptr->cmd.arg = 1; p_ptr->cmd.cmd = 'D'; repeat_check(); do_cmd_disarm(); /*cmd_insert(CMD_DISARM); cmd_set_arg_direction(cmd_get_top(), 0, coords_to_dir(cy,cx));*/ } else if (selected == 6) { /* walk onto an adjacent spot even if there is a trap there */ bool orig_disarm = easy_disarm; easy_disarm = always_pickup; p_ptr->cmd.dir = coords_to_dir(cx, cy); p_ptr->cmd.arg = 1; p_ptr->cmd.cmd = 'W'; repeat_check(); do_cmd_walk(always_pickup); easy_disarm = orig_disarm; /*cmd_insert(CMD_JUMP); cmd_set_arg_direction(cmd_get_top(), 0, coords_to_dir(cy,cx));*/ } else if (selected == 7) { /* close a door */ p_ptr->cmd.dir = coords_to_dir(cx, cy); /*p_ptr->cmd.arg = 1;*/ p_ptr->cmd.cmd = 'c'; repeat_check(); do_cmd_close(); /*cmd_insert(CMD_CLOSE); cmd_set_arg_direction(cmd_get_top(), 0, coords_to_dir(cy,cx));*/ } else if (selected == 8) { /* open a door or chest */ p_ptr->cmd.dir = coords_to_dir(cx, cy); /*p_ptr->cmd.arg = 1;*/ p_ptr->cmd.cmd = 'o'; repeat_check(); do_cmd_open(); /*cmd_insert(CMD_OPEN); cmd_set_arg_direction(cmd_get_top(), 0, coords_to_dir(cy,cx));*/ } else if (selected == 9) { /* bash a door */ p_ptr->cmd.dir = coords_to_dir(cx, cy); /*p_ptr->cmd.arg = 1;*/ p_ptr->cmd.cmd = 'o'; repeat_check(); do_cmd_open(); /*p_ptr->cmd.cmd = 'B'; do_cmd_bash();*/ /*cmd_insert(CMD_BASH); cmd_set_arg_direction(cmd_get_top(), 0, coords_to_dir(cy,cx));*/ } else if (selected == 10) { /* jam a door */ p_ptr->cmd.dir = coords_to_dir(cx, cy); /*p_ptr->cmd.arg = 1;*/ p_ptr->cmd.cmd = 'j'; repeat_check(); do_cmd_spike(); /*cmd_insert(CMD_JAM); cmd_set_arg_direction(cmd_get_top(), 0, coords_to_dir(cy,cx));*/ } else if (selected == 11) { /* Tunnel in a direction */ p_ptr->cmd.dir = coords_to_dir(cx, cy); p_ptr->cmd.arg = 16; p_ptr->cmd.cmd = 'T'; repeat_check(); do_cmd_tunnel(); /*cmd_insert(CMD_TUNNEL); cmd_set_arg_direction(cmd_get_top(), 0, coords_to_dir(cy,cx));*/ } else if (selected == 12) { /* Search */ /*p_ptr->cmd.arg = 1;*/ p_ptr->cmd.cmd = 's'; repeat_check(); do_cmd_search(); /*cmd_insert(CMD_SEARCH);*/ } else if (selected == 13) { /* pathfind to the spot */ /*p_ptr->cmd.arg = 16;*/ p_ptr->cmd.cmd = ','; do_cmd_pathfind(cx,cy); /*cmd_insert(CMD_PATHFIND); cmd_set_arg_point(cmd_get_top(), 0, cx, cy);*/ } else if (selected == 14) { /* walk towards the spot */ p_ptr->cmd.dir = coords_to_dir(cx, cy); p_ptr->cmd.cmd = ';'; repeat_check(); do_cmd_walk(always_pickup); /*cmd_insert(CMD_WALK); cmd_set_arg_direction(cmd_get_top(), 0, coords_to_dir(cy,cx));*/ } else if (selected == 15) { /* run towards the spot */ p_ptr->cmd.dir = coords_to_dir(cx, cy); p_ptr->cmd.cmd = '.'; repeat_check(); do_cmd_run(); /*cmd_insert(CMD_RUN); cmd_set_arg_direction(cmd_get_top(), 0, coords_to_dir(cy,cx));*/ } else if (selected == 16) { /* Fire ammo towards the spot */ p_ptr->cmd.dir = 5; p_ptr->cmd.cmd = 'f'; repeat_check(); do_cmd_fire(); /*cmd_insert(CMD_FIRE); cmd_set_arg_target(cmd_get_top(), 1, DIR_TARGET);*/ } else if (selected == 17) { /* throw an item towards the spot */ p_ptr->cmd.dir = 5; p_ptr->cmd.cmd = 'v'; repeat_check(); do_cmd_throw(); /*cmd_insert(CMD_THROW); cmd_set_arg_target(cmd_get_top(), 1, DIR_TARGET);*/ } else if (selected == 18) { /* recall monster Info */ monster_type *m_ptr = &m_list[c_ptr->m_idx]; if (m_ptr) { /* Save screen */ screen_save(); button_backup_all(TRUE); /* Recall on screen */ screen_roff_mon(m_ptr->r_idx, 0); /* wait for a key or mouse press */ inkey(); /* Load screen */ button_restore(); screen_load(); } } else if (selected == 19) { /* issue a pet command */ p_ptr->cmd.cmd = 'p'; repeat_check(); do_cmd_pet(); } return 1; }
/** * Search for hidden things */ bool search(bool verbose) { int py = p_ptr->py; int px = p_ptr->px; int y, x, chance; bool found = FALSE; object_type *o_ptr; /* Start with base search ability */ chance = p_ptr->state.skills[SKILL_SEARCH]; /* Penalize various conditions */ if (p_ptr->timed[TMD_BLIND] || no_light()) chance = chance / 10; if (p_ptr->timed[TMD_CONFUSED] || p_ptr->timed[TMD_IMAGE]) chance = chance / 10; /* Prevent fruitless searches */ if (chance <= 0) { if (verbose) { msg_print("You can't make out your surroundings well enough to search."); /* Cancel repeat */ disturb(0, 0); } return FALSE; } /* Search the nearby grids, which are always in bounds */ for (y = (py - 1); y <= (py + 1); y++) { for (x = (px - 1); x <= (px + 1); x++) { feature_type *f_ptr = &f_info[cave_feat[y][x]]; /* Sometimes, notice things */ if (randint0(100) < chance) { /* Invisible trap */ if (tf_has(f_ptr->flags, TF_TRAP_INVIS)) { found = TRUE; /* Pick a trap */ pick_trap(y, x); /* Message */ msg_print("You have found a trap."); /* Disturb */ disturb(0, 0); } /* Secret door */ if (cave_feat[y][x] == FEAT_SECRET) { found = TRUE; /* Message */ msg_print("You have found a secret door."); /* Pick a door */ place_closed_door(y, x); /* Disturb */ disturb(0, 0); } /* Scan all objects in the grid */ for (o_ptr = get_first_object(y, x); o_ptr; o_ptr = get_next_object(o_ptr)) { /* Skip non-chests */ if (o_ptr->tval != TV_CHEST) continue; /* Skip disarmed chests */ if (o_ptr->pval <= 0) continue; /* Skip non-trapped chests */ if (!chest_traps[o_ptr->pval]) continue; /* Identify once */ if (!object_known_p(o_ptr)) { found = TRUE; /* Message */ msg_print("You have discovered a trap on the chest!"); /* Know the trap */ object_known(o_ptr); /* Notice it */ disturb(0, 0); } } } } } if (verbose && !found) { if (chance >= 100) msg_print("There are no secrets here."); else msg_print("You found nothing."); } return TRUE; }