OSDN Git Service

4d5b1c0b9f3d0eeeae530e884e3967a13f89ee8a
[hengbandforosx/hengbandosx.git] / src / floor / object-scanner.cpp
1 #include "floor/object-scanner.h"
2 #include "flavor/flavor-describer.h"
3 #include "floor/cave.h"
4 #include "game-option/text-display-options.h"
5 #include "inventory/inventory-util.h"
6 #include "io/input-key-requester.h"
7 #include "locale/japanese.h"
8 #include "object/item-tester-hooker.h"
9 #include "object/object-mark-types.h"
10 #include "system/floor-type-definition.h"
11 #include "system/grid-type-definition.h"
12 #include "system/item-entity.h"
13 #include "system/player-type-definition.h"
14 #include "term/gameterm.h"
15 #include "term/screen-processor.h"
16
17 /*!
18  * @brief 床に落ちているオブジェクトの数を返す / scan floor items
19  * @param items オブジェクトのIDリストを返すための配列参照ポインタ
20  * @param y 走査するフロアのY座標
21  * @param x 走査するフロアのX座標
22  * @param mode オプションフラグ
23  * @return 対象のマスに落ちているアイテム数
24  * @details
25  * Return a list of o_list[] indexes of items at the given floor
26  * location. Valid flags are:
27  *
28  *              mode & 0x01 -- Item tester
29  *              mode & 0x02 -- Marked items only
30  *              mode & 0x04 -- Stop after first
31  */
32 ITEM_NUMBER scan_floor_items(PlayerType *player_ptr, OBJECT_IDX *items, POSITION y, POSITION x, BIT_FLAGS mode, const ItemTester &item_tester)
33 {
34     auto *floor_ptr = player_ptr->current_floor_ptr;
35     if (!in_bounds(floor_ptr, y, x)) {
36         return 0;
37     }
38
39     ITEM_NUMBER num = 0;
40     for (const auto this_o_idx : floor_ptr->grid_array[y][x].o_idx_list) {
41         ItemEntity *o_ptr;
42         o_ptr = &floor_ptr->o_list[this_o_idx];
43         if ((mode & SCAN_FLOOR_ITEM_TESTER) && !item_tester.okay(o_ptr)) {
44             continue;
45         }
46
47         if ((mode & SCAN_FLOOR_ONLY_MARKED) && o_ptr->marked.has_not(OmType::FOUND)) {
48             continue;
49         }
50
51         if (num < 23) {
52             items[num] = this_o_idx;
53         }
54
55         num++;
56         if (mode & SCAN_FLOOR_AT_MOST_ONE) {
57             break;
58         }
59     }
60
61     return num;
62 }
63
64 /*!
65  * @brief タグIDにあわせてタグアルファベットのリストを返す(床上アイテム用) /
66  * Move around label characters with correspond tags (floor version)
67  * @param label ラベルリストを取得する文字列参照ポインタ
68  * @param floor_list 床上アイテムの配列
69  * @param floor_num  床上アイテムの配列ID
70  */
71 /*
72  */
73 static void prepare_label_string_floor(FloorType *floor_ptr, char *label, FLOOR_IDX floor_list[], ITEM_NUMBER floor_num)
74 {
75     concptr alphabet_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
76     strcpy(label, alphabet_chars);
77     for (int i = 0; i < 52; i++) {
78         COMMAND_CODE index;
79         auto c = alphabet_chars[i];
80         if (!get_tag_floor(floor_ptr, &index, c, floor_list, floor_num)) {
81             continue;
82         }
83
84         if (label[i] == c) {
85             label[i] = ' ';
86         }
87
88         label[index] = c;
89     }
90 }
91
92 /*!
93  * @brief 床下に落ちているアイテムの一覧を返す / Display a list of the items on the floor at the given location.
94  * @param target_item カーソルの初期値
95  * @param y 走査するフロアのY座標
96  * @param x 走査するフロアのX座標
97  * @param min_width 表示の長さ
98  * @return 選択したアイテムの添え字
99  * @details
100  */
101 COMMAND_CODE show_floor_items(PlayerType *player_ptr, int target_item, POSITION y, POSITION x, TERM_LEN *min_width, const ItemTester &item_tester)
102 {
103     COMMAND_CODE i, m;
104     int j, k, l;
105     ItemEntity *o_ptr;
106     GAME_TEXT o_name[MAX_NLEN];
107     char tmp_val[80];
108     COMMAND_CODE out_index[23];
109     TERM_COLOR out_color[23];
110     char out_desc[23][MAX_NLEN];
111     COMMAND_CODE target_item_label = 0;
112     OBJECT_IDX floor_list[23];
113     ITEM_NUMBER floor_num;
114     TERM_LEN wid, hgt;
115     char floor_label[52 + 1];
116     bool dont_need_to_show_weights = true;
117     term_get_size(&wid, &hgt);
118     int len = std::max((*min_width), 20);
119     floor_num = scan_floor_items(player_ptr, floor_list, y, x, SCAN_FLOOR_ITEM_TESTER | SCAN_FLOOR_ONLY_MARKED, item_tester);
120     auto *floor_ptr = player_ptr->current_floor_ptr;
121     for (k = 0, i = 0; i < floor_num && i < 23; i++) {
122         o_ptr = &floor_ptr->o_list[floor_list[i]];
123         describe_flavor(player_ptr, o_name, o_ptr, 0);
124         out_index[k] = i;
125         const auto tval = o_ptr->bi_key.tval();
126         out_color[k] = tval_to_attr[enum2i(tval) & 0x7F];
127         strcpy(out_desc[k], o_name);
128         l = strlen(out_desc[k]) + 5;
129         if (show_weights) {
130             l += 9;
131         }
132
133         if (tval != ItemKindType::GOLD) {
134             dont_need_to_show_weights = false;
135         }
136
137         if (l > len) {
138             len = l;
139         }
140
141         k++;
142     }
143
144     if (show_weights && dont_need_to_show_weights) {
145         len -= 9;
146     }
147
148     *min_width = len;
149     int col = (len > wid - 4) ? 0 : (wid - len - 1);
150     prepare_label_string_floor(floor_ptr, floor_label, floor_list, floor_num);
151     for (j = 0; j < k; j++) {
152         m = floor_list[out_index[j]];
153         o_ptr = &floor_ptr->o_list[m];
154         prt("", j + 1, col ? col - 2 : col);
155         if (use_menu && target_item) {
156             if (j == (target_item - 1)) {
157                 strcpy(tmp_val, _("》", "> "));
158                 target_item_label = m;
159             } else {
160                 strcpy(tmp_val, "   ");
161             }
162         } else {
163             sprintf(tmp_val, "%c)", floor_label[j]);
164         }
165
166         put_str(tmp_val, j + 1, col);
167         c_put_str(out_color[j], out_desc[j], j + 1, col + 3);
168         if (show_weights && (o_ptr->bi_key.tval() != ItemKindType::GOLD)) {
169             int wgt = o_ptr->weight * o_ptr->number;
170             sprintf(tmp_val, _("%3d.%1d kg", "%3d.%1d lb"), _(lb_to_kg_integer(wgt), wgt / 10), _(lb_to_kg_fraction(wgt), wgt % 10));
171             prt(tmp_val, j + 1, wid - 9);
172         }
173     }
174
175     if (j && (j < 23)) {
176         prt("", j + 1, col ? col - 2 : col);
177     }
178
179     return target_item_label;
180 }