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 DEPTH level = r_info[o_ptr->pval].level;
51 } else if (level < 30) {
52 return 1000 + (level - 20) * 150;
53 } else if (level < 40) {
54 return 2500 + (level - 30) * 350;
55 } else if (level < 50) {
56 return 6000 + (level - 40) * 800;
58 return 14000 + (level - 50) * 2000;
61 case ItemKindType::CAPTURE:
65 return (r_info[o_ptr->pval].level) * 50 + 1000;
76 * @brief オブジェクト価格算出のメインルーチン /
77 * Return the price of an item including plusses (and charges)
78 * @param o_ptr 判明している現価格を確認したいオブジェクトの構造体参照ポインタ
79 * @return オブジェクトの判明している現価格
81 * This function returns the "value" of the given item (qty one)\n
83 * Never notice "unknown" bonuses or properties, including "curses",\n
84 * since that would give the player information he did not have.\n
86 * Note that discounted items stay discounted forever, even if\n
87 * the discount is "forgotten" by the player via memory loss.\n
89 PRICE object_value(const ObjectType *o_ptr)
93 if (o_ptr->is_known()) {
94 if (o_ptr->is_broken()) {
97 if (o_ptr->is_cursed()) {
101 value = object_value_real(o_ptr);
103 if ((o_ptr->ident & (IDENT_SENSE)) && o_ptr->is_broken()) {
106 if ((o_ptr->ident & (IDENT_SENSE)) && o_ptr->is_cursed()) {
110 value = object_value_base(o_ptr);
113 if (o_ptr->discount) {
114 value -= (value * o_ptr->discount / 100L);
121 * @brief オブジェクトの真の価格を算出する /
122 * Return the value of the flags the object has...
123 * @param o_ptr 本価格を確認したいオブジェクトの構造体参照ポインタ
126 * Return the "real" price of a "known" item, not including discounts\n
128 * Wand and staffs get cost for each charge\n
130 * Armor is worth an extra 100 gold per bonus point to armor class.\n
132 * Weapons are worth an extra 100 gold per bonus point (AC,TH,TD).\n
134 * Missiles are only worth 5 gold per bonus point, since they\n
135 * usually appear in groups of 20, and we want the player to get\n
136 * the same amount of cash for any "equivalent" item. Note that\n
137 * missiles never have any of the "pval" flags, and in fact, they\n
138 * only have a few of the available flags, primarily of the "slay"\n
139 * and "brand" and "ignore" variety.\n
141 * Armor with a negative armor bonus is worthless.\n
142 * Weapons with negative hit+damage bonuses are worthless.\n
144 * Every wearable item with a "pval" bonus is worth extra (see below).\n
146 PRICE object_value_real(const ObjectType *o_ptr)
148 auto *k_ptr = &k_info[o_ptr->k_idx];
150 if (!k_info[o_ptr->k_idx].cost) {
154 PRICE value = k_info[o_ptr->k_idx].cost;
155 auto flgs = object_flags(o_ptr);
156 if (o_ptr->is_fixed_artifact()) {
157 auto *a_ptr = &a_info[o_ptr->fixed_artifact_idx];
163 value += flag_cost(o_ptr, o_ptr->pval);
165 } else if (o_ptr->is_ego()) {
166 auto *e_ptr = &e_info[o_ptr->ego_idx];
171 value += e_ptr->cost;
172 value += flag_cost(o_ptr, o_ptr->pval);
174 if (o_ptr->art_flags.any()) {
175 value += flag_cost(o_ptr, o_ptr->pval);
179 /* Analyze pval bonus for normal object */
180 switch (o_ptr->tval) {
181 case ItemKindType::SHOT:
182 case ItemKindType::ARROW:
183 case ItemKindType::BOLT:
184 case ItemKindType::BOW:
185 case ItemKindType::DIGGING:
186 case ItemKindType::HAFTED:
187 case ItemKindType::POLEARM:
188 case ItemKindType::SWORD:
189 case ItemKindType::BOOTS:
190 case ItemKindType::GLOVES:
191 case ItemKindType::HELM:
192 case ItemKindType::CROWN:
193 case ItemKindType::SHIELD:
194 case ItemKindType::CLOAK:
195 case ItemKindType::SOFT_ARMOR:
196 case ItemKindType::HARD_ARMOR:
197 case ItemKindType::DRAG_ARMOR:
198 case ItemKindType::LITE:
199 case ItemKindType::AMULET:
200 case ItemKindType::RING:
204 if (o_ptr->pval < 0) {
208 if (flgs.has(TR_STR)) {
209 value += (o_ptr->pval * 200L);
211 if (flgs.has(TR_INT)) {
212 value += (o_ptr->pval * 200L);
214 if (flgs.has(TR_WIS)) {
215 value += (o_ptr->pval * 200L);
217 if (flgs.has(TR_DEX)) {
218 value += (o_ptr->pval * 200L);
220 if (flgs.has(TR_CON)) {
221 value += (o_ptr->pval * 200L);
223 if (flgs.has(TR_CHR)) {
224 value += (o_ptr->pval * 200L);
226 if (flgs.has(TR_MAGIC_MASTERY)) {
227 value += (o_ptr->pval * 100);
229 if (flgs.has(TR_STEALTH)) {
230 value += (o_ptr->pval * 100L);
232 if (flgs.has(TR_SEARCH)) {
233 value += (o_ptr->pval * 100L);
235 if (flgs.has(TR_INFRA)) {
236 value += (o_ptr->pval * 50L);
238 if (flgs.has(TR_TUNNEL)) {
239 value += (o_ptr->pval * 50L);
241 if (flgs.has(TR_BLOWS)) {
242 value += (o_ptr->pval * 5000L);
244 if (flgs.has(TR_SPEED)) {
245 value += (o_ptr->pval * 10000L);
253 switch (o_ptr->tval) {
254 case ItemKindType::WAND: {
255 /* Pay extra for charges, depending on standard number of
256 * charges. Handle new-style wands correctly. -LM-
258 value += (value * o_ptr->pval / o_ptr->number / (k_ptr->pval * 2));
261 case ItemKindType::STAFF: {
262 /* Pay extra for charges, depending on standard number of
265 value += (value * o_ptr->pval / (k_ptr->pval * 2));
268 case ItemKindType::RING:
269 case ItemKindType::AMULET: {
270 if (o_ptr->to_h + o_ptr->to_d + o_ptr->to_a < 0) {
274 value += ((o_ptr->to_h + o_ptr->to_d + o_ptr->to_a) * 200L);
277 case ItemKindType::BOOTS:
278 case ItemKindType::GLOVES:
279 case ItemKindType::CLOAK:
280 case ItemKindType::CROWN:
281 case ItemKindType::HELM:
282 case ItemKindType::SHIELD:
283 case ItemKindType::SOFT_ARMOR:
284 case ItemKindType::HARD_ARMOR:
285 case ItemKindType::DRAG_ARMOR: {
286 if (o_ptr->to_a < 0) {
290 value += (((o_ptr->to_h - k_ptr->to_h) + (o_ptr->to_d - k_ptr->to_d)) * 200L + (o_ptr->to_a) * 100L);
293 case ItemKindType::BOW:
294 case ItemKindType::DIGGING:
295 case ItemKindType::HAFTED:
296 case ItemKindType::SWORD:
297 case ItemKindType::POLEARM: {
298 if (o_ptr->to_h + o_ptr->to_d < 0) {
302 value += ((o_ptr->to_h + o_ptr->to_d + o_ptr->to_a) * 100L);
303 value += (o_ptr->dd - k_ptr->dd) * o_ptr->ds * 250L;
304 value += (o_ptr->ds - k_ptr->ds) * o_ptr->dd * 250L;
307 case ItemKindType::SHOT:
308 case ItemKindType::ARROW:
309 case ItemKindType::BOLT: {
310 if (o_ptr->to_h + o_ptr->to_d < 0) {
314 value += ((o_ptr->to_h + o_ptr->to_d) * 5L);
315 value += (o_ptr->dd - k_ptr->dd) * o_ptr->ds * 5L;
316 value += (o_ptr->ds - k_ptr->ds) * o_ptr->dd * 5L;
319 case ItemKindType::FIGURINE: {
320 DEPTH level = r_info[o_ptr->pval].level;
323 } else if (level < 30) {
324 value = 1000 + (level - 20) * 150L;
325 } else if (level < 40) {
326 value = 2500 + (level - 30) * 350L;
327 } else if (level < 50) {
328 value = 6000 + (level - 40) * 800L;
330 value = 14000 + (level - 50) * 2000L;
334 case ItemKindType::CAPTURE: {
338 value = ((r_info[o_ptr->pval].level) * 50L + 1000);
342 case ItemKindType::CHEST: {