OSDN Git Service

[Refactor] struct player_type を class PlayerType に置換。
[hengbandforosx/hengbandosx.git] / src / monster-floor / monster-object.cpp
1 /*!
2  * @brief モンスターが移動した結果、床のアイテムに重なった時の処理と、モンスターがアイテムを落とす処理
3  * @date 2020/03/07
4  * @author Hourier
5  */
6
7 #include "monster-floor/monster-object.h"
8 #include "flavor/flavor-describer.h"
9 #include "floor/floor-object.h"
10 #include "floor/cave.h"
11 #include "floor/geometry.h"
12 #include "monster-race/monster-race.h"
13 #include "monster-race/race-flags-resistance.h"
14 #include "monster-race/race-flags2.h"
15 #include "monster-race/race-flags3.h"
16 #include "monster/monster-describer.h"
17 #include "monster/monster-description-types.h"
18 #include "monster/monster-info.h"
19 #include "monster/monster-processor-util.h"
20 #include "monster/smart-learn-types.h"
21 #include "object-enchant/tr-types.h"
22 #include "object/object-flags.h"
23 #include "object/object-mark-types.h"
24 #include "system/floor-type-definition.h"
25 #include "system/grid-type-definition.h"
26 #include "system/monster-race-definition.h"
27 #include "system/monster-type-definition.h"
28 #include "system/object-type-definition.h"
29 #include "system/player-type-definition.h"
30 #include "util/bit-flags-calculator.h"
31 #include "view/display-messages.h"
32
33 /*!
34  * @brief オブジェクトのフラグを更新する
35  */
36 static void update_object_flags(const TrFlags &flgs, BIT_FLAGS *flg2, BIT_FLAGS *flg3, BIT_FLAGS *flgr)
37 {
38     if (flgs.has(TR_SLAY_DRAGON))
39         *flg3 |= (RF3_DRAGON);
40     if (flgs.has(TR_KILL_DRAGON))
41         *flg3 |= (RF3_DRAGON);
42     if (flgs.has(TR_SLAY_TROLL))
43         *flg3 |= (RF3_TROLL);
44     if (flgs.has(TR_KILL_TROLL))
45         *flg3 |= (RF3_TROLL);
46     if (flgs.has(TR_SLAY_GIANT))
47         *flg3 |= (RF3_GIANT);
48     if (flgs.has(TR_KILL_GIANT))
49         *flg3 |= (RF3_GIANT);
50     if (flgs.has(TR_SLAY_ORC))
51         *flg3 |= (RF3_ORC);
52     if (flgs.has(TR_KILL_ORC))
53         *flg3 |= (RF3_ORC);
54     if (flgs.has(TR_SLAY_DEMON))
55         *flg3 |= (RF3_DEMON);
56     if (flgs.has(TR_KILL_DEMON))
57         *flg3 |= (RF3_DEMON);
58     if (flgs.has(TR_SLAY_UNDEAD))
59         *flg3 |= (RF3_UNDEAD);
60     if (flgs.has(TR_KILL_UNDEAD))
61         *flg3 |= (RF3_UNDEAD);
62     if (flgs.has(TR_SLAY_ANIMAL))
63         *flg3 |= (RF3_ANIMAL);
64     if (flgs.has(TR_KILL_ANIMAL))
65         *flg3 |= (RF3_ANIMAL);
66     if (flgs.has(TR_SLAY_EVIL))
67         *flg3 |= (RF3_EVIL);
68     if (flgs.has(TR_KILL_EVIL))
69         *flg3 |= (RF3_EVIL);
70     if (flgs.has(TR_SLAY_GOOD))
71         *flg3 |= (RF3_GOOD);
72     if (flgs.has(TR_KILL_GOOD))
73         *flg3 |= (RF3_GOOD);
74     if (flgs.has(TR_SLAY_HUMAN))
75         *flg2 |= (RF2_HUMAN);
76     if (flgs.has(TR_KILL_HUMAN))
77         *flg2 |= (RF2_HUMAN);
78     if (flgs.has(TR_BRAND_ACID))
79         *flgr |= (RFR_IM_ACID);
80     if (flgs.has(TR_BRAND_ELEC))
81         *flgr |= (RFR_IM_ELEC);
82     if (flgs.has(TR_BRAND_FIRE))
83         *flgr |= (RFR_IM_FIRE);
84     if (flgs.has(TR_BRAND_COLD))
85         *flgr |= (RFR_IM_COLD);
86     if (flgs.has(TR_BRAND_POIS))
87         *flgr |= (RFR_IM_POIS);
88 }
89
90 /*!
91  * @brief モンスターがアイテムを拾うか壊す処理
92  * @param player_ptr プレイヤーへの参照ポインタ
93  * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
94  * @param m_idx モンスターID
95  * @param o_ptr オブジェクトへの参照ポインタ
96  * @param is_special_object モンスターが拾えないアイテム (アーティファクト等)であればTRUE
97  * @param ny 移動後の、モンスターのY座標
98  * @param nx 移動後の、モンスターのX座標
99  * @param m_name モンスター名
100  * @param o_name アイテム名
101  * @param this_o_idx モンスターが乗ったオブジェクトID
102  */
103 static void monster_pickup_object(PlayerType *player_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx, object_type *o_ptr, bool is_special_object,
104     POSITION ny, POSITION nx, GAME_TEXT *m_name, GAME_TEXT *o_name, OBJECT_IDX this_o_idx)
105 {
106     monster_type *m_ptr = &player_ptr->current_floor_ptr->m_list[m_idx];
107     monster_race *r_ptr = &r_info[m_ptr->r_idx];
108     if (is_special_object) {
109         if (turn_flags_ptr->do_take && (r_ptr->flags2 & RF2_STUPID)) {
110             turn_flags_ptr->did_take_item = true;
111             if (m_ptr->ml && player_can_see_bold(player_ptr, ny, nx)) {
112                 msg_format(_("%^sは%sを拾おうとしたが、だめだった。", "%^s tries to pick up %s, but fails."), m_name, o_name);
113             }
114         }
115
116         return;
117     }
118
119     if (turn_flags_ptr->do_take) {
120         turn_flags_ptr->did_take_item = true;
121         if (player_can_see_bold(player_ptr, ny, nx)) {
122             msg_format(_("%^sが%sを拾った。", "%^s picks up %s."), m_name, o_name);
123         }
124
125         excise_object_idx(player_ptr->current_floor_ptr, this_o_idx);
126         o_ptr->marked &= OM_TOUCHED;
127         o_ptr->iy = o_ptr->ix = 0;
128         o_ptr->held_m_idx = m_idx;
129         m_ptr->hold_o_idx_list.add(player_ptr->current_floor_ptr, this_o_idx);
130         return;
131     }
132
133     if (is_pet(m_ptr))
134         return;
135
136     turn_flags_ptr->did_kill_item = true;
137     if (player_has_los_bold(player_ptr, ny, nx)) {
138         msg_format(_("%^sが%sを破壊した。", "%^s destroys %s."), m_name, o_name);
139     }
140
141     delete_object_idx(player_ptr, this_o_idx);
142 }
143
144 /*!
145  * @brief モンスターの移動に伴うオブジェクト処理 (アイテム破壊等)
146  * @param player_ptr プレイヤーへの参照ポインタ
147  * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
148  * @param m_idx モンスターID
149  * @param ny 移動後の、モンスターのY座標
150  * @param nx 移動後の、モンスターのX座標
151  */
152 void update_object_by_monster_movement(PlayerType *player_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx, POSITION ny, POSITION nx)
153 {
154     monster_type *m_ptr = &player_ptr->current_floor_ptr->m_list[m_idx];
155     monster_race *r_ptr = &r_info[m_ptr->r_idx];
156     grid_type *g_ptr;
157     g_ptr = &player_ptr->current_floor_ptr->grid_array[ny][nx];
158
159     turn_flags_ptr->do_take = (r_ptr->flags2 & RF2_TAKE_ITEM) != 0;
160     for (auto it = g_ptr->o_idx_list.begin(); it != g_ptr->o_idx_list.end();) {
161         BIT_FLAGS flg2 = 0L, flg3 = 0L, flgr = 0L;
162         GAME_TEXT m_name[MAX_NLEN], o_name[MAX_NLEN];
163         OBJECT_IDX this_o_idx = *it++;
164         object_type *o_ptr = &player_ptr->current_floor_ptr->o_list[this_o_idx];
165
166         if (turn_flags_ptr->do_take) {
167             /* Skip gold, corpse and statue */
168             if (o_ptr->tval == ItemKindType::GOLD || (o_ptr->tval == ItemKindType::CORPSE) || (o_ptr->tval == ItemKindType::STATUE))
169                 continue;
170         }
171
172         auto flgs = object_flags(o_ptr);
173         describe_flavor(player_ptr, o_name, o_ptr, 0);
174         monster_desc(player_ptr, m_name, m_ptr, MD_INDEF_HIDDEN);
175         update_object_flags(flgs, &flg2, &flg3, &flgr);
176
177         bool is_special_object = o_ptr->is_artifact() || ((r_ptr->flags3 & flg3) != 0) || ((r_ptr->flags2 & flg2) != 0)
178             || (((~(r_ptr->flagsr) & flgr) != 0) && !(r_ptr->flagsr & RFR_RES_ALL));
179         monster_pickup_object(player_ptr, turn_flags_ptr, m_idx, o_ptr, is_special_object, ny, nx, m_name, o_name, this_o_idx);
180     }
181 }
182
183 /*!
184  * @brief モンスターが盗みや拾いで確保していたアイテムを全てドロップさせる / Drop all items carried by a monster
185  * @param player_ptr プレイヤーへの参照ポインタ
186  * @param m_ptr モンスター参照ポインタ
187  */
188 void monster_drop_carried_objects(PlayerType *player_ptr, monster_type *m_ptr)
189 {
190     for (auto it = m_ptr->hold_o_idx_list.begin(); it != m_ptr->hold_o_idx_list.end();) {
191         object_type forge;
192         object_type *o_ptr;
193         object_type *q_ptr;
194         const OBJECT_IDX this_o_idx = *it++;
195         o_ptr = &player_ptr->current_floor_ptr->o_list[this_o_idx];
196         q_ptr = &forge;
197         q_ptr->copy_from(o_ptr);
198         q_ptr->held_m_idx = 0;
199         delete_object_idx(player_ptr, this_o_idx);
200         (void)drop_near(player_ptr, q_ptr, -1, m_ptr->fy, m_ptr->fx);
201     }
202
203     m_ptr->hold_o_idx_list.clear();
204 }