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                 char tmp_val[80];
364                 strnfmt(tmp_val, sizeof(tmp_val), _("%c-%c,'(',')',", " %c-%c,'(',')',"), index_to_label(fis_ptr->i1), index_to_label(fis_ptr->i2));
365                 angband_strcat(fis_ptr->out_val, tmp_val, sizeof(fis_ptr->out_val));
366             }
367
368             if (!command_see && !use_menu) {
369                 angband_strcat(fis_ptr->out_val, _(" '*'一覧,", " * to see,"), sizeof(fis_ptr->out_val));
370             }
371
372             if (fis_ptr->allow_equip) {
373                 if (!use_menu) {
374                     angband_strcat(fis_ptr->out_val, _(" '/' 装備品,", " / for Equip,"), sizeof(fis_ptr->out_val));
375                 } else if (fis_ptr->allow_floor) {
376                     angband_strcat(fis_ptr->out_val, _(" '6' 装備品,", " 6 for Equip,"), sizeof(fis_ptr->out_val));
377                 } else {
378                     angband_strcat(fis_ptr->out_val, _(" '4'or'6' 装備品,", " 4 or 6 for Equip,"), sizeof(fis_ptr->out_val));
379                 }
380             }
381
382             if (fis_ptr->allow_floor) {
383                 if (!use_menu) {
384                     angband_strcat(fis_ptr->out_val, _(" '-'床上,", " - for floor,"), sizeof(fis_ptr->out_val));
385                 } else if (fis_ptr->allow_equip) {
386                     angband_strcat(fis_ptr->out_val, _(" '4' 床上,", " 4 for floor,"), sizeof(fis_ptr->out_val));
387                 } else {
388                     angband_strcat(fis_ptr->out_val, _(" '4'or'6' 床上,", " 4 or 6 for floor,"), sizeof(fis_ptr->out_val));
389                 }
390             }
391         } else if (command_wrk == (USE_EQUIP)) {
392             angband_strcpy(fis_ptr->out_val, _("装備品:", "Equip:"), sizeof(fis_ptr->out_val));
393             if (!use_menu) {
394                 char tmp_val[80];
395                 strnfmt(tmp_val, sizeof(tmp_val), _("%c-%c,'(',')',", " %c-%c,'(',')',"), index_to_label(fis_ptr->e1), index_to_label(fis_ptr->e2));
396                 angband_strcat(fis_ptr->out_val, tmp_val, sizeof(fis_ptr->out_val));
397             }
398
399             if (!command_see && !use_menu) {
400                 angband_strcat(fis_ptr->out_val, _(" '*'一覧,", " * to see,"), sizeof(fis_ptr->out_val));
401             }
402
403             if (fis_ptr->allow_inven) {
404                 if (!use_menu) {
405                     angband_strcat(fis_ptr->out_val, _(" '/' 持ち物,", " / for Inven,"), sizeof(fis_ptr->out_val));
406                 } else if (fis_ptr->allow_floor) {
407                     angband_strcat(fis_ptr->out_val, _(" '4' 持ち物,", " 4 for Inven,"), sizeof(fis_ptr->out_val));
408                 } else {
409                     angband_strcat(fis_ptr->out_val, _(" '4'or'6' 持ち物,", " 4 or 6 for Inven,"), sizeof(fis_ptr->out_val));
410                 }
411             }
412
413             if (fis_ptr->allow_floor) {
414                 if (!use_menu) {
415                     angband_strcat(fis_ptr->out_val, _(" '-'床上,", " - for floor,"), sizeof(fis_ptr->out_val));
416                 } else if (fis_ptr->allow_inven) {
417                     angband_strcat(fis_ptr->out_val, _(" '6' 床上,", " 6 for floor,"), sizeof(fis_ptr->out_val));
418                 } else {
419                     angband_strcat(fis_ptr->out_val, _(" '4'or'6' 床上,", " 4 or 6 for floor,"), sizeof(fis_ptr->out_val));
420                 }
421             }
422         } else if (command_wrk == USE_FLOOR) {
423             angband_strcpy(fis_ptr->out_val, _("床上:", "Floor:"), sizeof(fis_ptr->out_val));
424             if (!use_menu) {
425                 char tmp_val[80];
426                 strnfmt(tmp_val, sizeof(tmp_val), _("%c-%c,'(',')',", " %c-%c,'(',')',"), fis_ptr->n1, fis_ptr->n2);
427                 angband_strcat(fis_ptr->out_val, tmp_val, sizeof(fis_ptr->out_val));
428             }
429
430             if (!command_see && !use_menu) {
431                 angband_strcat(fis_ptr->out_val, _(" '*'一覧,", " * to see,"), sizeof(fis_ptr->out_val));
432             }
433
434             if (use_menu) {
435                 if (fis_ptr->allow_inven && fis_ptr->allow_equip) {
436                     angband_strcat(fis_ptr->out_val, _(" '4' 装備品, '6' 持ち物,", " 4 for Equip, 6 for Inven,"), sizeof(fis_ptr->out_val));
437                 } else if (fis_ptr->allow_inven) {
438                     angband_strcat(fis_ptr->out_val, _(" '4'or'6' 持ち物,", " 4 or 6 for Inven,"), sizeof(fis_ptr->out_val));
439                 } else if (fis_ptr->allow_equip) {
440                     angband_strcat(fis_ptr->out_val, _(" '4'or'6' 装備品,", " 4 or 6 for Equip,"), sizeof(fis_ptr->out_val));
441                 }
442             } else if (fis_ptr->allow_inven) {
443                 angband_strcat(fis_ptr->out_val, _(" '/' 持ち物,", " / for Inven,"), sizeof(fis_ptr->out_val));
444             } else if (fis_ptr->allow_equip) {
445                 angband_strcat(fis_ptr->out_val, _(" '/'装備品,", " / for Equip,"), sizeof(fis_ptr->out_val));
446             }
447
448             if (command_see && !use_menu) {
449                 angband_strcat(fis_ptr->out_val, _(" Enter 次,", " Enter for scroll down,"), sizeof(fis_ptr->out_val));
450             }
451         }
452
453         if (fis_ptr->force) {
454             angband_strcat(fis_ptr->out_val, _(" 'w'練気術,", " w for the Force,"), sizeof(fis_ptr->out_val));
455         }
456
457         angband_strcat(fis_ptr->out_val, " ESC", sizeof(fis_ptr->out_val));
458         strnfmt(fis_ptr->tmp_val, sizeof(fis_ptr->tmp_val), "(%s) %s", fis_ptr->out_val, pmt);
459         prt(fis_ptr->tmp_val, 0, 0);
460         fis_ptr->which = inkey();
461         if (use_menu) {
462             int max_line = 1;
463             if (command_wrk == USE_INVEN) {
464                 max_line = fis_ptr->max_inven;
465             } else if (command_wrk == USE_EQUIP) {
466                 max_line = fis_ptr->max_equip;
467             } else if (command_wrk == USE_FLOOR) {
468                 max_line = std::min(23, fis_ptr->floor_num);
469             }
470             switch (fis_ptr->which) {
471             case ESCAPE:
472             case 'z':
473             case 'Z':
474             case '0': {
475                 fis_ptr->done = true;
476                 break;
477             }
478             case '8':
479             case 'k':
480             case 'K': {
481                 fis_ptr->menu_line += (max_line - 1);
482                 break;
483             }
484             case '2':
485             case 'j':
486             case 'J': {
487                 fis_ptr->menu_line++;
488                 break;
489             }
490             case '4':
491             case 'h':
492             case 'H': {
493                 if (command_wrk == (USE_INVEN)) {
494                     if (fis_ptr->allow_floor) {
495                         command_wrk = USE_FLOOR;
496                     } else if (fis_ptr->allow_equip) {
497                         command_wrk = USE_EQUIP;
498                     } else {
499                         bell();
500                         break;
501                     }
502                 } else if (command_wrk == (USE_EQUIP)) {
503                     if (fis_ptr->allow_inven) {
504                         command_wrk = USE_INVEN;
505                     } else if (fis_ptr->allow_floor) {
506                         command_wrk = USE_FLOOR;
507                     } else {
508                         bell();
509                         break;
510                     }
511                 } else if (command_wrk == (USE_FLOOR)) {
512                     if (fis_ptr->allow_equip) {
513                         command_wrk = USE_EQUIP;
514                     } else if (fis_ptr->allow_inven) {
515                         command_wrk = USE_INVEN;
516                     } else {
517                         bell();
518                         break;
519                     }
520                 } else {
521                     bell();
522                     break;
523                 }
524
525                 if (command_see) {
526                     screen_load();
527                     screen_save();
528                 }
529
530                 if (command_wrk == USE_INVEN) {
531                     max_line = fis_ptr->max_inven;
532                 } else if (command_wrk == USE_EQUIP) {
533                     max_line = fis_ptr->max_equip;
534                 } else if (command_wrk == USE_FLOOR) {
535                     max_line = std::min(23, fis_ptr->floor_num);
536                 }
537
538                 if (fis_ptr->menu_line > max_line) {
539                     fis_ptr->menu_line = max_line;
540                 }
541
542                 break;
543             }
544             case '6':
545             case 'l':
546             case 'L': {
547                 if (command_wrk == (USE_INVEN)) {
548                     if (fis_ptr->allow_equip) {
549                         command_wrk = USE_EQUIP;
550                     } else if (fis_ptr->allow_floor) {
551                         command_wrk = USE_FLOOR;
552                     } else {
553                         bell();
554                         break;
555                     }
556                 } else if (command_wrk == (USE_EQUIP)) {
557                     if (fis_ptr->allow_floor) {
558                         command_wrk = USE_FLOOR;
559                     } else if (fis_ptr->allow_inven) {
560                         command_wrk = USE_INVEN;
561                     } else {
562                         bell();
563                         break;
564                     }
565                 } else if (command_wrk == (USE_FLOOR)) {
566                     if (fis_ptr->allow_inven) {
567                         command_wrk = USE_INVEN;
568                     } else if (fis_ptr->allow_equip) {
569                         command_wrk = USE_EQUIP;
570                     } else {
571                         bell();
572                         break;
573                     }
574                 } else {
575                     bell();
576                     break;
577                 }
578
579                 if (command_see) {
580                     screen_load();
581                     screen_save();
582                 }
583
584                 if (command_wrk == USE_INVEN) {
585                     max_line = fis_ptr->max_inven;
586                 } else if (command_wrk == USE_EQUIP) {
587                     max_line = fis_ptr->max_equip;
588                 } else if (command_wrk == USE_FLOOR) {
589                     max_line = std::min(23, fis_ptr->floor_num);
590                 }
591
592                 if (fis_ptr->menu_line > max_line) {
593                     fis_ptr->menu_line = max_line;
594                 }
595
596                 break;
597             }
598             case 'x':
599             case 'X':
600             case '\r':
601             case '\n': {
602                 if (command_wrk == USE_FLOOR) {
603                     *cp = -get_item_label;
604                 } else {
605                     if (!get_item_okay(player_ptr, get_item_label, item_tester)) {
606                         bell();
607                         break;
608                     }
609
610                     if (!get_item_allow(player_ptr, get_item_label)) {
611                         fis_ptr->done = true;
612                         break;
613                     }
614
615                     *cp = get_item_label;
616                 }
617
618                 fis_ptr->item = true;
619                 fis_ptr->done = true;
620                 break;
621             }
622             case 'w': {
623                 if (fis_ptr->force) {
624                     *cp = INVEN_FORCE;
625                     fis_ptr->item = true;
626                     fis_ptr->done = true;
627                     break;
628                 }
629             }
630             }
631
632             if (fis_ptr->menu_line > max_line) {
633                 fis_ptr->menu_line -= max_line;
634             }
635
636             continue;
637         }
638
639         switch (fis_ptr->which) {
640         case ESCAPE: {
641             fis_ptr->done = true;
642             break;
643         }
644         case '*':
645         case '?':
646         case ' ': {
647             if (command_see) {
648                 command_see = false;
649                 screen_load();
650             } else {
651                 screen_save();
652                 command_see = true;
653             }
654
655             break;
656         }
657         case '\n':
658         case '\r':
659         case '+': {
660             auto *g_ptr = &player_ptr->current_floor_ptr->grid_array[player_ptr->y][player_ptr->x];
661             if (command_wrk != (USE_FLOOR)) {
662                 break;
663             }
664
665             if (g_ptr->o_idx_list.size() < 2) {
666                 break;
667             }
668
669             const auto next_o_idx = fis_ptr->floor_list[1];
670             while (g_ptr->o_idx_list.front() != next_o_idx) {
671                 g_ptr->o_idx_list.rotate(player_ptr->current_floor_ptr);
672             }
673
674             rfu.set_flag(SubWindowRedrawingFlag::FLOOR_ITEMS);
675             window_stuff(player_ptr);
676             constexpr auto options = SCAN_FLOOR_ITEM_TESTER | SCAN_FLOOR_ONLY_MARKED;
677             fis_ptr->floor_num = scan_floor_items(player_ptr, fis_ptr->floor_list, player_ptr->y, player_ptr->x, options, item_tester);
678             if (command_see) {
679                 screen_load();
680                 screen_save();
681             }
682
683             break;
684         }
685         case '/': {
686             if (command_wrk == (USE_INVEN)) {
687                 if (!fis_ptr->allow_equip) {
688                     bell();
689                     break;
690                 }
691                 command_wrk = (USE_EQUIP);
692             } else if (command_wrk == (USE_EQUIP)) {
693                 if (!fis_ptr->allow_inven) {
694                     bell();
695                     break;
696                 }
697                 command_wrk = (USE_INVEN);
698             } else if (command_wrk == (USE_FLOOR)) {
699                 if (fis_ptr->allow_inven) {
700                     command_wrk = (USE_INVEN);
701                 } else if (fis_ptr->allow_equip) {
702                     command_wrk = (USE_EQUIP);
703                 } else {
704                     bell();
705                     break;
706                 }
707             }
708
709             if (command_see) {
710                 screen_load();
711                 screen_save();
712             }
713
714             break;
715         }
716         case '-': {
717             if (!fis_ptr->allow_floor) {
718                 bell();
719                 break;
720             }
721
722             if (fis_ptr->floor_num == 1) {
723                 if ((command_wrk == (USE_FLOOR)) || (!carry_query_flag)) {
724                     fis_ptr->k = 0 - fis_ptr->floor_list[0];
725                     if (!get_item_allow(player_ptr, fis_ptr->k)) {
726                         fis_ptr->done = true;
727                         break;
728                     }
729
730                     *cp = fis_ptr->k;
731                     fis_ptr->item = true;
732                     fis_ptr->done = true;
733                     break;
734                 }
735             }
736
737             if (command_see) {
738                 screen_load();
739                 screen_save();
740             }
741
742             command_wrk = (USE_FLOOR);
743             break;
744         }
745         case '0':
746         case '1':
747         case '2':
748         case '3':
749         case '4':
750         case '5':
751         case '6':
752         case '7':
753         case '8':
754         case '9': {
755             if (command_wrk != USE_FLOOR) {
756                 if (!get_tag(player_ptr, &fis_ptr->k, fis_ptr->which, command_wrk, item_tester)) {
757                     bell();
758                     break;
759                 }
760
761                 if ((fis_ptr->k < INVEN_MAIN_HAND) ? !fis_ptr->inven : !fis_ptr->equip) {
762                     bell();
763                     break;
764                 }
765
766                 if (!get_item_okay(player_ptr, fis_ptr->k, item_tester)) {
767                     bell();
768                     break;
769                 }
770             } else {
771                 if (get_tag_floor(player_ptr->current_floor_ptr, &fis_ptr->k, fis_ptr->which, fis_ptr->floor_list, fis_ptr->floor_num)) {
772                     fis_ptr->k = 0 - fis_ptr->floor_list[fis_ptr->k];
773                 } else {
774                     bell();
775                     break;
776                 }
777             }
778
779             if (!get_item_allow(player_ptr, fis_ptr->k)) {
780                 fis_ptr->done = true;
781                 break;
782             }
783
784             *cp = fis_ptr->k;
785             fis_ptr->item = true;
786             fis_ptr->done = true;
787             fis_ptr->cur_tag = fis_ptr->which;
788             break;
789         }
790         case 'w': {
791             if (fis_ptr->force) {
792                 *cp = INVEN_FORCE;
793                 fis_ptr->item = true;
794                 fis_ptr->done = true;
795                 break;
796             }
797         }
798             [[fallthrough]];
799         default: {
800             bool tag_not_found = false;
801
802             if (command_wrk != USE_FLOOR) {
803                 if (!get_tag(player_ptr, &fis_ptr->k, fis_ptr->which, command_wrk, item_tester)) {
804                     tag_not_found = true;
805                 } else if ((fis_ptr->k < INVEN_MAIN_HAND) ? !fis_ptr->inven : !fis_ptr->equip) {
806                     tag_not_found = true;
807                 }
808
809                 if (!tag_not_found) {
810                     fis_ptr->cur_tag = fis_ptr->which;
811                 }
812             } else {
813                 if (get_tag_floor(player_ptr->current_floor_ptr, &fis_ptr->k, fis_ptr->which, fis_ptr->floor_list, fis_ptr->floor_num)) {
814                     fis_ptr->k = 0 - fis_ptr->floor_list[fis_ptr->k];
815                     fis_ptr->cur_tag = fis_ptr->which;
816                 } else {
817                     tag_not_found = true;
818                 }
819             }
820
821             if (tag_not_found) {
822                 auto which = (char)tolower(fis_ptr->which);
823
824                 if (command_wrk == (USE_INVEN)) {
825                     if (which == '(') {
826                         fis_ptr->k = fis_ptr->i1;
827                     } else if (which == ')') {
828                         fis_ptr->k = fis_ptr->i2;
829                     } else {
830                         fis_ptr->k = label_to_inventory(player_ptr, which);
831                     }
832                 } else if (command_wrk == (USE_EQUIP)) {
833                     if (which == '(') {
834                         fis_ptr->k = fis_ptr->e1;
835                     } else if (which == ')') {
836                         fis_ptr->k = fis_ptr->e2;
837                     } else {
838                         fis_ptr->k = label_to_equipment(player_ptr, which);
839                     }
840                 } else if (command_wrk == USE_FLOOR) {
841                     if (which == '(') {
842                         fis_ptr->k = 0;
843                     } else if (which == ')') {
844                         fis_ptr->k = fis_ptr->floor_num - 1;
845                     } else {
846                         fis_ptr->k = islower(which) ? A2I(which) : -1;
847                     }
848                     if (fis_ptr->k < 0 || fis_ptr->k >= fis_ptr->floor_num || fis_ptr->k >= 23) {
849                         bell();
850                         break;
851                     }
852
853                     fis_ptr->k = 0 - fis_ptr->floor_list[fis_ptr->k];
854                 }
855             }
856
857             if ((command_wrk != USE_FLOOR) && !get_item_okay(player_ptr, fis_ptr->k, item_tester)) {
858                 bell();
859                 break;
860             }
861
862             auto ver = tag_not_found && isupper(fis_ptr->which);
863             if (ver && !verify(player_ptr, _("本当に", "Try"), fis_ptr->k)) {
864                 fis_ptr->done = true;
865                 break;
866             }
867
868             if (!get_item_allow(player_ptr, fis_ptr->k)) {
869                 fis_ptr->done = true;
870                 break;
871             }
872
873             *cp = fis_ptr->k;
874             fis_ptr->item = true;
875             fis_ptr->done = true;
876             break;
877         }
878         }
879     }
880
881     if (command_see) {
882         screen_load();
883         command_see = false;
884     }
885
886     if (fis_ptr->toggle) {
887         toggle_inventory_equipment();
888     }
889
890     rfu.set_flags(flags);
891     handle_stuff(player_ptr);
892     prt("", 0, 0);
893     if (fis_ptr->oops && str) {
894         msg_print(str);
895     }
896
897     if (fis_ptr->item) {
898         repeat_push(*cp);
899         if (command_cmd) {
900             prev_tag = fis_ptr->cur_tag;
901         }
902         command_cmd = 0;
903     }
904
905     return fis_ptr->item;
906 }