OSDN Git Service

b2b6bec34e40f7948a431e4fd9a081b18c27a2fb
[hengbandforosx/hengbandosx.git] / src / system / baseitem-info.cpp
1 /*!
2  * @brief ベースアイテム情報の構造体 / Information about object "kinds", including player knowledge.
3  * @date 2019/05/01
4  * @author deskull
5  * @details
6  * ゲーム進行用のセーブファイル上では aware と tried のみ保存対象とすること。と英文ではあるが実際はもっとある様子である。 /
7  * Only "aware" and "tried" are saved in the savefile
8  */
9
10 #include "system/baseitem-info.h"
11 #include "object/tval-types.h"
12 #include "sv-definition/sv-armor-types.h"
13 #include "sv-definition/sv-bow-types.h"
14 #include "sv-definition/sv-food-types.h"
15 #include "sv-definition/sv-lite-types.h"
16 #include "sv-definition/sv-protector-types.h"
17 #include "sv-definition/sv-rod-types.h"
18 #include "sv-definition/sv-weapon-types.h"
19 #include "system/angband-exceptions.h"
20 #include <set>
21 #include <unordered_map>
22
23 namespace {
24 constexpr auto ITEM_NOT_BOW = "This item is not a bow!";
25 constexpr auto ITEM_NOT_ROD = "This item is not a rod!";
26 constexpr auto ITEM_NOT_LITE = "This item is not a lite!";
27 }
28
29 bool BaseitemKey::operator==(const BaseitemKey &other) const
30 {
31     return (this->type_value == other.type_value) && (this->subtype_value == other.subtype_value);
32 }
33
34 // @details type_valueに大小があればそれを判定し、同一ならばsubtype_valueの大小を判定する.
35 bool BaseitemKey::operator<(const BaseitemKey &other) const
36 {
37     if (this->type_value < other.type_value) {
38         return true;
39     }
40
41     if (this->type_value > other.type_value) {
42         return false;
43     }
44
45     return this->subtype_value < other.subtype_value;
46 }
47
48 ItemKindType BaseitemKey::tval() const
49 {
50     return this->type_value;
51 }
52
53 std::optional<int> BaseitemKey::sval() const
54 {
55     return this->subtype_value;
56 }
57
58 /*!
59  * @brief 射撃武器に対応する矢/弾薬のベースアイテムIDを返す
60  * @return 対応する矢/弾薬のベースアイテムID
61  */
62 ItemKindType BaseitemKey::get_arrow_kind() const
63 {
64     if ((this->type_value != ItemKindType::BOW) || !this->subtype_value) {
65         THROW_EXCEPTION(std::logic_error, ITEM_NOT_BOW);
66     }
67
68     switch (*this->subtype_value) {
69     case SV_SLING:
70         return ItemKindType::SHOT;
71     case SV_SHORT_BOW:
72     case SV_LONG_BOW:
73     case SV_NAMAKE_BOW:
74         return ItemKindType::ARROW;
75     case SV_LIGHT_XBOW:
76     case SV_HEAVY_XBOW:
77         return ItemKindType::BOLT;
78     case SV_CRIMSON:
79     case SV_HARP:
80         return ItemKindType::NO_AMMO;
81     default:
82         return ItemKindType::NONE;
83     }
84 }
85
86 bool BaseitemKey::is_spell_book() const
87 {
88     switch (this->type_value) {
89     case ItemKindType::LIFE_BOOK:
90     case ItemKindType::SORCERY_BOOK:
91     case ItemKindType::NATURE_BOOK:
92     case ItemKindType::CHAOS_BOOK:
93     case ItemKindType::DEATH_BOOK:
94     case ItemKindType::TRUMP_BOOK:
95     case ItemKindType::ARCANE_BOOK:
96     case ItemKindType::CRAFT_BOOK:
97     case ItemKindType::DEMON_BOOK:
98     case ItemKindType::CRUSADE_BOOK:
99     case ItemKindType::MUSIC_BOOK:
100     case ItemKindType::HISSATSU_BOOK:
101     case ItemKindType::HEX_BOOK:
102         return true;
103     default:
104         return false;
105     }
106 }
107
108 bool BaseitemKey::is_high_level_book() const
109 {
110     if (!this->is_spell_book()) {
111         return false;
112     }
113
114     if (this->type_value == ItemKindType::ARCANE_BOOK) {
115         return false;
116     }
117
118     return this->subtype_value >= 2;
119 }
120
121 bool BaseitemKey::is_melee_weapon() const
122 {
123     switch (this->type_value) {
124     case ItemKindType::POLEARM:
125     case ItemKindType::SWORD:
126     case ItemKindType::DIGGING:
127     case ItemKindType::HAFTED:
128         return true;
129     default:
130         return false;
131     }
132 }
133
134 bool BaseitemKey::is_ammo() const
135 {
136     switch (this->type_value) {
137     case ItemKindType::SHOT:
138     case ItemKindType::ARROW:
139     case ItemKindType::BOLT:
140         return true;
141     default:
142         return false;
143     }
144 }
145
146 /*
147  * @brief 未鑑定名を持つか否かの判定
148  * @details FOODはキノコが該当する
149  */
150 bool BaseitemKey::has_unidentified_name() const
151 {
152     switch (this->type_value) {
153     case ItemKindType::AMULET:
154     case ItemKindType::RING:
155     case ItemKindType::STAFF:
156     case ItemKindType::WAND:
157     case ItemKindType::ROD:
158     case ItemKindType::SCROLL:
159     case ItemKindType::POTION:
160         return true;
161     case ItemKindType::FOOD:
162         return this->is_mushrooms();
163     default:
164         return false;
165     }
166 }
167
168 bool BaseitemKey::can_recharge() const
169 {
170     switch (this->type_value) {
171     case ItemKindType::STAFF:
172     case ItemKindType::WAND:
173     case ItemKindType::ROD:
174         return true;
175     default:
176         return false;
177     }
178 }
179
180 bool BaseitemKey::is_wand_rod() const
181 {
182     switch (this->type_value) {
183     case ItemKindType::WAND:
184     case ItemKindType::ROD:
185         return true;
186     default:
187         return false;
188     }
189 }
190
191 bool BaseitemKey::is_wand_staff() const
192 {
193     switch (this->type_value) {
194     case ItemKindType::WAND:
195     case ItemKindType::STAFF:
196         return true;
197     default:
198         return false;
199     }
200 }
201
202 bool BaseitemKey::is_protector() const
203 {
204     switch (this->type_value) {
205     case ItemKindType::BOOTS:
206     case ItemKindType::GLOVES:
207     case ItemKindType::HELM:
208     case ItemKindType::CROWN:
209     case ItemKindType::SHIELD:
210     case ItemKindType::CLOAK:
211     case ItemKindType::SOFT_ARMOR:
212     case ItemKindType::HARD_ARMOR:
213     case ItemKindType::DRAG_ARMOR:
214         return true;
215     default:
216         return false;
217     }
218 }
219
220 bool BaseitemKey::can_be_aura_protector() const
221 {
222     switch (this->type_value) {
223     case ItemKindType::CLOAK:
224     case ItemKindType::SOFT_ARMOR:
225     case ItemKindType::HARD_ARMOR:
226         return true;
227     default:
228         return false;
229     }
230 }
231
232 bool BaseitemKey::is_wearable() const
233 {
234     switch (this->type_value) {
235     case ItemKindType::BOW:
236     case ItemKindType::DIGGING:
237     case ItemKindType::HAFTED:
238     case ItemKindType::POLEARM:
239     case ItemKindType::SWORD:
240     case ItemKindType::BOOTS:
241     case ItemKindType::GLOVES:
242     case ItemKindType::HELM:
243     case ItemKindType::CROWN:
244     case ItemKindType::SHIELD:
245     case ItemKindType::CLOAK:
246     case ItemKindType::SOFT_ARMOR:
247     case ItemKindType::HARD_ARMOR:
248     case ItemKindType::DRAG_ARMOR:
249     case ItemKindType::LITE:
250     case ItemKindType::AMULET:
251     case ItemKindType::RING:
252     case ItemKindType::CARD:
253         return true;
254     default:
255         return false;
256     }
257 }
258
259 bool BaseitemKey::is_weapon() const
260 {
261     switch (this->type_value) {
262     case ItemKindType::BOW:
263     case ItemKindType::DIGGING:
264     case ItemKindType::HAFTED:
265     case ItemKindType::POLEARM:
266     case ItemKindType::SWORD:
267         return true;
268     default:
269         return false;
270     }
271 }
272
273 bool BaseitemKey::is_equipement() const
274 {
275     switch (this->type_value) {
276     case ItemKindType::SHOT:
277     case ItemKindType::ARROW:
278     case ItemKindType::BOLT:
279     case ItemKindType::BOW:
280     case ItemKindType::DIGGING:
281     case ItemKindType::HAFTED:
282     case ItemKindType::POLEARM:
283     case ItemKindType::SWORD:
284     case ItemKindType::BOOTS:
285     case ItemKindType::GLOVES:
286     case ItemKindType::HELM:
287     case ItemKindType::CROWN:
288     case ItemKindType::SHIELD:
289     case ItemKindType::CLOAK:
290     case ItemKindType::SOFT_ARMOR:
291     case ItemKindType::HARD_ARMOR:
292     case ItemKindType::DRAG_ARMOR:
293     case ItemKindType::LITE:
294     case ItemKindType::AMULET:
295     case ItemKindType::RING:
296     case ItemKindType::CARD:
297         return true;
298     default:
299         return false;
300     }
301 }
302
303 bool BaseitemKey::is_melee_ammo() const
304 {
305     switch (this->type_value) {
306     case ItemKindType::HAFTED:
307     case ItemKindType::POLEARM:
308     case ItemKindType::DIGGING:
309     case ItemKindType::BOLT:
310     case ItemKindType::ARROW:
311     case ItemKindType::SHOT:
312         return true;
313     case ItemKindType::SWORD:
314         return this->subtype_value != SV_POISON_NEEDLE;
315     default:
316         return false;
317     }
318 }
319
320 bool BaseitemKey::is_orthodox_melee_weapon() const
321 {
322     switch (this->type_value) {
323     case ItemKindType::HAFTED:
324     case ItemKindType::POLEARM:
325     case ItemKindType::DIGGING:
326         return true;
327     case ItemKindType::SWORD:
328         return this->subtype_value != SV_POISON_NEEDLE;
329     default:
330         return false;
331     }
332 }
333
334 bool BaseitemKey::is_broken_weapon() const
335 {
336     if (this->type_value != ItemKindType::SWORD) {
337         return false;
338     }
339
340     if (!this->subtype_value) {
341         return false;
342     }
343
344     switch (*this->subtype_value) {
345     case SV_BROKEN_DAGGER:
346     case SV_BROKEN_SWORD:
347         return true;
348     default:
349         return false;
350     }
351 }
352
353 bool BaseitemKey::is_throwable() const
354 {
355     switch (this->type_value) {
356     case ItemKindType::DIGGING:
357     case ItemKindType::HAFTED:
358     case ItemKindType::POLEARM:
359     case ItemKindType::SWORD:
360         return true;
361     default:
362         return false;
363     }
364 }
365
366 bool BaseitemKey::is_wieldable_in_etheir_hand() const
367 {
368     switch (this->type_value) {
369     case ItemKindType::DIGGING:
370     case ItemKindType::HAFTED:
371     case ItemKindType::POLEARM:
372     case ItemKindType::SWORD:
373     case ItemKindType::SHIELD:
374     case ItemKindType::CAPTURE:
375     case ItemKindType::CARD:
376         return true;
377     default:
378         return false;
379     }
380 }
381
382 bool BaseitemKey::is_rare() const
383 {
384     static const std::unordered_map<ItemKindType, const std::set<int>> rare_table = {
385         { ItemKindType::HAFTED, { SV_MACE_OF_DISRUPTION, SV_WIZSTAFF } },
386         { ItemKindType::POLEARM, { SV_SCYTHE_OF_SLICING, SV_DEATH_SCYTHE } },
387         { ItemKindType::SWORD, { SV_BLADE_OF_CHAOS, SV_DIAMOND_EDGE, SV_POISON_NEEDLE, SV_HAYABUSA } },
388         { ItemKindType::SHIELD, { SV_DRAGON_SHIELD, SV_MIRROR_SHIELD } },
389         { ItemKindType::HELM, { SV_DRAGON_HELM } },
390         { ItemKindType::BOOTS, { SV_PAIR_OF_DRAGON_GREAVE } },
391         { ItemKindType::CLOAK, { SV_ELVEN_CLOAK, SV_ETHEREAL_CLOAK, SV_SHADOW_CLOAK, SV_MAGIC_RESISTANCE_CLOAK } },
392         { ItemKindType::GLOVES, { SV_SET_OF_DRAGON_GLOVES } },
393         { ItemKindType::SOFT_ARMOR, { SV_KUROSHOUZOKU, SV_ABUNAI_MIZUGI } },
394         { ItemKindType::HARD_ARMOR, { SV_MITHRIL_CHAIN_MAIL, SV_MITHRIL_PLATE_MAIL, SV_ADAMANTITE_PLATE_MAIL } },
395         { ItemKindType::DRAG_ARMOR, { /* Any */ } },
396     };
397
398     if (!this->subtype_value) {
399         return false;
400     }
401
402     if (auto it = rare_table.find(this->type_value); it != rare_table.end()) {
403         const auto &svals = it->second;
404         return svals.empty() || (svals.find(*this->subtype_value) != svals.end());
405     }
406
407     return false;
408 }
409
410 short BaseitemKey::get_bow_energy() const
411 {
412     if ((this->type_value != ItemKindType::BOW) || !this->subtype_value) {
413         THROW_EXCEPTION(std::logic_error, ITEM_NOT_BOW);
414     }
415
416     switch (*this->subtype_value) {
417     case SV_SLING:
418         return 8000;
419     case SV_NAMAKE_BOW:
420         return 7777;
421     case SV_LIGHT_XBOW:
422         return 12000;
423     case SV_HEAVY_XBOW:
424         return 13333;
425     default:
426         return 10000;
427     }
428 }
429
430 int BaseitemKey::get_arrow_magnification() const
431 {
432     if ((this->type_value != ItemKindType::BOW) || !this->subtype_value) {
433         THROW_EXCEPTION(std::logic_error, ITEM_NOT_BOW);
434     }
435
436     switch (*this->subtype_value) {
437     case SV_SLING:
438     case SV_SHORT_BOW:
439         return 2;
440     case SV_LONG_BOW:
441     case SV_NAMAKE_BOW:
442     case SV_LIGHT_XBOW:
443         return 3;
444     case SV_HEAVY_XBOW:
445         return 4;
446     default:
447         return 0;
448     }
449 }
450
451 bool BaseitemKey::is_aiming_rod() const
452 {
453     if ((this->type_value != ItemKindType::ROD) || !this->subtype_value) {
454         THROW_EXCEPTION(std::logic_error, ITEM_NOT_ROD);
455     }
456
457     switch (*this->subtype_value) {
458     case SV_ROD_TELEPORT_AWAY:
459     case SV_ROD_DISARMING:
460     case SV_ROD_LITE:
461     case SV_ROD_SLEEP_MONSTER:
462     case SV_ROD_SLOW_MONSTER:
463     case SV_ROD_HYPODYNAMIA:
464     case SV_ROD_POLYMORPH:
465     case SV_ROD_ACID_BOLT:
466     case SV_ROD_ELEC_BOLT:
467     case SV_ROD_FIRE_BOLT:
468     case SV_ROD_COLD_BOLT:
469     case SV_ROD_ACID_BALL:
470     case SV_ROD_ELEC_BALL:
471     case SV_ROD_FIRE_BALL:
472     case SV_ROD_COLD_BALL:
473     case SV_ROD_STONE_TO_MUD:
474         return true;
475     default:
476         return false;
477     }
478 }
479
480 bool BaseitemKey::is_lite_requiring_fuel() const
481 {
482     if ((this->type_value != ItemKindType::LITE) || !this->subtype_value) {
483         THROW_EXCEPTION(std::logic_error, ITEM_NOT_LITE);
484     }
485
486     switch (*this->subtype_value) {
487     case SV_LITE_TORCH:
488     case SV_LITE_LANTERN:
489         return true;
490     default:
491         return false;
492     }
493 }
494
495 bool BaseitemKey::is_junk() const
496 {
497     switch (this->type_value) {
498     case ItemKindType::SKELETON:
499     case ItemKindType::BOTTLE:
500     case ItemKindType::JUNK:
501     case ItemKindType::STATUE:
502         return true;
503     default:
504         return false;
505     }
506 }
507
508 bool BaseitemKey::is_armour() const
509 {
510     switch (this->type_value) {
511     case ItemKindType::SOFT_ARMOR:
512     case ItemKindType::HARD_ARMOR:
513     case ItemKindType::DRAG_ARMOR:
514         return true;
515     default:
516         return false;
517     }
518 }
519
520 bool BaseitemKey::is_cross_bow() const
521 {
522     if ((this->type_value != ItemKindType::BOW) || !this->subtype_value) {
523         return false;
524     }
525
526     switch (*this->subtype_value) {
527     case SV_LIGHT_XBOW:
528     case SV_HEAVY_XBOW:
529         return true;
530     default:
531         return false;
532     }
533 }
534
535 bool BaseitemKey::is_mushrooms() const
536 {
537     if (!this->subtype_value) {
538         return false;
539     }
540
541     switch (*this->subtype_value) {
542     case SV_FOOD_POISON:
543     case SV_FOOD_BLINDNESS:
544     case SV_FOOD_PARANOIA:
545     case SV_FOOD_CONFUSION:
546     case SV_FOOD_HALLUCINATION:
547     case SV_FOOD_PARALYSIS:
548     case SV_FOOD_WEAKNESS:
549     case SV_FOOD_SICKNESS:
550     case SV_FOOD_STUPIDITY:
551     case SV_FOOD_NAIVETY:
552     case SV_FOOD_UNHEALTH:
553     case SV_FOOD_DISEASE:
554     case SV_FOOD_CURE_POISON:
555     case SV_FOOD_CURE_BLINDNESS:
556     case SV_FOOD_CURE_PARANOIA:
557     case SV_FOOD_CURE_CONFUSION:
558     case SV_FOOD_CURE_SERIOUS:
559     case SV_FOOD_RESTORE_STR:
560     case SV_FOOD_RESTORE_CON:
561     case SV_FOOD_RESTORING:
562         return true;
563     default:
564         return false;
565     }
566 }
567
568 BaseitemInfo::BaseitemInfo()
569     : bi_key(ItemKindType::NONE)
570 {
571 }
572
573 /*!
574  * @brief 最初から簡易な名称が明らかなベースアイテムにその旨のフラグを立てる
575  */
576 void BaseitemInfo::decide_easy_know()
577 {
578     switch (this->bi_key.tval()) {
579     case ItemKindType::LIFE_BOOK:
580     case ItemKindType::SORCERY_BOOK:
581     case ItemKindType::NATURE_BOOK:
582     case ItemKindType::CHAOS_BOOK:
583     case ItemKindType::DEATH_BOOK:
584     case ItemKindType::TRUMP_BOOK:
585     case ItemKindType::ARCANE_BOOK:
586     case ItemKindType::CRAFT_BOOK:
587     case ItemKindType::DEMON_BOOK:
588     case ItemKindType::CRUSADE_BOOK:
589     case ItemKindType::MUSIC_BOOK:
590     case ItemKindType::HISSATSU_BOOK:
591     case ItemKindType::HEX_BOOK:
592     case ItemKindType::FLASK:
593     case ItemKindType::JUNK:
594     case ItemKindType::BOTTLE:
595     case ItemKindType::SKELETON:
596     case ItemKindType::SPIKE:
597     case ItemKindType::WHISTLE:
598     case ItemKindType::FOOD:
599     case ItemKindType::POTION:
600     case ItemKindType::SCROLL:
601     case ItemKindType::ROD:
602     case ItemKindType::STATUE:
603     case ItemKindType::PARCHMENT:
604         this->easy_know = true;
605         return;
606     default:
607         this->easy_know = false;
608         return;
609     }
610 }
611
612 /*!
613  * @brief オブジェクトを試行済にする
614  */
615 void BaseitemInfo::mark_as_tried()
616 {
617     this->tried = true;
618 }
619
620 std::vector<BaseitemInfo> baseitems_info;