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 "object/tval-types.h"
8 #include "store/store-util.h"
9 #include "sv-definition/sv-potion-types.h"
10 #include "sv-definition/sv-rod-types.h"
11 #include "sv-definition/sv-scroll-types.h"
12 #include "sv-definition/sv-weapon-types.h"
13 #include "system/item-entity.h"
14 #include "system/monster-race-info.h"
15 #include "system/player-type-definition.h"
16 #include "util/bit-flags-calculator.h"
17 #include "util/string-processor.h"
20 * @brief オブジェクトが祝福されているかの判定を返す /
21 * @param item_ptr 判定したいオブジェクト構造体の参照ポインタ
22 * @return アイテムが祝福されたアイテムならばTRUEを返す
24 static bool is_blessed_item(const ItemEntity *item_ptr)
26 auto flags = object_flags(item_ptr);
27 return flags.has(TR_BLESSED);
30 static bool check_store_general(const ItemEntity &item)
32 const auto &bi_key = item.bi_key;
33 switch (bi_key.tval()) {
34 case ItemKindType::ROD:
35 return (bi_key.sval() == SV_ROD_PESTICIDE);
36 case ItemKindType::POTION:
37 return (bi_key.sval() == SV_POTION_WATER);
38 case ItemKindType::WHISTLE:
39 case ItemKindType::FOOD:
40 case ItemKindType::LITE:
41 case ItemKindType::FLASK:
42 case ItemKindType::SPIKE:
43 case ItemKindType::SHOT:
44 case ItemKindType::ARROW:
45 case ItemKindType::BOLT:
46 case ItemKindType::DIGGING:
47 case ItemKindType::CLOAK:
48 case ItemKindType::BOTTLE:
49 case ItemKindType::FIGURINE:
50 case ItemKindType::STATUE:
51 case ItemKindType::CAPTURE:
52 case ItemKindType::CARD:
59 static bool check_store_armoury(const ItemEntity &item)
61 switch (item.bi_key.tval()) {
62 case ItemKindType::BOOTS:
63 case ItemKindType::GLOVES:
64 case ItemKindType::CROWN:
65 case ItemKindType::HELM:
66 case ItemKindType::SHIELD:
67 case ItemKindType::CLOAK:
68 case ItemKindType::SOFT_ARMOR:
69 case ItemKindType::HARD_ARMOR:
70 case ItemKindType::DRAG_ARMOR:
77 static bool check_store_weapon(const ItemEntity &item)
79 switch (item.bi_key.tval()) {
80 case ItemKindType::SHOT:
81 case ItemKindType::BOLT:
82 case ItemKindType::ARROW:
83 case ItemKindType::BOW:
84 case ItemKindType::DIGGING:
85 case ItemKindType::POLEARM:
86 case ItemKindType::SWORD:
87 case ItemKindType::HISSATSU_BOOK:
89 case ItemKindType::HAFTED:
90 return item.bi_key.sval() != SV_WIZSTAFF;
96 static bool check_store_temple(const ItemEntity &item)
98 switch (item.bi_key.tval()) {
99 case ItemKindType::LIFE_BOOK:
100 case ItemKindType::CRUSADE_BOOK:
101 case ItemKindType::SCROLL:
102 case ItemKindType::POTION:
103 case ItemKindType::HAFTED:
105 case ItemKindType::FIGURINE:
106 case ItemKindType::STATUE: {
107 auto *r_ptr = &monraces_info[i2enum<MonsterRaceId>(item.pval)];
108 if (r_ptr->kind_flags.has_not(MonsterKindType::EVIL)) {
109 if ((r_ptr->kind_flags.has(MonsterKindType::GOOD)) || (r_ptr->kind_flags.has(MonsterKindType::ANIMAL)) || (angband_strchr("?!", r_ptr->d_char) != nullptr)) {
115 case ItemKindType::POLEARM:
116 case ItemKindType::SWORD:
117 if (is_blessed_item(&item)) {
127 static bool check_store_alchemist(const ItemEntity &item)
129 switch (item.bi_key.tval()) {
130 case ItemKindType::SCROLL:
131 case ItemKindType::POTION:
138 static bool check_store_magic(const ItemEntity &item)
140 switch (item.bi_key.tval()) {
141 case ItemKindType::SORCERY_BOOK:
142 case ItemKindType::NATURE_BOOK:
143 case ItemKindType::CHAOS_BOOK:
144 case ItemKindType::DEATH_BOOK:
145 case ItemKindType::TRUMP_BOOK:
146 case ItemKindType::ARCANE_BOOK:
147 case ItemKindType::CRAFT_BOOK:
148 case ItemKindType::DEMON_BOOK:
149 case ItemKindType::MUSIC_BOOK:
150 case ItemKindType::HEX_BOOK:
151 case ItemKindType::AMULET:
152 case ItemKindType::RING:
153 case ItemKindType::STAFF:
154 case ItemKindType::WAND:
155 case ItemKindType::ROD:
156 case ItemKindType::SCROLL:
157 case ItemKindType::POTION:
158 case ItemKindType::FIGURINE:
160 case ItemKindType::HAFTED:
161 return item.bi_key.sval() == SV_WIZSTAFF;
167 static bool check_store_book(const ItemEntity &item)
169 switch (item.bi_key.tval()) {
170 case ItemKindType::SORCERY_BOOK:
171 case ItemKindType::NATURE_BOOK:
172 case ItemKindType::CHAOS_BOOK:
173 case ItemKindType::DEATH_BOOK:
174 case ItemKindType::LIFE_BOOK:
175 case ItemKindType::TRUMP_BOOK:
176 case ItemKindType::ARCANE_BOOK:
177 case ItemKindType::CRAFT_BOOK:
178 case ItemKindType::DEMON_BOOK:
179 case ItemKindType::CRUSADE_BOOK:
180 case ItemKindType::MUSIC_BOOK:
181 case ItemKindType::HEX_BOOK:
188 static bool switch_store_check(const ItemEntity &item, StoreSaleType store_num)
191 case StoreSaleType::GENERAL:
192 return check_store_general(item);
193 case StoreSaleType::ARMOURY:
194 return check_store_armoury(item);
195 case StoreSaleType::WEAPON:
196 return check_store_weapon(item);
197 case StoreSaleType::TEMPLE:
198 return check_store_temple(item);
199 case StoreSaleType::ALCHEMIST:
200 return check_store_alchemist(item);
201 case StoreSaleType::MAGIC:
202 return check_store_magic(item);
203 case StoreSaleType::BOOK:
204 return check_store_book(item);
211 * @brief オブジェクトが所定の店舗で引き取れるかどうかを返す /
212 * Determine if the current store will purchase the given item
213 * @param o_ptr 判定したいオブジェクト構造体の参照ポインタ
214 * @return アイテムが買い取れるならばTRUEを返す
216 * Note that a shop-keeper must refuse to buy "worthless" items
219 bool store_will_buy(PlayerType *, const ItemEntity *o_ptr, StoreSaleType store_num)
221 if ((store_num == StoreSaleType::HOME) || (store_num == StoreSaleType::MUSEUM)) {
225 if (!switch_store_check(*o_ptr, store_num)) {
229 return o_ptr->get_price() > 0;
232 static int mass_lite_produce(const PRICE cost)
236 size += damroll(3, 5);
240 size += damroll(3, 5);
244 size += damroll(2, 2);
250 static int mass_scroll_produce(const ItemEntity &item, const PRICE cost)
254 size += damroll(3, 5);
258 size += damroll(1, 5);
261 const auto sval = item.bi_key.sval();
262 if (sval == SV_SCROLL_STAR_IDENTIFY) {
263 size += damroll(3, 5);
266 if (sval == SV_SCROLL_STAR_REMOVE_CURSE) {
267 size += damroll(1, 4);
273 static int mass_book_produce(const PRICE cost)
277 size += damroll(2, 3);
281 size += damroll(1, 3);
287 static int mass_equipment_produce(const ItemEntity &item, const PRICE cost)
290 if (item.is_fixed_or_random_artifact() || item.is_ego()) {
295 size += damroll(3, 5);
299 size += damroll(3, 5);
305 static int mass_arrow_produce(const PRICE cost)
309 size += damroll(5, 5);
313 size += damroll(5, 5);
317 size += damroll(5, 5);
323 static int mass_figurine_produce(const PRICE cost)
327 size += damroll(2, 2);
331 size += damroll(2, 2);
337 static int mass_magic_produce(const PRICE cost, StoreSaleType store_num)
340 if ((store_num != StoreSaleType::BLACK) || !one_in_(3)) {
345 size += damroll(1, 5);
346 } else if (cost < 3201L) {
347 size += damroll(1, 3);
353 static int switch_mass_production(const ItemEntity &item, const PRICE cost, StoreSaleType store_num)
355 switch (item.bi_key.tval()) {
356 case ItemKindType::FOOD:
357 case ItemKindType::FLASK:
358 case ItemKindType::LITE:
359 return mass_lite_produce(cost);
360 case ItemKindType::POTION:
361 case ItemKindType::SCROLL:
362 return mass_scroll_produce(item, cost);
363 case ItemKindType::LIFE_BOOK:
364 case ItemKindType::SORCERY_BOOK:
365 case ItemKindType::NATURE_BOOK:
366 case ItemKindType::CHAOS_BOOK:
367 case ItemKindType::DEATH_BOOK:
368 case ItemKindType::TRUMP_BOOK:
369 case ItemKindType::ARCANE_BOOK:
370 case ItemKindType::CRAFT_BOOK:
371 case ItemKindType::DEMON_BOOK:
372 case ItemKindType::CRUSADE_BOOK:
373 case ItemKindType::MUSIC_BOOK:
374 case ItemKindType::HISSATSU_BOOK:
375 case ItemKindType::HEX_BOOK:
376 return mass_book_produce(cost);
377 case ItemKindType::SOFT_ARMOR:
378 case ItemKindType::HARD_ARMOR:
379 case ItemKindType::SHIELD:
380 case ItemKindType::GLOVES:
381 case ItemKindType::BOOTS:
382 case ItemKindType::CLOAK:
383 case ItemKindType::HELM:
384 case ItemKindType::CROWN:
385 case ItemKindType::SWORD:
386 case ItemKindType::POLEARM:
387 case ItemKindType::HAFTED:
388 case ItemKindType::DIGGING:
389 case ItemKindType::BOW:
390 return mass_equipment_produce(item, cost);
391 case ItemKindType::SPIKE:
392 case ItemKindType::SHOT:
393 case ItemKindType::ARROW:
394 case ItemKindType::BOLT:
395 return mass_arrow_produce(cost);
396 case ItemKindType::FIGURINE:
397 return mass_figurine_produce(cost);
398 case ItemKindType::CAPTURE:
399 case ItemKindType::STATUE:
400 case ItemKindType::CARD:
402 case ItemKindType::ROD:
403 case ItemKindType::WAND:
404 case ItemKindType::STAFF:
405 return mass_magic_produce(cost, store_num);
411 static byte decide_discount_rate(const PRICE cost)
437 * @brief 安価な消耗品の販売数を増やし、低確率で割引にする /
438 * Certain "cheap" objects should be created in "piles"
439 * @param o_ptr 店舗に並べるオブジェクト構造体の参照ポインタ
442 * Some objects can be sold at a "discount" (in small piles)
445 void mass_produce(ItemEntity *o_ptr, StoreSaleType store_num)
447 const auto cost = o_ptr->get_price();
448 int size = switch_mass_production(*o_ptr, cost, store_num);
449 auto discount = decide_discount_rate(cost);
450 if (o_ptr->is_random_artifact()) {
454 o_ptr->discount = discount;
455 o_ptr->number = size - (size * discount / 100);
456 if (o_ptr->is_wand_rod()) {
457 o_ptr->pval *= (PARAMETER_VALUE)o_ptr->number;