2 * @brief アイテムが特定種別のものであるかどうかの判定関数群
7 #include "object/object-kind-hook.h"
8 #include "object/tval-types.h"
9 #include "sv-definition/sv-amulet-types.h"
10 #include "sv-definition/sv-other-types.h"
11 #include "sv-definition/sv-ring-types.h"
12 #include "system/baseitem-info.h"
18 // @brief 3冊目の魔法書からは上質アイテムとして扱う.
19 static const int SV_BOOK_MIN_GOOD = 2;
22 * @brief オブジェクトがクロークかどうかを判定する /
23 * @param bi_id 判定したいオブジェクトのベースアイテムID
24 * @return オブジェクトがクロークならばTRUEを返す
26 bool kind_is_cloak(short bi_id)
28 return baseitems_info[bi_id].bi_key.tval() == ItemKindType::CLOAK;
32 * @brief オブジェクトが竿状武器かどうかを判定する /
33 * @param bi_id 判定したいオブジェクトのベースアイテムID
34 * @return オブジェクトが竿状武器ならばTRUEを返す
36 bool kind_is_polearm(short bi_id)
38 return baseitems_info[bi_id].bi_key.tval() == ItemKindType::POLEARM;
42 * @brief オブジェクトが剣かどうかを判定する /
43 * @param bi_id 判定したいオブジェクトのベースアイテムID
44 * @return オブジェクトが剣ならばTRUEを返す
46 bool kind_is_sword(short bi_id)
48 const auto &baseitem = baseitems_info[bi_id];
49 return (baseitem.bi_key.tval() == ItemKindType::SWORD) && (baseitem.bi_key.sval() > 2);
53 * @brief オブジェクトが魔法書かどうかを判定する
54 * @param bi_id 判定したいオブジェクトのベースアイテムID
55 * @return オブジェクトが魔法書ならばTRUEを返す
57 bool kind_is_book(short bi_id)
59 const auto &baseitem = baseitems_info[bi_id];
60 return baseitem.bi_key.is_spell_book();
64 * @brief オブジェクトがベースアイテム時点でGOODかどうかを判定する
65 * @param bi_id 判定したいオブジェクトのベースアイテムID
66 * @return オブジェクトがベースアイテム時点でGOODなアイテムならばTRUEを返す
68 bool kind_is_good_book(short bi_id)
70 const auto &baseitem = baseitems_info[bi_id];
71 return baseitem.bi_key.is_high_level_book();
75 * @brief オブジェクトが鎧かどうかを判定する /
76 * @param bi_id 判定したいオブジェクトのベースアイテムID
77 * @return オブジェクトが鎧ならばTRUEを返す
79 bool kind_is_armor(short bi_id)
81 return baseitems_info[bi_id].bi_key.tval() == ItemKindType::HARD_ARMOR;
85 * @brief オブジェクトが打撃武器かどうかを判定する /
86 * @param bi_id 判定したいオブジェクトのベースアイテムID
87 * @return オブジェクトが打撃武器ならばTRUEを返す
89 bool kind_is_hafted(short bi_id)
91 return baseitems_info[bi_id].bi_key.tval() == ItemKindType::HAFTED;
95 * @brief オブジェクトが薬かどうかを判定する /
96 * @param bi_id 判定したいオブジェクトのベースアイテムID
97 * @return オブジェクトが薬ならばTRUEを返す
99 bool kind_is_potion(short bi_id)
101 return baseitems_info[bi_id].bi_key.tval() == ItemKindType::POTION;
105 * @brief オブジェクトが靴かどうかを判定する /
106 * @param bi_id 判定したいオブジェクトのベースアイテムID
107 * @return オブジェクトが靴ならばTRUEを返す
109 bool kind_is_boots(short bi_id)
111 return baseitems_info[bi_id].bi_key.tval() == ItemKindType::BOOTS;
115 * @brief オブジェクトがアミュレットかどうかを判定する /
116 * @param bi_id 判定したいオブジェクトのベースアイテムID
117 * @return オブジェクトがアミュレットならばTRUEを返す
119 bool kind_is_amulet(short bi_id)
121 return baseitems_info[bi_id].bi_key.tval() == ItemKindType::AMULET;
125 * @brief ベースアイテムが上質として扱われるかどうかを返す。
126 * Hack -- determine if a template is "good"
127 * @param bi_id 判定したいベースアイテムのID
128 * @return ベースアイテムが上質ならばTRUEを返す。
130 bool kind_is_good(short bi_id)
132 const auto &baseitem = baseitems_info[bi_id];
133 switch (baseitem.bi_key.tval()) {
134 /* Armor -- Good unless damaged */
135 case ItemKindType::HARD_ARMOR:
136 case ItemKindType::SOFT_ARMOR:
137 case ItemKindType::DRAG_ARMOR:
138 case ItemKindType::SHIELD:
139 case ItemKindType::CLOAK:
140 case ItemKindType::BOOTS:
141 case ItemKindType::GLOVES:
142 case ItemKindType::HELM:
143 case ItemKindType::CROWN:
144 return baseitem.to_a >= 0;
146 /* Weapons -- Good unless damaged */
147 case ItemKindType::BOW:
148 case ItemKindType::SWORD:
149 case ItemKindType::HAFTED:
150 case ItemKindType::POLEARM:
151 case ItemKindType::DIGGING:
152 return (baseitem.to_h >= 0) && (baseitem.to_d >= 0);
154 /* Ammo -- Arrows/Bolts are good */
155 case ItemKindType::BOLT:
156 case ItemKindType::ARROW:
159 /* Books -- High level books are good (except Arcane books) */
160 case ItemKindType::LIFE_BOOK:
161 case ItemKindType::SORCERY_BOOK:
162 case ItemKindType::NATURE_BOOK:
163 case ItemKindType::CHAOS_BOOK:
164 case ItemKindType::DEATH_BOOK:
165 case ItemKindType::TRUMP_BOOK:
166 case ItemKindType::CRAFT_BOOK:
167 case ItemKindType::DEMON_BOOK:
168 case ItemKindType::CRUSADE_BOOK:
169 case ItemKindType::MUSIC_BOOK:
170 case ItemKindType::HISSATSU_BOOK:
171 case ItemKindType::HEX_BOOK:
172 return baseitem.bi_key.sval() >= SV_BOOK_MIN_GOOD;
174 /* Rings -- Rings of Speed are good */
175 case ItemKindType::RING:
176 return (baseitem.bi_key.sval() == SV_RING_SPEED) || (baseitem.bi_key.sval() == SV_RING_LORDLY);
178 /* Amulets -- Amulets of the Magi and Resistance are good */
179 case ItemKindType::AMULET:
180 return (baseitem.bi_key.sval() == SV_AMULET_THE_MAGI) || (baseitem.bi_key.sval() == SV_AMULET_RESISTANCE);
187 * @brief 特定のtvalとランダムなsvalの組み合わせからベースアイテムを選択するためのキャッシュを生成する
188 * @return tvalをキーに、svalのリストを値とした辞書
190 static const std::map<ItemKindType, std::vector<int>> &create_baseitems_cache()
192 static std::map<ItemKindType, std::vector<int>> cache;
193 for (const auto &baseitem : baseitems_info) {
194 const auto &bi_key = baseitem.bi_key;
195 const auto tval = bi_key.tval();
196 if (tval == ItemKindType::NONE) {
200 cache[tval].push_back(bi_key.sval().value());
207 * @brief tvalとbi_key.svalに対応する、BaseitenDefinitions のIDを返すためのキャッシュを生成する
208 * @return tvalと(実在する)svalの組み合わせをキーに、ベースアイテムIDを値とした辞書
210 static const std::map<BaseitemKey, short> &create_baseitem_index_chache()
212 static std::map<BaseitemKey, short> cache;
213 for (const auto &baseitem : baseitems_info) {
214 const auto &bi_key = baseitem.bi_key;
215 if (bi_key.tval() == ItemKindType::NONE) {
219 cache[bi_key] = baseitem.idx;
226 * @brief tvalとsvalに対応するベースアイテムのIDを検索する
227 * @param key 検索したいベースアイテムの、tval/svalのペア (svalがnulloptの可能性はない)
228 * @return tvalとsvalに対応するベースアイテムが存在すればそのID、存在しなければ0
229 * @details 存在しないことはリファクタリング成果により考えにくく、自作の不存在例外を投げればいいはず.
230 * 但し呼び出し側全部の処理を保証するのが面倒なので旧処理のままとする.
232 static short exe_lookup(const BaseitemKey &key)
234 static const auto &cache = create_baseitem_index_chache();
235 const auto itr = cache.find(key);
236 if (itr == cache.end()) {
244 * @brief ベースアイテムのtval/svalからIDを引いて返す
245 * @param key tval/svalのペア、但しsvalはランダム (nullopt)の可能性がある
247 * @details 「tvalが不存在」という状況は事実上ないが、辞書探索のお作法として「有無チェック」を入れておく.
248 * 万が一tvalがキャッシュになかったらベースアイテムID 0を返す.
250 short lookup_baseitem_id(const BaseitemKey &key)
252 const auto sval = key.sval();
254 return exe_lookup(key);
257 static const auto &cache = create_baseitems_cache();
258 const auto itr = cache.find(key.tval());
259 if (itr == cache.end()) {
263 const auto &svals = itr->second;
264 return exe_lookup({ key.tval(), rand_choice(svals) });