OSDN Git Service

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