OSDN Git Service

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