OSDN Git Service

[Refactor] #929 Renamed get_virtues() to initialize_virtues()
[hengbandforosx/hengbandosx.git] / src / avatar / avatar-changer.cpp
1 /*
2  * @brief 敵への攻撃によって徳を変化させる処理
3  * @date 2021/08/05
4  * @author Hourier
5  */
6
7 #include "avatar/avatar-changer.h"
8 #include "dungeon/dungeon.h"
9 #include "monster-race/monster-race.h"
10 #include "monster-race/race-ability-mask.h"
11 #include "monster-race/race-flags1.h"
12 #include "monster-race/race-flags2.h"
13 #include "monster-race/race-flags3.h"
14 #include "monster-race/race-indice-types.h"
15 #include "player-info/avatar.h"
16 #include "system/floor-type-definition.h"
17 #include "system/monster-race-definition.h"
18 #include "system/monster-type-definition.h"
19 #include "system/player-type-definition.h"
20 #include "util/bit-flags-calculator.h"
21
22 AvatarChanger::AvatarChanger(player_type *target_ptr, monster_type *m_ptr)
23     : target_ptr(target_ptr)
24     , m_ptr(m_ptr)
25 {
26 }
27
28 void AvatarChanger::change_virtue()
29 {
30     this->change_virtue_non_beginner();
31     this->change_virtue_unique();
32     auto *r_ptr = &r_info[m_ptr->r_idx];
33     if (m_ptr->r_idx == MON_BEGGAR || m_ptr->r_idx == MON_LEPER) {
34         chg_virtue(this->target_ptr, V_COMPASSION, -1);
35     }
36
37     this->change_virtue_good_evil();
38     if (any_bits(r_ptr->flags3, RF3_UNDEAD) && any_bits(r_ptr->flags1, RF1_UNIQUE)) {
39         chg_virtue(this->target_ptr, V_VITALITY, 2);
40     }
41
42     this->change_virtue_revenge();
43     if (any_bits(r_ptr->flags2, RF2_MULTIPLY) && (r_ptr->r_akills > 1000) && one_in_(10)) {
44         chg_virtue(this->target_ptr, V_VALOUR, -1);
45     }
46
47     this->change_virtue_wild_thief();
48     this->change_virtue_good_animal();
49 }
50
51 void AvatarChanger::change_virtue_non_beginner()
52 {
53     auto *floor_ptr = this->target_ptr->current_floor_ptr;
54     auto *r_ptr = &r_info[m_ptr->r_idx];
55     if (d_info[this->target_ptr->dungeon_idx].flags.has(DF::BEGINNER)) {
56         return;
57     }
58
59     if ((floor_ptr->dun_level == 0) && !this->target_ptr->ambush_flag && !floor_ptr->inside_arena) {
60         chg_virtue(this->target_ptr, V_VALOUR, -1);
61     } else if (r_ptr->level > floor_ptr->dun_level) {
62         if (randint1(10) <= (r_ptr->level - floor_ptr->dun_level)) {
63             chg_virtue(this->target_ptr, V_VALOUR, 1);
64         }
65     }
66
67     if (r_ptr->level > 60) {
68         chg_virtue(this->target_ptr, V_VALOUR, 1);
69     }
70
71     if (r_ptr->level >= 2 * (this->target_ptr->lev + 1)) {
72         chg_virtue(this->target_ptr, V_VALOUR, 2);
73     }
74 }
75
76 void AvatarChanger::change_virtue_unique()
77 {
78     auto *r_ptr = &r_info[m_ptr->r_idx];
79     if (none_bits(r_ptr->flags1, RF1_UNIQUE)) {
80         return;
81     }
82
83     if (any_bits(r_ptr->flags3, RF3_EVIL | RF3_GOOD)) {
84         chg_virtue(this->target_ptr, V_HARMONY, 2);
85     }
86
87     if (any_bits(r_ptr->flags3, RF3_GOOD)) {
88         chg_virtue(this->target_ptr, V_UNLIFE, 2);
89         chg_virtue(this->target_ptr, V_VITALITY, -2);
90     }
91
92     if (one_in_(3)) {
93         chg_virtue(this->target_ptr, V_INDIVIDUALISM, -1);
94     }
95 }
96
97 /*
98  * @brief 攻撃を与えたモンスターが天使か悪魔だった場合、徳を変化させる
99  * @details 天使かつ悪魔だった場合、天使であることが優先される
100  */
101 void AvatarChanger::change_virtue_good_evil()
102 {
103     auto *floor_ptr = this->target_ptr->current_floor_ptr;
104     auto *r_ptr = &r_info[m_ptr->r_idx];
105     if (any_bits(r_ptr->flags3, RF3_GOOD) && ((r_ptr->level) / 10 + (3 * floor_ptr->dun_level) >= randint1(100))) {
106         chg_virtue(this->target_ptr, V_UNLIFE, 1);
107     }
108
109     if (any_bits(r_ptr->flags3, RF3_ANGEL)) {
110         if (any_bits(r_ptr->flags1, RF1_UNIQUE)) {
111             chg_virtue(this->target_ptr, V_FAITH, -2);
112         } else if ((r_ptr->level) / 10 + (3 * floor_ptr->dun_level) >= randint1(100)) {
113             auto change_value = any_bits(r_ptr->flags3, RF3_GOOD) ? -1 : 1;
114             chg_virtue(this->target_ptr, V_FAITH, change_value);
115         }
116
117         return;
118     }
119
120     if (any_bits(r_ptr->flags3, RF3_DEMON)) {
121         if (any_bits(r_ptr->flags1, RF1_UNIQUE)) {
122             chg_virtue(this->target_ptr, V_FAITH, 2);
123         } else if ((r_ptr->level) / 10 + (3 * floor_ptr->dun_level) >= randint1(100)) {
124             chg_virtue(this->target_ptr, V_FAITH, 1);
125         }
126     }
127 }
128
129 /*
130  * @brief 過去に@を殺したことがあるユニークにリゾンべを果たせたら徳を上げる
131  */
132 void AvatarChanger::change_virtue_revenge()
133 {
134     auto *floor_ptr = this->target_ptr->current_floor_ptr;
135     auto *r_ptr = &r_info[m_ptr->r_idx];
136     if (r_ptr->r_deaths == 0) {
137         return;
138     }
139
140     if (any_bits(r_ptr->flags1, RF1_UNIQUE)) {
141         chg_virtue(this->target_ptr, V_HONOUR, 10);
142         return;
143     }
144
145     if ((r_ptr->level) / 10 + (2 * floor_ptr->dun_level) >= randint1(100)) {
146         chg_virtue(this->target_ptr, V_HONOUR, 1);
147     }
148 }
149
150 /*
151  * @brief 盗み逃げをするモンスター及び地上のモンスターを攻撃した際に徳を変化させる
152  */
153 void AvatarChanger::change_virtue_wild_thief()
154 {
155     auto *floor_ptr = this->target_ptr->current_floor_ptr;
156     auto *r_ptr = &r_info[m_ptr->r_idx];
157     auto innocent = true;
158     auto thief = false;
159     for (auto i = 0; i < MAX_NUM_BLOWS; i++) {
160         if (r_ptr->blow[i].d_dice != 0) {
161             innocent = false;
162         }
163
164         if ((r_ptr->blow[i].effect == RBE_EAT_ITEM) || (r_ptr->blow[i].effect == RBE_EAT_GOLD)) {
165             thief = true;
166         }
167     }
168
169     if (r_ptr->level > 0) {
170         innocent = false;
171     }
172
173     if (thief) {
174         if (any_bits(r_ptr->flags1, RF1_UNIQUE)) {
175             chg_virtue(this->target_ptr, V_JUSTICE, 3);
176             return;
177         }
178
179         if (1 + ((r_ptr->level) / 10 + (2 * floor_ptr->dun_level)) >= randint1(100)) {
180             chg_virtue(this->target_ptr, V_JUSTICE, 1);
181         }
182
183         return;
184     }
185
186     if (innocent) {
187         chg_virtue(this->target_ptr, V_JUSTICE, -1);
188     }
189 }
190
191 /*
192  * @brief 邪悪でなく、魔法も持たない動物を攻撃した時に徳を下げる
193  */
194 void AvatarChanger::change_virtue_good_animal()
195 {
196     auto *r_ptr = &r_info[m_ptr->r_idx];
197     auto magic_ability_flags = r_ptr->ability_flags;
198     magic_ability_flags.reset(RF_ABILITY_NOMAGIC_MASK);
199     if (none_bits(r_ptr->flags3, RF3_ANIMAL) || any_bits(r_ptr->flags3, RF3_EVIL) || magic_ability_flags.any()) {
200         return;
201     }
202
203     if (one_in_(4)) {
204         chg_virtue(this->target_ptr, V_NATURE, -1);
205     }
206 }