OSDN Git Service

Merge branch 'master' of https://github.com/hengband/hengband
[hengbandforosx/hengbandosx.git] / src / inventory / floor-item-getter.cpp
1 /*!
2  * @brief オブジェクト選択処理
3  * @date 2020/07/02
4  * @author Hourier
5  */
6
7 #include "inventory/floor-item-getter.h"
8 #include "core/stuff-handler.h"
9 #include "core/window-redrawer.h"
10 #include "floor/floor-object.h"
11 #include "floor/object-scanner.h"
12 #include "game-option/input-options.h"
13 #include "game-option/option-flags.h"
14 #include "game-option/text-display-options.h"
15 #include "inventory/inventory-slot-types.h"
16 #include "inventory/inventory-util.h"
17 #include "inventory/item-selection-util.h"
18 #include "io/command-repeater.h"
19 #include "io/input-key-acceptor.h"
20 #include "io/input-key-requester.h"
21 #include "main/sound-of-music.h"
22 #include "object/item-tester-hooker.h"
23 #include "object/item-use-flags.h"
24 #include "object/object-info.h"
25 #include "player/player-status-flags.h"
26 #include "system/floor-type-definition.h"
27 #include "system/grid-type-definition.h"
28 #include "system/item-entity.h"
29 #include "system/player-type-definition.h"
30 #include "system/redrawing-flags-updater.h"
31 #include "term/gameterm.h"
32 #include "term/screen-processor.h"
33 #include "term/z-form.h"
34 #include "util/int-char-converter.h"
35 #include "util/string-processor.h"
36 #include "view/display-inventory.h"
37 #include "view/display-messages.h"
38 #include "window/display-sub-windows.h"
39
40 /*!
41  * @brief 床上アイテムへにタグ付けがされているかの調査処理 (のはず)
42  * @param player_ptr プレイヤーへの参照ポインタ
43  * @param fis_ptr 床上アイテムへの参照ポインタ
44  * @param prev_tag 前回選択したアイテムのタグ (のはず)
45  * @return プレイヤーによりアイテムが選択されたならTRUEを返す
46  * @todo 適切な関数名をどうしても付けられなかったので暫定でauxとした
47  */
48 static bool check_floor_item_tag_aux(PlayerType *player_ptr, fis_type *fis_ptr, char *prev_tag, const ItemTester &item_tester)
49 {
50     if (!fis_ptr->floor || (*fis_ptr->cp >= 0)) {
51         return false;
52     }
53
54     if (*prev_tag && command_cmd) {
55         fis_ptr->floor_num = scan_floor_items(player_ptr, fis_ptr->floor_list, player_ptr->y, player_ptr->x, SCAN_FLOOR_ITEM_TESTER | SCAN_FLOOR_ONLY_MARKED, item_tester);
56         if (get_tag_floor(player_ptr->current_floor_ptr, &fis_ptr->k, *prev_tag, fis_ptr->floor_list, fis_ptr->floor_num)) {
57             *fis_ptr->cp = 0 - fis_ptr->floor_list[fis_ptr->k];
58             command_cmd = 0;
59             return true;
60         }
61
62         *prev_tag = '\0';
63         return false;
64     }
65
66     if (!item_tester.okay(&player_ptr->current_floor_ptr->o_list[0 - (*fis_ptr->cp)]) && ((fis_ptr->mode & USE_FULL) == 0)) {
67         return false;
68     }
69
70     command_cmd = 0;
71     return true;
72 }
73
74 /*!
75  * @brief インベントリのアイテムにタグ付けを試みる
76  * @param player_ptr プレイヤーへの参照ポインタ
77  * @param fis_ptr 床上アイテムへの参照ポインタ
78  * @param prev_tag 前回選択したアイテムのタグ (のはず)
79  * @return プレイヤーによりアイテムが選択されたならTRUEを返す
80  */
81 static bool get_floor_item_tag_inventory(PlayerType *player_ptr, fis_type *fis_ptr, char *prev_tag, const ItemTester &item_tester)
82 {
83     bool flag = false;
84     item_use_flag use_flag = (*fis_ptr->cp >= INVEN_MAIN_HAND) ? USE_EQUIP : USE_INVEN;
85
86     flag |= !get_tag(player_ptr, &fis_ptr->k, *prev_tag, use_flag, item_tester);
87     flag |= !get_item_okay(player_ptr, fis_ptr->k, item_tester);
88
89     if (fis_ptr->k < INVEN_MAIN_HAND) {
90         flag |= !fis_ptr->inven;
91     } else {
92         flag |= !fis_ptr->equip;
93     }
94
95     if (flag) {
96         *prev_tag = '\0';
97         return false;
98     }
99
100     *fis_ptr->cp = fis_ptr->k;
101     command_cmd = 0;
102     return true;
103 }
104
105 /*!
106  * @brief インベントリのアイテムにタグ付けがされているかの調査処理 (のはず)
107  * @param player_ptr プレイヤーへの参照ポインタ
108  * @param fis_ptr 床上アイテムへの参照ポインタ
109  * @param prev_tag 前回選択したアイテムのタグ (のはず)
110  * @return プレイヤーによりアイテムが選択されたならTRUEを返す
111  */
112 static bool check_floor_item_tag_inventory(PlayerType *player_ptr, fis_type *fis_ptr, char *prev_tag, const ItemTester &item_tester)
113 {
114     if ((!fis_ptr->inven || (*fis_ptr->cp < 0) || (*fis_ptr->cp >= INVEN_PACK)) && (!fis_ptr->equip || (*fis_ptr->cp < INVEN_MAIN_HAND) || (*fis_ptr->cp >= INVEN_TOTAL))) {
115         return false;
116     }
117
118     if ((*prev_tag != '\0') && command_cmd) {
119         return get_floor_item_tag_inventory(player_ptr, fis_ptr, prev_tag, item_tester);
120     }
121
122     if (get_item_okay(player_ptr, *fis_ptr->cp, item_tester)) {
123         command_cmd = 0;
124         return true;
125     }
126
127     return false;
128 }
129
130 /*!
131  * @brief 床上アイテムにタグ付けがされているかの調査処理 (のはず)
132  * @param player_ptr プレイヤーへの参照ポインタ
133  * @param fis_ptr 床上アイテムへの参照ポインタ
134  * @param prev_tag 前回選択したアイテムのタグ (のはず)
135  * @return プレイヤーによりアイテムが選択されたならTRUEを返す
136  */
137 static bool check_floor_item_tag(PlayerType *player_ptr, fis_type *fis_ptr, char *prev_tag, const ItemTester &item_tester)
138 {
139     if (!repeat_pull(fis_ptr->cp)) {
140         return false;
141     }
142
143     if (fis_ptr->force && (*fis_ptr->cp == INVEN_FORCE)) {
144         command_cmd = 0;
145         return true;
146     }
147
148     if (check_floor_item_tag_aux(player_ptr, fis_ptr, prev_tag, item_tester)) {
149         return true;
150     }
151
152     return check_floor_item_tag_inventory(player_ptr, fis_ptr, prev_tag, item_tester);
153 }
154
155 /*!
156  * @brief インベントリ内のアイテムが妥当かを判定する
157  * @param player_ptr プレイヤーへの参照ポインタ
158  * @param fis_ptr 床上アイテムへの参照ポインタ
159  */
160 static void test_inventory_floor(PlayerType *player_ptr, fis_type *fis_ptr, const ItemTester &item_tester)
161 {
162     if (!fis_ptr->inven) {
163         fis_ptr->i2 = -1;
164         return;
165     }
166
167     if (!use_menu) {
168         return;
169     }
170
171     for (int i = 0; i < INVEN_PACK; i++) {
172         if (item_tester.okay(&player_ptr->inventory_list[i]) || (fis_ptr->mode & USE_FULL)) {
173             fis_ptr->max_inven++;
174         }
175     }
176 }
177
178 /*!
179  * @brief 装備品がが妥当かを判定する
180  * @param player_ptr プレイヤーへの参照ポインタ
181  * @param fis_ptr 床上アイテムへの参照ポインタ
182  */
183 static void test_equipment_floor(PlayerType *player_ptr, fis_type *fis_ptr, const ItemTester &item_tester)
184 {
185     if (!fis_ptr->equip) {
186         fis_ptr->e2 = -1;
187         return;
188     }
189
190     if (!use_menu) {
191         return;
192     }
193
194     for (int i = INVEN_MAIN_HAND; i < INVEN_TOTAL; i++) {
195         if (player_ptr->select_ring_slot ? is_ring_slot(i)
196                                          : item_tester.okay(&player_ptr->inventory_list[i]) || (fis_ptr->mode & USE_FULL)) {
197             fis_ptr->max_equip++;
198         }
199     }
200 }
201
202 /*!
203  * @brief オブジェクト選択の汎用関数(床上アイテム用) /
204  * Let the user select an item, save its "index"
205  * @param cp 選択したオブジェクトのIDを返す。
206  * @param pmt 選択目的のメッセージ
207  * @param str 選択できるオブジェクトがない場合のキャンセルメッセージ
208  * @param mode オプションフラグ
209  * @return プレイヤーによりアイテムが選択されたならTRUEを返す。/
210  */
211 bool get_item_floor(PlayerType *player_ptr, COMMAND_CODE *cp, concptr pmt, concptr str, BIT_FLAGS mode, const ItemTester &item_tester)
212 {
213     fis_type tmp_fis;
214     fis_type *fis_ptr = initialize_fis_type(&tmp_fis, cp, mode);
215     static char prev_tag = '\0';
216     if (check_floor_item_tag(player_ptr, fis_ptr, &prev_tag, item_tester)) {
217         return true;
218     }
219
220     msg_print(nullptr);
221     handle_stuff(player_ptr);
222     test_inventory_floor(player_ptr, fis_ptr, item_tester);
223     fis_ptr->done = false;
224     fis_ptr->item = false;
225     fis_ptr->i1 = 0;
226     fis_ptr->i2 = INVEN_PACK - 1;
227     while ((fis_ptr->i1 <= fis_ptr->i2) && (!get_item_okay(player_ptr, fis_ptr->i1, item_tester))) {
228         fis_ptr->i1++;
229     }
230
231     while ((fis_ptr->i1 <= fis_ptr->i2) && (!get_item_okay(player_ptr, fis_ptr->i2, item_tester))) {
232         fis_ptr->i2--;
233     }
234
235     fis_ptr->e1 = INVEN_MAIN_HAND;
236     fis_ptr->e2 = INVEN_TOTAL - 1;
237     test_equipment_floor(player_ptr, fis_ptr, item_tester);
238     if (has_two_handed_weapons(player_ptr) && !(fis_ptr->mode & IGNORE_BOTHHAND_SLOT)) {
239         fis_ptr->max_equip++;
240     }
241
242     while ((fis_ptr->e1 <= fis_ptr->e2) && (!get_item_okay(player_ptr, fis_ptr->e1, item_tester))) {
243         fis_ptr->e1++;
244     }
245
246     while ((fis_ptr->e1 <= fis_ptr->e2) && (!get_item_okay(player_ptr, fis_ptr->e2, item_tester))) {
247         fis_ptr->e2--;
248     }
249
250     if (fis_ptr->equip && has_two_handed_weapons(player_ptr) && !(fis_ptr->mode & IGNORE_BOTHHAND_SLOT)) {
251         if (can_attack_with_main_hand(player_ptr)) {
252             if (fis_ptr->e2 < INVEN_SUB_HAND) {
253                 fis_ptr->e2 = INVEN_SUB_HAND;
254             }
255         } else if (can_attack_with_sub_hand(player_ptr)) {
256             fis_ptr->e1 = INVEN_MAIN_HAND;
257         }
258     }
259
260     fis_ptr->floor_num = 0;
261     if (fis_ptr->floor) {
262         constexpr auto options = SCAN_FLOOR_ITEM_TESTER | SCAN_FLOOR_ONLY_MARKED;
263         fis_ptr->floor_num = scan_floor_items(player_ptr, fis_ptr->floor_list, player_ptr->y, player_ptr->x, options, item_tester);
264     }
265
266     if ((mode & USE_INVEN) && (fis_ptr->i1 <= fis_ptr->i2)) {
267         fis_ptr->allow_inven = true;
268     }
269
270     if ((mode & USE_EQUIP) && (fis_ptr->e1 <= fis_ptr->e2)) {
271         fis_ptr->allow_equip = true;
272     }
273
274     if ((mode & USE_FLOOR) && (fis_ptr->floor_num)) {
275         fis_ptr->allow_floor = true;
276     }
277
278     if (!fis_ptr->allow_inven && !fis_ptr->allow_equip && !fis_ptr->allow_floor) {
279         command_see = false;
280         fis_ptr->oops = true;
281         fis_ptr->done = true;
282
283         if (fis_ptr->force) {
284             *cp = INVEN_FORCE;
285             fis_ptr->item = true;
286         }
287     } else {
288         if (command_see && (command_wrk == USE_EQUIP) && fis_ptr->allow_equip) {
289             command_wrk = USE_EQUIP;
290         } else if (fis_ptr->allow_inven) {
291             command_wrk = USE_INVEN;
292         } else if (fis_ptr->allow_equip) {
293             command_wrk = USE_EQUIP;
294         } else if (fis_ptr->allow_floor) {
295             command_wrk = USE_FLOOR;
296         }
297     }
298
299     /* 追加オプション(always_show_list)が設定されている場合は常に一覧を表示する */
300     if (always_show_list || use_menu) {
301         command_see = true;
302     }
303
304     if (command_see) {
305         screen_save();
306     }
307
308     auto &rfu = RedrawingFlagsUpdater::get_instance();
309     static constexpr auto flags = {
310         SubWindowRedrawingFlag::INVENTORY,
311         SubWindowRedrawingFlag::EQUIPMENT,
312     };
313     while (!fis_ptr->done) {
314         int ni = 0;
315         int ne = 0;
316         for (auto i = 0U; i < angband_terms.size(); ++i) {
317             if (!angband_terms[i]) {
318                 continue;
319             }
320
321             if (g_window_flags[i].has(SubWindowRedrawingFlag::INVENTORY)) {
322                 ni++;
323             }
324
325             if (g_window_flags[i].has(SubWindowRedrawingFlag::EQUIPMENT)) {
326                 ne++;
327             }
328         }
329
330         if ((command_wrk == (USE_EQUIP) && ni && !ne) || (command_wrk == (USE_INVEN) && !ni && ne)) {
331             toggle_inventory_equipment();
332             fis_ptr->toggle = !fis_ptr->toggle;
333         }
334
335         rfu.set_flags(flags);
336         handle_stuff(player_ptr);
337         COMMAND_CODE get_item_label = 0;
338         if (command_wrk == USE_INVEN) {
339             fis_ptr->n1 = I2A(fis_ptr->i1);
340             fis_ptr->n2 = I2A(fis_ptr->i2);
341             if (command_see) {
342                 get_item_label = show_inventory(player_ptr, fis_ptr->menu_line, fis_ptr->mode, item_tester);
343             }
344         } else if (command_wrk == USE_EQUIP) {
345             fis_ptr->n1 = I2A(fis_ptr->e1 - INVEN_MAIN_HAND);
346             fis_ptr->n2 = I2A(fis_ptr->e2 - INVEN_MAIN_HAND);
347             if (command_see) {
348                 get_item_label = show_equipment(player_ptr, fis_ptr->menu_line, mode, item_tester);
349             }
350         } else if (command_wrk == USE_FLOOR) {
351             int j = fis_ptr->floor_top;
352             fis_ptr->k = std::min(fis_ptr->floor_top + 23, fis_ptr->floor_num) - 1;
353             fis_ptr->n1 = I2A(j - fis_ptr->floor_top); // TODO: 常に'0'になる。どんな意図でこのようなコードになっているのか不明.
354             fis_ptr->n2 = I2A(fis_ptr->k - fis_ptr->floor_top);
355             if (command_see) {
356                 get_item_label = show_floor_items(player_ptr, fis_ptr->menu_line, player_ptr->y, player_ptr->x, &fis_ptr->min_width, item_tester);
357             }
358         }
359
360         if (command_wrk == USE_INVEN) {
361             angband_strcpy(fis_ptr->out_val, _("持ち物:", "Inven:"), sizeof(fis_ptr->out_val));
362             if (!use_menu) {
363                 const auto tmp_val = format(_("%c-%c,'(',')',", " %c-%c,'(',')',"), index_to_label(fis_ptr->i1), index_to_label(fis_ptr->i2));
364                 angband_strcat(fis_ptr->out_val, tmp_val, sizeof(fis_ptr->out_val));
365             }
366
367             if (!command_see && !use_menu) {
368                 angband_strcat(fis_ptr->out_val, _(" '*'一覧,", " * to see,"), sizeof(fis_ptr->out_val));
369             }
370
371             if (fis_ptr->allow_equip) {
372                 if (!use_menu) {
373                     angband_strcat(fis_ptr->out_val, _(" '/' 装備品,", " / for Equip,"), sizeof(fis_ptr->out_val));
374                 } else if (fis_ptr->allow_floor) {
375                     angband_strcat(fis_ptr->out_val, _(" '6' 装備品,", " 6 for Equip,"), sizeof(fis_ptr->out_val));
376                 } else {
377                     angband_strcat(fis_ptr->out_val, _(" '4'or'6' 装備品,", " 4 or 6 for Equip,"), sizeof(fis_ptr->out_val));
378                 }
379             }
380
381             if (fis_ptr->allow_floor) {
382                 if (!use_menu) {
383                     angband_strcat(fis_ptr->out_val, _(" '-'床上,", " - for floor,"), sizeof(fis_ptr->out_val));
384                 } else if (fis_ptr->allow_equip) {
385                     angband_strcat(fis_ptr->out_val, _(" '4' 床上,", " 4 for floor,"), sizeof(fis_ptr->out_val));
386                 } else {
387                     angband_strcat(fis_ptr->out_val, _(" '4'or'6' 床上,", " 4 or 6 for floor,"), sizeof(fis_ptr->out_val));
388                 }
389             }
390         } else if (command_wrk == (USE_EQUIP)) {
391             angband_strcpy(fis_ptr->out_val, _("装備品:", "Equip:"), sizeof(fis_ptr->out_val));
392             if (!use_menu) {
393                 const auto tmp_val = format(_("%c-%c,'(',')',", " %c-%c,'(',')',"), index_to_label(fis_ptr->e1), index_to_label(fis_ptr->e2));
394                 angband_strcat(fis_ptr->out_val, tmp_val, sizeof(fis_ptr->out_val));
395             }
396
397             if (!command_see && !use_menu) {
398                 angband_strcat(fis_ptr->out_val, _(" '*'一覧,", " * to see,"), sizeof(fis_ptr->out_val));
399             }
400
401             if (fis_ptr->allow_inven) {
402                 if (!use_menu) {
403                     angband_strcat(fis_ptr->out_val, _(" '/' 持ち物,", " / for Inven,"), sizeof(fis_ptr->out_val));
404                 } else if (fis_ptr->allow_floor) {
405                     angband_strcat(fis_ptr->out_val, _(" '4' 持ち物,", " 4 for Inven,"), sizeof(fis_ptr->out_val));
406                 } else {
407                     angband_strcat(fis_ptr->out_val, _(" '4'or'6' 持ち物,", " 4 or 6 for Inven,"), sizeof(fis_ptr->out_val));
408                 }
409             }
410
411             if (fis_ptr->allow_floor) {
412                 if (!use_menu) {
413                     angband_strcat(fis_ptr->out_val, _(" '-'床上,", " - for floor,"), sizeof(fis_ptr->out_val));
414                 } else if (fis_ptr->allow_inven) {
415                     angband_strcat(fis_ptr->out_val, _(" '6' 床上,", " 6 for floor,"), sizeof(fis_ptr->out_val));
416                 } else {
417                     angband_strcat(fis_ptr->out_val, _(" '4'or'6' 床上,", " 4 or 6 for floor,"), sizeof(fis_ptr->out_val));
418                 }
419             }
420         } else if (command_wrk == USE_FLOOR) {
421             angband_strcpy(fis_ptr->out_val, _("床上:", "Floor:"), sizeof(fis_ptr->out_val));
422             if (!use_menu) {
423                 const auto tmp_val = format(_("%c-%c,'(',')',", " %c-%c,'(',')',"), fis_ptr->n1, fis_ptr->n2);
424                 angband_strcat(fis_ptr->out_val, tmp_val, sizeof(fis_ptr->out_val));
425             }
426
427             if (!command_see && !use_menu) {
428                 angband_strcat(fis_ptr->out_val, _(" '*'一覧,", " * to see,"), sizeof(fis_ptr->out_val));
429             }
430
431             if (use_menu) {
432                 if (fis_ptr->allow_inven && fis_ptr->allow_equip) {
433                     angband_strcat(fis_ptr->out_val, _(" '4' 装備品, '6' 持ち物,", " 4 for Equip, 6 for Inven,"), sizeof(fis_ptr->out_val));
434                 } else if (fis_ptr->allow_inven) {
435                     angband_strcat(fis_ptr->out_val, _(" '4'or'6' 持ち物,", " 4 or 6 for Inven,"), sizeof(fis_ptr->out_val));
436                 } else if (fis_ptr->allow_equip) {
437                     angband_strcat(fis_ptr->out_val, _(" '4'or'6' 装備品,", " 4 or 6 for Equip,"), sizeof(fis_ptr->out_val));
438                 }
439             } else if (fis_ptr->allow_inven) {
440                 angband_strcat(fis_ptr->out_val, _(" '/' 持ち物,", " / for Inven,"), sizeof(fis_ptr->out_val));
441             } else if (fis_ptr->allow_equip) {
442                 angband_strcat(fis_ptr->out_val, _(" '/'装備品,", " / for Equip,"), sizeof(fis_ptr->out_val));
443             }
444
445             if (command_see && !use_menu) {
446                 angband_strcat(fis_ptr->out_val, _(" Enter 次,", " Enter for scroll down,"), sizeof(fis_ptr->out_val));
447             }
448         }
449
450         if (fis_ptr->force) {
451             angband_strcat(fis_ptr->out_val, _(" 'w'練気術,", " w for the Force,"), sizeof(fis_ptr->out_val));
452         }
453
454         angband_strcat(fis_ptr->out_val, " ESC", sizeof(fis_ptr->out_val));
455         prt(format("(%s) %s", fis_ptr->out_val, pmt), 0, 0);
456         fis_ptr->which = inkey();
457         if (use_menu) {
458             int max_line = 1;
459             if (command_wrk == USE_INVEN) {
460                 max_line = fis_ptr->max_inven;
461             } else if (command_wrk == USE_EQUIP) {
462                 max_line = fis_ptr->max_equip;
463             } else if (command_wrk == USE_FLOOR) {
464                 max_line = std::min(23, fis_ptr->floor_num);
465             }
466             switch (fis_ptr->which) {
467             case ESCAPE:
468             case 'z':
469             case 'Z':
470             case '0': {
471                 fis_ptr->done = true;
472                 break;
473             }
474             case '8':
475             case 'k':
476             case 'K': {
477                 fis_ptr->menu_line += (max_line - 1);
478                 break;
479             }
480             case '2':
481             case 'j':
482             case 'J': {
483                 fis_ptr->menu_line++;
484                 break;
485             }
486             case '4':
487             case 'h':
488             case 'H': {
489                 if (command_wrk == (USE_INVEN)) {
490                     if (fis_ptr->allow_floor) {
491                         command_wrk = USE_FLOOR;
492                     } else if (fis_ptr->allow_equip) {
493                         command_wrk = USE_EQUIP;
494                     } else {
495                         bell();
496                         break;
497                     }
498                 } else if (command_wrk == (USE_EQUIP)) {
499                     if (fis_ptr->allow_inven) {
500                         command_wrk = USE_INVEN;
501                     } else if (fis_ptr->allow_floor) {
502                         command_wrk = USE_FLOOR;
503                     } else {
504                         bell();
505                         break;
506                     }
507                 } else if (command_wrk == (USE_FLOOR)) {
508                     if (fis_ptr->allow_equip) {
509                         command_wrk = USE_EQUIP;
510                     } else if (fis_ptr->allow_inven) {
511                         command_wrk = USE_INVEN;
512                     } else {
513                         bell();
514                         break;
515                     }
516                 } else {
517                     bell();
518                     break;
519                 }
520
521                 if (command_see) {
522                     screen_load();
523                     screen_save();
524                 }
525
526                 if (command_wrk == USE_INVEN) {
527                     max_line = fis_ptr->max_inven;
528                 } else if (command_wrk == USE_EQUIP) {
529                     max_line = fis_ptr->max_equip;
530                 } else if (command_wrk == USE_FLOOR) {
531                     max_line = std::min(23, fis_ptr->floor_num);
532                 }
533
534                 if (fis_ptr->menu_line > max_line) {
535                     fis_ptr->menu_line = max_line;
536                 }
537
538                 break;
539             }
540             case '6':
541             case 'l':
542             case 'L': {
543                 if (command_wrk == (USE_INVEN)) {
544                     if (fis_ptr->allow_equip) {
545                         command_wrk = USE_EQUIP;
546                     } else if (fis_ptr->allow_floor) {
547                         command_wrk = USE_FLOOR;
548                     } else {
549                         bell();
550                         break;
551                     }
552                 } else if (command_wrk == (USE_EQUIP)) {
553                     if (fis_ptr->allow_floor) {
554                         command_wrk = USE_FLOOR;
555                     } else if (fis_ptr->allow_inven) {
556                         command_wrk = USE_INVEN;
557                     } else {
558                         bell();
559                         break;
560                     }
561                 } else if (command_wrk == (USE_FLOOR)) {
562                     if (fis_ptr->allow_inven) {
563                         command_wrk = USE_INVEN;
564                     } else if (fis_ptr->allow_equip) {
565                         command_wrk = USE_EQUIP;
566                     } else {
567                         bell();
568                         break;
569                     }
570                 } else {
571                     bell();
572                     break;
573                 }
574
575                 if (command_see) {
576                     screen_load();
577                     screen_save();
578                 }
579
580                 if (command_wrk == USE_INVEN) {
581                     max_line = fis_ptr->max_inven;
582                 } else if (command_wrk == USE_EQUIP) {
583                     max_line = fis_ptr->max_equip;
584                 } else if (command_wrk == USE_FLOOR) {
585                     max_line = std::min(23, fis_ptr->floor_num);
586                 }
587
588                 if (fis_ptr->menu_line > max_line) {
589                     fis_ptr->menu_line = max_line;
590                 }
591
592                 break;
593             }
594             case 'x':
595             case 'X':
596             case '\r':
597             case '\n': {
598                 if (command_wrk == USE_FLOOR) {
599                     *cp = -get_item_label;
600                 } else {
601                     if (!get_item_okay(player_ptr, get_item_label, item_tester)) {
602                         bell();
603                         break;
604                     }
605
606                     if (!get_item_allow(player_ptr, get_item_label)) {
607                         fis_ptr->done = true;
608                         break;
609                     }
610
611                     *cp = get_item_label;
612                 }
613
614                 fis_ptr->item = true;
615                 fis_ptr->done = true;
616                 break;
617             }
618             case 'w': {
619                 if (fis_ptr->force) {
620                     *cp = INVEN_FORCE;
621                     fis_ptr->item = true;
622                     fis_ptr->done = true;
623                     break;
624                 }
625             }
626             }
627
628             if (fis_ptr->menu_line > max_line) {
629                 fis_ptr->menu_line -= max_line;
630             }
631
632             continue;
633         }
634
635         switch (fis_ptr->which) {
636         case ESCAPE: {
637             fis_ptr->done = true;
638             break;
639         }
640         case '*':
641         case '?':
642         case ' ': {
643             if (command_see) {
644                 command_see = false;
645                 screen_load();
646             } else {
647                 screen_save();
648                 command_see = true;
649             }
650
651             break;
652         }
653         case '\n':
654         case '\r':
655         case '+': {
656             auto *g_ptr = &player_ptr->current_floor_ptr->grid_array[player_ptr->y][player_ptr->x];
657             if (command_wrk != (USE_FLOOR)) {
658                 break;
659             }
660
661             if (g_ptr->o_idx_list.size() < 2) {
662                 break;
663             }
664
665             const auto next_o_idx = fis_ptr->floor_list[1];
666             while (g_ptr->o_idx_list.front() != next_o_idx) {
667                 g_ptr->o_idx_list.rotate(player_ptr->current_floor_ptr);
668             }
669
670             rfu.set_flag(SubWindowRedrawingFlag::FLOOR_ITEMS);
671             window_stuff(player_ptr);
672             constexpr auto options = SCAN_FLOOR_ITEM_TESTER | SCAN_FLOOR_ONLY_MARKED;
673             fis_ptr->floor_num = scan_floor_items(player_ptr, fis_ptr->floor_list, player_ptr->y, player_ptr->x, options, item_tester);
674             if (command_see) {
675                 screen_load();
676                 screen_save();
677             }
678
679             break;
680         }
681         case '/': {
682             if (command_wrk == (USE_INVEN)) {
683                 if (!fis_ptr->allow_equip) {
684                     bell();
685                     break;
686                 }
687                 command_wrk = (USE_EQUIP);
688             } else if (command_wrk == (USE_EQUIP)) {
689                 if (!fis_ptr->allow_inven) {
690                     bell();
691                     break;
692                 }
693                 command_wrk = (USE_INVEN);
694             } else if (command_wrk == (USE_FLOOR)) {
695                 if (fis_ptr->allow_inven) {
696                     command_wrk = (USE_INVEN);
697                 } else if (fis_ptr->allow_equip) {
698                     command_wrk = (USE_EQUIP);
699                 } else {
700                     bell();
701                     break;
702                 }
703             }
704
705             if (command_see) {
706                 screen_load();
707                 screen_save();
708             }
709
710             break;
711         }
712         case '-': {
713             if (!fis_ptr->allow_floor) {
714                 bell();
715                 break;
716             }
717
718             if (fis_ptr->floor_num == 1) {
719                 if ((command_wrk == (USE_FLOOR)) || (!carry_query_flag)) {
720                     fis_ptr->k = 0 - fis_ptr->floor_list[0];
721                     if (!get_item_allow(player_ptr, fis_ptr->k)) {
722                         fis_ptr->done = true;
723                         break;
724                     }
725
726                     *cp = fis_ptr->k;
727                     fis_ptr->item = true;
728                     fis_ptr->done = true;
729                     break;
730                 }
731             }
732
733             if (command_see) {
734                 screen_load();
735                 screen_save();
736             }
737
738             command_wrk = (USE_FLOOR);
739             break;
740         }
741         case '0':
742         case '1':
743         case '2':
744         case '3':
745         case '4':
746         case '5':
747         case '6':
748         case '7':
749         case '8':
750         case '9': {
751             if (command_wrk != USE_FLOOR) {
752                 if (!get_tag(player_ptr, &fis_ptr->k, fis_ptr->which, command_wrk, item_tester)) {
753                     bell();
754                     break;
755                 }
756
757                 if ((fis_ptr->k < INVEN_MAIN_HAND) ? !fis_ptr->inven : !fis_ptr->equip) {
758                     bell();
759                     break;
760                 }
761
762                 if (!get_item_okay(player_ptr, fis_ptr->k, item_tester)) {
763                     bell();
764                     break;
765                 }
766             } else {
767                 if (get_tag_floor(player_ptr->current_floor_ptr, &fis_ptr->k, fis_ptr->which, fis_ptr->floor_list, fis_ptr->floor_num)) {
768                     fis_ptr->k = 0 - fis_ptr->floor_list[fis_ptr->k];
769                 } else {
770                     bell();
771                     break;
772                 }
773             }
774
775             if (!get_item_allow(player_ptr, fis_ptr->k)) {
776                 fis_ptr->done = true;
777                 break;
778             }
779
780             *cp = fis_ptr->k;
781             fis_ptr->item = true;
782             fis_ptr->done = true;
783             fis_ptr->cur_tag = fis_ptr->which;
784             break;
785         }
786         case 'w': {
787             if (fis_ptr->force) {
788                 *cp = INVEN_FORCE;
789                 fis_ptr->item = true;
790                 fis_ptr->done = true;
791                 break;
792             }
793         }
794             [[fallthrough]];
795         default: {
796             bool tag_not_found = false;
797
798             if (command_wrk != USE_FLOOR) {
799                 if (!get_tag(player_ptr, &fis_ptr->k, fis_ptr->which, command_wrk, item_tester)) {
800                     tag_not_found = true;
801                 } else if ((fis_ptr->k < INVEN_MAIN_HAND) ? !fis_ptr->inven : !fis_ptr->equip) {
802                     tag_not_found = true;
803                 }
804
805                 if (!tag_not_found) {
806                     fis_ptr->cur_tag = fis_ptr->which;
807                 }
808             } else {
809                 if (get_tag_floor(player_ptr->current_floor_ptr, &fis_ptr->k, fis_ptr->which, fis_ptr->floor_list, fis_ptr->floor_num)) {
810                     fis_ptr->k = 0 - fis_ptr->floor_list[fis_ptr->k];
811                     fis_ptr->cur_tag = fis_ptr->which;
812                 } else {
813                     tag_not_found = true;
814                 }
815             }
816
817             if (tag_not_found) {
818                 auto which = (char)tolower(fis_ptr->which);
819
820                 if (command_wrk == (USE_INVEN)) {
821                     if (which == '(') {
822                         fis_ptr->k = fis_ptr->i1;
823                     } else if (which == ')') {
824                         fis_ptr->k = fis_ptr->i2;
825                     } else {
826                         fis_ptr->k = label_to_inventory(player_ptr, which);
827                     }
828                 } else if (command_wrk == (USE_EQUIP)) {
829                     if (which == '(') {
830                         fis_ptr->k = fis_ptr->e1;
831                     } else if (which == ')') {
832                         fis_ptr->k = fis_ptr->e2;
833                     } else {
834                         fis_ptr->k = label_to_equipment(player_ptr, which);
835                     }
836                 } else if (command_wrk == USE_FLOOR) {
837                     if (which == '(') {
838                         fis_ptr->k = 0;
839                     } else if (which == ')') {
840                         fis_ptr->k = fis_ptr->floor_num - 1;
841                     } else {
842                         fis_ptr->k = islower(which) ? A2I(which) : -1;
843                     }
844                     if (fis_ptr->k < 0 || fis_ptr->k >= fis_ptr->floor_num || fis_ptr->k >= 23) {
845                         bell();
846                         break;
847                     }
848
849                     fis_ptr->k = 0 - fis_ptr->floor_list[fis_ptr->k];
850                 }
851             }
852
853             if ((command_wrk != USE_FLOOR) && !get_item_okay(player_ptr, fis_ptr->k, item_tester)) {
854                 bell();
855                 break;
856             }
857
858             auto ver = tag_not_found && isupper(fis_ptr->which);
859             if (ver && !verify(player_ptr, _("本当に", "Try"), fis_ptr->k)) {
860                 fis_ptr->done = true;
861                 break;
862             }
863
864             if (!get_item_allow(player_ptr, fis_ptr->k)) {
865                 fis_ptr->done = true;
866                 break;
867             }
868
869             *cp = fis_ptr->k;
870             fis_ptr->item = true;
871             fis_ptr->done = true;
872             break;
873         }
874         }
875     }
876
877     if (command_see) {
878         screen_load();
879         command_see = false;
880     }
881
882     if (fis_ptr->toggle) {
883         toggle_inventory_equipment();
884     }
885
886     rfu.set_flags(flags);
887     handle_stuff(player_ptr);
888     prt("", 0, 0);
889     if (fis_ptr->oops && str) {
890         msg_print(str);
891     }
892
893     if (fis_ptr->item) {
894         repeat_push(*cp);
895         if (command_cmd) {
896             prev_tag = fis_ptr->cur_tag;
897         }
898         command_cmd = 0;
899     }
900
901     return fis_ptr->item;
902 }