OSDN Git Service

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