2 * @file item-entity.cpp
3 * @brief アイテム実体とそれにまつわる判定処理群
6 * @details オブジェクトの状態を変更するメソッドは道半ば
9 #include "system/item-entity.h"
10 #include "artifact/fixed-art-types.h"
11 #include "artifact/random-art-effects.h"
12 #include "monster-race/monster-race.h"
13 #include "object-enchant/activation-info-table.h"
14 #include "object-enchant/dragon-breaths-table.h"
15 #include "object-enchant/item-feeling.h"
16 #include "object-enchant/object-curse.h"
17 #include "object-enchant/special-object-flags.h"
18 #include "object/object-value.h"
19 #include "object/tval-types.h"
20 #include "smith/object-smith.h"
21 #include "sv-definition/sv-lite-types.h"
22 #include "sv-definition/sv-other-types.h"
23 #include "sv-definition/sv-ring-types.h"
24 #include "sv-definition/sv-weapon-types.h"
25 #include "system/artifact-type-definition.h"
26 #include "system/baseitem-info.h"
27 #include "system/monster-race-info.h"
28 #include "term/term-color-types.h"
29 #include "util/bit-flags-calculator.h"
30 #include "util/enum-converter.h"
31 #include "util/string-processor.h"
34 ItemEntity::ItemEntity()
35 : bi_key(BaseitemKey(ItemKindType::NONE))
36 , fixed_artifact_idx(FixedArtifactId::NONE)
42 * Wipe an object clean.
44 void ItemEntity::wipe()
51 * Wipe an object clean.
52 * @param j_ptr 複製元のオブジェクトの構造体参照ポインタ
54 void ItemEntity::copy_from(const ItemEntity *j_ptr)
60 * @brief アイテム構造体にベースアイテムを作成する
61 * @param player_ptr プレイヤーへの参照ポインタ
62 * @param bi_id 新たに作成したいベースアイテム情報のID
64 void ItemEntity::prep(short new_bi_id)
66 const auto &baseitem = baseitems_info[new_bi_id];
67 auto old_stack_idx = this->stack_idx;
69 this->stack_idx = old_stack_idx;
70 this->bi_id = new_bi_id;
71 this->bi_key = baseitem.bi_key;
72 this->pval = baseitem.pval;
74 this->weight = baseitem.weight;
75 this->to_h = baseitem.to_h;
76 this->to_d = baseitem.to_d;
77 this->to_a = baseitem.to_a;
78 this->ac = baseitem.ac;
79 this->dd = baseitem.dd;
80 this->ds = baseitem.ds;
82 if (baseitem.act_idx > RandomArtActType::NONE) {
83 this->activation_id = baseitem.act_idx;
86 if (this->get_baseitem().cost <= 0) {
87 this->ident |= (IDENT_BROKEN);
90 if (baseitem.gen_flags.has(ItemGenerationTraitType::CURSED)) {
91 this->curse_flags.set(CurseTraitType::CURSED);
94 if (baseitem.gen_flags.has(ItemGenerationTraitType::HEAVY_CURSE)) {
95 this->curse_flags.set(CurseTraitType::HEAVY_CURSE);
98 if (baseitem.gen_flags.has(ItemGenerationTraitType::PERMA_CURSE)) {
99 this->curse_flags.set(CurseTraitType::PERMA_CURSE);
102 if (baseitem.gen_flags.has(ItemGenerationTraitType::RANDOM_CURSE0)) {
103 this->curse_flags.set(get_curse(0, this));
106 if (baseitem.gen_flags.has(ItemGenerationTraitType::RANDOM_CURSE1)) {
107 this->curse_flags.set(get_curse(1, this));
110 if (baseitem.gen_flags.has(ItemGenerationTraitType::RANDOM_CURSE2)) {
111 this->curse_flags.set(get_curse(2, this));
116 * @brief アイテムが武器として装備できるかどうかを返す / Check if an object is weapon (including bows)
117 * @return 武器として使えるならばtrueを返す
119 bool ItemEntity::is_weapon() const
121 return this->bi_key.is_weapon();
125 * @brief アイテムが武器や矢弾として使用できるかを返す
126 * @return 武器や矢弾として使えるならばtrueを返す
128 bool ItemEntity::is_weapon_ammo() const
130 return this->is_weapon() || this->is_ammo();
134 * @brief アイテムが武器、防具、矢弾として使用できるかを返す / Check if an object is weapon, armour or ammo
135 * @return 武器、防具、矢弾として使えるならばtrueを返す
137 bool ItemEntity::is_weapon_armour_ammo() const
139 return this->is_weapon_ammo() || this->is_protector();
143 * @brief アイテムが近接武器として装備できるかを返す / Melee weapons
144 * @return 近接武器として使えるならばtrueを返す
146 bool ItemEntity::is_melee_weapon() const
148 return this->bi_key.is_melee_weapon();
152 * @brief エッセンスの付加可能な武器や矢弾かを返す
153 * @return エッセンスの付加可能な武器か矢弾ならばtrueを返す。
155 bool ItemEntity::is_melee_ammo() const
157 return this->bi_key.is_melee_ammo();
161 * @brief アイテムが装備可能であるかを返す / Wearable including all weapon, all armour, bow, light source, amulet, and ring
162 * @return 装備可能ならばTRUEを返す
164 bool ItemEntity::is_wearable() const
166 return this->bi_key.is_wearable();
170 * @brief アイテムが装備品であるかを返す(ItemEntity::is_wearableに矢弾を含む) / Equipment including all wearable objects and ammo
171 * @return 装備品ならばtrueを返す
173 bool ItemEntity::is_equipment() const
175 return this->bi_key.is_equipement();
179 * @brief 武器匠の「武器」鑑定対象になるかを判定する。/ Hook to specify "weapon"
180 * @return 対象になるならtrueを返す。
182 bool ItemEntity::is_orthodox_melee_weapons() const
184 return this->bi_key.is_orthodox_melee_weapon();
188 * @brief 修復対象となる壊れた武器かを判定する。 / Hook to specify "broken weapon"
189 * @return 修復対象になるならTRUEを返す。
191 bool ItemEntity::is_broken_weapon() const
193 return this->bi_key.is_broken_weapon();
197 * @brief アイテムが投射可能な武器かどうかを返す。
198 * @return 投射可能な武器ならばtrue
200 bool ItemEntity::is_throwable() const
202 return this->bi_key.is_throwable();
206 * @brief アイテムがどちらの手にも装備できる武器かどうかの判定
207 * @return 左右両方の手で装備できるならばtrueを返す。
209 bool ItemEntity::is_wieldable_in_etheir_hand() const
211 return this->bi_key.is_wieldable_in_etheir_hand();
215 * @brief アイテムが強化不能武器であるかを返す / Poison needle can not be enchanted
216 * @return 強化不能ならばtrueを返す
218 bool ItemEntity::refuse_enchant_weapon() const
220 return this->bi_key == BaseitemKey(ItemKindType::SWORD, SV_POISON_NEEDLE);
224 * @brief アイテムが強化可能武器であるかを返す /
225 * Check if an object is weapon (including bows and ammo) and allows enchantment
226 * @return 強化可能ならばtrueを返す
228 bool ItemEntity::allow_enchant_weapon() const
230 return this->is_weapon_ammo() && !this->refuse_enchant_weapon();
234 * @brief アイテムが強化可能な近接武器であるかを返す /
235 * Check if an object is melee weapon and allows enchantment
236 * @return 強化可能な近接武器ならばtrueを返す
238 bool ItemEntity::allow_enchant_melee_weapon() const
240 return this->is_melee_weapon() && !this->refuse_enchant_weapon();
244 * @brief アイテムが両手持ち可能な武器かを返す /
245 * Check if an object is melee weapon and allows wielding with two-hands
246 * @return 両手持ち可能ならばTRUEを返す
248 bool ItemEntity::allow_two_hands_wielding() const
250 return this->is_melee_weapon() && ((this->weight > 99) || (this->bi_key.tval() == ItemKindType::POLEARM));
254 * @brief アイテムが矢弾として使用できるかどうかを返す / Check if an object is ammo
255 * @return 矢弾として使えるならばtrueを返す
257 bool ItemEntity::is_ammo() const
259 return this->bi_key.is_ammo();
263 * @brief 対象のアイテムが矢やクロスボウの矢の材料になるかを返す。/
264 * Hook to determine if an object is contertible in an arrow/bolt
265 * @return 材料にできるならtrueを返す
267 bool ItemEntity::is_convertible() const
269 const auto tval = this->bi_key.tval();
270 auto is_convertible = (tval == ItemKindType::JUNK) || (tval == ItemKindType::SKELETON);
271 is_convertible |= this->bi_key == BaseitemKey(ItemKindType::CORPSE, SV_SKELETON);
272 return is_convertible;
275 bool ItemEntity::is_lance() const
277 auto is_lance = this->bi_key == BaseitemKey(ItemKindType::POLEARM, SV_LANCE);
278 is_lance |= this->bi_key == BaseitemKey(ItemKindType::POLEARM, SV_HEAVY_LANCE);
283 * @brief アイテムが防具として装備できるかどうかを返す
284 * @return 防具として装備できるならばtrueを返す
286 bool ItemEntity::is_protector() const
288 return this->bi_key.is_protector();
292 * @brief アイテムがオーラを纏える防具かどうかを返す
293 * @return オーラを纏えるならばtrueを返す
295 bool ItemEntity::can_be_aura_protector() const
297 return this->bi_key.can_be_aura_protector();
301 * @brief アイテムがレアアイテムかどうかを返す /
302 * Rare weapons/aromors including Blade of Chaos, Dragon armors, etc.
303 * @return レアアイテムならばTRUEを返す
305 bool ItemEntity::is_rare() const
307 return this->bi_key.is_rare();
311 * @brief アイテムがエゴアイテムかどうかを返す
312 * @return エゴアイテムならばtrueを返す
314 bool ItemEntity::is_ego() const
316 return this->ego_idx != EgoType::NONE;
320 * @brief アイテムが鍛冶師のエッセンス付加済みかを返す /
321 * Check if an object is made by a smith's special ability
322 * @return エッセンス付加済みならばTRUEを返す
324 bool ItemEntity::is_smith() const
326 return Smith::object_effect(this) || Smith::object_activation(this);
330 * @brief アイテムが固定アーティファクトもしくはランダムアーティファクトであるかを返す /
331 * Check if an object is artifact
332 * @return 固定アーティファクトもしくはランダムアーティファクトならばtrueを返す
334 bool ItemEntity::is_fixed_or_random_artifact() const
336 return this->is_fixed_artifact() || this->randart_name;
340 * @brief アイテムが固定アーティファクトかを返す /
341 * Check if an object is fixed artifact
342 * @return 固定アーティファクトならばtrueを返す
344 bool ItemEntity::is_fixed_artifact() const
346 return !this->is_specific_artifact(FixedArtifactId::NONE);
350 * @brief アイテムがランダムアーティファクトかを返す /
351 * Check if an object is random artifact
352 * @return ランダムアーティファクトならばtrueを返す
354 bool ItemEntity::is_random_artifact() const
356 return this->is_fixed_or_random_artifact() && !this->is_fixed_artifact();
360 * @brief アイテムが通常のアイテム(アーティファクト、エゴ、鍛冶師エッセンス付加いずれでもない)かを返す /
361 * Check if an object is neither artifact, ego, nor 'smith' object
362 * @return 通常のアイテムならばtrueを返す
364 bool ItemEntity::is_nameless() const
366 return !this->is_fixed_or_random_artifact() && !this->is_ego() && !this->is_smith();
369 bool ItemEntity::is_valid() const
371 return this->bi_id != 0;
374 bool ItemEntity::is_broken() const
376 return any_bits(this->ident, IDENT_BROKEN);
379 bool ItemEntity::is_cursed() const
381 return this->curse_flags.any();
384 bool ItemEntity::is_held_by_monster() const
386 return this->held_m_idx != 0;
390 * Determine if a given inventory item is "known"
391 * Test One -- Check for special "known" tag
392 * Test Two -- Check for "Easy Know" + "Aware"
394 bool ItemEntity::is_known() const
396 const auto &baseitem = this->get_baseitem();
397 return any_bits(this->ident, IDENT_KNOWN) || (baseitem.easy_know && baseitem.aware);
400 bool ItemEntity::is_fully_known() const
402 return any_bits(this->ident, IDENT_FULL_KNOWN);
406 * @brief 与えられたオブジェクトのベースアイテムが鑑定済かを返す / Determine if a given inventory item is "aware"
409 bool ItemEntity::is_aware() const
411 return this->get_baseitem().aware;
415 * Determine if a given inventory item is "tried"
417 bool ItemEntity::is_tried() const
419 return this->get_baseitem().tried;
423 * @brief アイテムが薬であるかを返す
424 * @return オブジェクトが薬ならばtrueを返す
426 bool ItemEntity::is_potion() const
428 return this->bi_key.tval() == ItemKindType::POTION;
432 * @brief アイテムをプレイヤーが読むことができるかを判定する /
433 * Hook to determine if an object is readable
434 * @return 読むことが可能ならばtrueを返す
436 bool ItemEntity::is_readable() const
438 const auto tval = this->bi_key.tval();
439 auto can_read = tval == ItemKindType::SCROLL;
440 can_read |= tval == ItemKindType::PARCHMENT;
441 can_read |= this->is_specific_artifact(FixedArtifactId::GHB);
442 can_read |= this->is_specific_artifact(FixedArtifactId::POWER);
447 * @brief アイテムがランタンの燃料になるかどうかを判定する
448 * An "item_tester_hook" for refilling lanterns
449 * @return オブジェクトがランタンの燃料になるならばTRUEを返す
451 bool ItemEntity::can_refill_lantern() const
453 const auto tval = this->bi_key.tval();
454 return (tval == ItemKindType::FLASK) || (this->bi_key == BaseitemKey(ItemKindType::LITE, SV_LITE_LANTERN));
458 * @brief アイテムが松明に束ねられるかどうかを判定する
459 * An "item_tester_hook" for refilling torches
460 * @return オブジェクトが松明に束ねられるならばTRUEを返す
462 bool ItemEntity::can_refill_torch() const
464 return this->bi_key == BaseitemKey(ItemKindType::LITE, SV_LITE_TORCH);
468 * @brief 魔力充填が可能なアイテムかどうか判定する
469 * @return 魔力充填が可能ならばTRUEを返す
471 bool ItemEntity::can_recharge() const
473 return this->bi_key.can_recharge();
477 * @brief 悪魔領域のグレーターデーモン召喚に利用可能な死体かどうかを返す。 / An "item_tester_hook" for offer
478 * @return 生贄に使用可能な死体ならばTRUEを返す。
480 bool ItemEntity::is_offerable() const
482 if (this->bi_key != BaseitemKey(ItemKindType::CORPSE, SV_CORPSE)) {
486 return angband_strchr("pht", monraces_info[i2enum<MonsterRaceId>(this->pval)].d_char) != nullptr;
490 * @brief アイテムをプレイヤーが魔道具として発動できるかを判定する /
491 * Hook to determine if an object is activatable
492 * @return 魔道具として発動可能ならばTRUEを返す
494 bool ItemEntity::is_activatable() const
496 if (!this->is_known()) {
500 const auto flags = this->get_flags();
501 return flags.has(TR_ACTIVATE);
505 * @brief アイテムが燃料として使えるかを判定する
508 bool ItemEntity::is_fuel() const
510 auto is_fuel = this->bi_key == BaseitemKey(ItemKindType::LITE, SV_LITE_TORCH);
511 is_fuel |= this->bi_key == BaseitemKey(ItemKindType::LITE, SV_LITE_LANTERN);
512 is_fuel |= this->bi_key == BaseitemKey(ItemKindType::FLASK, SV_FLASK_OIL);
517 * @brief アイテムが魔法書かどうかを判定する
520 bool ItemEntity::is_spell_book() const
522 return this->bi_key.is_spell_book();
526 * @brief アイテムが同一の命中値上昇及びダメージ上昇があるかを判定する
528 * @details 鍛冶師が篭手に殺戮エッセンスを付加した場合のみこの判定に意味がある
530 bool ItemEntity::is_glove_same_temper(const ItemEntity *j_ptr) const
532 if (!this->is_smith() || !j_ptr->is_smith()) {
536 if (this->smith_hit != j_ptr->smith_hit) {
540 if (this->smith_damage != j_ptr->smith_damage) {
548 * @brief アイテムが「2つの~~」と重ねられるかを一般的に判定する
550 * @details 個別のアイテムによっては別途条件があるが、それはこの関数では判定しない
552 bool ItemEntity::can_pile(const ItemEntity *j_ptr) const
554 if (this->is_known() != j_ptr->is_known()) {
558 if (this->feeling != j_ptr->feeling) {
562 if (this->to_h != j_ptr->to_h) {
566 if (this->to_d != j_ptr->to_d) {
570 if (this->to_a != j_ptr->to_a) {
574 if (this->pval != j_ptr->pval) {
578 if (this->is_fixed_or_random_artifact() || j_ptr->is_fixed_or_random_artifact()) {
582 if (this->ego_idx != j_ptr->ego_idx) {
586 if (this->timeout || j_ptr->timeout) {
590 if (this->ac != j_ptr->ac) {
594 if (this->dd != j_ptr->dd) {
598 if (this->ds != j_ptr->ds) {
602 if (Smith::object_effect(this) != Smith::object_effect(j_ptr)) {
606 if (Smith::object_activation(this) != Smith::object_activation(j_ptr)) {
615 * @details 未鑑定名のあるアイテム (薬等)は、未鑑定名の割り当てられた色を返す
616 * 未鑑定名のないアイテム (魔法書等)はベースアイテム定義そのままを返す
617 * その中でモンスターの死体以外は、ベースアイテムの色を返す
618 * モンスターの死体は、元モンスターの色を返す
619 * 異常アイテム (「何か」)の場合、ベースアイテム定義に基づき黒を返す
621 TERM_COLOR ItemEntity::get_color() const
623 const auto &baseitem = this->get_baseitem();
624 const auto flavor = baseitem.flavor;
626 return baseitems_info[flavor].x_attr;
629 auto has_attr = !this->is_valid();
630 has_attr |= this->bi_key != BaseitemKey(ItemKindType::CORPSE, SV_CORPSE);
631 has_attr |= baseitem.x_attr != TERM_DARK;
633 return baseitem.x_attr;
636 return monraces_info[i2enum<MonsterRaceId>(this->pval)].x_attr;
640 * @brief アイテムシンボルを取得する
641 * @details 未鑑定名のないアイテム (魔法書等)はベースアイテム定義そのまま
642 * 未鑑定名のあるアイテム (薬等)は、未鑑定名の割り当てられたシンボル
643 * 以上について、設定で変更しているシンボルならばそれを、していないならば定義シンボルを返す
645 char ItemEntity::get_symbol() const
647 const auto &baseitem = this->get_baseitem();
648 const auto flavor = baseitem.flavor;
649 return flavor ? baseitems_info[flavor].x_char : baseitem.x_char;
653 * @brief アイテム価格算出のメインルーチン
654 * @return オブジェクトの判明している現価格
656 int ItemEntity::get_price() const
659 const auto is_worthless = this->is_broken() || this->is_cursed();
660 if (this->is_known()) {
665 value = object_value_real(this);
667 if (any_bits(this->ident, IDENT_SENSE) && is_worthless) {
671 value = this->get_baseitem_price();
674 if (this->discount) {
675 value -= (value * this->discount / 100L);
682 * @brief 未鑑定なベースアイテムの基本価格を返す
683 * @return オブジェクトの未鑑定価格
685 int ItemEntity::get_baseitem_price() const
687 if (this->is_aware()) {
688 return this->get_baseitem().cost;
691 switch (this->bi_key.tval()) {
692 case ItemKindType::FOOD:
694 case ItemKindType::POTION:
695 case ItemKindType::SCROLL:
697 case ItemKindType::STAFF:
699 case ItemKindType::WAND:
701 case ItemKindType::ROD:
703 case ItemKindType::RING:
704 case ItemKindType::AMULET:
706 case ItemKindType::FIGURINE:
707 return this->calc_figurine_value();
708 case ItemKindType::CAPTURE:
709 return this->calc_capture_value();
715 int ItemEntity::calc_figurine_value() const
717 auto figure_r_idx = i2enum<MonsterRaceId>(this->pval);
718 auto level = monraces_info[figure_r_idx].level;
724 return 1000 + (level - 20) * 150;
728 return 2500 + (level - 30) * 350;
732 return 6000 + (level - 40) * 800;
735 return 14000 + (level - 50) * 2000;
738 int ItemEntity::calc_capture_value() const
740 auto capture_r_idx = i2enum<MonsterRaceId>(this->pval);
741 if (!MonsterRace(capture_r_idx).is_valid()) {
745 return (monraces_info[capture_r_idx].level) * 50 + 1000;
748 bool ItemEntity::is_specific_artifact(FixedArtifactId id) const
750 return this->fixed_artifact_idx == id;
753 bool ItemEntity::has_unidentified_name() const
755 return this->bi_key.has_unidentified_name();
758 ItemKindType ItemEntity::get_arrow_kind() const
760 return this->bi_key.get_arrow_kind();
763 bool ItemEntity::is_wand_rod() const
765 return this->bi_key.is_wand_rod();
768 bool ItemEntity::is_wand_staff() const
770 return this->bi_key.is_wand_staff();
773 short ItemEntity::get_bow_energy() const
775 return this->bi_key.get_bow_energy();
778 int ItemEntity::get_arrow_magnification() const
780 return this->bi_key.get_arrow_magnification();
783 bool ItemEntity::is_aiming_rod() const
785 return this->bi_key.is_aiming_rod();
788 bool ItemEntity::is_lite_requiring_fuel() const
790 return this->bi_key.is_lite_requiring_fuel();
793 bool ItemEntity::is_junk() const
795 return this->bi_key.is_junk();
798 bool ItemEntity::is_armour() const
800 return this->bi_key.is_armour();
803 bool ItemEntity::is_cross_bow() const
805 return this->bi_key.is_cross_bow();
808 bool ItemEntity::is_inscribed() const
810 return this->inscription != std::nullopt;
814 * @brief オブジェクトから発動効果構造体を取得する。
815 * @return 発動効果構造体 (なかったら無効イテレータ)
817 std::vector<activation_type>::const_iterator ItemEntity::find_activation_info() const
819 const auto index = this->get_activation_index();
820 return std::find_if(activation_info.begin(), activation_info.end(), [index](const auto &x) { return x.index == index; });
823 bool ItemEntity::has_activation() const
825 return this->get_activation_index() != RandomArtActType::NONE;
828 BaseitemInfo &ItemEntity::get_baseitem() const
830 return baseitems_info[this->bi_id];
833 EgoItemDefinition &ItemEntity::get_ego() const
835 return egos_info.at(this->ego_idx);
838 ArtifactType &ItemEntity::get_fixed_artifact() const
840 return ArtifactsInfo::get_instance().get_artifact(this->fixed_artifact_idx);
843 TrFlags ItemEntity::get_flags() const
845 const auto &baseitem = this->get_baseitem();
846 auto flags = baseitem.flags;
848 if (this->is_fixed_artifact()) {
849 flags = this->get_fixed_artifact().flags;
852 if (this->is_ego()) {
853 const auto &ego = this->get_ego();
854 flags.set(ego.flags);
855 this->modify_ego_lite_flags(flags);
858 flags.set(this->art_flags);
859 if (auto effect = Smith::object_effect(this); effect) {
860 auto tr_flags = Smith::get_effect_tr_flags(*effect);
864 if (Smith::object_activation(this)) {
865 flags.set(TR_ACTIVATE);
871 TrFlags ItemEntity::get_flags_known() const
874 if (!this->is_aware()) {
878 const auto &baseitem = this->get_baseitem();
879 flags = baseitem.flags;
880 if (!this->is_known()) {
884 if (this->is_ego()) {
885 const auto &ego = this->get_ego();
886 flags.set(ego.flags);
887 this->modify_ego_lite_flags(flags);
890 if (this->is_fully_known()) {
891 if (this->is_fixed_artifact()) {
892 flags = this->get_fixed_artifact().flags;
895 flags.set(this->art_flags);
898 if (auto effect = Smith::object_effect(this); effect) {
899 auto tr_flags = Smith::get_effect_tr_flags(*effect);
903 if (Smith::object_activation(this)) {
904 flags.set(TR_ACTIVATE);
910 std::string ItemEntity::build_activation_description(const activation_type &act) const
913 case RandomArtActType::NONE:
915 case RandomArtActType::BR_FIRE:
916 if (this->bi_key == BaseitemKey(ItemKindType::RING, SV_RING_FLAMES)) {
917 return _("火炎のブレス (200) と火への耐性", "breathe fire (200) and resist fire");
921 case RandomArtActType::BR_COLD:
922 if (this->bi_key == BaseitemKey(ItemKindType::RING, SV_RING_ICE)) {
923 return _("冷気のブレス (200) と冷気への耐性", "breathe cold (200) and resist cold");
927 case RandomArtActType::BR_DRAGON:
928 return this->build_activation_description_dragon_breath();
929 case RandomArtActType::AGGRAVATE:
930 if (this->is_specific_artifact(FixedArtifactId::HYOUSIGI)) {
931 return _("拍子木を打ちならす", "beat wooden clappers");
935 case RandomArtActType::ACID_BALL_AND_RESISTANCE:
936 return _("アシッド・ボール (100) と酸への耐性", "ball of acid (100) and resist acid");
937 case RandomArtActType::FIRE_BALL_AND_RESISTANCE:
938 return _("ファイア・ボール (100) と火への耐性", "ball of fire (100) and resist fire");
939 case RandomArtActType::COLD_BALL_AND_RESISTANCE:
940 return _("アイス・ボール (100) と冷気への耐性", "ball of cold (100) and resist cold");
941 case RandomArtActType::ELEC_BALL_AND_RESISTANCE:
942 return _("サンダー・ボール (100) と電撃への耐性", "ball of elec (100) and resist elec");
943 case RandomArtActType::POIS_BALL_AND_RESISTANCE:
944 return _("ポイズン・ボール (100) と毒への耐性", "ball of poison (100) and resist elec");
945 case RandomArtActType::RESIST_ACID:
946 return _("一時的な酸への耐性", "temporary resist acid");
947 case RandomArtActType::RESIST_FIRE:
948 return _("一時的な火への耐性", "temporary resist fire");
949 case RandomArtActType::RESIST_COLD:
950 return _("一時的な冷気への耐性", "temporary resist cold");
951 case RandomArtActType::RESIST_ELEC:
952 return _("一時的な電撃への耐性", "temporary resist elec");
953 case RandomArtActType::RESIST_POIS:
954 return _("一時的な毒への耐性", "temporary resist elec");
960 std::string ItemEntity::build_timeout_description(const activation_type &act) const
962 const auto constant = act.timeout.constant;
963 const auto dice = act.timeout.dice;
964 if (constant == 0 && dice == 0) {
965 return _("いつでも", "every turn");
969 std::stringstream ss;
970 ss << _("", "every ");
982 ss << _(" ターン毎", " turns");
986 std::stringstream ss;
988 case RandomArtActType::BR_FIRE:
989 ss << _("", "every ") << (this->bi_key == BaseitemKey(ItemKindType::RING, SV_RING_FLAMES) ? 200 : 250) << _(" ターン毎", " turns");
991 case RandomArtActType::BR_COLD:
992 ss << _("", "every ") << (this->bi_key == BaseitemKey(ItemKindType::RING, SV_RING_ICE) ? 200 : 250) << _(" ターン毎", " turns");
994 case RandomArtActType::TERROR:
995 return _("3*(レベル+10) ターン毎", "every 3 * (level+10) turns");
996 case RandomArtActType::MURAMASA:
997 return _("確率50%で壊れる", "(destroyed 50%)");
1004 * @brief オブジェクトを鑑定済にする
1006 void ItemEntity::mark_as_known()
1008 this->feeling = FEEL_NONE;
1009 this->ident &= ~(IDENT_SENSE);
1010 this->ident &= ~(IDENT_EMPTY);
1011 this->ident |= (IDENT_KNOWN);
1015 * @brief オブジェクトを試行済にする
1017 void ItemEntity::mark_as_tried()
1019 this->get_baseitem().mark_as_tried();
1023 * @brief エゴ光源のフラグを修正する
1025 * 寿命のある光源で寿命が0ターンの時、光源エゴアイテムに起因するフラグは
1026 * 灼熱エゴの火炎耐性を除き付与されないようにする。
1028 * @param flags フラグ情報を受け取る配列
1030 void ItemEntity::modify_ego_lite_flags(TrFlags &flags) const
1032 if (this->bi_key.tval() != ItemKindType::LITE) {
1036 if (!this->is_lite_requiring_fuel() || this->fuel != 0) {
1040 switch (this->ego_idx) {
1041 case EgoType::LITE_AURA_FIRE:
1042 flags.reset(TR_SH_FIRE);
1044 case EgoType::LITE_INFRA:
1045 flags.reset(TR_INFRA);
1047 case EgoType::LITE_EYE:
1048 flags.reset({ TR_RES_BLIND, TR_SEE_INVIS });
1056 * @brief オブジェクトから能力発動IDを取得する。
1057 * @details いくつかのケースで定義されている発動効果から、
1058 * 鍛冶師による付与>固定アーティファクト>エゴ>ランダムアーティファクト>ベースアイテムの優先順位で走査していく。
1059 * @param o_ptr 対象のオブジェクト構造体ポインタ
1060 * @return 発動効果のIDを返す
1062 RandomArtActType ItemEntity::get_activation_index() const
1064 if (auto act_idx = Smith::object_activation(this); act_idx) {
1068 if (this->is_fixed_artifact()) {
1069 const auto &artifact = this->get_fixed_artifact();
1070 if (artifact.flags.has(TR_ACTIVATE)) {
1071 return artifact.act_idx;
1075 if (this->is_ego()) {
1076 const auto &ego = this->get_ego();
1077 if (ego.flags.has(TR_ACTIVATE)) {
1082 if (!this->is_random_artifact()) {
1083 const auto &baseitem = this->get_baseitem();
1084 if (baseitem.flags.has(TR_ACTIVATE)) {
1085 return baseitem.act_idx;
1089 return this->activation_id;
1093 * @brief アイテムの発動効果名称を返す (ドラゴンブレス)
1096 std::string ItemEntity::build_activation_description_dragon_breath() const
1098 std::stringstream ss;
1099 ss << _("", "breathe ");
1101 const auto flags = this->get_flags();
1102 for (auto i = 0; dragonbreath_info[i].flag != 0; i++) {
1103 if (flags.has(dragonbreath_info[i].flag)) {
1108 ss << dragonbreath_info[i].name;
1113 ss << _("のブレス(250)", " (250)");