OSDN Git Service

[Refactor/WIP] モンスター種族IDをenum class化
[hengbandforosx/hengbandosx.git] / src / object / object-value.cpp
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"
17
18 /*!
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 オブジェクトの未鑑定価格
23  */
24 static PRICE object_value_base(const ObjectType *o_ptr)
25 {
26     if (o_ptr->is_aware()) {
27         return k_info[o_ptr->k_idx].cost;
28     }
29
30     switch (o_ptr->tval) {
31     case ItemKindType::FOOD:
32         return 5;
33     case ItemKindType::POTION:
34         return 20;
35     case ItemKindType::SCROLL:
36         return 20;
37     case ItemKindType::STAFF:
38         return 70;
39     case ItemKindType::WAND:
40         return 50;
41     case ItemKindType::ROD:
42         return 90;
43     case ItemKindType::RING:
44         return 45;
45     case ItemKindType::AMULET:
46         return 45;
47     case ItemKindType::FIGURINE: {
48         auto figure_r_idx = i2enum<MonsterRaceId>(o_ptr->pval);
49         DEPTH level = r_info[figure_r_idx].level;
50         if (level < 20) {
51             return level * 50L;
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;
58         } else {
59             return 14000 + (level - 50) * 2000;
60         }
61     }
62     case ItemKindType::CAPTURE: {
63         auto capture_r_idx = i2enum<MonsterRaceId>(o_ptr->pval);
64         if (!is_valid_monster_race(capture_r_idx)) {
65             return 1000;
66         } else {
67             return (r_info[capture_r_idx].level) * 50 + 1000;
68         }
69     }
70
71     default:
72         break;
73     }
74
75     return 0;
76 }
77
78 /*!
79  * @brief オブジェクト価格算出のメインルーチン /
80  * Return the price of an item including plusses (and charges)
81  * @param o_ptr 判明している現価格を確認したいオブジェクトの構造体参照ポインタ
82  * @return オブジェクトの判明している現価格
83  * @details
84  * This function returns the "value" of the given item (qty one)\n
85  *\n
86  * Never notice "unknown" bonuses or properties, including "curses",\n
87  * since that would give the player information he did not have.\n
88  *\n
89  * Note that discounted items stay discounted forever, even if\n
90  * the discount is "forgotten" by the player via memory loss.\n
91  */
92 PRICE object_value(const ObjectType *o_ptr)
93 {
94     PRICE value;
95
96     if (o_ptr->is_known()) {
97         if (o_ptr->is_broken()) {
98             return 0;
99         }
100         if (o_ptr->is_cursed()) {
101             return 0;
102         }
103
104         value = object_value_real(o_ptr);
105     } else {
106         if ((o_ptr->ident & (IDENT_SENSE)) && o_ptr->is_broken()) {
107             return 0;
108         }
109         if ((o_ptr->ident & (IDENT_SENSE)) && o_ptr->is_cursed()) {
110             return 0;
111         }
112
113         value = object_value_base(o_ptr);
114     }
115
116     if (o_ptr->discount) {
117         value -= (value * o_ptr->discount / 100L);
118     }
119
120     return value;
121 }
122
123 /*!
124  * @brief オブジェクトの真の価格を算出する /
125  * Return the value of the flags the object has...
126  * @param o_ptr 本価格を確認したいオブジェクトの構造体参照ポインタ
127  * @return オブジェクトの本価格
128  * @details
129  * Return the "real" price of a "known" item, not including discounts\n
130  *\n
131  * Wand and staffs get cost for each charge\n
132  *\n
133  * Armor is worth an extra 100 gold per bonus point to armor class.\n
134  *\n
135  * Weapons are worth an extra 100 gold per bonus point (AC,TH,TD).\n
136  *\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
143  *\n
144  * Armor with a negative armor bonus is worthless.\n
145  * Weapons with negative hit+damage bonuses are worthless.\n
146  *\n
147  * Every wearable item with a "pval" bonus is worth extra (see below).\n
148  */
149 PRICE object_value_real(const ObjectType *o_ptr)
150 {
151     auto *k_ptr = &k_info[o_ptr->k_idx];
152
153     if (!k_info[o_ptr->k_idx].cost) {
154         return 0;
155     }
156
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];
161         if (!a_ptr->cost) {
162             return 0;
163         }
164
165         value = a_ptr->cost;
166         value += flag_cost(o_ptr, o_ptr->pval);
167         return value;
168     } else if (o_ptr->is_ego()) {
169         auto *e_ptr = &e_info[o_ptr->ego_idx];
170         if (!e_ptr->cost) {
171             return 0;
172         }
173
174         value += e_ptr->cost;
175         value += flag_cost(o_ptr, o_ptr->pval);
176     } else {
177         if (o_ptr->art_flags.any()) {
178             value += flag_cost(o_ptr, o_ptr->pval);
179         }
180     }
181
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:
204         if (!o_ptr->pval) {
205             break;
206         }
207         if (o_ptr->pval < 0) {
208             return 0;
209         }
210
211         if (flgs.has(TR_STR)) {
212             value += (o_ptr->pval * 200L);
213         }
214         if (flgs.has(TR_INT)) {
215             value += (o_ptr->pval * 200L);
216         }
217         if (flgs.has(TR_WIS)) {
218             value += (o_ptr->pval * 200L);
219         }
220         if (flgs.has(TR_DEX)) {
221             value += (o_ptr->pval * 200L);
222         }
223         if (flgs.has(TR_CON)) {
224             value += (o_ptr->pval * 200L);
225         }
226         if (flgs.has(TR_CHR)) {
227             value += (o_ptr->pval * 200L);
228         }
229         if (flgs.has(TR_MAGIC_MASTERY)) {
230             value += (o_ptr->pval * 100);
231         }
232         if (flgs.has(TR_STEALTH)) {
233             value += (o_ptr->pval * 100L);
234         }
235         if (flgs.has(TR_SEARCH)) {
236             value += (o_ptr->pval * 100L);
237         }
238         if (flgs.has(TR_INFRA)) {
239             value += (o_ptr->pval * 50L);
240         }
241         if (flgs.has(TR_TUNNEL)) {
242             value += (o_ptr->pval * 50L);
243         }
244         if (flgs.has(TR_BLOWS)) {
245             value += (o_ptr->pval * 5000L);
246         }
247         if (flgs.has(TR_SPEED)) {
248             value += (o_ptr->pval * 10000L);
249         }
250         break;
251
252     default:
253         break;
254     }
255
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-
260          */
261         value += (value * o_ptr->pval / o_ptr->number / (k_ptr->pval * 2));
262         break;
263     }
264     case ItemKindType::STAFF: {
265         /* Pay extra for charges, depending on standard number of
266          * charges.  -LM-
267          */
268         value += (value * o_ptr->pval / (k_ptr->pval * 2));
269         break;
270     }
271     case ItemKindType::RING:
272     case ItemKindType::AMULET: {
273         if (o_ptr->to_h + o_ptr->to_d + o_ptr->to_a < 0) {
274             return 0;
275         }
276
277         value += ((o_ptr->to_h + o_ptr->to_d + o_ptr->to_a) * 200L);
278         break;
279     }
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) {
290             return 0;
291         }
292
293         value += (((o_ptr->to_h - k_ptr->to_h) + (o_ptr->to_d - k_ptr->to_d)) * 200L + (o_ptr->to_a) * 100L);
294         break;
295     }
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) {
302             return 0;
303         }
304
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;
308         break;
309     }
310     case ItemKindType::SHOT:
311     case ItemKindType::ARROW:
312     case ItemKindType::BOLT: {
313         if (o_ptr->to_h + o_ptr->to_d < 0) {
314             return 0;
315         }
316
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;
320         break;
321     }
322     case ItemKindType::FIGURINE: {
323         auto figure_r_idx = i2enum<MonsterRaceId>(o_ptr->pval);
324         DEPTH level = r_info[figure_r_idx].level;
325         if (level < 20) {
326             value = level * 50L;
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;
333         } else {
334             value = 14000 + (level - 50) * 2000L;
335         }
336         break;
337     }
338     case ItemKindType::CAPTURE: {
339         auto capture_r_idx = i2enum<MonsterRaceId>(o_ptr->pval);
340         if (!is_valid_monster_race(capture_r_idx)) {
341             value = 1000L;
342         } else {
343             value = ((r_info[capture_r_idx].level) * 50L + 1000);
344         }
345         break;
346     }
347     case ItemKindType::CHEST: {
348         if (!o_ptr->pval) {
349             value = 0L;
350         }
351         break;
352     }
353
354     default:
355         break;
356     }
357
358     if (value < 0) {
359         return 0L;
360     }
361
362     return value;
363 }