Skip to content

Commit 6e244a3

Browse files
committed
Object lookup now reports rarity, materials, and more.
Follow-up to the monster lookup expansion: the encyclopedia's add_obj_info() omitted generation frequency, the randomized-materials system, several weapon facts, and any class line for six object classes. All additions are display-only: * src/pager.c: - Generation frequency: "Makes up N.N% of randomly generated <class>." after the cost/weight line, or "Not randomly generated." when oc_prob is 0. Percentages are computed the same way mkobj() rolls them - oc_prob is a relative weight summed over the class from bases[], not a fixed per-mille (rings all carry weight 1), so the display normalizes by the real class total. Only printed for classes in mkobj's random mixture; venom/rock/ball/chain/coin would mislead (venom only comes from monster spit). - Weapon facts: launchers state what they fire (bow -> arrows, crossbow -> bolts, sling -> bullets/stones/gems); "Can be coated with poison." and "Normally generated in stacks." mirror the is_poisonable and is_multigen macros exactly. - Material alternates: after "Normally made of X.", list the other materials the type can randomly generate as, by probing valid_obj_material() with a zeroobj-based dummy. The inline wood/vegetable-matter noun fixups are factored into a new material_noun() helper shared by both lines. - Class lines for amulets, coins, boulders/statues, iron balls, chains, and venom, matching the existing "Potion."/"Scroll." pattern; removes the stale comment noting amulets had none.
1 parent 9e211c6 commit 6e244a3

2 files changed

Lines changed: 99 additions & 18 deletions

File tree

‎doc/evilhack-changelog.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5556,4 +5556,5 @@ The following changes to date are:
55565556
- Fix: monsters could waste casts on learned charm monster
55575557
- Fix: pets avoided passive attackers they were protected against
55585558
- Monster lookup now reports many more species attributes
5559+
- Object lookup now reports rarity, materials, and more
55595560

‎src/pager.c‎

Lines changed: 98 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ STATIC_DCL struct permonst *FDECL(lookat, (int, int, char *, char *));
2020
STATIC_DCL char *FDECL(hallucinatory_armor, (char *));
2121
STATIC_DCL void FDECL(add_mon_info, (winid, struct permonst *));
2222
STATIC_DCL void FDECL(add_obj_info, (winid, SHORT_P));
23+
STATIC_DCL const char *FDECL(material_noun, (int));
2324
STATIC_DCL void FDECL(add_arti_info, (winid, int));
2425
STATIC_DCL const char *FDECL(arti_adtyp_str, (int, BOOLEAN_P));
2526
STATIC_DCL const char *FDECL(arti_invprop_str, (int));
@@ -1302,6 +1303,18 @@ extern const struct propname {
13021303
const char* prop_name;
13031304
} propertynames[]; /* located in timeout.c */
13041305

1306+
/* materialnm[] uses adjectival forms; two entries differ as nouns */
1307+
STATIC_OVL const char *
1308+
material_noun(mat)
1309+
int mat;
1310+
{
1311+
if (mat == WOOD)
1312+
return "wood";
1313+
if (mat == VEGGY)
1314+
return "vegetable matter";
1315+
return materialnm[mat];
1316+
}
1317+
13051318
/* Add some information to an encyclopedia window which is printing information
13061319
* about an object. */
13071320
STATIC_OVL void
@@ -1325,6 +1338,8 @@ short otyp;
13251338
boolean has_precipes;
13261339
const struct trap_recipe *trecipe;
13271340
boolean has_trecipes;
1341+
struct obj dummy;
1342+
int mat, j, totprob, pmil;
13281343

13291344
#define OBJPUTSTR(str) putstr(datawin, ATR_NONE, str)
13301345
#define ADDCLASSPROP(cond, str) \
@@ -1337,7 +1352,6 @@ short otyp;
13371352
putstr(datawin, ATR_BOLD, buf);
13381353
OBJPUTSTR("");
13391354

1340-
/* Object classes currently with no special messages here: amulets. */
13411355
if (olet == WEAPON_CLASS || weptool || gemammo) {
13421356
const int skill = oc.oc_skill;
13431357
const char* dmgtyp = "blunt";
@@ -1449,6 +1463,20 @@ short otyp;
14491463
Sprintf(buf, "Has a %s%d %s to hit.", (oc.oc_hitbon >= 0 ? "+" : ""),
14501464
oc.oc_hitbon, (oc.oc_hitbon >= 0 ? "bonus" : "penalty"));
14511465
OBJPUTSTR(buf);
1466+
if (skill >= P_BOW && skill <= P_CROSSBOW) {
1467+
Sprintf(buf, "Fires %s.",
1468+
(skill == P_BOW) ? "arrows"
1469+
: (skill == P_CROSSBOW) ? "crossbow bolts"
1470+
: "sling bullets, stones, and gems");
1471+
OBJPUTSTR(buf);
1472+
}
1473+
if (olet == WEAPON_CLASS
1474+
&& !(skill >= P_BOW && skill <= P_CROSSBOW)
1475+
&& oc.oc_dir != WHACK)
1476+
OBJPUTSTR("Can be coated with poison.");
1477+
if (olet == WEAPON_CLASS
1478+
&& skill >= -P_SHURIKEN && skill <= -P_BOW)
1479+
OBJPUTSTR("Normally generated in stacks.");
14521480
}
14531481
if (olet == ARMOR_CLASS) {
14541482
/* Indexes here correspond to ARM_SHIELD, etc; not the W_* masks.
@@ -1606,11 +1634,61 @@ short otyp;
16061634
buf[0] -= ('a' - 'A');
16071635
OBJPUTSTR(buf);
16081636
}
1637+
if (olet == AMULET_CLASS) {
1638+
OBJPUTSTR("Amulet.");
1639+
}
1640+
if (olet == COIN_CLASS) {
1641+
OBJPUTSTR("Coin.");
1642+
}
1643+
if (olet == ROCK_CLASS) {
1644+
OBJPUTSTR(otyp == STATUE ? "Statue." : "Boulder.");
1645+
}
1646+
if (olet == BALL_CLASS) {
1647+
OBJPUTSTR("Heavy iron ball.");
1648+
}
1649+
if (olet == CHAIN_CLASS) {
1650+
OBJPUTSTR("Chain.");
1651+
}
1652+
if (olet == VENOM_CLASS) {
1653+
OBJPUTSTR("Venom.");
1654+
}
16091655

16101656
/* cost, wt should go next */
16111657
Sprintf(buf, "Base cost %d, weighs %d aum.", oc.oc_cost, oc.oc_weight);
16121658
OBJPUTSTR(buf);
16131659

1660+
/* generation frequency, only for the object classes that are part
1661+
of mkobj's random mixture */
1662+
if (olet == WEAPON_CLASS || olet == ARMOR_CLASS || olet == RING_CLASS
1663+
|| olet == AMULET_CLASS || olet == TOOL_CLASS || olet == FOOD_CLASS
1664+
|| olet == POTION_CLASS || olet == SCROLL_CLASS
1665+
|| olet == SPBOOK_CLASS || olet == WAND_CLASS
1666+
|| olet == GEM_CLASS) {
1667+
if (!oc.oc_prob) {
1668+
OBJPUTSTR("Not randomly generated.");
1669+
} else {
1670+
/* oc_prob values are relative weights, normalized over the
1671+
class total at selection time (see mkobj); not every
1672+
class sums its weights to 1000 */
1673+
totprob = 0;
1674+
for (j = bases[(int) olet];
1675+
j < NUM_OBJECTS && objects[j].oc_class == olet; j++)
1676+
totprob += objects[j].oc_prob;
1677+
pmil = (oc.oc_prob * 1000 + totprob / 2) / totprob;
1678+
if (pmil == 0)
1679+
Sprintf(buf, "Makes up less than 0.1%% of randomly"
1680+
" generated %s.",
1681+
(olet == GEM_CLASS) ? "gems and stones"
1682+
: def_oc_syms[(int) olet].name);
1683+
else
1684+
Sprintf(buf, "Makes up %d.%d%% of randomly generated %s.",
1685+
pmil / 10, pmil % 10,
1686+
(olet == GEM_CLASS) ? "gems and stones"
1687+
: def_oc_syms[(int) olet].name);
1688+
OBJPUTSTR(buf);
1689+
}
1690+
}
1691+
16141692
/* Scrolls or spellbooks: ink cost */
16151693
if (olet == SCROLL_CLASS || olet == SPBOOK_CLASS) {
16161694
if (otyp == SCR_BLANK_PAPER || otyp == SPE_BLANK_PAPER) {
@@ -1706,24 +1784,26 @@ short otyp;
17061784
* Object classes where this may matter: rings, wands. All randomized tools
17071785
* share materials, and all scrolls and potions are the same material. */
17081786
if (!(olet == RING_CLASS || olet == WAND_CLASS) || oc.oc_name_known) {
1709-
/* char array converting materials to strings; if this is ever needed
1710-
* anywhere else it should be externified. Corresponds exactly to the
1711-
* materials defined in objclass.h.
1712-
* This is very similar to materialnm[], but the slight difference is
1713-
* that this is always the noun form whereas materialnm uses adjective
1714-
* forms; most materials have the same noun and adjective forms but two
1715-
* (wood/wooden, vegetable matter/organic) don't */
1716-
const char* mat_str = materialnm[oc.oc_material];
1717-
/* Two exceptions to materialnm, which uses adjectival forms: most of
1718-
* these work fine as nouns but two don't. */
1719-
if (oc.oc_material == WOOD) {
1720-
mat_str = "wood";
1721-
} else if (oc.oc_material == VEGGY) {
1722-
mat_str = "vegetable matter";
1723-
}
1724-
1725-
Sprintf(buf, "Normally made of %s.", mat_str);
1787+
Sprintf(buf, "Normally made of %s.", material_noun(oc.oc_material));
17261788
OBJPUTSTR(buf);
1789+
1790+
/* other materials this object type can randomly generate as;
1791+
the dummy stands in for a generic non-artifact instance */
1792+
dummy = zeroobj;
1793+
dummy.otyp = otyp;
1794+
dummy.oclass = olet;
1795+
buf[0] = '\0';
1796+
for (mat = 1; mat < NUM_MATERIAL_TYPES; mat++) {
1797+
if (mat == (int) oc.oc_material)
1798+
continue;
1799+
if (valid_obj_material(&dummy, mat)) {
1800+
ADDCLASSPROP(TRUE, material_noun(mat));
1801+
}
1802+
}
1803+
if (*buf) {
1804+
Sprintf(buf2, "Can also be made of %s.", buf);
1805+
OBJPUTSTR(buf2);
1806+
}
17271807
}
17281808

17291809
/* TODO: prevent obj lookup from displaying with monster database entry

0 commit comments

Comments
 (0)