2 * @brief インベントリ関係のユーティリティ
5 * @details 少々雑多なので後で整理を検討する
8 #include "inventory/inventory-util.h"
9 #include "core/asking-player.h"
10 #include "flavor/flavor-describer.h"
11 #include "inventory/inventory-slot-types.h"
12 #include "io/input-key-requester.h"
13 #include "object/item-tester-hooker.h"
14 #include "object/item-use-flags.h"
15 #include "system/floor-type-definition.h"
16 #include "system/item-entity.h"
17 #include "system/player-type-definition.h"
18 #include "util/bit-flags-calculator.h"
19 #include "util/int-char-converter.h"
20 #include "util/string-processor.h"
24 * @brief プレイヤーの所持/装備オブジェクトIDが指輪枠かを返す /
25 * @param i プレイヤーの所持/装備オブジェクトID
26 * @return 指輪枠ならばTRUEを返す。
28 bool is_ring_slot(int i)
30 return (i == INVEN_MAIN_RING) || (i == INVEN_SUB_RING);
34 * @brief 床オブジェクトに選択タグを与える/タグに該当するオブジェクトがあるかを返す /
35 * Find the "first" inventory object with the given "tag".
36 * @param cp 対応するタグIDを与える参照ポインタ
37 * @param tag 該当するオブジェクトがあるかを調べたいタグ
38 * @param floor_list 床上アイテムの配列
39 * @param floor_num 床上アイテムの配列ID
40 * @return タグに該当するオブジェクトがあるならTRUEを返す
42 * A "tag" is a numeral "n" appearing as "@n" anywhere in the\n
43 * inscription of an object. Alphabetical characters don't work as a\n
46 * Also, the tag "@xn" will work as well, where "n" is a any tag-char,\n
47 * and "x" is the "current" command_cmd code.\n
49 bool get_tag_floor(FloorType *floor_ptr, COMMAND_CODE *cp, char tag, FLOOR_IDX floor_list[], ITEM_NUMBER floor_num)
51 for (COMMAND_CODE i = 0; i < floor_num && i < 23; i++) {
52 auto *o_ptr = &floor_ptr->o_list[floor_list[i]];
53 if (!o_ptr->is_inscribed()) {
57 auto s = angband_strchr(o_ptr->inscription->data(), '@');
59 if ((s[1] == command_cmd) && (s[2] == tag)) {
64 s = angband_strchr(s + 1, '@');
68 if (tag < '0' || '9' < tag) {
72 for (COMMAND_CODE i = 0; i < floor_num && i < 23; i++) {
73 auto *o_ptr = &floor_ptr->o_list[floor_list[i]];
74 if (!o_ptr->is_inscribed()) {
78 auto s = angband_strchr(o_ptr->inscription->data(), '@');
85 s = angband_strchr(s + 1, '@');
93 * @brief 所持/装備オブジェクトに選択タグを与える/タグに該当するオブジェクトがあるかを返す /
94 * Find the "first" inventory object with the given "tag".
95 * @param player_ptr プレイヤーへの参照ポインタ
96 * @param cp 対応するタグIDを与える参照ポインタ
97 * @param tag 該当するオブジェクトがあるかを調べたいタグ
98 * @param mode 所持、装備の切り替え
99 * @return タグに該当するオブジェクトがあるならTRUEを返す
101 * A "tag" is a numeral "n" appearing as "@n" anywhere in the\n
102 * inscription of an object. Alphabetical characters don't work as a\n
103 * tag in this form.\n
105 * Also, the tag "@xn" will work as well, where "n" is a any tag-char,\n
106 * and "x" is the "current" command_cmd code.\n
108 bool get_tag(PlayerType *player_ptr, COMMAND_CODE *cp, char tag, BIT_FLAGS mode, const ItemTester &item_tester)
110 COMMAND_CODE start, end;
113 start = INVEN_MAIN_HAND;
114 end = INVEN_TOTAL - 1;
119 end = INVEN_PACK - 1;
126 for (COMMAND_CODE i = start; i <= end; i++) {
127 auto *o_ptr = &player_ptr->inventory_list[i];
128 if (!o_ptr->is_valid() || !o_ptr->is_inscribed()) {
132 if (!item_tester.okay(o_ptr) && !(mode & USE_FULL)) {
136 auto s = angband_strchr(o_ptr->inscription->data(), '@');
138 if ((s[1] == command_cmd) && (s[2] == tag)) {
143 s = angband_strchr(s + 1, '@');
147 if (tag < '0' || '9' < tag) {
151 for (COMMAND_CODE i = start; i <= end; i++) {
152 auto *o_ptr = &player_ptr->inventory_list[i];
153 if (!o_ptr->is_valid() || !o_ptr->is_inscribed()) {
157 if (!item_tester.okay(o_ptr) && !(mode & USE_FULL)) {
161 auto s = angband_strchr(o_ptr->inscription->data(), '@');
168 s = angband_strchr(s + 1, '@');
176 * @brief プレイヤーの所持/装備オブジェクトが正規のものかを返す /
177 * Auxiliary function for "get_item()" -- test an index
179 * @return 正規のIDならばTRUEを返す。
181 bool get_item_okay(PlayerType *player_ptr, OBJECT_IDX i, const ItemTester &item_tester)
183 if ((i < 0) || (i >= INVEN_TOTAL)) {
187 if (player_ptr->select_ring_slot) {
188 return is_ring_slot(i);
191 return item_tester.okay(&player_ptr->inventory_list[i]);
195 * @brief 選択したアイテムの確認処理のメインルーチン
196 * @param player_ptr プレイヤーへの参照ポインタ
197 * @param i_idx 選択アイテムID
198 * @return 確認がYesならTRUEを返す。
200 bool get_item_allow(PlayerType *player_ptr, INVENTORY_IDX i_idx)
208 o_ptr = &player_ptr->inventory_list[i_idx];
210 o_ptr = &player_ptr->current_floor_ptr->o_list[0 - i_idx];
213 if (!o_ptr->is_inscribed()) {
217 auto s = angband_strchr(o_ptr->inscription->data(), '!');
219 if ((s[1] == command_cmd) || (s[1] == '*')) {
220 if (!verify(player_ptr, _("本当に", "Really try"), i_idx)) {
225 s = angband_strchr(s + 1, '!');
232 * @brief 選択アルファベットラベルからプレイヤーの装備オブジェクトIDを返す /
233 * @param player_ptr プレイヤーへの参照ポインタ
234 * Convert a label into the index of a item in the "equip"
235 * @return 対応するID。該当スロットにオブジェクトが存在しなかった場合-1を返す / Return "-1" if the label does not indicate a real item
237 INVENTORY_IDX label_to_equipment(PlayerType *player_ptr, int c)
239 INVENTORY_IDX i = (INVENTORY_IDX)(islower(c) ? A2I(c) : -1) + INVEN_MAIN_HAND;
241 if ((i < INVEN_MAIN_HAND) || (i >= INVEN_TOTAL)) {
245 if (player_ptr->select_ring_slot) {
246 return is_ring_slot(i) ? i : -1;
249 if (!player_ptr->inventory_list[i].bi_id) {
257 * @brief 選択アルファベットラベルからプレイヤーの所持オブジェクトIDを返す /
258 * Convert a label into the index of an item in the "inven"
259 * @param player_ptr プレイヤーへの参照ポインタ
260 * @param c 選択されたアルファベット
261 * @return 対応するID。該当スロットにオブジェクトが存在しなかった場合-1を返す / Return "-1" if the label does not indicate a real item
262 * @details Note that the label does NOT distinguish inven/equip.
264 INVENTORY_IDX label_to_inventory(PlayerType *player_ptr, int c)
266 INVENTORY_IDX i = (INVENTORY_IDX)(islower(c) ? A2I(c) : -1);
268 if ((i < 0) || (i > INVEN_PACK) || !player_ptr->inventory_list[i].is_valid()) {
276 * @brief 選択したアイテムの確認処理の補助
277 * @param player_ptr プレイヤーへの参照ポインタ
278 * @param prompt メッセージ表示の一部
279 * @param i_idx 選択アイテムID
280 * @return 確認がYesならTRUEを返す。
282 bool verify(PlayerType *player_ptr, concptr prompt, INVENTORY_IDX i_idx)
286 o_ptr = &player_ptr->inventory_list[i_idx];
288 o_ptr = &player_ptr->current_floor_ptr->o_list[0 - i_idx];
291 const auto item_name = describe_flavor(player_ptr, o_ptr, 0);
292 std::stringstream ss;
297 ss << item_name << _("ですか? ", "? ");
298 return input_check(ss.str());
302 * @brief タグIDにあわせてタグアルファベットのリストを返す /
303 * Move around label characters with correspond tags
304 * @param player_ptr プレイヤーへの参照ポインタ
305 * @param label ラベルリストを取得する文字列参照ポインタ
306 * @param mode 所持品リストか装備品リストかの切り替え
308 void prepare_label_string(PlayerType *player_ptr, char *label, BIT_FLAGS mode, const ItemTester &item_tester)
310 concptr alphabet_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
311 int offset = match_bits(mode, USE_EQUIP, USE_EQUIP) ? INVEN_MAIN_HAND : 0;
312 strcpy(label, alphabet_chars);
313 for (int i = 0; i < 52; i++) {
315 auto c = alphabet_chars[i];
316 if (!get_tag(player_ptr, &index, c, mode, item_tester)) {
324 label[index - offset] = c;