OSDN Git Service

Merge pull request #3387 from habu1010/feature/throw-exception-macro
[hengbandforosx/hengbandosx.git] / src / player-info / alignment.cpp
1 #include "player-info/alignment.h"
2 #include "artifact/fixed-art-types.h"
3 #include "avatar/avatar.h"
4 #include "game-option/text-display-options.h"
5 #include "inventory/inventory-slot-types.h"
6 #include "monster-race/monster-race.h"
7 #include "monster-race/race-flags3.h"
8 #include "monster/monster-info.h"
9 #include "monster/monster-status.h"
10 #include "player-info/equipment-info.h"
11 #include "player-info/race-info.h"
12 #include "system/angband-exceptions.h"
13 #include "system/floor-type-definition.h"
14 #include "system/item-entity.h"
15 #include "system/monster-entity.h"
16 #include "system/monster-race-info.h"
17 #include "system/player-type-definition.h"
18 #include "util/bit-flags-calculator.h"
19
20 PlayerAlignment::PlayerAlignment(PlayerType *player_ptr)
21 {
22     this->player_ptr = player_ptr;
23 }
24
25 /*!
26  * @brief プレイヤーの抽象的善悪アライメントの表記を返す。 / Return alignment title
27  * @param with_value 徳の情報と一緒に表示する時だけtrue
28  * @return アライメントの表記を返す。
29  */
30 std::string PlayerAlignment::get_alignment_description(bool with_value)
31 {
32     auto s = alignment_label();
33     if (with_value || show_actual_value) {
34         return format(_("%s(%ld)", "%s (%ld)"), s, static_cast<long>(this->player_ptr->alignment));
35     }
36
37     return s;
38 }
39
40 /*
41  * @brief アライメント情報の更新
42  * @param なし
43  */
44 void PlayerAlignment::update_alignment()
45 {
46     this->reset_alignment();
47     auto *floor_ptr = this->player_ptr->current_floor_ptr;
48     for (MONSTER_IDX m_idx = floor_ptr->m_max - 1; m_idx >= 1; m_idx--) {
49         auto *m_ptr = &floor_ptr->m_list[m_idx];
50         if (!m_ptr->is_valid()) {
51             continue;
52         }
53         auto *r_ptr = &monraces_info[m_ptr->r_idx];
54
55         if (!m_ptr->is_pet()) {
56             continue;
57         }
58
59         if (r_ptr->kind_flags.has(MonsterKindType::GOOD)) {
60             this->bias_good_alignment(r_ptr->level);
61         }
62
63         if (r_ptr->kind_flags.has(MonsterKindType::EVIL)) {
64             this->bias_evil_alignment(r_ptr->level);
65         }
66     }
67
68     switch (this->player_ptr->mimic_form) {
69     case MimicKindType::NONE:
70         switch (this->player_ptr->prace) {
71         case PlayerRaceType::ARCHON:
72             this->bias_good_alignment(200);
73             break;
74         case PlayerRaceType::BALROG:
75             this->bias_evil_alignment(200);
76             break;
77         default:
78             break;
79         }
80
81         break;
82     case MimicKindType::DEMON:
83         this->bias_evil_alignment(200);
84         break;
85     case MimicKindType::DEMON_LORD:
86         this->bias_evil_alignment(200);
87         break;
88     case MimicKindType::VAMPIRE:
89         break;
90     default:
91         THROW_EXCEPTION(std::logic_error, "Invalid MimicKindType was specified!");
92     }
93
94     for (int i = 0; i < 2; i++) {
95         const auto &wielding_weapon = this->player_ptr->inventory_list[INVEN_MAIN_HAND + i];
96         if (!has_melee_weapon(this->player_ptr, INVEN_MAIN_HAND + i) || !wielding_weapon.is_specific_artifact(FixedArtifactId::IRON_BALL)) {
97             continue;
98         }
99
100         this->bias_evil_alignment(1000);
101     }
102
103     int j = 0;
104     int neutral[2];
105     for (int i = 0; i < 8; i++) {
106         switch (this->player_ptr->vir_types[i]) {
107         case Virtue::JUSTICE:
108             this->bias_good_alignment(this->player_ptr->virtues[i] * 2);
109             break;
110         case Virtue::CHANCE:
111             break;
112         case Virtue::NATURE:
113         case Virtue::HARMONY:
114             neutral[j++] = i;
115             break;
116         case Virtue::UNLIFE:
117             this->bias_evil_alignment(this->player_ptr->virtues[i]);
118             break;
119         default:
120             this->bias_good_alignment(this->player_ptr->virtues[i]);
121             break;
122         }
123     }
124
125     for (int i = 0; i < j; i++) {
126         if (this->player_ptr->alignment > 0) {
127             this->bias_evil_alignment(this->player_ptr->virtues[neutral[i]] / 2);
128             if (this->player_ptr->alignment < 0) {
129                 this->reset_alignment();
130             }
131         } else if (this->player_ptr->alignment < 0) {
132             this->bias_good_alignment(this->player_ptr->virtues[neutral[i]] / 2);
133             if (this->player_ptr->alignment > 0) {
134                 this->reset_alignment();
135             }
136         }
137     }
138 }
139
140 void PlayerAlignment::bias_good_alignment(int value)
141 {
142     this->player_ptr->alignment += value;
143 }
144
145 void PlayerAlignment::bias_evil_alignment(int value)
146 {
147     this->player_ptr->alignment -= value;
148 }
149
150 void PlayerAlignment::reset_alignment()
151 {
152     this->player_ptr->alignment = 0;
153 }
154
155 /*!
156  * @brief プレイヤーの抽象的善悪アライメントの表記名のみを返す。 / Return only alignment title
157  * @param player_ptr プレイヤーへの参照ポインタ。
158  * @return アライメントの表記名
159  */
160 concptr PlayerAlignment::alignment_label()
161 {
162     if (this->player_ptr->alignment > 150) {
163         return _("大善", "Lawful");
164     } else if (this->player_ptr->alignment > 50) {
165         return _("中善", "Good");
166     } else if (this->player_ptr->alignment > 10) {
167         return _("小善", "Neutral Good");
168     } else if (this->player_ptr->alignment > -11) {
169         return _("中立", "Neutral");
170     } else if (this->player_ptr->alignment > -51) {
171         return _("小悪", "Neutral Evil");
172     } else if (this->player_ptr->alignment > -151) {
173         return _("中悪", "Evil");
174     } else {
175         return _("大悪", "Chaotic");
176     }
177 }