1 #include "object/object-value.h"
2 #include "monster-race/monster-race.h"
3 #include "object-enchant/object-curse.h"
4 #include "object-enchant/object-ego.h"
5 #include "object-enchant/special-object-flags.h"
6 #include "object-enchant/tr-types.h"
7 #include "object/object-broken.h"
8 #include "object/object-flags.h"
9 #include "object/object-kind.h"
10 #include "object/object-value-calc.h"
11 #include "perception/object-perception.h"
12 #include "system/artifact-type-definition.h"
13 #include "system/monster-race-definition.h"
14 #include "system/object-type-definition.h"
15 #include "system/player-type-definition.h"
16 #include "util/bit-flags-calculator.h"
19 * @brief 未鑑定なベースアイテムの基本価格を返す /
20 * Return the "value" of an "unknown" item Make a guess at the value of non-aware items
21 * @param o_ptr 未鑑定価格を確認したいオブジェクトの構造体参照ポインタ
22 * @return オブジェクトの未鑑定価格
24 static PRICE object_value_base(const ObjectType *o_ptr)
26 if (o_ptr->is_aware()) {
27 return k_info[o_ptr->k_idx].cost;
30 switch (o_ptr->tval) {
31 case ItemKindType::FOOD:
33 case ItemKindType::POTION:
35 case ItemKindType::SCROLL:
37 case ItemKindType::STAFF:
39 case ItemKindType::WAND:
41 case ItemKindType::ROD:
43 case ItemKindType::RING:
45 case ItemKindType::AMULET:
47 case ItemKindType::FIGURINE: {
48 auto figure_r_idx = i2enum<MonsterRaceId>(o_ptr->pval);
49 DEPTH level = r_info[figure_r_idx].level;
52 } else if (level < 30) {
53 return 1000 + (level - 20) * 150;
54 } else if (level < 40) {
55 return 2500 + (level - 30) * 350;
56 } else if (level < 50) {
57 return 6000 + (level - 40) * 800;
59 return 14000 + (level - 50) * 2000;
62 case ItemKindType::CAPTURE: {
63 auto capture_r_idx = i2enum<MonsterRaceId>(o_ptr->pval);
64 if (!is_valid_monster_race(capture_r_idx)) {
67 return (r_info[capture_r_idx].level) * 50 + 1000;
79 * @brief オブジェクト価格算出のメインルーチン /
80 * Return the price of an item including plusses (and charges)
81 * @param o_ptr 判明している現価格を確認したいオブジェクトの構造体参照ポインタ
82 * @return オブジェクトの判明している現価格
84 * This function returns the "value" of the given item (qty one)\n
86 * Never notice "unknown" bonuses or properties, including "curses",\n
87 * since that would give the player information he did not have.\n
89 * Note that discounted items stay discounted forever, even if\n
90 * the discount is "forgotten" by the player via memory loss.\n
92 PRICE object_value(const ObjectType *o_ptr)
96 if (o_ptr->is_known()) {
97 if (o_ptr->is_broken()) {
100 if (o_ptr->is_cursed()) {
104 value = object_value_real(o_ptr);
106 if ((o_ptr->ident & (IDENT_SENSE)) && o_ptr->is_broken()) {
109 if ((o_ptr->ident & (IDENT_SENSE)) && o_ptr->is_cursed()) {
113 value = object_value_base(o_ptr);
116 if (o_ptr->discount) {
117 value -= (value * o_ptr->discount / 100L);
124 * @brief オブジェクトの真の価格を算出する /
125 * Return the value of the flags the object has...
126 * @param o_ptr 本価格を確認したいオブジェクトの構造体参照ポインタ
129 * Return the "real" price of a "known" item, not including discounts\n
131 * Wand and staffs get cost for each charge\n
133 * Armor is worth an extra 100 gold per bonus point to armor class.\n
135 * Weapons are worth an extra 100 gold per bonus point (AC,TH,TD).\n
137 * Missiles are only worth 5 gold per bonus point, since they\n
138 * usually appear in groups of 20, and we want the player to get\n
139 * the same amount of cash for any "equivalent" item. Note that\n
140 * missiles never have any of the "pval" flags, and in fact, they\n
141 * only have a few of the available flags, primarily of the "slay"\n
142 * and "brand" and "ignore" variety.\n
144 * Armor with a negative armor bonus is worthless.\n
145 * Weapons with negative hit+damage bonuses are worthless.\n
147 * Every wearable item with a "pval" bonus is worth extra (see below).\n
149 PRICE object_value_real(const ObjectType *o_ptr)
151 auto *k_ptr = &k_info[o_ptr->k_idx];
153 if (!k_info[o_ptr->k_idx].cost) {
157 PRICE value = k_info[o_ptr->k_idx].cost;
158 auto flgs = object_flags(o_ptr);
159 if (o_ptr->is_fixed_artifact()) {
160 auto *a_ptr = &a_info[o_ptr->fixed_artifact_idx];
166 value += flag_cost(o_ptr, o_ptr->pval);
168 } else if (o_ptr->is_ego()) {
169 auto *e_ptr = &e_info[o_ptr->ego_idx];
174 value += e_ptr->cost;
175 value += flag_cost(o_ptr, o_ptr->pval);
177 if (o_ptr->art_flags.any()) {
178 value += flag_cost(o_ptr, o_ptr->pval);
182 /* Analyze pval bonus for normal object */
183 switch (o_ptr->tval) {
184 case ItemKindType::SHOT:
185 case ItemKindType::ARROW:
186 case ItemKindType::BOLT:
187 case ItemKindType::BOW:
188 case ItemKindType::DIGGING:
189 case ItemKindType::HAFTED:
190 case ItemKindType::POLEARM:
191 case ItemKindType::SWORD:
192 case ItemKindType::BOOTS:
193 case ItemKindType::GLOVES:
194 case ItemKindType::HELM:
195 case ItemKindType::CROWN:
196 case ItemKindType::SHIELD:
197 case ItemKindType::CLOAK:
198 case ItemKindType::SOFT_ARMOR:
199 case ItemKindType::HARD_ARMOR:
200 case ItemKindType::DRAG_ARMOR:
201 case ItemKindType::LITE:
202 case ItemKindType::AMULET:
203 case ItemKindType::RING:
207 if (o_ptr->pval < 0) {
211 if (flgs.has(TR_STR)) {
212 value += (o_ptr->pval * 200L);
214 if (flgs.has(TR_INT)) {
215 value += (o_ptr->pval * 200L);
217 if (flgs.has(TR_WIS)) {
218 value += (o_ptr->pval * 200L);
220 if (flgs.has(TR_DEX)) {
221 value += (o_ptr->pval * 200L);
223 if (flgs.has(TR_CON)) {
224 value += (o_ptr->pval * 200L);
226 if (flgs.has(TR_CHR)) {
227 value += (o_ptr->pval * 200L);
229 if (flgs.has(TR_MAGIC_MASTERY)) {
230 value += (o_ptr->pval * 100);
232 if (flgs.has(TR_STEALTH)) {
233 value += (o_ptr->pval * 100L);
235 if (flgs.has(TR_SEARCH)) {
236 value += (o_ptr->pval * 100L);
238 if (flgs.has(TR_INFRA)) {
239 value += (o_ptr->pval * 50L);
241 if (flgs.has(TR_TUNNEL)) {
242 value += (o_ptr->pval * 50L);
244 if (flgs.has(TR_BLOWS)) {
245 value += (o_ptr->pval * 5000L);
247 if (flgs.has(TR_SPEED)) {
248 value += (o_ptr->pval * 10000L);
256 switch (o_ptr->tval) {
257 case ItemKindType::WAND: {
258 /* Pay extra for charges, depending on standard number of
259 * charges. Handle new-style wands correctly. -LM-
261 value += (value * o_ptr->pval / o_ptr->number / (k_ptr->pval * 2));
264 case ItemKindType::STAFF: {
265 /* Pay extra for charges, depending on standard number of
268 value += (value * o_ptr->pval / (k_ptr->pval * 2));
271 case ItemKindType::RING:
272 case ItemKindType::AMULET: {
273 if (o_ptr->to_h + o_ptr->to_d + o_ptr->to_a < 0) {
277 value += ((o_ptr->to_h + o_ptr->to_d + o_ptr->to_a) * 200L);
280 case ItemKindType::BOOTS:
281 case ItemKindType::GLOVES:
282 case ItemKindType::CLOAK:
283 case ItemKindType::CROWN:
284 case ItemKindType::HELM:
285 case ItemKindType::SHIELD:
286 case ItemKindType::SOFT_ARMOR:
287 case ItemKindType::HARD_ARMOR:
288 case ItemKindType::DRAG_ARMOR: {
289 if (o_ptr->to_a < 0) {
293 value += (((o_ptr->to_h - k_ptr->to_h) + (o_ptr->to_d - k_ptr->to_d)) * 200L + (o_ptr->to_a) * 100L);
296 case ItemKindType::BOW:
297 case ItemKindType::DIGGING:
298 case ItemKindType::HAFTED:
299 case ItemKindType::SWORD:
300 case ItemKindType::POLEARM: {
301 if (o_ptr->to_h + o_ptr->to_d < 0) {
305 value += ((o_ptr->to_h + o_ptr->to_d + o_ptr->to_a) * 100L);
306 value += (o_ptr->dd - k_ptr->dd) * o_ptr->ds * 250L;
307 value += (o_ptr->ds - k_ptr->ds) * o_ptr->dd * 250L;
310 case ItemKindType::SHOT:
311 case ItemKindType::ARROW:
312 case ItemKindType::BOLT: {
313 if (o_ptr->to_h + o_ptr->to_d < 0) {
317 value += ((o_ptr->to_h + o_ptr->to_d) * 5L);
318 value += (o_ptr->dd - k_ptr->dd) * o_ptr->ds * 5L;
319 value += (o_ptr->ds - k_ptr->ds) * o_ptr->dd * 5L;
322 case ItemKindType::FIGURINE: {
323 auto figure_r_idx = i2enum<MonsterRaceId>(o_ptr->pval);
324 DEPTH level = r_info[figure_r_idx].level;
327 } else if (level < 30) {
328 value = 1000 + (level - 20) * 150L;
329 } else if (level < 40) {
330 value = 2500 + (level - 30) * 350L;
331 } else if (level < 50) {
332 value = 6000 + (level - 40) * 800L;
334 value = 14000 + (level - 50) * 2000L;
338 case ItemKindType::CAPTURE: {
339 auto capture_r_idx = i2enum<MonsterRaceId>(o_ptr->pval);
340 if (!is_valid_monster_race(capture_r_idx)) {
343 value = ((r_info[capture_r_idx].level) * 50L + 1000);
347 case ItemKindType::CHEST: {