OSDN Git Service

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