OSDN Git Service

Since its used as an adverb, replace "much slower" with "much more slowly" in the...
[hengband/hengband.git] / src / store / home.c
1 #include "store/home.h"
2 #include "floor/floor-town.h"
3 #include "game-option/birth-options.h"
4 #include "game-option/game-play-options.h"
5 #include "object/object-generator.h"
6 #include "object/object-stack.h"
7 #include "object/object-value.h"
8 #include "player-info/avatar.h"
9 #include "store/store-util.h"
10 #include "util/object-sort.h"
11
12 /*!
13  * @brief 我が家にオブジェクトを加える /
14  * Add the item "o_ptr" to the inventory of the "Home"
15  * @param o_ptr 加えたいオブジェクトの構造体参照ポインタ
16  * @return 収めた先のID
17  * @details
18  * <pre>
19  * In all cases, return the slot (or -1) where the object was placed
20  * Note that this is a hacked up version of "store_item_to_inventory()".
21  * Also note that it may not correctly "adapt" to "knowledge" bacoming
22  * known, the player may have to pick stuff up and drop it again.
23  * </pre>
24  */
25 int home_carry(player_type *player_ptr, object_type *o_ptr)
26 {
27     bool old_stack_force_notes = stack_force_notes;
28     bool old_stack_force_costs = stack_force_costs;
29     if (cur_store_num != STORE_HOME) {
30         stack_force_notes = FALSE;
31         stack_force_costs = FALSE;
32     }
33
34     for (int slot = 0; slot < st_ptr->stock_num; slot++) {
35         object_type *j_ptr;
36         j_ptr = &st_ptr->stock[slot];
37         if (object_similar(j_ptr, o_ptr)) {
38             object_absorb(j_ptr, o_ptr);
39             if (cur_store_num != STORE_HOME) {
40                 stack_force_notes = old_stack_force_notes;
41                 stack_force_costs = old_stack_force_costs;
42             }
43
44             return (slot);
45         }
46     }
47
48     if (cur_store_num != STORE_HOME) {
49         stack_force_notes = old_stack_force_notes;
50         stack_force_costs = old_stack_force_costs;
51     }
52
53     /* No space? */
54     /*
55      * 隠し機能: オプション powerup_home が設定されていると
56      *           我が家が 20 ページまで使える
57      */
58     if ((cur_store_num != STORE_HOME) || (powerup_home == TRUE)) {
59         if (st_ptr->stock_num >= st_ptr->stock_size) {
60             return -1;
61         }
62     } else {
63         if (st_ptr->stock_num >= ((st_ptr->stock_size) / 10)) {
64             return -1;
65         }
66     }
67
68     PRICE value = object_value(player_ptr, o_ptr);
69     int slot;
70     for (slot = 0; slot < st_ptr->stock_num; slot++)
71         if (object_sort_comp(player_ptr, o_ptr, value, &st_ptr->stock[slot]))
72             break;
73
74     for (int i = st_ptr->stock_num; i > slot; i--)
75         st_ptr->stock[i] = st_ptr->stock[i - 1];
76
77     st_ptr->stock_num++;
78     st_ptr->stock[slot] = *o_ptr;
79     chg_virtue(player_ptr, V_SACRIFICE, -1);
80     (void)combine_and_reorder_home(player_ptr, cur_store_num);
81     return slot;
82 }
83
84 static bool exe_combine_store_items(object_type *o_ptr, object_type *j_ptr, const int max_num, const int i, bool *combined)
85 {
86     if (o_ptr->number + j_ptr->number > max_num)
87         return FALSE;
88
89     object_absorb(j_ptr, o_ptr);
90     st_ptr->stock_num--;
91     int k;
92     for (k = i; k < st_ptr->stock_num; k++)
93         st_ptr->stock[k] = st_ptr->stock[k + 1];
94
95     object_wipe(&st_ptr->stock[k]);
96     *combined = TRUE;
97     return TRUE;
98 }
99
100 static void sweep_reorder_store_item(object_type *o_ptr, const int i, bool *combined)
101 {
102     for (int j = 0; j < i; j++) {
103         object_type *j_ptr;
104         j_ptr = &st_ptr->stock[j];
105         if (!j_ptr->k_idx)
106             continue;
107
108         int max_num = object_similar_part(j_ptr, o_ptr);
109         if (max_num == 0 || j_ptr->number >= max_num)
110             continue;
111
112         if (exe_combine_store_items(o_ptr, j_ptr, max_num, i, combined))
113             break;
114
115         ITEM_NUMBER old_num = o_ptr->number;
116         ITEM_NUMBER remain = j_ptr->number + o_ptr->number - max_num;
117         object_absorb(j_ptr, o_ptr);
118         o_ptr->number = remain;
119         if (o_ptr->tval == TV_ROD) {
120             o_ptr->pval = o_ptr->pval * remain / old_num;
121             o_ptr->timeout = o_ptr->timeout * remain / old_num;
122         } else if (o_ptr->tval == TV_WAND) {
123             o_ptr->pval = o_ptr->pval * remain / old_num;
124         }
125
126         *combined = TRUE;
127         break;
128     }
129 }
130
131 static void exe_reorder_store_item(player_type *player_ptr, bool *flag)
132 {
133     for (int i = 0; i < st_ptr->stock_num; i++) {
134         object_type *o_ptr;
135         o_ptr = &st_ptr->stock[i];
136         if (!o_ptr->k_idx)
137             continue;
138
139         s32b o_value = object_value(player_ptr, o_ptr);
140         int j;
141         for (j = 0; j < st_ptr->stock_num; j++)
142             if (object_sort_comp(player_ptr, o_ptr, o_value, &st_ptr->stock[j]))
143                 break;
144
145         if (j >= i)
146             continue;
147
148         *flag = TRUE;
149         object_type *j_ptr;
150         object_type forge;
151         j_ptr = &forge;
152         object_copy(j_ptr, &st_ptr->stock[i]);
153         for (int k = i; k > j; k--)
154             object_copy(&st_ptr->stock[k], &st_ptr->stock[k - 1]);
155
156         object_copy(&st_ptr->stock[j], j_ptr);
157     }
158 }
159
160 /*!
161  * @brief 現在の町の指定された店舗のアイテムを整理する /
162  * Combine and reorder items in store.
163  * @param store_num 店舗ID
164  * @return 実際に整理が行われたならばTRUEを返す。
165  */
166 bool combine_and_reorder_home(player_type *player_ptr, const int store_num)
167 {
168     bool old_stack_force_notes = stack_force_notes;
169     bool old_stack_force_costs = stack_force_costs;
170     store_type *old_st_ptr = st_ptr;
171     st_ptr = &town_info[1].store[store_num];
172     bool flag = FALSE;
173     if (store_num != STORE_HOME) {
174         stack_force_notes = FALSE;
175         stack_force_costs = FALSE;
176     }
177
178     bool combined = TRUE;
179     while (combined) {
180         combined = FALSE;
181         for (int i = st_ptr->stock_num - 1; i > 0; i--) {
182             object_type *o_ptr;
183             o_ptr = &st_ptr->stock[i];
184             if (!o_ptr->k_idx)
185                 continue;
186
187             sweep_reorder_store_item(o_ptr, i, &combined);
188         }
189
190         flag |= combined;
191     }
192
193     exe_reorder_store_item(player_ptr, &flag);
194     st_ptr = old_st_ptr;
195     if (store_num != STORE_HOME) {
196         stack_force_notes = old_stack_force_notes;
197         stack_force_costs = old_stack_force_costs;
198     }
199
200     return flag;
201 }