OSDN Git Service

Merge pull request #716 from sikabane-works/release/3.0.0Alpha16
[hengbandforosx/hengbandosx.git] / src / store / purchase-order.cpp
1 #include "store/purchase-order.h"
2 #include "autopick/autopick.h"
3 #include "core/asking-player.h"
4 #include "core/stuff-handler.h"
5 #include "flavor/flavor-describer.h"
6 #include "flavor/object-flavor-types.h"
7 #include "game-option/birth-options.h"
8 #include "game-option/play-record-options.h"
9 #include "grid/feature.h"
10 #include "inventory/inventory-object.h"
11 #include "io/write-diary.h"
12 #include "main/sound-definitions-table.h"
13 #include "main/sound-of-music.h"
14 #include "object-enchant/item-feeling.h"
15 #include "object-enchant/special-object-flags.h"
16 #include "object/object-generator.h"
17 #include "object/object-info.h"
18 #include "object/object-stack.h"
19 #include "object/object-value.h"
20 #include "perception/object-perception.h"
21 #include "player-info/avatar.h"
22 #include "player/race-info-table.h"
23 #include "store/home.h"
24 #include "store/owner-insults.h"
25 #include "store/pricing.h"
26 #include "store/say-comments.h"
27 #include "store/store-util.h"
28 #include "store/store.h"
29 #include "term/screen-processor.h"
30 #include "util/int-char-converter.h"
31 #include "view/display-messages.h"
32 #include "view/display-store.h"
33 #include "world/world.h"
34
35 typedef struct haggle_type {
36     object_type *o_ptr;
37     s32b *price;
38     s32b cur_ask;
39     s32b final_ask;
40     int noneed;
41     bool final;
42     concptr pmt;
43     s32b min_per;
44     s32b max_per;
45     s32b last_offer;
46     s32b offer;
47     bool flag;
48     int annoyed;
49     bool cancel;
50 } haggle_type;
51
52 static haggle_type *initialize_haggle_type(player_type *player_ptr, haggle_type *haggle_ptr, object_type *o_ptr, s32b *price)
53 {
54     haggle_ptr->o_ptr = o_ptr;
55     haggle_ptr->price = price;
56     haggle_ptr->cur_ask = price_item(player_ptr, o_ptr, ot_ptr->max_inflate, FALSE);
57     haggle_ptr->final_ask = price_item(player_ptr, o_ptr, ot_ptr->min_inflate, FALSE);
58     haggle_ptr->noneed = noneedtobargain(haggle_ptr->final_ask);
59     haggle_ptr->final = FALSE;
60     haggle_ptr->pmt = _("提示価格", "Asking");
61     return haggle_ptr;
62 }
63
64 static void settle_haggle_result(haggle_type *haggle_ptr)
65 {
66     if (!haggle_ptr->noneed && manual_haggle)
67         return;
68
69     if (haggle_ptr->noneed) {
70         msg_print(_("結局この金額にまとまった。", "You eventually agree upon the price."));
71         msg_print(NULL);
72     } else {
73         msg_print(_("すんなりとこの金額にまとまった。", "You quickly agree upon the price."));
74         msg_print(NULL);
75         haggle_ptr->final_ask += haggle_ptr->final_ask / 10;
76     }
77
78     haggle_ptr->cur_ask = haggle_ptr->final_ask;
79     haggle_ptr->pmt = _("最終提示価格", "Final Offer");
80     haggle_ptr->final = TRUE;
81 }
82
83 static void decide_haggle_offer(player_type *player_ptr, haggle_type *haggle_ptr)
84 {
85     haggle_ptr->cur_ask *= haggle_ptr->o_ptr->number;
86     haggle_ptr->final_ask *= haggle_ptr->o_ptr->number;
87     haggle_ptr->min_per = ot_ptr->haggle_per;
88     haggle_ptr->max_per = haggle_ptr->min_per * 3;
89     haggle_ptr->last_offer = object_value(player_ptr, haggle_ptr->o_ptr) * haggle_ptr->o_ptr->number;
90     haggle_ptr->last_offer = haggle_ptr->last_offer * (200 - (int)(ot_ptr->max_inflate)) / 100L;
91     if (haggle_ptr->last_offer <= 0)
92         haggle_ptr->last_offer = 1;
93 }
94
95 static void initialize_haggle_offer(haggle_type *haggle_ptr)
96 {
97     haggle_ptr->offer = 0;
98     allow_inc = FALSE;
99     haggle_ptr->flag = FALSE;
100     haggle_ptr->annoyed = 0;
101     haggle_ptr->cancel = FALSE;
102     *haggle_ptr->price = 0;
103 }
104
105 static void suggest_haggle_offer(haggle_type *haggle_ptr)
106 {
107     bool loop_flag = TRUE;
108     while (!haggle_ptr->flag && loop_flag) {
109         char out_val[160];
110         (void)sprintf(out_val, "%s :  %ld", haggle_ptr->pmt, (long)haggle_ptr->cur_ask);
111         put_str(out_val, 1, 0);
112         haggle_ptr->cancel
113             = receive_offer(_("提示する金額? ", "What do you offer? "), &haggle_ptr->offer, haggle_ptr->last_offer, 1, haggle_ptr->cur_ask, haggle_ptr->final);
114         if (haggle_ptr->cancel) {
115             haggle_ptr->flag = TRUE;
116         } else if (haggle_ptr->offer > haggle_ptr->cur_ask) {
117             say_comment_6();
118             haggle_ptr->offer = haggle_ptr->last_offer;
119         } else if (haggle_ptr->offer == haggle_ptr->cur_ask) {
120             haggle_ptr->flag = TRUE;
121             *haggle_ptr->price = haggle_ptr->offer;
122         } else {
123             loop_flag = FALSE;
124         }
125     }
126 }
127
128 static void final_haggle_offer(haggle_type *haggle_ptr)
129 {
130     haggle_ptr->final = TRUE;
131     haggle_ptr->cur_ask = haggle_ptr->final_ask;
132     haggle_ptr->pmt = _("最終提示価格", "What do you offer? ");
133     haggle_ptr->annoyed++;
134     if (haggle_ptr->annoyed <= 3)
135         return;
136
137     (void)increase_insults();
138     haggle_ptr->cancel = TRUE;
139     haggle_ptr->flag = TRUE;
140 }
141
142 static void show_last_haggle_offer(haggle_type *haggle_ptr)
143 {
144     haggle_ptr->last_offer = haggle_ptr->offer;
145     allow_inc = TRUE;
146     prt("", 1, 0);
147     char out_val[160];
148     (void)sprintf(out_val, _("前回の提示金額: $%ld", "Your last offer: %ld"), (long)haggle_ptr->last_offer);
149     put_str(out_val, 1, 39);
150     say_comment_2(haggle_ptr->cur_ask, haggle_ptr->annoyed);
151 }
152
153 /*!
154  * @brief プレイヤーが購入する時の値切り処理メインルーチン /
155  * Haggling routine                             -RAK-
156  * @param player_ptr プレーヤーへの参照ポインタ
157  * @param o_ptr オブジェクトの構造体参照ポインタ
158  * @param price 最終価格を返す参照ポインタ
159  * @return プレイヤーの価格に対して店主が不服ならばTRUEを返す /
160  * Return TRUE if purchase is NOT successful
161  */
162 static bool purchase_haggle(player_type *player_ptr, object_type *o_ptr, s32b *price)
163 {
164     haggle_type tmp_haggle;
165     haggle_type *haggle_ptr = initialize_haggle_type(player_ptr, &tmp_haggle, o_ptr, price);
166     settle_haggle_result(haggle_ptr);
167     decide_haggle_offer(player_ptr, haggle_ptr);
168     initialize_haggle_offer(haggle_ptr);
169     while (!haggle_ptr->flag) {
170         suggest_haggle_offer(haggle_ptr);
171         if (haggle_ptr->flag)
172             continue;
173
174         s32b x1 = 100 * (haggle_ptr->offer - haggle_ptr->last_offer) / (haggle_ptr->cur_ask - haggle_ptr->last_offer);
175         if (x1 < haggle_ptr->min_per) {
176             if (haggle_insults()) {
177                 haggle_ptr->flag = TRUE;
178                 haggle_ptr->cancel = TRUE;
179             }
180         } else if (x1 > haggle_ptr->max_per) {
181             x1 = x1 * 3 / 4;
182             if (x1 < haggle_ptr->max_per)
183                 x1 = haggle_ptr->max_per;
184         }
185
186         s32b x2 = rand_range(x1 - 2, x1 + 2);
187         s32b x3 = ((haggle_ptr->cur_ask - haggle_ptr->offer) * x2 / 100L) + 1;
188         if (x3 < 0)
189             x3 = 0;
190         haggle_ptr->cur_ask -= x3;
191
192         if (haggle_ptr->cur_ask < haggle_ptr->final_ask)
193             final_haggle_offer(haggle_ptr);
194         else if (haggle_ptr->offer >= haggle_ptr->cur_ask) {
195             haggle_ptr->flag = TRUE;
196             *haggle_ptr->price = haggle_ptr->offer;
197         }
198
199         if (haggle_ptr->flag)
200             continue;
201
202         show_last_haggle_offer(haggle_ptr);
203     }
204
205     if (haggle_ptr->cancel)
206         return TRUE;
207
208     updatebargain(*price, haggle_ptr->final_ask, o_ptr->number);
209     return FALSE;
210 }
211
212 static bool show_store_select_item(COMMAND_CODE *item, const int i)
213 {
214     char out_val[160];
215 #ifdef JP
216     /* ブラックマーケットの時は別のメッセージ */
217     switch (cur_store_num) {
218     case 7:
219         sprintf(out_val, "どのアイテムを取りますか? ");
220         break;
221     case 6:
222         sprintf(out_val, "どれ? ");
223         break;
224     default:
225         sprintf(out_val, "どの品物が欲しいんだい? ");
226         break;
227     }
228 #else
229     if (cur_store_num == STORE_HOME) {
230         sprintf(out_val, "Which item do you want to take? ");
231     } else {
232         sprintf(out_val, "Which item are you interested in? ");
233     }
234 #endif
235
236     return get_stock(item, out_val, 0, i - 1) != 0;
237 }
238
239 static bool process_purchase_result(player_type *player_ptr, object_type *o_ptr, object_type *j_ptr, COMMAND_CODE *item_new,const int amt, int *i, const COMMAND_CODE item)
240 {
241     if (cur_store_num != STORE_HOME)
242         return FALSE;
243
244     bool combined_or_reordered;
245     distribute_charges(o_ptr, j_ptr, amt);
246     *item_new = store_item_to_inventory(player_ptr, j_ptr);
247     GAME_TEXT o_name[MAX_NLEN];
248     describe_flavor(player_ptr, o_name, &player_ptr->inventory_list[*item_new], 0);
249     handle_stuff(player_ptr);
250     msg_format(_("%s(%c)を取った。", "You have %s (%c)."), o_name, index_to_label(*item_new));
251     *i = st_ptr->stock_num;
252     store_item_increase(item, -amt);
253     store_item_optimize(item);
254     combined_or_reordered = combine_and_reorder_home(player_ptr, STORE_HOME);
255     if (*i == st_ptr->stock_num) {
256         if (combined_or_reordered)
257             display_store_inventory(player_ptr);
258         else
259             display_entry(player_ptr, item);
260
261         return TRUE;
262     }
263
264     if (st_ptr->stock_num == 0)
265         store_top = 0;
266     else if (store_top >= st_ptr->stock_num)
267         store_top -= store_bottom;
268
269     display_store_inventory(player_ptr);
270     chg_virtue(player_ptr, V_SACRIFICE, 1);
271     return TRUE;
272 }
273
274 static void shuffle_store(player_type *player_ptr)
275 {
276     if (!one_in_(STORE_SHUFFLE)) {
277         msg_print(_("店主は新たな在庫を取り出した。", "The shopkeeper brings out some new stock."));
278         return;
279     }
280
281     char buf[80];
282     msg_print(_("店主は引退した。", "The shopkeeper retires."));
283     store_shuffle(player_ptr, cur_store_num);
284     prt("", 3, 0);
285     sprintf(buf, "%s (%s)", ot_ptr->owner_name, race_info[ot_ptr->owner_race].title);
286     put_str(buf, 3, 10);
287     sprintf(buf, "%s (%ld)", f_info[cur_store_feat].name.c_str(), (long)(ot_ptr->max_cost));
288     prt(buf, 3, 50);
289 }
290
291 static void switch_store_stock(player_type *player_ptr, const int i, const COMMAND_CODE item)
292 {
293     if (st_ptr->stock_num == 0) {
294         shuffle_store(player_ptr);
295         store_maintenance(player_ptr, player_ptr->town_num, cur_store_num, 10);
296
297         store_top = 0;
298         display_store_inventory(player_ptr);
299         return;
300     }
301     
302     if (st_ptr->stock_num != i) {
303         if (store_top >= st_ptr->stock_num)
304             store_top -= store_bottom;
305
306         display_store_inventory(player_ptr);
307         return;
308     }
309
310     display_entry(player_ptr, item);
311 }
312
313 /*!
314  * @brief 店からの購入処理のメインルーチン /
315  * Buy an item from a store                     -RAK-
316  * @param player_ptr プレーヤーへの参照ポインタ
317  * @return なし
318  */
319 void store_purchase(player_type *player_ptr)
320 {
321     if (cur_store_num == STORE_MUSEUM) {
322         msg_print(_("博物館から取り出すことはできません。", "Items cannot be taken out of the Museum."));
323         return;
324     }
325
326     if (st_ptr->stock_num <= 0) {
327         if (cur_store_num == STORE_HOME)
328             msg_print(_("我が家には何も置いてありません。", "Your home is empty."));
329         else
330             msg_print(_("現在商品の在庫を切らしています。", "I am currently out of stock."));
331         return;
332     }
333
334     int i = (st_ptr->stock_num - store_top);
335     if (i > store_bottom)
336         i = store_bottom;
337
338     COMMAND_CODE item;
339     if (!show_store_select_item(&item, i))
340         return;
341
342     item = item + store_top;
343     object_type *o_ptr;
344     o_ptr = &st_ptr->stock[item];
345     ITEM_NUMBER amt = 1;
346     object_type forge;
347     object_type *j_ptr;
348     j_ptr = &forge;
349     object_copy(j_ptr, o_ptr);
350
351     /*
352      * If a rod or wand, allocate total maximum timeouts or charges
353      * between those purchased and left on the shelf.
354      */
355     reduce_charges(j_ptr, o_ptr->number - amt);
356     j_ptr->number = amt;
357     if (!check_store_item_to_inventory(player_ptr, j_ptr)) {
358         msg_print(_("そんなにアイテムを持てない。", "You cannot carry that many different items."));
359         return;
360     }
361
362     PRICE best = price_item(player_ptr, j_ptr, ot_ptr->min_inflate, FALSE);
363     if (o_ptr->number > 1) {
364         if ((cur_store_num != STORE_HOME) && (o_ptr->ident & IDENT_FIXED)) {
365             msg_format(_("一つにつき $%ldです。", "That costs %ld gold per item."), (long)(best));
366         }
367
368         amt = get_quantity(NULL, o_ptr->number);
369         if (amt <= 0)
370             return;
371     }
372
373     j_ptr = &forge;
374     object_copy(j_ptr, o_ptr);
375
376     /*
377      * If a rod or wand, allocate total maximum timeouts or charges
378      * between those purchased and left on the shelf.
379      */
380     reduce_charges(j_ptr, o_ptr->number - amt);
381     j_ptr->number = amt;
382     if (!check_store_item_to_inventory(player_ptr, j_ptr)) {
383         msg_print(_("ザックにそのアイテムを入れる隙間がない。", "You cannot carry that many items."));
384         return;
385     }
386
387     COMMAND_CODE item_new;
388     if (process_purchase_result(player_ptr, o_ptr, j_ptr, &item_new, amt, &i, item))
389         return;
390
391     int choice;
392     PRICE price;
393     if (o_ptr->ident & (IDENT_FIXED)) {
394         choice = 0;
395         price = (best * j_ptr->number);
396     } else {
397         GAME_TEXT o_name[MAX_NLEN];
398         describe_flavor(player_ptr, o_name, j_ptr, 0);
399         msg_format(_("%s(%c)を購入する。", "Buying %s (%c)."), o_name, I2A(item));
400         msg_print(NULL);
401         choice = purchase_haggle(player_ptr, j_ptr, &price);
402         if (st_ptr->store_open >= current_world_ptr->game_turn)
403             return;
404     }
405
406     if (choice != 0)
407         return;
408
409     if (price == (best * j_ptr->number))
410         o_ptr->ident |= (IDENT_FIXED);
411
412     if (player_ptr->au < price) {
413         msg_print(_("お金が足りません。", "You do not have enough gold."));
414         return;
415     }
416
417     say_comment_1(player_ptr);
418     if (cur_store_num == STORE_BLACK)
419         chg_virtue(player_ptr, V_JUSTICE, -1);
420     if ((o_ptr->tval == TV_BOTTLE) && (cur_store_num != STORE_HOME))
421         chg_virtue(player_ptr, V_NATURE, -1);
422
423     sound(SOUND_BUY);
424     decrease_insults();
425     player_ptr->au -= price;
426     store_prt_gold(player_ptr);
427     object_aware(player_ptr, j_ptr);
428     j_ptr->ident &= ~(IDENT_FIXED);
429     GAME_TEXT o_name[MAX_NLEN];
430     describe_flavor(player_ptr, o_name, j_ptr, 0);
431
432     msg_format(_("%sを $%ldで購入しました。", "You bought %s for %ld gold."), o_name, (long)price);
433
434     strcpy(record_o_name, o_name);
435     record_turn = current_world_ptr->game_turn;
436
437     if (record_buy)
438         exe_write_diary(player_ptr, DIARY_BUY, 0, o_name);
439     describe_flavor(player_ptr, o_name, o_ptr, OD_NAME_ONLY);
440     if (record_rand_art && o_ptr->art_name)
441         exe_write_diary(player_ptr, DIARY_ART, 0, o_name);
442
443     j_ptr->inscription = 0;
444     j_ptr->feeling = FEEL_NONE;
445     j_ptr->ident &= ~(IDENT_STORE);
446     item_new = store_item_to_inventory(player_ptr, j_ptr);
447     handle_stuff(player_ptr);
448
449     describe_flavor(player_ptr, o_name, &player_ptr->inventory_list[item_new], 0);
450     msg_format(_("%s(%c)を手に入れた。", "You have %s (%c)."), o_name, index_to_label(item_new));
451
452     autopick_alter_item(player_ptr, item_new, FALSE);
453     if ((o_ptr->tval == TV_ROD) || (o_ptr->tval == TV_WAND))
454         o_ptr->pval -= j_ptr->pval;
455
456     i = st_ptr->stock_num;
457     store_item_increase(item, -amt);
458     store_item_optimize(item);
459     switch_store_stock(player_ptr, i, item);
460 }