2 #include "market/store-util.h"
3 #include "object-hook.h"
4 #include "objectkind.h"
7 store_type *st_ptr = NULL;
10 * @brief 店舗のオブジェクト数を増やす /
11 * Add the item "o_ptr" to a real stores inventory.
12 * @param item 増やしたいアイテムのID
17 * Increase, by a given amount, the number of a certain item
18 * in a certain store. This can result in zero items.
20 * @todo numは本来ITEM_NUMBER型にしたい。
22 void store_item_increase(INVENTORY_IDX item, int num)
25 o_ptr = &st_ptr->stock[item];
26 int cnt = o_ptr->number + num;
27 if (cnt > 255) cnt = 255;
28 else if (cnt < 0) cnt = 0;
30 num = cnt - o_ptr->number;
31 o_ptr->number += (ITEM_NUMBER)num;
36 * @brief 店舗のオブジェクト数を削除する /
37 * Remove a slot if it is empty
38 * @param item 削除したいアイテムのID
41 void store_item_optimize(INVENTORY_IDX item)
44 o_ptr = &st_ptr->stock[item];
45 if (!o_ptr->k_idx) return;
46 if (o_ptr->number) return;
49 for (int j = item; j < st_ptr->stock_num; j++)
51 st_ptr->stock[j] = st_ptr->stock[j + 1];
54 object_wipe(&st_ptr->stock[st_ptr->stock_num]);
59 * @brief 店舗の品揃え変化のためにアイテムを削除する /
60 * Attempt to delete (some of) a random item from the store
64 * Hack -- we attempt to "maintain" piles of items when possible.
67 void store_delete(void)
69 INVENTORY_IDX what = (INVENTORY_IDX)randint0(st_ptr->stock_num);
70 int num = st_ptr->stock[what].number;
71 if (randint0(100) < 50) num = (num + 1) / 2;
72 if (randint0(100) < 50) num = 1;
73 if ((st_ptr->stock[what].tval == TV_ROD) || (st_ptr->stock[what].tval == TV_WAND))
75 st_ptr->stock[what].pval -= num * st_ptr->stock[what].pval / st_ptr->stock[what].number;
78 store_item_increase(what, -num);
79 store_item_optimize(what);
84 * @brief 安価な消耗品の販売数を増やし、低確率で割引にする /
85 * Certain "cheap" objects should be created in "piles"
86 * @param o_ptr 店舗に並べるオブジェクト構造体の参照ポインタ
90 * Some objects can be sold at a "discount" (in small piles)
93 static void mass_produce(object_type *o_ptr)
96 PRICE cost = object_value(o_ptr);
103 if (cost <= 5L) size += damroll(3, 5);
104 if (cost <= 20L) size += damroll(3, 5);
105 if (cost <= 50L) size += damroll(2, 2);
111 if (cost <= 60L) size += damroll(3, 5);
112 if (cost <= 240L) size += damroll(1, 5);
113 if (o_ptr->sval == SV_SCROLL_STAR_IDENTIFY) size += damroll(3, 5);
114 if (o_ptr->sval == SV_SCROLL_STAR_REMOVE_CURSE) size += damroll(1, 4);
118 case TV_SORCERY_BOOK:
126 case TV_CRUSADE_BOOK:
128 case TV_HISSATSU_BOOK:
131 if (cost <= 50L) size += damroll(2, 3);
132 if (cost <= 500L) size += damroll(1, 3);
149 if (object_is_artifact(o_ptr)) break;
150 if (object_is_ego(o_ptr)) break;
151 if (cost <= 10L) size += damroll(3, 5);
152 if (cost <= 100L) size += damroll(3, 5);
160 if (cost <= 5L) size += damroll(5, 5);
161 if (cost <= 50L) size += damroll(5, 5);
162 if (cost <= 500L) size += damroll(5, 5);
167 if (cost <= 100L) size += damroll(2, 2);
168 if (cost <= 1000L) size += damroll(2, 2);
180 * Because many rods (and a few wands and staffs) are useful mainly
181 * in quantity, the Black Market will occasionally have a bunch of
188 if ((cur_store_num == STORE_BLACK) && one_in_(3))
190 if (cost < 1601L) size += damroll(1, 5);
191 else if (cost < 3201L) size += damroll(1, 3);
197 DISCOUNT_RATE discount = 0;
202 else if (one_in_(25))
206 else if (one_in_(150))
210 else if (one_in_(300))
214 else if (one_in_(500))
224 o_ptr->discount = discount;
225 o_ptr->number = size - (size * discount / 100);
226 if ((o_ptr->tval == TV_ROD) || (o_ptr->tval == TV_WAND))
228 o_ptr->pval *= (PARAMETER_VALUE)o_ptr->number;
234 * @brief 店舗の品揃え変化のためにアイテムを追加する /
235 * Creates a random item and gives it to a store
236 * @param player_ptr プレーヤーへの参照ポインタ
240 * This algorithm needs to be rethought. A lot.
241 * Currently, "normal" stores use a pre-built array.
242 * Note -- the "level" given to "obj_get_num()" is a "favored"
243 * level, that is, there is a much higher chance of getting
244 * items with a level approaching that of the given level...
245 * Should we check for "permission" to have the given item?
248 void store_create(player_type *player_ptr, bool (*black_market_crap)(player_type*, object_type*))
250 if (st_ptr->stock_num >= st_ptr->stock_size) return;
252 for (int tries = 0; tries < 4; tries++)
256 if (cur_store_num == STORE_BLACK)
258 /* Pick a level for object/magic */
259 level = 25 + randint0(25);
261 /* Random item (usually of given level) */
262 i = get_obj_num(player_ptr, level, 0x00000000);
265 if (i == 0) continue;
269 i = st_ptr->table[randint0(st_ptr->table_num)];
270 level = rand_range(1, STORE_OBJ_LEVEL);
276 object_prep(q_ptr, i);
277 apply_magic(player_ptr, q_ptr, level, AM_NO_FIXED_ART);
278 if (!store_will_buy(q_ptr)) continue;
280 if (q_ptr->tval == TV_LITE)
282 if (q_ptr->sval == SV_LITE_TORCH) q_ptr->xtra4 = FUEL_TORCH / 2;
283 if (q_ptr->sval == SV_LITE_LANTERN) q_ptr->xtra4 = FUEL_LAMP / 2;
287 q_ptr->ident |= IDENT_STORE;
288 if (q_ptr->tval == TV_CHEST) continue;
290 if (cur_store_num == STORE_BLACK)
292 if (black_market_crap(player_ptr, q_ptr)) continue;
293 if (object_value(q_ptr) < 10) continue;
297 if (object_value(q_ptr) <= 0) continue;
301 (void)store_carry(q_ptr);
308 * @brief オブジェクトが祝福されているかの判定を返す /
309 * @param o_ptr 判定したいオブジェクト構造体の参照ポインタ
310 * @return アイテムが祝福されたアイテムならばTRUEを返す
312 static bool is_blessed_item(object_type *o_ptr)
314 BIT_FLAGS flgs[TR_FLAG_SIZE];
315 object_flags(o_ptr, flgs);
316 if (have_flag(flgs, TR_BLESSED)) return TRUE;
322 * @brief オブジェクトが所定の店舗で引き取れるかどうかを返す /
323 * Determine if the current store will purchase the given item
324 * @param o_ptr 判定したいオブジェクト構造体の参照ポインタ
325 * @return アイテムが買い取れるならばTRUEを返す
327 * Note that a shop-keeper must refuse to buy "worthless" items
329 bool store_will_buy(object_type *o_ptr)
331 if ((cur_store_num == STORE_HOME) || (cur_store_num == STORE_MUSEUM)) return TRUE;
332 switch (cur_store_num)
339 if (o_ptr->sval != SV_POTION_WATER) return FALSE;
394 case TV_HISSATSU_BOOK:
398 if (o_ptr->sval == SV_WIZSTAFF) return FALSE;
412 case TV_CRUSADE_BOOK:
422 monster_race *r_ptr = &r_info[o_ptr->pval];
423 if (!(r_ptr->flags3 & RF3_EVIL))
425 if (r_ptr->flags3 & RF3_GOOD) break;
426 if (r_ptr->flags3 & RF3_ANIMAL) break;
427 if (my_strchr("?!", r_ptr->d_char)) break;
434 if (is_blessed_item(o_ptr)) break;
443 case STORE_ALCHEMIST:
460 case TV_SORCERY_BOOK:
481 if (o_ptr->sval == SV_WIZSTAFF) break;
494 case TV_SORCERY_BOOK:
503 case TV_CRUSADE_BOOK:
515 if (object_value(o_ptr) <= 0) return FALSE;
521 * @brief 店舗に並べた品を同一品であるかどうか判定する /
522 * Determine if a store item can "absorb" another item
523 * @param o_ptr 判定するオブジェクト構造体の参照ポインタ1
524 * @param j_ptr 判定するオブジェクト構造体の参照ポインタ2
525 * @return 同一扱いできるならTRUEを返す
528 * See "object_similar()" for the same function for the "player"
531 bool store_object_similar(object_type *o_ptr, object_type *j_ptr)
533 if (o_ptr == j_ptr) return 0;
534 if (o_ptr->k_idx != j_ptr->k_idx) return 0;
535 if ((o_ptr->pval != j_ptr->pval) && (o_ptr->tval != TV_WAND) && (o_ptr->tval != TV_ROD)) return 0;
536 if (o_ptr->to_h != j_ptr->to_h) return 0;
537 if (o_ptr->to_d != j_ptr->to_d) return 0;
538 if (o_ptr->to_a != j_ptr->to_a) return 0;
539 if (o_ptr->name2 != j_ptr->name2) return 0;
540 if (object_is_artifact(o_ptr) || object_is_artifact(j_ptr)) return 0;
541 for (int i = 0; i < TR_FLAG_SIZE; i++)
542 if (o_ptr->art_flags[i] != j_ptr->art_flags[i]) return 0;
543 if (o_ptr->xtra1 || j_ptr->xtra1) return 0;
544 if (o_ptr->timeout || j_ptr->timeout) return 0;
545 if (o_ptr->ac != j_ptr->ac) return 0;
546 if (o_ptr->dd != j_ptr->dd) return 0;
547 if (o_ptr->ds != j_ptr->ds) return 0;
548 if (o_ptr->tval == TV_CHEST) return 0;
549 if (o_ptr->tval == TV_STATUE) return 0;
550 if (o_ptr->tval == TV_CAPTURE) return 0;
551 if (o_ptr->discount != j_ptr->discount) return 0;
557 * @brief 店舗に並べた品を重ね合わせできるかどうか判定する /
558 * Allow a store item to absorb another item
559 * @param o_ptr 判定するオブジェクト構造体の参照ポインタ1
560 * @param j_ptr 判定するオブジェクト構造体の参照ポインタ2
561 * @return 重ね合わせできるならTRUEを返す
564 * See "object_similar()" for the same function for the "player"
567 static void store_object_absorb(object_type *o_ptr, object_type *j_ptr)
569 int max_num = (o_ptr->tval == TV_ROD) ?
570 MIN(99, MAX_SHORT / k_info[o_ptr->k_idx].pval) : 99;
571 int total = o_ptr->number + j_ptr->number;
572 int diff = (total > max_num) ? total - max_num : 0;
573 o_ptr->number = (total > max_num) ? max_num : total;
574 if (o_ptr->tval == TV_ROD)
576 o_ptr->pval += j_ptr->pval * (j_ptr->number - diff) / j_ptr->number;
579 if (o_ptr->tval == TV_WAND)
581 o_ptr->pval += j_ptr->pval * (j_ptr->number - diff) / j_ptr->number;
587 * @brief 店舗にオブジェクトを加える /
588 * Add the item "o_ptr" to a real stores inventory.
589 * @param o_ptr 加えたいオブジェクトの構造体参照ポインタ
593 * In all cases, return the slot (or -1) where the object was placed
594 * Note that this is a hacked up version of "inven_carry()".
595 * Also note that it may not correctly "adapt" to "knowledge" bacoming
596 * known, the player may have to pick stuff up and drop it again.
599 int store_carry(object_type *o_ptr)
601 PRICE value = object_value(o_ptr);
602 if (value <= 0) return -1;
603 o_ptr->ident |= IDENT_FULL_KNOWN;
604 o_ptr->inscription = 0;
605 o_ptr->feeling = FEEL_NONE;
607 for (slot = 0; slot < st_ptr->stock_num; slot++)
610 j_ptr = &st_ptr->stock[slot];
611 if (store_object_similar(j_ptr, o_ptr))
613 store_object_absorb(j_ptr, o_ptr);
618 if (st_ptr->stock_num >= st_ptr->stock_size) return -1;
620 for (slot = 0; slot < st_ptr->stock_num; slot++)
623 j_ptr = &st_ptr->stock[slot];
624 if (o_ptr->tval > j_ptr->tval) break;
625 if (o_ptr->tval < j_ptr->tval) continue;
626 if (o_ptr->sval < j_ptr->sval) break;
627 if (o_ptr->sval > j_ptr->sval) continue;
628 if (o_ptr->tval == TV_ROD)
630 if (o_ptr->pval < j_ptr->pval) break;
631 if (o_ptr->pval > j_ptr->pval) continue;
634 PRICE j_value = object_value(j_ptr);
635 if (value > j_value) break;
636 if (value < j_value) continue;
639 for (int i = st_ptr->stock_num; i > slot; i--)
641 st_ptr->stock[i] = st_ptr->stock[i - 1];
645 st_ptr->stock[slot] = *o_ptr;