From: kmhugo Date: Sat, 2 Feb 2002 19:21:33 +0000 (+0000) Subject: Artifact prices X-Git-Tag: MOVE2GIT~3287 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=532242f07f6d9e625567028c83c302da2aa1b045;p=nethack Artifact prices Each artifact has its own individual price, rather than being solely based on the cost of its base item. --- diff --git a/include/artifact.h b/include/artifact.h index c97a71d5e..21296686e 100644 --- a/include/artifact.h +++ b/include/artifact.h @@ -47,6 +47,7 @@ struct artifact { aligntyp alignment; /* alignment of bequeathing gods */ short role; /* character role associated with */ short race; /* character race associated with */ + long cost; /* price when sold to hero (default 100 x base cost) */ }; /* invoked properties with special powers */ diff --git a/include/artilist.h b/include/artilist.h index 27a1bc3f7..ce58f24db 100644 --- a/include/artilist.h +++ b/include/artilist.h @@ -5,14 +5,14 @@ #ifdef MAKEDEFS_C /* in makedefs.c, all we care about is the list of names */ -#define A(nam,typ,s1,s2,mt,atk,dfn,cry,inv,al,cl,rac) nam +#define A(nam,typ,s1,s2,mt,atk,dfn,cry,inv,al,cl,rac,cost) nam static const char *artifact_names[] = { #else /* in artifact.c, set up the actual artifact list structure */ -#define A(nam,typ,s1,s2,mt,atk,dfn,cry,inv,al,cl, rac) \ - { typ, nam, s1, s2, mt, atk, dfn, cry, inv, al, cl, rac } +#define A(nam,typ,s1,s2,mt,atk,dfn,cry,inv,al,cl,rac,cost) \ + { typ, nam, s1, s2, mt, atk, dfn, cry, inv, al, cl, rac, cost } #define NO_ATTK {0,0,0,0} /* no attack */ #define NO_DFNS {0,0,0,0} /* no defense */ @@ -29,41 +29,48 @@ static const char *artifact_names[] = { STATIC_OVL NEARDATA struct artifact artilist[] = { #endif /* MAKEDEFS_C */ +/* Artifact cost rationale: + * 1. The more useful the artifact, the better its cost. + * 2. Quest artifacts are highly valued. + * 3. Chaotic artifacts are inflated due to scarcity (and balance). + */ + + /* dummy element #0, so that all interesting indices are non-zero */ A("", STRANGE_OBJECT, - 0, 0, 0, NO_ATTK, NO_DFNS, NO_CARY, 0, A_NONE, NON_PM, NON_PM ), + 0, 0, 0, NO_ATTK, NO_DFNS, NO_CARY, 0, A_NONE, NON_PM, NON_PM, 0L ), A("Excalibur", LONG_SWORD, (SPFX_NOGEN|SPFX_RESTR|SPFX_SEEK|SPFX_DEFN|SPFX_INTEL|SPFX_SEARCH),0,0, - PHYS(5,10), DRLI(0,0), NO_CARY, 0, A_LAWFUL, PM_KNIGHT, NON_PM ), + PHYS(5,10), DRLI(0,0), NO_CARY, 0, A_LAWFUL, PM_KNIGHT, NON_PM, 4000L ), /* * Stormbringer only has a 2 because it can drain a level, * providing 8 more. */ A("Stormbringer", RUNESWORD, (SPFX_RESTR|SPFX_ATTK|SPFX_DEFN|SPFX_INTEL|SPFX_DRLI), 0, 0, - DRLI(5,2), DRLI(0,0), NO_CARY, 0, A_CHAOTIC, NON_PM, NON_PM ), + DRLI(5,2), DRLI(0,0), NO_CARY, 0, A_CHAOTIC, NON_PM, NON_PM, 8000L ), /* * Mjollnir will return to the hand of the wielder when thrown * if the wielder is a Valkyrie wearing Gauntlets of Power. */ A("Mjollnir", WAR_HAMMER, /* Mjo:llnir */ (SPFX_RESTR|SPFX_ATTK), 0, 0, - ELEC(5,24), NO_DFNS, NO_CARY, 0, A_NEUTRAL, PM_VALKYRIE, NON_PM ), + ELEC(5,24), NO_DFNS, NO_CARY, 0, A_NEUTRAL, PM_VALKYRIE, NON_PM, 4000L ), A("Cleaver", BATTLE_AXE, SPFX_RESTR, 0, 0, - PHYS(3,6), NO_DFNS, NO_CARY, 0, A_NEUTRAL, PM_BARBARIAN, NON_PM ), + PHYS(3,6), NO_DFNS, NO_CARY, 0, A_NEUTRAL, PM_BARBARIAN, NON_PM, 1500L ), A("Grimtooth", ORCISH_DAGGER, SPFX_RESTR, 0, 0, - PHYS(2,6), NO_DFNS, NO_CARY, 0, A_CHAOTIC, NON_PM, PM_ORC ), + PHYS(2,6), NO_DFNS, NO_CARY, 0, A_CHAOTIC, NON_PM, PM_ORC, 300L ), /* * Orcrist and Sting have same alignment as elves. */ A("Orcrist", ELVEN_BROADSWORD, SPFX_DFLAG2, 0, M2_ORC, - PHYS(5,0), NO_DFNS, NO_CARY, 0, A_CHAOTIC, NON_PM, PM_ELF ), + PHYS(5,0), NO_DFNS, NO_CARY, 0, A_CHAOTIC, NON_PM, PM_ELF, 2000L ), /* * The combination of SPFX_WARN and M2_something on an artifact @@ -73,50 +80,50 @@ A("Orcrist", ELVEN_BROADSWORD, */ A("Sting", ELVEN_DAGGER, (SPFX_WARN|SPFX_DFLAG2), 0, M2_ORC, - PHYS(5,0), NO_DFNS, NO_CARY, 0, A_CHAOTIC, NON_PM, PM_ELF ), + PHYS(5,0), NO_DFNS, NO_CARY, 0, A_CHAOTIC, NON_PM, PM_ELF, 800L ), /* * Magicbane is a bit different! Its magic fanfare * unbalances victims in addition to doing some damage. */ A("Magicbane", ATHAME, (SPFX_RESTR|SPFX_ATTK|SPFX_DEFN), 0, 0, - STUN(3,4), DFNS(AD_MAGM), NO_CARY, 0, A_NEUTRAL, PM_WIZARD, NON_PM ), + STUN(3,4), DFNS(AD_MAGM), NO_CARY, 0, A_NEUTRAL, PM_WIZARD, NON_PM, 3500L ), A("Frost Brand", LONG_SWORD, (SPFX_RESTR|SPFX_ATTK|SPFX_DEFN), 0, 0, - COLD(5,0), COLD(0,0), NO_CARY, 0, A_NONE, NON_PM, NON_PM ), + COLD(5,0), COLD(0,0), NO_CARY, 0, A_NONE, NON_PM, NON_PM, 3200L ), A("Fire Brand", LONG_SWORD, (SPFX_RESTR|SPFX_ATTK|SPFX_DEFN), 0, 0, - FIRE(5,0), FIRE(0,0), NO_CARY, 0, A_NONE, NON_PM, NON_PM ), + FIRE(5,0), FIRE(0,0), NO_CARY, 0, A_NONE, NON_PM, NON_PM, 3000L ), A("Dragonbane", BROADSWORD, (SPFX_RESTR|SPFX_DCLAS), 0, S_DRAGON, - PHYS(5,0), NO_DFNS, NO_CARY, 0, A_NONE, NON_PM, NON_PM ), + PHYS(5,0), NO_DFNS, NO_CARY, 0, A_NONE, NON_PM, NON_PM, 500L ), A("Demonbane", LONG_SWORD, (SPFX_RESTR|SPFX_DFLAG2), 0, M2_DEMON, - PHYS(5,0), NO_DFNS, NO_CARY, 0, A_LAWFUL, NON_PM, NON_PM ), + PHYS(5,0), NO_DFNS, NO_CARY, 0, A_LAWFUL, NON_PM, NON_PM, 2500L ), A("Werebane", SILVER_SABER, (SPFX_RESTR|SPFX_DFLAG2), 0, M2_WERE, - PHYS(5,0), NO_DFNS, NO_CARY, 0, A_NONE, NON_PM, NON_PM ), + PHYS(5,0), NO_DFNS, NO_CARY, 0, A_NONE, NON_PM, NON_PM, 1500L ), A("Grayswandir", SILVER_SABER, (SPFX_RESTR|SPFX_HALRES), 0, 0, - PHYS(5,0), NO_DFNS, NO_CARY, 0, A_LAWFUL, NON_PM, NON_PM ), + PHYS(5,0), NO_DFNS, NO_CARY, 0, A_LAWFUL, NON_PM, NON_PM, 8000L ), A("Giantslayer", LONG_SWORD, (SPFX_RESTR|SPFX_DFLAG2), 0, M2_GIANT, - PHYS(5,0), NO_DFNS, NO_CARY, 0, A_NEUTRAL, NON_PM, NON_PM ), + PHYS(5,0), NO_DFNS, NO_CARY, 0, A_NEUTRAL, NON_PM, NON_PM, 200L ), A("Ogresmasher", WAR_HAMMER, (SPFX_RESTR|SPFX_DCLAS), 0, S_OGRE, - PHYS(5,0), NO_DFNS, NO_CARY, 0, A_NONE, NON_PM, NON_PM ), + PHYS(5,0), NO_DFNS, NO_CARY, 0, A_NONE, NON_PM, NON_PM, 200L ), A("Trollsbane", MORNING_STAR, (SPFX_RESTR|SPFX_DCLAS), 0, S_TROLL, - PHYS(5,0), NO_DFNS, NO_CARY, 0, A_NONE, NON_PM, NON_PM ), + PHYS(5,0), NO_DFNS, NO_CARY, 0, A_NONE, NON_PM, NON_PM, 200L ), /* * Two problems: 1) doesn't let trolls regenerate heads, * 2) doesn't give unusual message for 2-headed monsters (but @@ -124,7 +131,7 @@ A("Trollsbane", MORNING_STAR, */ A("Vorpal Blade", LONG_SWORD, (SPFX_RESTR|SPFX_BEHEAD), 0, 0, - PHYS(5,1), NO_DFNS, NO_CARY, 0, A_NEUTRAL, NON_PM, NON_PM ), + PHYS(5,1), NO_DFNS, NO_CARY, 0, A_NEUTRAL, NON_PM, NON_PM, 4000L ), /* * Ah, never shall I forget the cry, * or the shriek that shrieked he, @@ -135,11 +142,11 @@ A("Vorpal Blade", LONG_SWORD, */ A("Snickersnee", KATANA, SPFX_RESTR, 0, 0, - PHYS(0,8), NO_DFNS, NO_CARY, 0, A_LAWFUL, PM_SAMURAI, NON_PM ), + PHYS(0,8), NO_DFNS, NO_CARY, 0, A_LAWFUL, PM_SAMURAI, NON_PM, 1200L ), A("Sunsword", LONG_SWORD, (SPFX_RESTR|SPFX_DFLAG2), 0, M2_UNDEAD, - PHYS(5,0), DFNS(AD_BLND), NO_CARY, 0, A_LAWFUL, NON_PM, NON_PM ), + PHYS(5,0), DFNS(AD_BLND), NO_CARY, 0, A_LAWFUL, NON_PM, NON_PM, 1500L ), /* * The artifacts for the quest dungeon, all self-willed. @@ -148,86 +155,86 @@ A("Sunsword", LONG_SWORD, A("The Orb of Detection", CRYSTAL_BALL, (SPFX_NOGEN|SPFX_RESTR|SPFX_INTEL), (SPFX_ESP|SPFX_HSPDAM), 0, NO_ATTK, NO_DFNS, CARY(AD_MAGM), - INVIS, A_LAWFUL, PM_ARCHEOLOGIST, NON_PM ), + INVIS, A_LAWFUL, PM_ARCHEOLOGIST, NON_PM, 2500L ), A("The Heart of Ahriman", LUCKSTONE, (SPFX_NOGEN|SPFX_RESTR|SPFX_INTEL), SPFX_STLTH, 0, /* this stone does double damage if used as a projectile weapon */ PHYS(5,0), NO_DFNS, NO_CARY, - LEVITATION, A_NEUTRAL, PM_BARBARIAN, NON_PM ), + LEVITATION, A_NEUTRAL, PM_BARBARIAN, NON_PM, 2500L ), A("The Sceptre of Might", MACE, (SPFX_NOGEN|SPFX_RESTR|SPFX_INTEL|SPFX_DALIGN), 0, 0, PHYS(5,0), NO_DFNS, CARY(AD_MAGM), - CONFLICT, A_LAWFUL, PM_CAVEMAN, NON_PM ), + CONFLICT, A_LAWFUL, PM_CAVEMAN, NON_PM, 2500L ), #if 0 /* OBSOLETE */ A("The Palantir of Westernesse", CRYSTAL_BALL, (SPFX_NOGEN|SPFX_RESTR|SPFX_INTEL), (SPFX_ESP|SPFX_REGEN|SPFX_HSPDAM), 0, NO_ATTK, NO_DFNS, NO_CARY, - TAMING, A_CHAOTIC, NON_PM , PM_ELF), + TAMING, A_CHAOTIC, NON_PM , PM_ELF, 8000L ), #endif A("The Staff of Aesculapius", QUARTERSTAFF, (SPFX_NOGEN|SPFX_RESTR|SPFX_ATTK|SPFX_INTEL|SPFX_DRLI|SPFX_REGEN), 0,0, DRLI(0,0), DRLI(0,0), NO_CARY, - HEALING, A_NEUTRAL, PM_HEALER, NON_PM ), + HEALING, A_NEUTRAL, PM_HEALER, NON_PM, 5000L ), A("The Magic Mirror of Merlin", MIRROR, (SPFX_NOGEN|SPFX_RESTR|SPFX_INTEL|SPFX_SPEAK), SPFX_ESP, 0, NO_ATTK, NO_DFNS, CARY(AD_MAGM), - 0, A_LAWFUL, PM_KNIGHT, NON_PM ), + 0, A_LAWFUL, PM_KNIGHT, NON_PM, 1500L ), A("The Eyes of the Overworld", LENSES, (SPFX_NOGEN|SPFX_RESTR|SPFX_INTEL|SPFX_XRAY), 0, 0, NO_ATTK, NO_DFNS, CARY(AD_MAGM), - ENLIGHTENING, A_NEUTRAL, PM_MONK, NON_PM ), + ENLIGHTENING, A_NEUTRAL, PM_MONK, NON_PM, 2500L ), A("The Mitre of Holiness", HELM_OF_BRILLIANCE, (SPFX_NOGEN|SPFX_RESTR|SPFX_DFLAG2|SPFX_INTEL), 0, M2_UNDEAD, NO_ATTK, NO_DFNS, CARY(AD_FIRE), - ENERGY_BOOST, A_LAWFUL, PM_PRIEST, NON_PM ), + ENERGY_BOOST, A_LAWFUL, PM_PRIEST, NON_PM, 2000L ), A("The Longbow of Diana", BOW, (SPFX_NOGEN|SPFX_RESTR|SPFX_INTEL|SPFX_REFLECT), SPFX_ESP, 0, PHYS(5,0), NO_DFNS, NO_CARY, - CREATE_AMMO, A_CHAOTIC, PM_RANGER, NON_PM ), + CREATE_AMMO, A_CHAOTIC, PM_RANGER, NON_PM, 8000L ), A("The Master Key of Thievery", SKELETON_KEY, (SPFX_NOGEN|SPFX_RESTR|SPFX_INTEL|SPFX_SPEAK), (SPFX_WARN|SPFX_TCTRL|SPFX_HPHDAM), 0, NO_ATTK, NO_DFNS, NO_CARY, - UNTRAP, A_CHAOTIC, PM_ROGUE, NON_PM ), + UNTRAP, A_CHAOTIC, PM_ROGUE, NON_PM, 7000L ), A("The Tsurugi of Muramasa", TSURUGI, (SPFX_NOGEN|SPFX_RESTR|SPFX_INTEL|SPFX_BEHEAD|SPFX_LUCK), 0, 0, PHYS(0,8), NO_DFNS, NO_CARY, - 0, A_LAWFUL, PM_SAMURAI, NON_PM ), + 0, A_LAWFUL, PM_SAMURAI, NON_PM, 4000L ), #ifdef TOURIST A("The Platinum Yendorian Express Card", CREDIT_CARD, (SPFX_NOGEN|SPFX_RESTR|SPFX_INTEL|SPFX_DEFN), (SPFX_ESP|SPFX_HSPDAM), 0, NO_ATTK, NO_DFNS, CARY(AD_MAGM), - CHARGE_OBJ, A_NEUTRAL, PM_TOURIST, NON_PM ), + CHARGE_OBJ, A_NEUTRAL, PM_TOURIST, NON_PM, 7000L ), #endif A("The Orb of Fate", CRYSTAL_BALL, (SPFX_NOGEN|SPFX_RESTR|SPFX_INTEL|SPFX_LUCK), (SPFX_WARN|SPFX_HSPDAM|SPFX_HPHDAM), 0, NO_ATTK, NO_DFNS, NO_CARY, - LEV_TELE, A_NEUTRAL, PM_VALKYRIE, NON_PM ), + LEV_TELE, A_NEUTRAL, PM_VALKYRIE, NON_PM, 2500L ), A("The Eye of the Aethiopica", AMULET_OF_ESP, (SPFX_NOGEN|SPFX_RESTR|SPFX_INTEL), (SPFX_EREGEN|SPFX_HSPDAM), 0, NO_ATTK, NO_DFNS, CARY(AD_MAGM), - CREATE_PORTAL, A_NEUTRAL, PM_WIZARD, NON_PM ), + CREATE_PORTAL, A_NEUTRAL, PM_WIZARD, NON_PM, 4000L ), /* * terminator; otyp must be zero */ -A(0, 0, 0, 0, 0, NO_ATTK, NO_DFNS, NO_CARY, 0, A_NONE, NON_PM, NON_PM ) +A(0, 0, 0, 0, 0, NO_ATTK, NO_DFNS, NO_CARY, 0, A_NONE, NON_PM, NON_PM, 0L ) }; /* artilist[] (or artifact_names[]) */ diff --git a/include/extern.h b/include/extern.h index 0020b1d80..2fe4fb7ea 100644 --- a/include/extern.h +++ b/include/extern.h @@ -79,6 +79,7 @@ E void FDECL(arti_speak, (struct obj *)); E boolean FDECL(artifact_light, (struct obj *)); E long FDECL(spec_m2, (struct obj *)); E boolean FDECL(artifact_has_invprop, (struct obj *,UCHAR_P)); +E long FDECL(arti_cost, (struct obj *)); /* ### attrib.c ### */ diff --git a/src/artifact.c b/src/artifact.c index 8df5d0184..3c21c8718 100644 --- a/src/artifact.c +++ b/src/artifact.c @@ -1342,6 +1342,19 @@ uchar inv_prop; return((boolean)(arti && (arti->inv_prop == inv_prop))); } +/* Return the price sold to the hero of a given artifact or unique item */ +long +arti_cost(otmp) +struct obj *otmp; +{ + if (!otmp->oartifact) + return ((long)objects[otmp->otyp].oc_cost); + else if (artilist[otmp->oartifact].cost) + return (artilist[otmp->oartifact].cost); + else + return (100L * (long)objects[otmp->otyp].oc_cost); +} + #endif /* OVLB */ /*artifact.c*/ diff --git a/src/end.c b/src/end.c index 85c795bdf..237d804fc 100644 --- a/src/end.c +++ b/src/end.c @@ -469,8 +469,7 @@ struct obj *list; otmp->otyp == BELL_OF_OPENING || otmp->otyp == SPE_BOOK_OF_THE_DEAD || otmp->otyp == CANDELABRUM_OF_INVOCATION) { - /* shopkeepers charge 100x; 250x is arbitrary */ - u.urexp += 250L * (long)objects[otmp->otyp].oc_cost; + u.urexp += (arti_cost(otmp) * 5 / 2); if (Has_contents(otmp)) add_artifact_score(otmp->cobj); } @@ -498,8 +497,8 @@ winid endwin; Sprintf(pbuf, "%s (worth %ld %s and %ld points)", otmp->oartifact ? artifact_name(xname(otmp), &dummy) : OBJ_NAME(objects[otmp->otyp]), - 100L * (long)objects[otmp->otyp].oc_cost, currency(2L), - 250L * (long)objects[otmp->otyp].oc_cost); + arti_cost(otmp), currency(2L), + arti_cost(otmp) * 5 / 2); putstr(endwin, 0, pbuf); } if (Has_contents(otmp)) diff --git a/src/objects.c b/src/objects.c index 73031d067..b78b64768 100644 --- a/src/objects.c +++ b/src/objects.c @@ -553,7 +553,7 @@ OBJECT(OBJ("cheap plastic imitation of the Amulet of Yendor", AMULET_CLASS, 0, 0, 20, 0, 0, 0, 0, 0, 1, HI_METAL), OBJECT(OBJ("Amulet of Yendor", /* note: description == name */ "Amulet of Yendor"), BITS(0,0,1,0,1,0,1,1,0,0,0,0,MITHRIL), 0, - AMULET_CLASS, 0, 0, 20, 3500, 0, 0, 0, 0, 20, HI_METAL), + AMULET_CLASS, 0, 0, 20, 30000, 0, 0, 0, 0, 20, HI_METAL), #undef AMULET /* tools ... */ @@ -653,10 +653,10 @@ WEPTOOL("unicorn horn", (char *)0, /* two special unique artifact "tools" */ OBJECT(OBJ("Candelabrum of Invocation", "candelabrum"), BITS(0,0,1,0,1,0,1,1,0,0,0,P_NONE,GOLD), 0, - TOOL_CLASS, 0, 0,10, 3000, 0, 0, 0, 0, 200, HI_GOLD), + TOOL_CLASS, 0, 0,10, 5000, 0, 0, 0, 0, 200, HI_GOLD), OBJECT(OBJ("Bell of Opening", "silver bell"), BITS(0,0,1,0,1,1,1,1,0,0,0,P_NONE,SILVER), 0, - TOOL_CLASS, 0, 0,10, 1000, 0, 0, 0, 0, 50, HI_SILVER), + TOOL_CLASS, 0, 0,10, 5000, 0, 0, 0, 0, 50, HI_SILVER), #undef TOOL #undef WEPTOOL @@ -835,7 +835,7 @@ SPELL("freeze sphere", "hardcover", P_MATTER_SPELL, 20, 2, 1, 1, NODIR, CLR SPELL("blank paper", "plain", P_NONE, 18, 0, 0, 0, 0, HI_PAPER), /* a special, one of a kind, spellbook */ OBJECT(OBJ("Book of the Dead", "papyrus"), BITS(0,0,1,0,1,0,1,1,0,0,0,P_NONE,PAPER), 0, - SPBOOK_CLASS, 0, 0,20, 3500, 0, 0, 0, 7, 20, HI_PAPER), + SPBOOK_CLASS, 0, 0,20, 10000, 0, 0, 0, 7, 20, HI_PAPER), #undef SPELL /* wands ... */ diff --git a/src/shk.c b/src/shk.c index 7ec8d6b5d..61ebf24df 100644 --- a/src/shk.c +++ b/src/shk.c @@ -2800,6 +2800,10 @@ boolean shk_buying; { register long tmp = (long) objects[obj->otyp].oc_cost; + if (obj->oartifact) { + tmp = arti_cost(obj); + if (shk_buying) tmp /= 4; + } switch(obj->oclass) { case FOOD_CLASS: /* simpler hunger check, (2-4)*cost */ @@ -2823,7 +2827,6 @@ boolean shk_buying; tmp /= 2L; break; } - if (obj->oartifact) tmp *= 25L; return tmp; }