OSDN Git Service

Merge pull request #2285 from sikabane-works/feature/refactor-wizard-get_value
[hengbandforosx/hengbandosx.git] / src / object / object-value.cpp
1 #include "object/object-value.h"
2 #include "monster-race/monster-race.h"
3 #include "object/object-flags.h"
4 #include "object/object-value-calc.h"
5 #include "object/tval-types.h"
6 #include "system/artifact-type-definition.h"
7 #include "system/baseitem-info-definition.h"
8 #include "system/monster-race-definition.h"
9 #include "system/player-type-definition.h"
10
11 /*!
12  * @brief オブジェクトの真の価格を算出する /
13  * Return the value of the flags the object has...
14  * @param o_ptr 本価格を確認したいオブジェクトの構造体参照ポインタ
15  * @return オブジェクトの本価格
16  * @details
17  * Return the "real" price of a "known" item, not including discounts\n
18  *\n
19  * Wand and staffs get cost for each charge\n
20  *\n
21  * Armor is worth an extra 100 gold per bonus point to armor class.\n
22  *\n
23  * Weapons are worth an extra 100 gold per bonus point (AC,TH,TD).\n
24  *\n
25  * Missiles are only worth 5 gold per bonus point, since they\n
26  * usually appear in groups of 20, and we want the player to get\n
27  * the same amount of cash for any "equivalent" item.  Note that\n
28  * missiles never have any of the "pval" flags, and in fact, they\n
29  * only have a few of the available flags, primarily of the "slay"\n
30  * and "brand" and "ignore" variety.\n
31  *\n
32  * Armor with a negative armor bonus is worthless.\n
33  * Weapons with negative hit+damage bonuses are worthless.\n
34  *\n
35  * Every wearable item with a "pval" bonus is worth extra (see below).\n
36  */
37 PRICE object_value_real(const ObjectType *o_ptr)
38 {
39     auto *k_ptr = &k_info[o_ptr->k_idx];
40
41     if (!k_info[o_ptr->k_idx].cost) {
42         return 0;
43     }
44
45     PRICE value = k_info[o_ptr->k_idx].cost;
46     auto flgs = object_flags(o_ptr);
47     if (o_ptr->is_fixed_artifact()) {
48         const auto &a_ref = a_info.at(o_ptr->fixed_artifact_idx);
49         if (!a_ref.cost) {
50             return 0;
51         }
52
53         value = a_ref.cost;
54         value += flag_cost(o_ptr, o_ptr->pval);
55         return value;
56     } else if (o_ptr->is_ego()) {
57         const auto &e_ref = e_info[o_ptr->ego_idx];
58         if (!e_ref.cost) {
59             return 0;
60         }
61
62         value += e_ref.cost;
63         value += flag_cost(o_ptr, o_ptr->pval);
64     } else {
65         if (o_ptr->art_flags.any()) {
66             value += flag_cost(o_ptr, o_ptr->pval);
67         }
68     }
69
70     /* Analyze pval bonus for normal object */
71     switch (o_ptr->tval) {
72     case ItemKindType::SHOT:
73     case ItemKindType::ARROW:
74     case ItemKindType::BOLT:
75     case ItemKindType::BOW:
76     case ItemKindType::DIGGING:
77     case ItemKindType::HAFTED:
78     case ItemKindType::POLEARM:
79     case ItemKindType::SWORD:
80     case ItemKindType::BOOTS:
81     case ItemKindType::GLOVES:
82     case ItemKindType::HELM:
83     case ItemKindType::CROWN:
84     case ItemKindType::SHIELD:
85     case ItemKindType::CLOAK:
86     case ItemKindType::SOFT_ARMOR:
87     case ItemKindType::HARD_ARMOR:
88     case ItemKindType::DRAG_ARMOR:
89     case ItemKindType::LITE:
90     case ItemKindType::AMULET:
91     case ItemKindType::RING:
92         if (!o_ptr->pval) {
93             break;
94         }
95         if (o_ptr->pval < 0) {
96             return 0;
97         }
98
99         if (flgs.has(TR_STR)) {
100             value += (o_ptr->pval * 200L);
101         }
102         if (flgs.has(TR_INT)) {
103             value += (o_ptr->pval * 200L);
104         }
105         if (flgs.has(TR_WIS)) {
106             value += (o_ptr->pval * 200L);
107         }
108         if (flgs.has(TR_DEX)) {
109             value += (o_ptr->pval * 200L);
110         }
111         if (flgs.has(TR_CON)) {
112             value += (o_ptr->pval * 200L);
113         }
114         if (flgs.has(TR_CHR)) {
115             value += (o_ptr->pval * 200L);
116         }
117         if (flgs.has(TR_MAGIC_MASTERY)) {
118             value += (o_ptr->pval * 100);
119         }
120         if (flgs.has(TR_STEALTH)) {
121             value += (o_ptr->pval * 100L);
122         }
123         if (flgs.has(TR_SEARCH)) {
124             value += (o_ptr->pval * 100L);
125         }
126         if (flgs.has(TR_INFRA)) {
127             value += (o_ptr->pval * 50L);
128         }
129         if (flgs.has(TR_TUNNEL)) {
130             value += (o_ptr->pval * 50L);
131         }
132         if (flgs.has(TR_BLOWS)) {
133             value += (o_ptr->pval * 5000L);
134         }
135         if (flgs.has(TR_SPEED)) {
136             value += (o_ptr->pval * 10000L);
137         }
138         break;
139
140     default:
141         break;
142     }
143
144     switch (o_ptr->tval) {
145     case ItemKindType::WAND: {
146         /* Pay extra for charges, depending on standard number of
147          * charges.  Handle new-style wands correctly. -LM-
148          */
149         value += (value * o_ptr->pval / o_ptr->number / (k_ptr->pval * 2));
150         break;
151     }
152     case ItemKindType::STAFF: {
153         /* Pay extra for charges, depending on standard number of
154          * charges.  -LM-
155          */
156         value += (value * o_ptr->pval / (k_ptr->pval * 2));
157         break;
158     }
159     case ItemKindType::RING:
160     case ItemKindType::AMULET: {
161         if (o_ptr->to_h + o_ptr->to_d + o_ptr->to_a < 0) {
162             return 0;
163         }
164
165         value += ((o_ptr->to_h + o_ptr->to_d + o_ptr->to_a) * 200L);
166         break;
167     }
168     case ItemKindType::BOOTS:
169     case ItemKindType::GLOVES:
170     case ItemKindType::CLOAK:
171     case ItemKindType::CROWN:
172     case ItemKindType::HELM:
173     case ItemKindType::SHIELD:
174     case ItemKindType::SOFT_ARMOR:
175     case ItemKindType::HARD_ARMOR:
176     case ItemKindType::DRAG_ARMOR: {
177         if (o_ptr->to_a < 0) {
178             return 0;
179         }
180
181         value += (((o_ptr->to_h - k_ptr->to_h) + (o_ptr->to_d - k_ptr->to_d)) * 200L + (o_ptr->to_a) * 100L);
182         break;
183     }
184     case ItemKindType::BOW:
185     case ItemKindType::DIGGING:
186     case ItemKindType::HAFTED:
187     case ItemKindType::SWORD:
188     case ItemKindType::POLEARM: {
189         if (o_ptr->to_h + o_ptr->to_d < 0) {
190             return 0;
191         }
192
193         value += ((o_ptr->to_h + o_ptr->to_d + o_ptr->to_a) * 100L);
194         value += (o_ptr->dd - k_ptr->dd) * o_ptr->ds * 250L;
195         value += (o_ptr->ds - k_ptr->ds) * o_ptr->dd * 250L;
196         break;
197     }
198     case ItemKindType::SHOT:
199     case ItemKindType::ARROW:
200     case ItemKindType::BOLT: {
201         if (o_ptr->to_h + o_ptr->to_d < 0) {
202             return 0;
203         }
204
205         value += ((o_ptr->to_h + o_ptr->to_d) * 5L);
206         value += (o_ptr->dd - k_ptr->dd) * o_ptr->ds * 5L;
207         value += (o_ptr->ds - k_ptr->ds) * o_ptr->dd * 5L;
208         break;
209     }
210     case ItemKindType::FIGURINE: {
211         auto figure_r_idx = i2enum<MonsterRaceId>(o_ptr->pval);
212         DEPTH level = r_info[figure_r_idx].level;
213         if (level < 20) {
214             value = level * 50L;
215         } else if (level < 30) {
216             value = 1000 + (level - 20) * 150L;
217         } else if (level < 40) {
218             value = 2500 + (level - 30) * 350L;
219         } else if (level < 50) {
220             value = 6000 + (level - 40) * 800L;
221         } else {
222             value = 14000 + (level - 50) * 2000L;
223         }
224         break;
225     }
226     case ItemKindType::CAPTURE: {
227         auto capture_r_idx = i2enum<MonsterRaceId>(o_ptr->pval);
228         if (!MonsterRace(capture_r_idx).is_valid()) {
229             value = 1000L;
230         } else {
231             value = ((r_info[capture_r_idx].level) * 50L + 1000);
232         }
233         break;
234     }
235     case ItemKindType::CHEST: {
236         if (!o_ptr->pval) {
237             value = 0L;
238         }
239         break;
240     }
241
242     default:
243         break;
244     }
245
246     if (value < 0) {
247         return 0L;
248     }
249
250     return value;
251 }