1 #include "store/service-checker.h"
2 #include "object-enchant/tr-types.h"
3 #include "object/object-value.h"
4 #include "object/tval-types.h"
5 #include "store/store-util.h"
6 #include "sv-definition/sv-potion-types.h"
7 #include "sv-definition/sv-rod-types.h"
8 #include "sv-definition/sv-scroll-types.h"
9 #include "sv-definition/sv-weapon-types.h"
10 #include "system/item-entity.h"
11 #include "system/monster-race-info.h"
12 #include "system/player-type-definition.h"
13 #include "util/bit-flags-calculator.h"
14 #include "util/string-processor.h"
17 * @brief オブジェクトが祝福されているかの判定を返す /
18 * @param item_ptr 判定したいオブジェクト構造体の参照ポインタ
19 * @return アイテムが祝福されたアイテムならばTRUEを返す
21 static bool is_blessed_item(const ItemEntity *item_ptr)
23 return item_ptr->get_flags().has(TR_BLESSED);
26 static bool check_store_general(const ItemEntity &item)
28 const auto &bi_key = item.bi_key;
29 switch (bi_key.tval()) {
30 case ItemKindType::ROD:
31 return (bi_key.sval() == SV_ROD_PESTICIDE);
32 case ItemKindType::POTION:
33 return (bi_key.sval() == SV_POTION_WATER);
34 case ItemKindType::WHISTLE:
35 case ItemKindType::FOOD:
36 case ItemKindType::LITE:
37 case ItemKindType::FLASK:
38 case ItemKindType::SPIKE:
39 case ItemKindType::SHOT:
40 case ItemKindType::ARROW:
41 case ItemKindType::BOLT:
42 case ItemKindType::DIGGING:
43 case ItemKindType::CLOAK:
44 case ItemKindType::BOTTLE:
45 case ItemKindType::FIGURINE:
46 case ItemKindType::STATUE:
47 case ItemKindType::CAPTURE:
48 case ItemKindType::CARD:
55 static bool check_store_armoury(const ItemEntity &item)
57 switch (item.bi_key.tval()) {
58 case ItemKindType::BOOTS:
59 case ItemKindType::GLOVES:
60 case ItemKindType::CROWN:
61 case ItemKindType::HELM:
62 case ItemKindType::SHIELD:
63 case ItemKindType::CLOAK:
64 case ItemKindType::SOFT_ARMOR:
65 case ItemKindType::HARD_ARMOR:
66 case ItemKindType::DRAG_ARMOR:
73 static bool check_store_weapon(const ItemEntity &item)
75 switch (item.bi_key.tval()) {
76 case ItemKindType::SHOT:
77 case ItemKindType::BOLT:
78 case ItemKindType::ARROW:
79 case ItemKindType::BOW:
80 case ItemKindType::DIGGING:
81 case ItemKindType::POLEARM:
82 case ItemKindType::SWORD:
83 case ItemKindType::HISSATSU_BOOK:
85 case ItemKindType::HAFTED:
86 return item.bi_key.sval() != SV_WIZSTAFF;
92 static bool check_store_temple(const ItemEntity &item)
94 switch (item.bi_key.tval()) {
95 case ItemKindType::LIFE_BOOK:
96 case ItemKindType::CRUSADE_BOOK:
97 case ItemKindType::SCROLL:
98 case ItemKindType::POTION:
99 case ItemKindType::HAFTED:
101 case ItemKindType::FIGURINE:
102 case ItemKindType::STATUE: {
103 const auto &monrace = item.get_monrace();
104 if (monrace.kind_flags.has_not(MonsterKindType::EVIL)) {
105 auto can_sell = monrace.kind_flags.has(MonsterKindType::GOOD);
106 can_sell |= monrace.kind_flags.has(MonsterKindType::ANIMAL);
107 can_sell |= monrace.symbol_char_is_any_of("?!");
114 case ItemKindType::POLEARM:
115 case ItemKindType::SWORD:
116 if (is_blessed_item(&item)) {
126 static bool check_store_alchemist(const ItemEntity &item)
128 switch (item.bi_key.tval()) {
129 case ItemKindType::SCROLL:
130 case ItemKindType::POTION:
137 static bool check_store_magic(const ItemEntity &item)
139 switch (item.bi_key.tval()) {
140 case ItemKindType::SORCERY_BOOK:
141 case ItemKindType::NATURE_BOOK:
142 case ItemKindType::CHAOS_BOOK:
143 case ItemKindType::DEATH_BOOK:
144 case ItemKindType::TRUMP_BOOK:
145 case ItemKindType::ARCANE_BOOK:
146 case ItemKindType::CRAFT_BOOK:
147 case ItemKindType::DEMON_BOOK:
148 case ItemKindType::MUSIC_BOOK:
149 case ItemKindType::HEX_BOOK:
150 case ItemKindType::AMULET:
151 case ItemKindType::RING:
152 case ItemKindType::STAFF:
153 case ItemKindType::WAND:
154 case ItemKindType::ROD:
155 case ItemKindType::SCROLL:
156 case ItemKindType::POTION:
157 case ItemKindType::FIGURINE:
159 case ItemKindType::HAFTED:
160 return item.bi_key.sval() == SV_WIZSTAFF;
166 static bool check_store_book(const ItemEntity &item)
168 switch (item.bi_key.tval()) {
169 case ItemKindType::SORCERY_BOOK:
170 case ItemKindType::NATURE_BOOK:
171 case ItemKindType::CHAOS_BOOK:
172 case ItemKindType::DEATH_BOOK:
173 case ItemKindType::LIFE_BOOK:
174 case ItemKindType::TRUMP_BOOK:
175 case ItemKindType::ARCANE_BOOK:
176 case ItemKindType::CRAFT_BOOK:
177 case ItemKindType::DEMON_BOOK:
178 case ItemKindType::CRUSADE_BOOK:
179 case ItemKindType::MUSIC_BOOK:
180 case ItemKindType::HEX_BOOK:
187 static bool switch_store_check(const ItemEntity &item, StoreSaleType store_num)
190 case StoreSaleType::GENERAL:
191 return check_store_general(item);
192 case StoreSaleType::ARMOURY:
193 return check_store_armoury(item);
194 case StoreSaleType::WEAPON:
195 return check_store_weapon(item);
196 case StoreSaleType::TEMPLE:
197 return check_store_temple(item);
198 case StoreSaleType::ALCHEMIST:
199 return check_store_alchemist(item);
200 case StoreSaleType::MAGIC:
201 return check_store_magic(item);
202 case StoreSaleType::BOOK:
203 return check_store_book(item);
210 * @brief オブジェクトが所定の店舗で引き取れるかどうかを返す /
211 * Determine if the current store will purchase the given item
212 * @param o_ptr 判定したいオブジェクト構造体の参照ポインタ
213 * @return アイテムが買い取れるならばTRUEを返す
215 * Note that a shop-keeper must refuse to buy "worthless" items
218 bool store_will_buy(PlayerType *, const ItemEntity *o_ptr, StoreSaleType store_num)
220 if ((store_num == StoreSaleType::HOME) || (store_num == StoreSaleType::MUSEUM)) {
224 if (!switch_store_check(*o_ptr, store_num)) {
228 return o_ptr->get_price() > 0;
231 static int mass_lite_produce(const PRICE cost)
235 size += damroll(3, 5);
239 size += damroll(3, 5);
243 size += damroll(2, 2);
249 static int mass_scroll_produce(const ItemEntity &item, const PRICE cost)
253 size += damroll(3, 5);
257 size += damroll(1, 5);
260 const auto sval = item.bi_key.sval();
261 if (sval == SV_SCROLL_STAR_IDENTIFY) {
262 size += damroll(3, 5);
265 if (sval == SV_SCROLL_STAR_REMOVE_CURSE) {
266 size += damroll(1, 4);
272 static int mass_book_produce(const PRICE cost)
276 size += damroll(2, 3);
280 size += damroll(1, 3);
286 static int mass_equipment_produce(const ItemEntity &item, const PRICE cost)
289 if (item.is_fixed_or_random_artifact() || item.is_ego()) {
294 size += damroll(3, 5);
298 size += damroll(3, 5);
304 static int mass_arrow_produce(const PRICE cost)
308 size += damroll(5, 5);
312 size += damroll(5, 5);
316 size += damroll(5, 5);
322 static int mass_figurine_produce(const PRICE cost)
326 size += damroll(2, 2);
330 size += damroll(2, 2);
336 static int mass_magic_produce(const PRICE cost, StoreSaleType store_num)
339 if ((store_num != StoreSaleType::BLACK) || !one_in_(3)) {
344 size += damroll(1, 5);
345 } else if (cost < 3201L) {
346 size += damroll(1, 3);
352 static int switch_mass_production(const ItemEntity &item, const PRICE cost, StoreSaleType store_num)
354 switch (item.bi_key.tval()) {
355 case ItemKindType::FOOD:
356 case ItemKindType::FLASK:
357 case ItemKindType::LITE:
358 return mass_lite_produce(cost);
359 case ItemKindType::POTION:
360 case ItemKindType::SCROLL:
361 return mass_scroll_produce(item, cost);
362 case ItemKindType::LIFE_BOOK:
363 case ItemKindType::SORCERY_BOOK:
364 case ItemKindType::NATURE_BOOK:
365 case ItemKindType::CHAOS_BOOK:
366 case ItemKindType::DEATH_BOOK:
367 case ItemKindType::TRUMP_BOOK:
368 case ItemKindType::ARCANE_BOOK:
369 case ItemKindType::CRAFT_BOOK:
370 case ItemKindType::DEMON_BOOK:
371 case ItemKindType::CRUSADE_BOOK:
372 case ItemKindType::MUSIC_BOOK:
373 case ItemKindType::HISSATSU_BOOK:
374 case ItemKindType::HEX_BOOK:
375 return mass_book_produce(cost);
376 case ItemKindType::SOFT_ARMOR:
377 case ItemKindType::HARD_ARMOR:
378 case ItemKindType::SHIELD:
379 case ItemKindType::GLOVES:
380 case ItemKindType::BOOTS:
381 case ItemKindType::CLOAK:
382 case ItemKindType::HELM:
383 case ItemKindType::CROWN:
384 case ItemKindType::SWORD:
385 case ItemKindType::POLEARM:
386 case ItemKindType::HAFTED:
387 case ItemKindType::DIGGING:
388 case ItemKindType::BOW:
389 return mass_equipment_produce(item, cost);
390 case ItemKindType::SPIKE:
391 case ItemKindType::SHOT:
392 case ItemKindType::ARROW:
393 case ItemKindType::BOLT:
394 return mass_arrow_produce(cost);
395 case ItemKindType::FIGURINE:
396 return mass_figurine_produce(cost);
397 case ItemKindType::CAPTURE:
398 case ItemKindType::STATUE:
399 case ItemKindType::CARD:
401 case ItemKindType::ROD:
402 case ItemKindType::WAND:
403 case ItemKindType::STAFF:
404 return mass_magic_produce(cost, store_num);
410 static byte decide_discount_rate(const PRICE cost)
436 * @brief 安価な消耗品の販売数を増やし、低確率で割引にする /
437 * Certain "cheap" objects should be created in "piles"
438 * @param o_ptr 店舗に並べるオブジェクト構造体の参照ポインタ
441 * Some objects can be sold at a "discount" (in small piles)
444 void mass_produce(ItemEntity *o_ptr, StoreSaleType store_num)
446 const auto cost = o_ptr->get_price();
447 int size = switch_mass_production(*o_ptr, cost, store_num);
448 auto discount = decide_discount_rate(cost);
449 if (o_ptr->is_random_artifact()) {
453 o_ptr->discount = discount;
454 o_ptr->number = size - (size * discount / 100);
455 if (o_ptr->is_wand_rod()) {
456 o_ptr->pval *= (PARAMETER_VALUE)o_ptr->number;