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/int-char-converter.h"
19 #include "util/quarks.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 item 選択アイテムID
198 * @return 確認がYesならTRUEを返す。
199 * @details The item can be negative to mean "item on floor".
200 * Hack -- allow user to "prevent" certain choices
202 bool get_item_allow(PlayerType *player_ptr, INVENTORY_IDX item)
210 o_ptr = &player_ptr->inventory_list[item];
212 o_ptr = &player_ptr->current_floor_ptr->o_list[0 - item];
215 if (!o_ptr->is_inscribed()) {
219 auto s = angband_strchr(o_ptr->inscription->data(), '!');
221 if ((s[1] == command_cmd) || (s[1] == '*')) {
222 if (!verify(player_ptr, _("本当に", "Really try"), item)) {
227 s = angband_strchr(s + 1, '!');
234 * @brief 選択アルファベットラベルからプレイヤーの装備オブジェクトIDを返す /
235 * @param player_ptr プレイヤーへの参照ポインタ
236 * Convert a label into the index of a item in the "equip"
237 * @return 対応するID。該当スロットにオブジェクトが存在しなかった場合-1を返す / Return "-1" if the label does not indicate a real item
239 INVENTORY_IDX label_to_equipment(PlayerType *player_ptr, int c)
241 INVENTORY_IDX i = (INVENTORY_IDX)(islower(c) ? A2I(c) : -1) + INVEN_MAIN_HAND;
243 if ((i < INVEN_MAIN_HAND) || (i >= INVEN_TOTAL)) {
247 if (player_ptr->select_ring_slot) {
248 return is_ring_slot(i) ? i : -1;
251 if (!player_ptr->inventory_list[i].bi_id) {
259 * @brief 選択アルファベットラベルからプレイヤーの所持オブジェクトIDを返す /
260 * Convert a label into the index of an item in the "inven"
261 * @param player_ptr プレイヤーへの参照ポインタ
262 * @param c 選択されたアルファベット
263 * @return 対応するID。該当スロットにオブジェクトが存在しなかった場合-1を返す / Return "-1" if the label does not indicate a real item
264 * @details Note that the label does NOT distinguish inven/equip.
266 INVENTORY_IDX label_to_inventory(PlayerType *player_ptr, int c)
268 INVENTORY_IDX i = (INVENTORY_IDX)(islower(c) ? A2I(c) : -1);
270 if ((i < 0) || (i > INVEN_PACK) || !player_ptr->inventory_list[i].is_valid()) {
278 * @brief 選択したアイテムの確認処理の補助 /
279 * Verify the choice of an item.
280 * @param player_ptr プレイヤーへの参照ポインタ
281 * @param prompt メッセージ表示の一部
282 * @param item 選択アイテムID
283 * @return 確認がYesならTRUEを返す。
284 * @details The item can be negative to mean "item on floor".
286 bool verify(PlayerType *player_ptr, concptr prompt, INVENTORY_IDX item)
290 o_ptr = &player_ptr->inventory_list[item];
292 o_ptr = &player_ptr->current_floor_ptr->o_list[0 - item];
295 const auto item_name = describe_flavor(player_ptr, o_ptr, 0);
296 std::stringstream ss;
301 ss << item_name << _("ですか? ", "? ");
302 return get_check(ss.str());
306 * @brief タグIDにあわせてタグアルファベットのリストを返す /
307 * Move around label characters with correspond tags
308 * @param player_ptr プレイヤーへの参照ポインタ
309 * @param label ラベルリストを取得する文字列参照ポインタ
310 * @param mode 所持品リストか装備品リストかの切り替え
312 void prepare_label_string(PlayerType *player_ptr, char *label, BIT_FLAGS mode, const ItemTester &item_tester)
314 concptr alphabet_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
315 int offset = (mode == USE_EQUIP) ? INVEN_MAIN_HAND : 0;
316 strcpy(label, alphabet_chars);
317 for (int i = 0; i < 52; i++) {
319 auto c = alphabet_chars[i];
320 if (!get_tag(player_ptr, &index, c, mode, item_tester)) {
328 label[index - offset] = c;