/* function: mon_race_name */ static int toluaI_monst_mon_race_name00(lua_State* tolua_S) { if (!tolua_istype(tolua_S,1,tolua_tag(tolua_S,"monster_race"),0) || !tolua_isnoobj(tolua_S,2)) { TOLUA_ERR_FN(mon_race_name); } else { monster_race* r_ptr = ((monster_race*) tolua_getusertype(tolua_S,1,0)); cptr toluaI_ret = (cptr) mon_race_name(r_ptr); tolua_pushstring(tolua_S,(const char*)toluaI_ret); } return 1; }
/* * 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); } }