OSDN Git Service

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