2 * @brief 同種のアイテムをインベントリや床に重ね合わせたり、その判断を行う処理
7 #include "object/object-stack.h"
8 #include "game-option/game-play-options.h"
9 #include "object-enchant/object-ego.h"
10 #include "object-enchant/special-object-flags.h"
11 #include "object-enchant/trc-types.h"
12 #include "object/object-value.h"
13 #include "object/tval-types.h"
14 #include "smith/object-smith.h"
15 #include "sv-definition/sv-other-types.h"
16 #include "system/baseitem-info.h"
17 #include "system/item-entity.h"
18 #include "util/bit-flags-calculator.h"
21 * @brief 魔法棒やロッドのスロット分割時に使用回数を分配する /
22 * Distribute charges of rods or wands.
23 * @param o_ptr 分割元オブジェクトの構造体参照ポインタ source item
24 * @param q_ptr 分割先オブジェクトの構造体参照ポインタ target item, must be of the same type as o_ptr
25 * @param amt 分割したい回数量 number of items that are transfered
27 * Hack -- If rods or wands are dropped, the total maximum timeout or\n
28 * charges need to be allocated between the two stacks. If all the items\n
29 * are being dropped, it makes for a neater message to leave the original\n
30 * stack's pval alone. -LM-\n
32 void distribute_charges(ItemEntity *o_ptr, ItemEntity *q_ptr, int amt)
34 if (!o_ptr->is_wand_rod()) {
38 q_ptr->pval = o_ptr->pval * amt / o_ptr->number;
39 if (amt < o_ptr->number) {
40 o_ptr->pval -= q_ptr->pval;
43 if ((o_ptr->bi_key.tval() != ItemKindType::ROD) || !o_ptr->timeout) {
47 if (q_ptr->pval > o_ptr->timeout) {
48 q_ptr->timeout = o_ptr->timeout;
50 q_ptr->timeout = q_ptr->pval;
53 if (amt < o_ptr->number) {
54 o_ptr->timeout -= q_ptr->timeout;
59 * @brief 魔法棒やロッドの使用回数を減らす /
60 * @param o_ptr オブジェクトの構造体参照ポインタ source item
61 * @param amt 減らしたい回数量 number of items that are transfered
63 * Hack -- If rods or wand are destroyed, the total maximum timeout or\n
64 * charges of the stack needs to be reduced, unless all the items are\n
65 * being destroyed. -LM-\n
67 void reduce_charges(ItemEntity *o_ptr, int amt)
69 if (o_ptr->is_wand_rod() && (amt < o_ptr->number)) {
70 o_ptr->pval -= o_ptr->pval * amt / o_ptr->number;
75 * @brief 両オブジェクトをスロットに重ね合わせ可能な最大数を返す。
76 * Determine if an item can partly absorb a second item. Return maximum number of stack.
77 * @param o_ptr 検証したいオブジェクトの構造体参照ポインタ1
78 * @param j_ptr 検証したいオブジェクトの構造体参照ポインタ2
79 * @return 重ね合わせ可能なアイテム数
81 int object_similar_part(const ItemEntity *o_ptr, const ItemEntity *j_ptr)
83 if (o_ptr->bi_id != j_ptr->bi_id) {
87 constexpr auto max_stack_size = 99;
88 auto max_num = max_stack_size;
89 switch (o_ptr->bi_key.tval()) {
90 case ItemKindType::CHEST:
91 case ItemKindType::CARD:
92 case ItemKindType::CAPTURE:
94 case ItemKindType::STATUE: {
95 const auto o_sval = o_ptr->bi_key.sval();
96 const auto j_sval = j_ptr->bi_key.sval();
97 if ((o_sval != SV_PHOTO) || (j_sval != SV_PHOTO) || (o_ptr->pval != j_ptr->pval)) {
103 case ItemKindType::FIGURINE:
104 case ItemKindType::CORPSE:
105 if (o_ptr->pval != j_ptr->pval) {
110 case ItemKindType::FOOD:
111 case ItemKindType::POTION:
112 case ItemKindType::SCROLL:
114 case ItemKindType::STAFF:
115 if ((none_bits(o_ptr->ident, IDENT_EMPTY) && !o_ptr->is_known()) || (none_bits(j_ptr->ident, IDENT_EMPTY) && !j_ptr->is_known())) {
119 if (o_ptr->pval != j_ptr->pval) {
124 case ItemKindType::WAND:
125 if ((!(o_ptr->ident & (IDENT_EMPTY)) && !o_ptr->is_known()) || (!(j_ptr->ident & (IDENT_EMPTY)) && !j_ptr->is_known())) {
130 case ItemKindType::ROD:
131 max_num = std::min(max_num, MAX_SHORT / o_ptr->get_baseitem().pval);
133 case ItemKindType::GLOVES:
134 if (o_ptr->is_glove_same_temper(j_ptr)) {
138 if (!o_ptr->is_known() || !j_ptr->is_known()) {
142 if (!o_ptr->can_pile(j_ptr)) {
147 case ItemKindType::LITE:
148 if (o_ptr->fuel != j_ptr->fuel) {
152 if (!o_ptr->is_known() || !j_ptr->is_known()) {
156 if (!o_ptr->can_pile(j_ptr)) {
161 case ItemKindType::BOW:
162 case ItemKindType::DIGGING:
163 case ItemKindType::HAFTED:
164 case ItemKindType::POLEARM:
165 case ItemKindType::SWORD:
166 case ItemKindType::BOOTS:
167 case ItemKindType::HELM:
168 case ItemKindType::CROWN:
169 case ItemKindType::SHIELD:
170 case ItemKindType::CLOAK:
171 case ItemKindType::SOFT_ARMOR:
172 case ItemKindType::HARD_ARMOR:
173 case ItemKindType::DRAG_ARMOR:
174 case ItemKindType::RING:
175 case ItemKindType::AMULET:
176 case ItemKindType::WHISTLE:
177 if (!o_ptr->is_known() || !j_ptr->is_known()) {
181 if (!o_ptr->can_pile(j_ptr)) {
186 case ItemKindType::BOLT:
187 case ItemKindType::ARROW:
188 case ItemKindType::SHOT:
189 if (!o_ptr->can_pile(j_ptr)) {
195 if (!o_ptr->is_known() || !j_ptr->is_known()) {
202 if (o_ptr->art_flags != j_ptr->art_flags) {
206 if (o_ptr->curse_flags != j_ptr->curse_flags) {
210 if (any_bits(o_ptr->ident, IDENT_BROKEN) != any_bits(j_ptr->ident, IDENT_BROKEN)) {
214 if (o_ptr->is_inscribed() && j_ptr->is_inscribed() && (o_ptr->inscription != j_ptr->inscription)) {
218 if (!stack_force_notes && (o_ptr->inscription != j_ptr->inscription)) {
222 if (!stack_force_costs && (o_ptr->discount != j_ptr->discount)) {
230 * @brief 両オブジェクトをスロットに重ねることができるかどうかを返す。
231 * Determine if an item can absorb a second item.
232 * @param o_ptr 検証したいオブジェクトの構造体参照ポインタ1
233 * @param j_ptr 検証したいオブジェクトの構造体参照ポインタ2
234 * @return 重ね合わせ可能ならばTRUEを返す。
236 bool object_similar(const ItemEntity *o_ptr, const ItemEntity *j_ptr)
238 int total = o_ptr->number + j_ptr->number;
239 int max_num = object_similar_part(o_ptr, j_ptr);
243 if (total > max_num) {
251 * @brief 両オブジェクトをスロットに重ね合わせる。
252 * Allow one item to "absorb" another, assuming they are similar
253 * @param o_ptr 重ね合わせ先のオブジェクトの構造体参照ポインタ
254 * @param j_ptr 重ね合わせ元のオブジェクトの構造体参照ポインタ
256 void object_absorb(ItemEntity *o_ptr, ItemEntity *j_ptr)
258 int max_num = object_similar_part(o_ptr, j_ptr);
259 int total = o_ptr->number + j_ptr->number;
260 int diff = (total > max_num) ? total - max_num : 0;
262 o_ptr->number = (total > max_num) ? max_num : total;
263 if (j_ptr->is_known()) {
264 o_ptr->mark_as_known();
267 if (((o_ptr->ident & IDENT_STORE) || (j_ptr->ident & IDENT_STORE)) && (!((o_ptr->ident & IDENT_STORE) && (j_ptr->ident & IDENT_STORE)))) {
268 if (j_ptr->ident & IDENT_STORE) {
269 j_ptr->ident &= 0xEF;
271 if (o_ptr->ident & IDENT_STORE) {
272 o_ptr->ident &= 0xEF;
276 if (j_ptr->is_fully_known()) {
277 o_ptr->ident |= (IDENT_FULL_KNOWN);
279 if (j_ptr->is_inscribed()) {
280 o_ptr->inscription = j_ptr->inscription;
282 if (j_ptr->feeling) {
283 o_ptr->feeling = j_ptr->feeling;
285 if (o_ptr->discount < j_ptr->discount) {
286 o_ptr->discount = j_ptr->discount;
289 const auto tval = o_ptr->bi_key.tval();
290 if (tval == ItemKindType::ROD) {
291 o_ptr->pval += j_ptr->pval * (j_ptr->number - diff) / j_ptr->number;
292 o_ptr->timeout += j_ptr->timeout * (j_ptr->number - diff) / j_ptr->number;
295 if (tval == ItemKindType::WAND) {
296 o_ptr->pval += j_ptr->pval * (j_ptr->number - diff) / j_ptr->number;