OSDN Git Service

[Refactor] #2124 Changed struct object_type to class ObjectType
[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/object-type-definition.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     floor_type *floor_ptr = player_ptr->current_floor_ptr;
35     if (!in_bounds(floor_ptr, y, x))
36         return 0;
37
38     ITEM_NUMBER num = 0;
39     for (const auto this_o_idx : floor_ptr->grid_array[y][x].o_idx_list) {
40         ObjectType *o_ptr;
41         o_ptr = &floor_ptr->o_list[this_o_idx];
42         if ((mode & SCAN_FLOOR_ITEM_TESTER) && !item_tester.okay(o_ptr))
43             continue;
44
45         if ((mode & SCAN_FLOOR_ONLY_MARKED) && !(o_ptr->marked & OM_FOUND))
46             continue;
47
48         if (num < 23)
49             items[num] = this_o_idx;
50
51         num++;
52         if (mode & SCAN_FLOOR_AT_MOST_ONE)
53             break;
54     }
55
56     return num;
57 }
58
59 /*!
60  * @brief タグIDにあわせてタグアルファベットのリストを返す(床上アイテム用) /
61  * Move around label characters with correspond tags (floor version)
62  * @param label ラベルリストを取得する文字列参照ポインタ
63  * @param floor_list 床上アイテムの配列
64  * @param floor_num  床上アイテムの配列ID
65  */
66 /*
67  */
68 static void prepare_label_string_floor(floor_type *floor_ptr, char *label, FLOOR_IDX floor_list[], ITEM_NUMBER floor_num)
69 {
70     concptr alphabet_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
71     strcpy(label, alphabet_chars);
72     for (int i = 0; i < 52; i++) {
73         COMMAND_CODE index;
74         SYMBOL_CODE c = alphabet_chars[i];
75         if (!get_tag_floor(floor_ptr, &index, c, floor_list, floor_num))
76             continue;
77
78         if (label[i] == c)
79             label[i] = ' ';
80
81         label[index] = c;
82     }
83 }
84
85 /*!
86  * @brief 床下に落ちているアイテムの一覧を返す / Display a list of the items on the floor at the given location.
87  * @param target_item カーソルの初期値
88  * @param y 走査するフロアのY座標
89  * @param x 走査するフロアのX座標
90  * @param min_width 表示の長さ
91  * @return 選択したアイテムの添え字
92  * @details
93  */
94 COMMAND_CODE show_floor_items(PlayerType *player_ptr, int target_item, POSITION y, POSITION x, TERM_LEN *min_width, const ItemTester &item_tester)
95 {
96     COMMAND_CODE i, m;
97     int j, k, l;
98     ObjectType *o_ptr;
99     GAME_TEXT o_name[MAX_NLEN];
100     char tmp_val[80];
101     COMMAND_CODE out_index[23];
102     TERM_COLOR out_color[23];
103     char out_desc[23][MAX_NLEN];
104     COMMAND_CODE target_item_label = 0;
105     OBJECT_IDX floor_list[23];
106     ITEM_NUMBER floor_num;
107     TERM_LEN wid, hgt;
108     char floor_label[52 + 1];
109     bool dont_need_to_show_weights = true;
110     term_get_size(&wid, &hgt);
111     int len = std::max((*min_width), 20);
112     floor_num = scan_floor_items(player_ptr, floor_list, y, x, SCAN_FLOOR_ITEM_TESTER | SCAN_FLOOR_ONLY_MARKED, item_tester);
113     floor_type *floor_ptr = player_ptr->current_floor_ptr;
114     for (k = 0, i = 0; i < floor_num && i < 23; i++) {
115         o_ptr = &floor_ptr->o_list[floor_list[i]];
116         describe_flavor(player_ptr, o_name, o_ptr, 0);
117         out_index[k] = i;
118         out_color[k] = tval_to_attr[enum2i(o_ptr->tval) & 0x7F];
119         strcpy(out_desc[k], o_name);
120         l = strlen(out_desc[k]) + 5;
121         if (show_weights)
122             l += 9;
123
124         if (o_ptr->tval != ItemKindType::GOLD)
125             dont_need_to_show_weights = false;
126
127         if (l > len)
128             len = l;
129
130         k++;
131     }
132
133     if (show_weights && dont_need_to_show_weights)
134         len -= 9;
135
136     *min_width = len;
137     int col = (len > wid - 4) ? 0 : (wid - len - 1);
138     prepare_label_string_floor(floor_ptr, floor_label, floor_list, floor_num);
139     for (j = 0; j < k; j++) {
140         m = floor_list[out_index[j]];
141         o_ptr = &floor_ptr->o_list[m];
142         prt("", j + 1, col ? col - 2 : col);
143         if (use_menu && target_item) {
144             if (j == (target_item - 1)) {
145                 strcpy(tmp_val, _("》", "> "));
146                 target_item_label = m;
147             } else
148                 strcpy(tmp_val, "   ");
149         } else {
150             sprintf(tmp_val, "%c)", floor_label[j]);
151         }
152
153         put_str(tmp_val, j + 1, col);
154         c_put_str(out_color[j], out_desc[j], j + 1, col + 3);
155         if (show_weights && (o_ptr->tval != ItemKindType::GOLD)) {
156             int wgt = o_ptr->weight * o_ptr->number;
157             sprintf(tmp_val, _("%3d.%1d kg", "%3d.%1d lb"), _(lb_to_kg_integer(wgt), wgt / 10), _(lb_to_kg_fraction(wgt), wgt % 10));
158             prt(tmp_val, j + 1, wid - 9);
159         }
160     }
161
162     if (j && (j < 23))
163         prt("", j + 1, col ? col - 2 : col);
164
165     return target_item_label;
166 }