2 * @brief 店舗処理関係のユーティリティ
7 #include "store/store-util.h"
8 #include "object-enchant/item-feeling.h"
9 #include "object-enchant/special-object-flags.h"
10 #include "object/object-value.h"
11 #include "object/tval-types.h"
12 #include "system/baseitem-info.h"
13 #include "system/item-entity.h"
15 store_type *st_ptr = nullptr;
18 * @brief 店舗のオブジェクト数を増やす /
19 * Add the item "o_ptr" to a real stores inventory.
20 * @param item 増やしたいアイテムのID
24 * Increase, by a given amount, the number of a certain item
25 * in a certain store. This can result in zero items.
28 void store_item_increase(INVENTORY_IDX item, ITEM_NUMBER num)
31 o_ptr = &st_ptr->stock[item];
32 int cnt = o_ptr->number + num;
39 num = cnt - o_ptr->number;
44 * @brief 店舗のオブジェクト数を削除する /
45 * Remove a slot if it is empty
46 * @param item 削除したいアイテムのID
48 void store_item_optimize(INVENTORY_IDX item)
50 const auto *o_ptr = &st_ptr->stock[item];
51 if (!o_ptr->is_valid() || (o_ptr->number != 0)) {
56 for (int j = item; j < st_ptr->stock_num; j++) {
57 st_ptr->stock[j] = st_ptr->stock[j + 1];
60 (&st_ptr->stock[st_ptr->stock_num])->wipe();
64 * @brief 店舗の品揃え変化のためにアイテムを削除する /
65 * Attempt to delete (some of) a random item from the store
68 * Hack -- we attempt to "maintain" piles of items when possible.
71 void store_delete(void)
73 INVENTORY_IDX what = (INVENTORY_IDX)randint0(st_ptr->stock_num);
74 int num = st_ptr->stock[what].number;
75 if (randint0(100) < 50) {
79 if (randint0(100) < 50) {
83 if (st_ptr->stock[what].is_wand_rod()) {
84 st_ptr->stock[what].pval -= num * st_ptr->stock[what].pval / st_ptr->stock[what].number;
87 store_item_increase(what, -num);
88 store_item_optimize(what);
92 * @brief 店舗販売中の杖と魔法棒のpvalのリストを返す
93 * @param j_ptr これから売ろうとしているオブジェクト
94 * @return plavリスト(充填数)
96 * 回数の違う杖と魔法棒がスロットを圧迫するのでスロット数制限をかける
98 std::vector<PARAMETER_VALUE> store_same_magic_device_pvals(ItemEntity *j_ptr)
100 auto list = std::vector<PARAMETER_VALUE>();
101 for (INVENTORY_IDX i = 0; i < st_ptr->stock_num; i++) {
102 auto *o_ptr = &st_ptr->stock[i];
103 if ((o_ptr == j_ptr) || (o_ptr->bi_id != j_ptr->bi_id) || !o_ptr->is_wand_staff()) {
107 list.push_back(o_ptr->pval);
114 * @brief 店舗に並べた品を同一品であるかどうか判定する /
115 * Determine if a store item can "absorb" another item
116 * @param o_ptr 判定するオブジェクト構造体の参照ポインタ1
117 * @param j_ptr 判定するオブジェクト構造体の参照ポインタ2
118 * @return 同一扱いできるならTRUEを返す
121 * See "object_similar()" for the same function for the "player"
124 bool store_object_similar(ItemEntity *o_ptr, ItemEntity *j_ptr)
126 if (o_ptr == j_ptr) {
130 if (o_ptr->bi_id != j_ptr->bi_id) {
134 if ((o_ptr->pval != j_ptr->pval) && !o_ptr->is_wand_rod()) {
138 if (o_ptr->to_h != j_ptr->to_h) {
142 if (o_ptr->to_d != j_ptr->to_d) {
146 if (o_ptr->to_a != j_ptr->to_a) {
150 if (o_ptr->ego_idx != j_ptr->ego_idx) {
154 if (o_ptr->is_fixed_or_random_artifact() || j_ptr->is_fixed_or_random_artifact()) {
158 if (o_ptr->art_flags != j_ptr->art_flags) {
162 if (o_ptr->timeout || j_ptr->timeout) {
166 if (o_ptr->ac != j_ptr->ac) {
170 if (o_ptr->dd != j_ptr->dd) {
174 if (o_ptr->ds != j_ptr->ds) {
178 const auto tval = o_ptr->bi_key.tval();
179 if (tval == ItemKindType::CHEST) {
183 if (tval == ItemKindType::STATUE) {
187 if (tval == ItemKindType::CAPTURE) {
191 if ((tval == ItemKindType::LITE) && (o_ptr->fuel != j_ptr->fuel)) {
195 if (o_ptr->discount != j_ptr->discount) {
203 * @brief 店舗に並べた品を重ね合わせできるかどうか判定する /
204 * Allow a store item to absorb another item
205 * @param o_ptr 判定するオブジェクト構造体の参照ポインタ1
206 * @param j_ptr 判定するオブジェクト構造体の参照ポインタ2
207 * @return 重ね合わせできるならTRUEを返す
210 * See "object_similar()" for the same function for the "player"
213 static void store_object_absorb(ItemEntity *o_ptr, ItemEntity *j_ptr)
215 int max_num = (o_ptr->bi_key.tval() == ItemKindType::ROD) ? std::min(99, MAX_SHORT / o_ptr->get_baseitem().pval) : 99;
216 int total = o_ptr->number + j_ptr->number;
217 int diff = (total > max_num) ? total - max_num : 0;
218 o_ptr->number = (total > max_num) ? max_num : total;
219 if (o_ptr->is_wand_rod()) {
220 o_ptr->pval += j_ptr->pval * (j_ptr->number - diff) / j_ptr->number;
225 * @brief 店舗にオブジェクトを加える /
226 * Add the item "o_ptr" to a real stores inventory.
227 * @param o_ptr 加えたいオブジェクトの構造体参照ポインタ
231 * In all cases, return the slot (or -1) where the object was placed
232 * Note that this is a hacked up version of "store_item_to_inventory()".
233 * Also note that it may not correctly "adapt" to "knowledge" bacoming
234 * known, the player may have to pick stuff up and drop it again.
237 int store_carry(ItemEntity *o_ptr)
239 const auto value = o_ptr->get_price();
244 o_ptr->ident |= IDENT_FULL_KNOWN;
245 o_ptr->inscription.reset();
246 o_ptr->feeling = FEEL_NONE;
248 for (slot = 0; slot < st_ptr->stock_num; slot++) {
250 j_ptr = &st_ptr->stock[slot];
251 if (store_object_similar(j_ptr, o_ptr)) {
252 store_object_absorb(j_ptr, o_ptr);
257 if (st_ptr->stock_num >= st_ptr->stock_size) {
261 const auto o_tval = o_ptr->bi_key.tval();
262 const auto o_sval = o_ptr->bi_key.sval();
263 for (slot = 0; slot < st_ptr->stock_num; slot++) {
264 const auto *j_ptr = &st_ptr->stock[slot];
265 const auto j_tval = j_ptr->bi_key.tval();
266 const auto j_sval = j_ptr->bi_key.sval();
267 if (o_tval > j_tval) {
271 if (o_tval < j_tval) {
275 if (o_sval < j_sval) {
279 if (o_sval > j_sval) {
283 if (o_tval == ItemKindType::ROD) {
284 if (o_ptr->pval < j_ptr->pval) {
287 if (o_ptr->pval > j_ptr->pval) {
292 auto j_value = j_ptr->get_price();
293 if (value > j_value) {
297 if (value < j_value) {
302 for (int i = st_ptr->stock_num; i > slot; i--) {
303 st_ptr->stock[i] = st_ptr->stock[i - 1];
307 st_ptr->stock[slot] = *o_ptr;