OSDN Git Service

[Refactor] #1766 Changed ItemPrimaryType from enum to enum class
[hengbandforosx/hengbandosx.git] / src / store / service-checker.cpp
1 #include "store/service-checker.h"
2 #include "monster-race/monster-race.h"
3 #include "monster-race/race-flags3.h"
4 #include "object-enchant/tr-types.h"
5 #include "object/object-flags.h"
6 #include "object/object-value.h"
7 #include "store/store-util.h"
8 #include "sv-definition/sv-potion-types.h"
9 #include "sv-definition/sv-rod-types.h"
10 #include "sv-definition/sv-scroll-types.h"
11 #include "sv-definition/sv-weapon-types.h"
12 #include "system/monster-race-definition.h"
13 #include "system/object-type-definition.h"
14 #include "system/player-type-definition.h"
15 #include "util/bit-flags-calculator.h"
16 #include "util/string-processor.h"
17
18 /*!
19  * @brief オブジェクトが祝福されているかの判定を返す /
20  * @param o_ptr 判定したいオブジェクト構造体の参照ポインタ
21  * @return アイテムが祝福されたアイテムならばTRUEを返す
22  */
23 static bool is_blessed_item(const object_type *o_ptr)
24 {
25     auto flgs = object_flags(o_ptr);
26     return flgs.has(TR_BLESSED);
27 }
28
29 static bool check_store_general(const object_type *o_ptr)
30 {
31     switch (o_ptr->tval) {
32     case ItemPrimaryType::TV_ROD:
33         return (o_ptr->sval == SV_ROD_PESTICIDE);
34     case ItemPrimaryType::TV_POTION:
35         return (o_ptr->sval == SV_POTION_WATER);
36     case ItemPrimaryType::TV_WHISTLE:
37     case ItemPrimaryType::TV_FOOD:
38     case ItemPrimaryType::TV_LITE:
39     case ItemPrimaryType::TV_FLASK:
40     case ItemPrimaryType::TV_SPIKE:
41     case ItemPrimaryType::TV_SHOT:
42     case ItemPrimaryType::TV_ARROW:
43     case ItemPrimaryType::TV_BOLT:
44     case ItemPrimaryType::TV_DIGGING:
45     case ItemPrimaryType::TV_CLOAK:
46     case ItemPrimaryType::TV_BOTTLE:
47     case ItemPrimaryType::TV_FIGURINE:
48     case ItemPrimaryType::TV_STATUE:
49     case ItemPrimaryType::TV_CAPTURE:
50     case ItemPrimaryType::TV_CARD:
51         return true;
52     default:
53         return false;
54     }
55 }
56
57 static bool check_store_armoury(const object_type *o_ptr)
58 {
59     switch (o_ptr->tval) {
60     case ItemPrimaryType::TV_BOOTS:
61     case ItemPrimaryType::TV_GLOVES:
62     case ItemPrimaryType::TV_CROWN:
63     case ItemPrimaryType::TV_HELM:
64     case ItemPrimaryType::TV_SHIELD:
65     case ItemPrimaryType::TV_CLOAK:
66     case ItemPrimaryType::TV_SOFT_ARMOR:
67     case ItemPrimaryType::TV_HARD_ARMOR:
68     case ItemPrimaryType::TV_DRAG_ARMOR:
69         return true;
70     default:
71         return false;
72     }
73 }
74
75 static bool check_store_weapon(const object_type *o_ptr)
76 {
77     switch (o_ptr->tval) {
78     case ItemPrimaryType::TV_SHOT:
79     case ItemPrimaryType::TV_BOLT:
80     case ItemPrimaryType::TV_ARROW:
81     case ItemPrimaryType::TV_BOW:
82     case ItemPrimaryType::TV_DIGGING:
83     case ItemPrimaryType::TV_POLEARM:
84     case ItemPrimaryType::TV_SWORD:
85     case ItemPrimaryType::TV_HISSATSU_BOOK:
86         return true;
87     case ItemPrimaryType::TV_HAFTED:
88         return o_ptr->sval != SV_WIZSTAFF;
89     default:
90         return false;
91     }
92 }
93
94 static bool check_store_temple(const object_type *o_ptr)
95 {
96     switch (o_ptr->tval) {
97     case ItemPrimaryType::TV_LIFE_BOOK:
98     case ItemPrimaryType::TV_CRUSADE_BOOK:
99     case ItemPrimaryType::TV_SCROLL:
100     case ItemPrimaryType::TV_POTION:
101     case ItemPrimaryType::TV_HAFTED:
102         return true;
103     case ItemPrimaryType::TV_FIGURINE:
104     case ItemPrimaryType::TV_STATUE: {
105         monster_race *r_ptr = &r_info[o_ptr->pval];
106         if (!(r_ptr->flags3 & RF3_EVIL))
107             if (((r_ptr->flags3 & RF3_GOOD) != 0) || ((r_ptr->flags3 & RF3_ANIMAL) != 0) || (angband_strchr("?!", r_ptr->d_char) != nullptr))
108                 return true;
109     }
110         /* Fall through */
111     case ItemPrimaryType::TV_POLEARM:
112     case ItemPrimaryType::TV_SWORD:
113         if (is_blessed_item(o_ptr))
114             return true;
115
116         /* Fall through */
117     default:
118         return false;
119     }
120 }
121
122 static bool check_store_alchemist(const object_type *o_ptr)
123 {
124     switch (o_ptr->tval) {
125     case ItemPrimaryType::TV_SCROLL:
126     case ItemPrimaryType::TV_POTION:
127         return true;
128     default:
129         return false;
130     }
131 }
132
133 static bool check_store_magic(const object_type *o_ptr)
134 {
135     switch (o_ptr->tval) {
136     case ItemPrimaryType::TV_SORCERY_BOOK:
137     case ItemPrimaryType::TV_NATURE_BOOK:
138     case ItemPrimaryType::TV_CHAOS_BOOK:
139     case ItemPrimaryType::TV_DEATH_BOOK:
140     case ItemPrimaryType::TV_TRUMP_BOOK:
141     case ItemPrimaryType::TV_ARCANE_BOOK:
142     case ItemPrimaryType::TV_CRAFT_BOOK:
143     case ItemPrimaryType::TV_DEMON_BOOK:
144     case ItemPrimaryType::TV_MUSIC_BOOK:
145     case ItemPrimaryType::TV_HEX_BOOK:
146     case ItemPrimaryType::TV_AMULET:
147     case ItemPrimaryType::TV_RING:
148     case ItemPrimaryType::TV_STAFF:
149     case ItemPrimaryType::TV_WAND:
150     case ItemPrimaryType::TV_ROD:
151     case ItemPrimaryType::TV_SCROLL:
152     case ItemPrimaryType::TV_POTION:
153     case ItemPrimaryType::TV_FIGURINE:
154         return true;
155     case ItemPrimaryType::TV_HAFTED:
156         return o_ptr->sval == SV_WIZSTAFF;
157     default:
158         return false;
159     }
160 }
161
162 static bool check_store_book(const object_type *o_ptr)
163 {
164     switch (o_ptr->tval) {
165     case ItemPrimaryType::TV_SORCERY_BOOK:
166     case ItemPrimaryType::TV_NATURE_BOOK:
167     case ItemPrimaryType::TV_CHAOS_BOOK:
168     case ItemPrimaryType::TV_DEATH_BOOK:
169     case ItemPrimaryType::TV_LIFE_BOOK:
170     case ItemPrimaryType::TV_TRUMP_BOOK:
171     case ItemPrimaryType::TV_ARCANE_BOOK:
172     case ItemPrimaryType::TV_CRAFT_BOOK:
173     case ItemPrimaryType::TV_DEMON_BOOK:
174     case ItemPrimaryType::TV_CRUSADE_BOOK:
175     case ItemPrimaryType::TV_MUSIC_BOOK:
176     case ItemPrimaryType::TV_HEX_BOOK:
177         return true;
178     default:
179         return false;
180     }
181 }
182
183 static bool switch_store_check(const object_type *o_ptr)
184 {
185     switch (cur_store_num) {
186     case StoreSaleType::GENERAL:
187         return check_store_general(o_ptr);
188     case StoreSaleType::ARMOURY:
189         return check_store_armoury(o_ptr);
190     case StoreSaleType::WEAPON:
191         return check_store_weapon(o_ptr);
192     case StoreSaleType::TEMPLE:
193         return check_store_temple(o_ptr);
194     case StoreSaleType::ALCHEMIST:
195         return check_store_alchemist(o_ptr);
196     case StoreSaleType::MAGIC:
197         return check_store_magic(o_ptr);
198     case StoreSaleType::BOOK:
199         return check_store_book(o_ptr);
200     default:
201         return true;
202     }
203 }
204
205 /*!
206  * @brief オブジェクトが所定の店舗で引き取れるかどうかを返す /
207  * Determine if the current store will purchase the given item
208  * @param o_ptr 判定したいオブジェクト構造体の参照ポインタ
209  * @return アイテムが買い取れるならばTRUEを返す
210  * @note
211  * Note that a shop-keeper must refuse to buy "worthless" items
212  */
213 bool store_will_buy(player_type *, const object_type *o_ptr)
214 {
215     if ((cur_store_num == StoreSaleType::HOME) || (cur_store_num == StoreSaleType::MUSEUM))
216         return true;
217
218     if (!switch_store_check(o_ptr))
219         return false;
220
221     return object_value(o_ptr) > 0;
222 }
223
224 static int mass_lite_produce(const PRICE cost)
225 {
226     int size = 1;
227     if (cost <= 5L)
228         size += damroll(3, 5);
229
230     if (cost <= 20L)
231         size += damroll(3, 5);
232
233     if (cost <= 50L)
234         size += damroll(2, 2);
235
236     return size;
237 }
238
239 static int mass_scroll_produce(object_type *o_ptr, const PRICE cost)
240 {
241     int size = 1;
242     if (cost <= 60L)
243         size += damroll(3, 5);
244
245     if (cost <= 240L)
246         size += damroll(1, 5);
247
248     if (o_ptr->sval == SV_SCROLL_STAR_IDENTIFY)
249         size += damroll(3, 5);
250
251     if (o_ptr->sval == SV_SCROLL_STAR_REMOVE_CURSE)
252         size += damroll(1, 4);
253
254     return size;
255 }
256
257 static int mass_book_produce(const PRICE cost)
258 {
259     int size = 1;
260     if (cost <= 50L)
261         size += damroll(2, 3);
262
263     if (cost <= 500L)
264         size += damroll(1, 3);
265
266     return size;
267 }
268
269 static int mass_equipment_produce(object_type *o_ptr, const PRICE cost)
270 {
271     int size = 1;
272     if (o_ptr->is_artifact() || o_ptr->is_ego())
273         return size;
274
275     if (cost <= 10L)
276         size += damroll(3, 5);
277
278     if (cost <= 100L)
279         size += damroll(3, 5);
280
281     return size;
282 }
283
284 static int mass_arrow_produce(const PRICE cost)
285 {
286     int size = 1;
287     if (cost <= 5L)
288         size += damroll(5, 5);
289
290     if (cost <= 50L)
291         size += damroll(5, 5);
292
293     if (cost <= 500L)
294         size += damroll(5, 5);
295
296     return size;
297 }
298
299 static int mass_figurine_produce(const PRICE cost)
300 {
301     int size = 1;
302     if (cost <= 100L)
303         size += damroll(2, 2);
304
305     if (cost <= 1000L)
306         size += damroll(2, 2);
307
308     return size;
309 }
310
311 static int mass_magic_produce(const PRICE cost)
312 {
313     int size = 1;
314     if ((cur_store_num != StoreSaleType::BLACK) || !one_in_(3))
315         return size;
316
317     if (cost < 1601L)
318         size += damroll(1, 5);
319     else if (cost < 3201L)
320         size += damroll(1, 3);
321
322     return size;
323 }
324
325 static int switch_mass_production(object_type *o_ptr, const PRICE cost)
326 {
327     switch (o_ptr->tval) {
328     case ItemPrimaryType::TV_FOOD:
329     case ItemPrimaryType::TV_FLASK:
330     case ItemPrimaryType::TV_LITE:
331         return mass_lite_produce(cost);
332     case ItemPrimaryType::TV_POTION:
333     case ItemPrimaryType::TV_SCROLL:
334         return mass_scroll_produce(o_ptr, cost);
335     case ItemPrimaryType::TV_LIFE_BOOK:
336     case ItemPrimaryType::TV_SORCERY_BOOK:
337     case ItemPrimaryType::TV_NATURE_BOOK:
338     case ItemPrimaryType::TV_CHAOS_BOOK:
339     case ItemPrimaryType::TV_DEATH_BOOK:
340     case ItemPrimaryType::TV_TRUMP_BOOK:
341     case ItemPrimaryType::TV_ARCANE_BOOK:
342     case ItemPrimaryType::TV_CRAFT_BOOK:
343     case ItemPrimaryType::TV_DEMON_BOOK:
344     case ItemPrimaryType::TV_CRUSADE_BOOK:
345     case ItemPrimaryType::TV_MUSIC_BOOK:
346     case ItemPrimaryType::TV_HISSATSU_BOOK:
347     case ItemPrimaryType::TV_HEX_BOOK:
348         return mass_book_produce(cost);
349     case ItemPrimaryType::TV_SOFT_ARMOR:
350     case ItemPrimaryType::TV_HARD_ARMOR:
351     case ItemPrimaryType::TV_SHIELD:
352     case ItemPrimaryType::TV_GLOVES:
353     case ItemPrimaryType::TV_BOOTS:
354     case ItemPrimaryType::TV_CLOAK:
355     case ItemPrimaryType::TV_HELM:
356     case ItemPrimaryType::TV_CROWN:
357     case ItemPrimaryType::TV_SWORD:
358     case ItemPrimaryType::TV_POLEARM:
359     case ItemPrimaryType::TV_HAFTED:
360     case ItemPrimaryType::TV_DIGGING:
361     case ItemPrimaryType::TV_BOW:
362         return mass_equipment_produce(o_ptr, cost);
363     case ItemPrimaryType::TV_SPIKE:
364     case ItemPrimaryType::TV_SHOT:
365     case ItemPrimaryType::TV_ARROW:
366     case ItemPrimaryType::TV_BOLT:
367         return mass_arrow_produce(cost);
368     case ItemPrimaryType::TV_FIGURINE:
369         return mass_figurine_produce(cost);
370     case ItemPrimaryType::TV_CAPTURE:
371     case ItemPrimaryType::TV_STATUE:
372     case ItemPrimaryType::TV_CARD:
373         return 1;
374     case ItemPrimaryType::TV_ROD:
375     case ItemPrimaryType::TV_WAND:
376     case ItemPrimaryType::TV_STAFF:
377         return mass_magic_produce(cost);
378     default:
379         return 1;
380     }
381 }
382
383 static byte decide_discount_rate(const PRICE cost)
384 {
385     if (cost < 5)
386         return 0;
387     
388     if (one_in_(25))
389         return 25;
390     
391     if (one_in_(150))
392         return 50;
393     
394     if (one_in_(300))
395         return 75;
396     
397     if (one_in_(500))
398         return 90;
399
400     return 0;
401 }
402
403 /*!
404  * @brief 安価な消耗品の販売数を増やし、低確率で割引にする /
405  * Certain "cheap" objects should be created in "piles"
406  * @param o_ptr 店舗に並べるオブジェクト構造体の参照ポインタ
407  * @details
408  * <pre>
409  * Some objects can be sold at a "discount" (in small piles)
410  * </pre>
411  */
412 void mass_produce(player_type *, object_type *o_ptr)
413 {
414     const PRICE cost = object_value(o_ptr);
415     int size = switch_mass_production(o_ptr, cost);
416     auto discount = decide_discount_rate(cost);
417     if (o_ptr->art_name)
418         discount = 0;
419
420     o_ptr->discount = discount;
421     o_ptr->number = size - (size * discount / 100);
422     if ((o_ptr->tval == ItemPrimaryType::TV_ROD) || (o_ptr->tval == ItemPrimaryType::TV_WAND))
423         o_ptr->pval *= (PARAMETER_VALUE)o_ptr->number;
424 }