OSDN Git Service

[Refactor] #40521 Added reference for item_selection_ptr to mode and tval
[hengbandforosx/hengbandosx.git] / src / inventory / item-getter.c
1 #include "inventory/item-getter.h"
2 #include "core/stuff-handler.h"
3 #include "floor/floor.h"
4 #include "game-option/input-options.h"
5 #include "game-option/option-flags.h"
6 #include "game-option/text-display-options.h"
7 #include "grid/grid.h"
8 #include "inventory/floor-item-getter.h"
9 #include "inventory/inventory-util.h"
10 #include "inventory/item-selection-util.h"
11 #include "io/command-repeater.h"
12 #include "io/input-key-acceptor.h"
13 #include "io/input-key-requester.h"
14 #include "main/sound-of-music.h"
15 #include "object/item-tester-hooker.h"
16 #include "object/item-use-flags.h"
17 #include "object/object-info.h"
18 #include "object/object-mark-types.h"
19 #include "term/gameterm.h"
20 #include "term/screen-processor.h"
21 #include "util/int-char-converter.h"
22 #include "view/display-inventory.h"
23 #include "view/display-messages.h"
24 #include "view/display-sub-windows.h"
25
26 /*!
27  * @brief オブジェクト選択の汎用関数 / General function for the selection of item
28  * Let the user select an item, save its "index"
29  * @param owner_ptr プレーヤーへの参照ポインタ
30  * @param cp 選択したオブジェクトのID
31  * @param pmt 選択目的のメッセージ
32  * @param str 選択できるオブジェクトがない場合のキャンセルメッセージ
33  * @param mode オプションフラグ
34  * @return プレイヤーによりアイテムが選択されたならTRUEを返す
35  * Return TRUE only if an acceptable item was chosen by the user
36  */
37 bool get_item(player_type *owner_ptr, OBJECT_IDX *cp, concptr pmt, concptr str, BIT_FLAGS mode, tval_type tval)
38 {
39     static char prev_tag = '\0'; // TODO: repeat_pull の中だけポインタにする
40     if (easy_floor || use_menu)
41         return get_item_floor(owner_ptr, cp, pmt, str, mode, tval);
42
43     item_selection_type tmp_selection;
44     item_selection_type *item_selection_ptr = initialize_item_selection_type(&tmp_selection, cp, mode, tval);
45     if (item_selection_ptr->mode & USE_EQUIP)
46         item_selection_ptr->equip = TRUE;
47
48     if (item_selection_ptr->mode & USE_INVEN)
49         item_selection_ptr->inven = TRUE;
50
51     if (item_selection_ptr->mode & USE_FLOOR)
52         item_selection_ptr->floor = TRUE;
53
54     if (repeat_pull(item_selection_ptr->cp)) {
55         if (item_selection_ptr->mode & USE_FORCE && (*item_selection_ptr->cp == INVEN_FORCE)) {
56             item_selection_ptr->tval = 0;
57             item_tester_hook = NULL;
58             command_cmd = 0;
59             return TRUE;
60         } else if (item_selection_ptr->floor && (*item_selection_ptr->cp < 0)) {
61             object_type *o_ptr;
62             item_selection_ptr->k = 0 - (*item_selection_ptr->cp);
63             o_ptr = &owner_ptr->current_floor_ptr->o_list[item_selection_ptr->k];
64             if (item_tester_okay(owner_ptr, o_ptr, item_selection_ptr->tval) || (item_selection_ptr->mode & USE_FULL)) {
65                 item_selection_ptr->tval = 0;
66                 item_tester_hook = NULL;
67                 command_cmd = 0;
68                 return TRUE;
69             }
70         } else if ((item_selection_ptr->inven && (*item_selection_ptr->cp >= 0) && (*item_selection_ptr->cp < INVEN_PACK)) || (item_selection_ptr->equip && (*item_selection_ptr->cp >= INVEN_RARM) && (*item_selection_ptr->cp < INVEN_TOTAL))) {
71             if (prev_tag && command_cmd) {
72                 if (!get_tag(owner_ptr, &item_selection_ptr->k, prev_tag, (*item_selection_ptr->cp >= INVEN_RARM) ? USE_EQUIP : USE_INVEN, item_selection_ptr->tval)) /* Reject */
73                     ;
74                 else if ((item_selection_ptr->k < INVEN_RARM) ? !item_selection_ptr->inven : !item_selection_ptr->equip) /* Reject */
75                     ;
76                 else if (!get_item_okay(owner_ptr, item_selection_ptr->k, item_selection_ptr->tval)) /* Reject */
77                     ;
78                 else {
79                     *item_selection_ptr->cp = item_selection_ptr->k;
80                     item_selection_ptr->tval = 0;
81                     item_tester_hook = NULL;
82                     command_cmd = 0;
83                     return TRUE;
84                 }
85
86                 prev_tag = '\0';
87             } else if (get_item_okay(owner_ptr, *item_selection_ptr->cp, item_selection_ptr->tval)) {
88                 item_selection_ptr->tval = 0;
89                 item_tester_hook = NULL;
90                 command_cmd = 0;
91                 return TRUE;
92             }
93         }
94     }
95
96     msg_print(NULL);
97     item_selection_ptr->done = FALSE;
98     item_selection_ptr->item = FALSE;
99     item_selection_ptr->i1 = 0;
100     item_selection_ptr->i2 = INVEN_PACK - 1;
101     if (!item_selection_ptr->inven)
102         item_selection_ptr->i2 = -1;
103     else if (use_menu)
104         for (int j = 0; j < INVEN_PACK; j++)
105             if (item_tester_okay(owner_ptr, &owner_ptr->inventory_list[j], item_selection_ptr->tval) || (item_selection_ptr->mode & USE_FULL))
106                 item_selection_ptr->max_inven++;
107
108     while ((item_selection_ptr->i1 <= item_selection_ptr->i2) && (!get_item_okay(owner_ptr, item_selection_ptr->i1, item_selection_ptr->tval)))
109         item_selection_ptr->i1++;
110
111     while ((item_selection_ptr->i1 <= item_selection_ptr->i2) && (!get_item_okay(owner_ptr, item_selection_ptr->i2, item_selection_ptr->tval)))
112         item_selection_ptr->i2--;
113
114     item_selection_ptr->e1 = INVEN_RARM;
115     item_selection_ptr->e2 = INVEN_TOTAL - 1;
116     if (!item_selection_ptr->equip)
117         item_selection_ptr->e2 = -1;
118     else if (use_menu) {
119         for (int j = INVEN_RARM; j < INVEN_TOTAL; j++)
120             if (select_ring_slot ? is_ring_slot(j) : item_tester_okay(owner_ptr, &owner_ptr->inventory_list[j], item_selection_ptr->tval) || (item_selection_ptr->mode & USE_FULL))
121                 item_selection_ptr->max_equip++;
122
123         if (owner_ptr->ryoute && !(item_selection_ptr->mode & IGNORE_BOTHHAND_SLOT))
124             item_selection_ptr->max_equip++;
125     }
126
127     while ((item_selection_ptr->e1 <= item_selection_ptr->e2) && (!get_item_okay(owner_ptr, item_selection_ptr->e1, item_selection_ptr->tval)))
128         item_selection_ptr->e1++;
129
130     while ((item_selection_ptr->e1 <= item_selection_ptr->e2) && (!get_item_okay(owner_ptr, item_selection_ptr->e2, item_selection_ptr->tval)))
131         item_selection_ptr->e2--;
132
133     if (item_selection_ptr->equip && owner_ptr->ryoute && !(item_selection_ptr->mode & IGNORE_BOTHHAND_SLOT)) {
134         if (owner_ptr->migite) {
135             if (item_selection_ptr->e2 < INVEN_LARM)
136                 item_selection_ptr->e2 = INVEN_LARM;
137         } else if (owner_ptr->hidarite)
138             item_selection_ptr->e1 = INVEN_RARM;
139     }
140
141     if (item_selection_ptr->floor) {
142         for (item_selection_ptr->this_o_idx = owner_ptr->current_floor_ptr->grid_array[owner_ptr->y][owner_ptr->x].o_idx; item_selection_ptr->this_o_idx; item_selection_ptr->this_o_idx = item_selection_ptr->next_o_idx) {
143             object_type *o_ptr;
144             o_ptr = &owner_ptr->current_floor_ptr->o_list[item_selection_ptr->this_o_idx];
145             item_selection_ptr->next_o_idx = o_ptr->next_o_idx;
146             if ((item_tester_okay(owner_ptr, o_ptr, item_selection_ptr->tval) || (item_selection_ptr->mode & USE_FULL)) && (o_ptr->marked & OM_FOUND))
147                 item_selection_ptr->allow_floor = TRUE;
148         }
149     }
150
151     if (!item_selection_ptr->allow_floor && (item_selection_ptr->i1 > item_selection_ptr->i2) && (item_selection_ptr->e1 > item_selection_ptr->e2)) {
152         command_see = FALSE;
153         item_selection_ptr->oops = TRUE;
154         item_selection_ptr->done = TRUE;
155
156         if (item_selection_ptr->mode & USE_FORCE) {
157             *item_selection_ptr->cp = INVEN_FORCE;
158             item_selection_ptr->item = TRUE;
159         }
160     } else {
161         if (command_see && command_wrk && item_selection_ptr->equip)
162             command_wrk = TRUE;
163         else if (item_selection_ptr->inven)
164             command_wrk = FALSE;
165         else if (item_selection_ptr->equip)
166             command_wrk = TRUE;
167         else
168             command_wrk = FALSE;
169     }
170
171     /* 追加オプション(always_show_list)が設定されている場合は常に一覧を表示する */
172     if ((always_show_list == TRUE) || use_menu)
173         command_see = TRUE;
174
175     if (command_see)
176         screen_save();
177
178     while (!item_selection_ptr->done) {
179         COMMAND_CODE get_item_label = 0;
180         int ni = 0;
181         int ne = 0;
182         for (int j = 0; j < 8; j++) {
183             if (!angband_term[j])
184                 continue;
185
186             if (window_flag[j] & (PW_INVEN))
187                 ni++;
188
189             if (window_flag[j] & (PW_EQUIP))
190                 ne++;
191         }
192
193         if ((command_wrk && ni && !ne) || (!command_wrk && !ni && ne)) {
194             toggle_inventory_equipment(owner_ptr);
195             item_selection_ptr->toggle = !item_selection_ptr->toggle;
196         }
197
198         owner_ptr->window |= (PW_INVEN | PW_EQUIP);
199         handle_stuff(owner_ptr);
200
201         if (!command_wrk) {
202             if (command_see)
203                 get_item_label = show_inventory(owner_ptr, item_selection_ptr->menu_line, item_selection_ptr->mode, item_selection_ptr->tval);
204         } else {
205             if (command_see)
206                 get_item_label = show_equipment(owner_ptr, item_selection_ptr->menu_line, item_selection_ptr->mode, item_selection_ptr->tval);
207         }
208
209         if (!command_wrk) {
210             sprintf(item_selection_ptr->out_val, _("持ち物:", "Inven:"));
211             if ((item_selection_ptr->i1 <= item_selection_ptr->i2) && !use_menu) {
212                 sprintf(item_selection_ptr->tmp_val, _("%c-%c,'(',')',", " %c-%c,'(',')',"), index_to_label(item_selection_ptr->i1), index_to_label(item_selection_ptr->i2));
213                 strcat(item_selection_ptr->out_val, item_selection_ptr->tmp_val);
214             }
215
216             if (!command_see && !use_menu)
217                 strcat(item_selection_ptr->out_val, _(" '*'一覧,", " * to see,"));
218
219             if (item_selection_ptr->equip)
220                 strcat(item_selection_ptr->out_val, format(_(" %s 装備品,", " %s for Equip,"), use_menu ? _("'4'or'6'", "4 or 6") : _("'/'", "/")));
221         } else {
222             sprintf(item_selection_ptr->out_val, _("装備品:", "Equip:"));
223             if ((item_selection_ptr->e1 <= item_selection_ptr->e2) && !use_menu) {
224                 sprintf(item_selection_ptr->tmp_val, _("%c-%c,'(',')',", " %c-%c,'(',')',"), index_to_label(item_selection_ptr->e1), index_to_label(item_selection_ptr->e2));
225                 strcat(item_selection_ptr->out_val, item_selection_ptr->tmp_val);
226             }
227
228             if (!command_see && !use_menu)
229                 strcat(item_selection_ptr->out_val, _(" '*'一覧,", " * to see,"));
230
231             if (item_selection_ptr->inven)
232                 strcat(item_selection_ptr->out_val, format(_(" %s 持ち物,", " %s for Inven,"), use_menu ? _("'4'or'6'", "4 or 6") : _("'/'", "'/'")));
233         }
234
235         if (item_selection_ptr->allow_floor)
236             strcat(item_selection_ptr->out_val, _(" '-'床上,", " - for item_selection_ptr->floor,"));
237
238         if (item_selection_ptr->mode & USE_FORCE)
239             strcat(item_selection_ptr->out_val, _(" 'w'練気術,", " w for the Force,"));
240
241         strcat(item_selection_ptr->out_val, " ESC");
242         sprintf(item_selection_ptr->tmp_val, "(%s) %s", item_selection_ptr->out_val, pmt);
243         prt(item_selection_ptr->tmp_val, 0, 0);
244         item_selection_ptr->which = inkey();
245         if (use_menu) {
246             int max_line = (command_wrk ? item_selection_ptr->max_equip : item_selection_ptr->max_inven);
247             switch (item_selection_ptr->which) {
248             case ESCAPE:
249             case 'z':
250             case 'Z':
251             case '0': {
252                 item_selection_ptr->done = TRUE;
253                 break;
254             }
255
256             case '8':
257             case 'k':
258             case 'K': {
259                 item_selection_ptr->menu_line += (max_line - 1);
260                 break;
261             }
262
263             case '2':
264             case 'j':
265             case 'J': {
266                 item_selection_ptr->menu_line++;
267                 break;
268             }
269
270             case '4':
271             case '6':
272             case 'h':
273             case 'H':
274             case 'l':
275             case 'L': {
276                 if (!item_selection_ptr->inven || !item_selection_ptr->equip) {
277                     bell();
278                     break;
279                 }
280
281                 if (command_see) {
282                     screen_load();
283                     screen_save();
284                 }
285
286                 command_wrk = !command_wrk;
287                 max_line = (command_wrk ? item_selection_ptr->max_equip : item_selection_ptr->max_inven);
288                 if (item_selection_ptr->menu_line > max_line)
289                     item_selection_ptr->menu_line = max_line;
290
291                 break;
292             }
293
294             case 'x':
295             case 'X':
296             case '\r':
297             case '\n': {
298                 if (command_wrk == USE_FLOOR) {
299                     *item_selection_ptr->cp = -get_item_label;
300                 } else {
301                     if (!get_item_okay(owner_ptr, get_item_label, item_selection_ptr->tval)) {
302                         bell();
303                         break;
304                     }
305
306                     if (!get_item_allow(owner_ptr, get_item_label)) {
307                         item_selection_ptr->done = TRUE;
308                         break;
309                     }
310
311                     *item_selection_ptr->cp = get_item_label;
312                 }
313
314                 item_selection_ptr->item = TRUE;
315                 item_selection_ptr->done = TRUE;
316                 break;
317             }
318             case 'w': {
319                 if (item_selection_ptr->mode & USE_FORCE) {
320                     *item_selection_ptr->cp = INVEN_FORCE;
321                     item_selection_ptr->item = TRUE;
322                     item_selection_ptr->done = TRUE;
323                     break;
324                 }
325             }
326             }
327
328             if (item_selection_ptr->menu_line > max_line)
329                 item_selection_ptr->menu_line -= max_line;
330
331             continue;
332         }
333
334         switch (item_selection_ptr->which) {
335         case ESCAPE: {
336             item_selection_ptr->done = TRUE;
337             break;
338         }
339         case '*':
340         case '?':
341         case ' ': {
342             if (command_see) {
343                 command_see = FALSE;
344                 screen_load();
345             } else {
346                 screen_save();
347                 command_see = TRUE;
348             }
349
350             break;
351         }
352         case '/': {
353             if (!item_selection_ptr->inven || !item_selection_ptr->equip) {
354                 bell();
355                 break;
356             }
357
358             if (command_see) {
359                 screen_load();
360                 screen_save();
361             }
362
363             command_wrk = !command_wrk;
364             break;
365         }
366         case '-': {
367             if (item_selection_ptr->allow_floor) {
368                 for (item_selection_ptr->this_o_idx = owner_ptr->current_floor_ptr->grid_array[owner_ptr->y][owner_ptr->x].o_idx; item_selection_ptr->this_o_idx; item_selection_ptr->this_o_idx = item_selection_ptr->next_o_idx) {
369                     object_type *o_ptr;
370                     o_ptr = &owner_ptr->current_floor_ptr->o_list[item_selection_ptr->this_o_idx];
371                     item_selection_ptr->next_o_idx = o_ptr->next_o_idx;
372                     if (!item_tester_okay(owner_ptr, o_ptr, item_selection_ptr->tval) && !(item_selection_ptr->mode & USE_FULL))
373                         continue;
374
375                     item_selection_ptr->k = 0 - item_selection_ptr->this_o_idx;
376                     if (other_query_flag && !verify(owner_ptr, _("本当に", "Try"), item_selection_ptr->k) || !get_item_allow(owner_ptr, item_selection_ptr->k))
377                         continue;
378
379                     *item_selection_ptr->cp = item_selection_ptr->k;
380                     item_selection_ptr->item = TRUE;
381                     item_selection_ptr->done = TRUE;
382                     break;
383                 }
384
385                 if (item_selection_ptr->done)
386                     break;
387             }
388
389             bell();
390             break;
391         }
392         case '0':
393         case '1':
394         case '2':
395         case '3':
396         case '4':
397         case '5':
398         case '6':
399         case '7':
400         case '8':
401         case '9': {
402             if (!get_tag(owner_ptr, &item_selection_ptr->k, item_selection_ptr->which, command_wrk ? USE_EQUIP : USE_INVEN, item_selection_ptr->tval)) {
403                 bell();
404                 break;
405             }
406
407             if ((item_selection_ptr->k < INVEN_RARM) ? !item_selection_ptr->inven : !item_selection_ptr->equip) {
408                 bell();
409                 break;
410             }
411
412             if (!get_item_okay(owner_ptr, item_selection_ptr->k, item_selection_ptr->tval)) {
413                 bell();
414                 break;
415             }
416
417             if (!get_item_allow(owner_ptr, item_selection_ptr->k)) {
418                 item_selection_ptr->done = TRUE;
419                 break;
420             }
421
422             *item_selection_ptr->cp = item_selection_ptr->k;
423             item_selection_ptr->item = TRUE;
424             item_selection_ptr->done = TRUE;
425             item_selection_ptr->cur_tag = item_selection_ptr->which;
426             break;
427         }
428         case 'w': {
429             if (item_selection_ptr->mode & USE_FORCE) {
430                 *item_selection_ptr->cp = INVEN_FORCE;
431                 item_selection_ptr->item = TRUE;
432                 item_selection_ptr->done = TRUE;
433                 break;
434             }
435         }
436             /* Fall through */
437         default: {
438             int ver;
439             bool not_found = FALSE;
440             if (!get_tag(owner_ptr, &item_selection_ptr->k, item_selection_ptr->which, command_wrk ? USE_EQUIP : USE_INVEN, item_selection_ptr->tval)) {
441                 not_found = TRUE;
442             } else if ((item_selection_ptr->k < INVEN_RARM) ? !item_selection_ptr->inven : !item_selection_ptr->equip) {
443                 not_found = TRUE;
444             } else if (!get_item_okay(owner_ptr, item_selection_ptr->k, item_selection_ptr->tval)) {
445                 not_found = TRUE;
446             }
447
448             if (!not_found) {
449                 *item_selection_ptr->cp = item_selection_ptr->k;
450                 item_selection_ptr->item = TRUE;
451                 item_selection_ptr->done = TRUE;
452                 item_selection_ptr->cur_tag = item_selection_ptr->which;
453                 break;
454             }
455
456             ver = isupper(item_selection_ptr->which);
457             item_selection_ptr->which = (char)tolower(item_selection_ptr->which);
458             if (!command_wrk) {
459                 if (item_selection_ptr->which == '(')
460                     item_selection_ptr->k = item_selection_ptr->i1;
461                 else if (item_selection_ptr->which == ')')
462                     item_selection_ptr->k = item_selection_ptr->i2;
463                 else
464                     item_selection_ptr->k = label_to_inventory(owner_ptr, item_selection_ptr->which);
465             } else {
466                 if (item_selection_ptr->which == '(')
467                     item_selection_ptr->k = item_selection_ptr->e1;
468                 else if (item_selection_ptr->which == ')')
469                     item_selection_ptr->k = item_selection_ptr->e2;
470                 else
471                     item_selection_ptr->k = label_to_equipment(owner_ptr, item_selection_ptr->which);
472             }
473
474             if (!get_item_okay(owner_ptr, item_selection_ptr->k, item_selection_ptr->tval)) {
475                 bell();
476                 break;
477             }
478
479             if (ver && !verify(owner_ptr, _("本当に", "Try"), item_selection_ptr->k)) {
480                 item_selection_ptr->done = TRUE;
481                 break;
482             }
483
484             if (!get_item_allow(owner_ptr, item_selection_ptr->k)) {
485                 item_selection_ptr->done = TRUE;
486                 break;
487             }
488
489             *item_selection_ptr->cp = item_selection_ptr->k;
490             item_selection_ptr->item = TRUE;
491             item_selection_ptr->done = TRUE;
492             break;
493         }
494         }
495     }
496
497     if (command_see) {
498         screen_load();
499         command_see = FALSE;
500     }
501
502     item_selection_ptr->tval = 0;
503     item_tester_hook = NULL;
504     if (item_selection_ptr->toggle)
505         toggle_inventory_equipment(owner_ptr);
506
507     owner_ptr->window |= (PW_INVEN | PW_EQUIP);
508     handle_stuff(owner_ptr);
509     prt("", 0, 0);
510     if (item_selection_ptr->oops && str)
511         msg_print(str);
512
513     if (item_selection_ptr->item) {
514         repeat_push(*item_selection_ptr->cp);
515         if (command_cmd)
516             prev_tag = item_selection_ptr->cur_tag;
517         command_cmd = 0;
518     }
519
520     return item_selection_ptr->item;
521 }