OSDN Git Service

[Implement] #37285 能力低下ダメージの減衰式を追加 / Added attenuation caluclation for lose-base...
[hengband/hengband.git] / src / monster-attack / monster-attack-switcher.c
1 /*!
2  * @brief モンスターからプレーヤーへの直接攻撃をその種別において振り分ける
3  * @date 2020/05/31
4  * @author Hourier
5  * @details 長い処理はインクルード先の別ファイルにて行っている
6  */
7
8 #include "monster-attack/monster-attack-switcher.h"
9 #include "inventory/inventory-slot-types.h"
10 #include "mind/drs-types.h"
11 #include "mind/mind-mirror-master.h"
12 #include "monster-attack/monster-attack-status.h"
13 #include "monster-attack/monster-eating.h"
14 #include "monster/monster-status.h"
15 #include "monster/monster-update.h"
16 #include "player/player-damage.h"
17 #include "player/player-status-flags.h"
18 #include "player/player-status-resist.h"
19 #include "spell-kind/earthquake.h"
20 #include "spell-kind/spells-equipment.h"
21 #include "status/bad-status-setter.h"
22 #include "status/base-status.h"
23 #include "status/element-resistance.h"
24 #include "status/experience.h"
25 #include "system/object-type-definition.h"
26 #include "view/display-messages.h"
27
28 /*!
29  * @brief 毒ダメージを計算する
30  * @param target_ptr プレーヤーへの参照ポインタ
31  * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
32  * @return なし
33  * @detail 減衰の計算式がpoisではなくnukeなのは仕様 (1/3では減衰が強すぎると判断したため)
34  */
35 static void calc_blow_poison(player_type *target_ptr, monap_type *monap_ptr)
36 {
37     if (monap_ptr->explode)
38         return;
39
40     if (!(target_ptr->resist_pois || is_oppose_pois(target_ptr)) && !check_multishadow(target_ptr)
41         && set_poisoned(target_ptr, target_ptr->poisoned + randint1(monap_ptr->rlev) + 5))
42         monap_ptr->obvious = TRUE;
43
44     monap_ptr->damage = monap_ptr->damage * calc_nuke_damage_rate(target_ptr) / 100;
45     monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
46     update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_POIS);
47 }
48
49 /*!
50  * @brief 劣化ダメージを計算する (耐性があれば、(1d4 + 4) / 9になる)
51  * @param target_ptr プレーヤーへの参照ポインタ
52  * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
53  * @return なし
54  */
55 static void calc_blow_disenchant(player_type *target_ptr, monap_type *monap_ptr)
56 {
57     if (monap_ptr->explode)
58         return;
59
60     if (!target_ptr->resist_disen && !check_multishadow(target_ptr) && apply_disenchant(target_ptr, 0)) {
61         update_creature(target_ptr);
62         monap_ptr->obvious = TRUE;
63     }
64
65     if (is_resist_disen(target_ptr))
66         monap_ptr->damage = monap_ptr->damage * (randint1(4) + 4) / 9;
67
68     monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
69     update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_DISEN);
70 }
71
72 /*!
73  * @brief 盲目ダメージを計算する (耐性があれば、(1d4 + 3) / 8になる)
74  * @param target_ptr プレーヤーへの参照ポインタ
75  * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
76  * @return なし
77  */
78 static void calc_blow_blind(player_type *target_ptr, monap_type *monap_ptr)
79 {
80     if (is_resist_blind(target_ptr))
81         monap_ptr->damage = monap_ptr->damage * (randint1(4) + 3) / 8;
82
83     monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
84     if (target_ptr->is_dead)
85         return;
86
87     process_blind_attack(target_ptr, monap_ptr);
88     update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_BLIND);
89 }
90
91 /*!
92  * @brief 混乱ダメージを計算する (耐性があれば、(1d4 + 3) / 8になる)
93  * @param target_ptr プレーヤーへの参照ポインタ
94  * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
95  * @return なし
96  */
97 static void calc_blow_confusion(player_type *target_ptr, monap_type *monap_ptr)
98 {
99     if (monap_ptr->explode)
100         return;
101
102     if (is_resist_conf(target_ptr))
103         monap_ptr->damage = monap_ptr->damage * (randint1(4) + 3) / 8;
104
105     monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
106     if (target_ptr->is_dead)
107         return;
108
109     if (!target_ptr->resist_conf && !check_multishadow(target_ptr) && set_confused(target_ptr, target_ptr->confused + 3 + randint1(monap_ptr->rlev)))
110         monap_ptr->obvious = TRUE;
111
112     update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_CONF);
113 }
114
115 /*!
116  * @brief 恐怖ダメージを計算する (耐性があれば、(1d4 + 3) / 8になる)
117  * @param target_ptr プレーヤーへの参照ポインタ
118  * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
119  * @return なし
120  */
121 static void calc_blow_fear(player_type *target_ptr, monap_type *monap_ptr)
122 {
123     if (is_resist_fear(target_ptr))
124         monap_ptr->damage = monap_ptr->damage * (randint1(4) + 3) / 8;
125
126     monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
127     if (target_ptr->is_dead)
128         return;
129
130     process_terrify_attack(target_ptr, monap_ptr);
131     update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_FEAR);
132 }
133
134 /*!
135  * @brief 麻痺ダメージを計算する (耐性があれば、(1d4 + 3) / 8になる)
136  * @param target_ptr プレーヤーへの参照ポインタ
137  * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
138  * @return なし
139  */
140 static void calc_blow_paralysis(player_type *target_ptr, monap_type *monap_ptr)
141 {
142     if (has_free_act(target_ptr))
143         monap_ptr->damage = monap_ptr->damage * (randint1(4) + 3) / 8;
144
145     monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
146     if (target_ptr->is_dead)
147         return;
148
149     process_paralyze_attack(target_ptr, monap_ptr);
150     update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_FREE);
151 }
152
153 /*!
154  * @brief 病気ダメージを計算する (毒耐性があれば、(1d4 + 4) / 9になる。二重耐性なら更に(1d4 + 4) / 9)
155  * @param target_ptr プレーヤーへの参照ポインタ
156  * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
157  * @return なし
158  * @details 10% (毒の一次耐性があれば4%、二重耐性ならば1.6%)の確率で耐久が低下し、更に1/10の確率で永久低下する
159  */
160 static void calc_blow_disease(player_type *target_ptr, monap_type *monap_ptr)
161 {
162     if (is_resist_pois(target_ptr))
163         monap_ptr->damage = monap_ptr->damage * (randint1(4) + 4) / 9;
164
165     if (is_oppose_pois(target_ptr))
166         monap_ptr->damage = monap_ptr->damage * (randint1(4) + 4) / 9;
167     
168     monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
169     if (target_ptr->is_dead || check_multishadow(target_ptr))
170         return;
171
172     if (!(target_ptr->resist_pois || is_oppose_pois(target_ptr)) && set_poisoned(target_ptr, target_ptr->poisoned + randint1(monap_ptr->rlev) + 5))
173         monap_ptr->obvious = TRUE;
174
175     bool disease_possibility = randint1(100) > calc_nuke_damage_rate(target_ptr);
176     if (disease_possibility || (randint1(100) > 10) || (target_ptr->prace == RACE_ANDROID))
177         return;
178
179     bool perm = one_in_(10);
180     if (dec_stat(target_ptr, A_CON, randint1(10), perm)) {
181         msg_print(_("病があなたを蝕んでいる気がする。", "You feel sickly."));
182         monap_ptr->obvious = TRUE;
183     }
184 }
185
186 /*!
187  * @brief 腕力低下ダメージを計算する (維持があれば、(1d4 + 4) / 9になる)
188  * @param target_ptr プレーヤーへの参照ポインタ
189  * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
190  * @return なし
191  */
192 static void calc_blow_lose_strength(player_type *target_ptr, monap_type *monap_ptr)
193 {
194     if (is_sustain_str(target_ptr))
195         monap_ptr->get_damage = monap_ptr->get_damage * (randint1(4) + 4) / 9;
196
197     monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
198     if (target_ptr->is_dead || check_multishadow(target_ptr))
199         return;
200
201     if (do_dec_stat(target_ptr, A_STR))
202         monap_ptr->obvious = TRUE;
203 }
204
205 /*!
206  * @brief 知能低下ダメージを計算する (維持があれば、(1d4 + 4) / 9になる)
207  * @param target_ptr プレーヤーへの参照ポインタ
208  * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
209  * @return なし
210  */
211 static void calc_blow_lose_intelligence(player_type *target_ptr, monap_type *monap_ptr)
212 {
213     if (is_sustain_int(target_ptr))
214         monap_ptr->get_damage = monap_ptr->get_damage * (randint1(4) + 4) / 9;
215
216     monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
217     if (target_ptr->is_dead || check_multishadow(target_ptr))
218         return;
219
220     if (do_dec_stat(target_ptr, A_INT))
221         monap_ptr->obvious = TRUE;
222 }
223
224 /*!
225  * @brief 賢さ低下ダメージを計算する (維持があれば、(1d4 + 4) / 9になる)
226  * @param target_ptr プレーヤーへの参照ポインタ
227  * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
228  * @return なし
229  */
230 static void calc_blow_lose_wisdom(player_type *target_ptr, monap_type *monap_ptr)
231 {
232     if (is_sustain_wis(target_ptr))
233         monap_ptr->get_damage = monap_ptr->get_damage * (randint1(4) + 4) / 9;
234
235     monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
236     if (target_ptr->is_dead || check_multishadow(target_ptr))
237         return;
238
239     if (do_dec_stat(target_ptr, A_WIS))
240         monap_ptr->obvious = TRUE;
241 }
242
243 /*!
244  * @brief 器用低下ダメージを計算する (維持があれば、(1d4 + 4) / 9になる)
245  * @param target_ptr プレーヤーへの参照ポインタ
246  * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
247  * @return なし
248  */
249 static void calc_blow_lose_dexterity(player_type *target_ptr, monap_type *monap_ptr)
250 {
251     if (is_sustain_dex(target_ptr))
252         monap_ptr->get_damage = monap_ptr->get_damage * (randint1(4) + 4) / 9;
253
254     monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
255     if (target_ptr->is_dead || check_multishadow(target_ptr))
256         return;
257
258     if (do_dec_stat(target_ptr, A_DEX))
259         monap_ptr->obvious = TRUE;
260 }
261
262 /*!
263  * @brief 耐久低下ダメージを計算する (維持があれば、(1d4 + 4) / 9になる)
264  * @param target_ptr プレーヤーへの参照ポインタ
265  * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
266  * @return なし
267  */
268 static void calc_blow_lose_constitution(player_type *target_ptr, monap_type *monap_ptr)
269 {
270     if (is_sustain_con(target_ptr))
271         monap_ptr->get_damage = monap_ptr->get_damage * (randint1(4) + 4) / 9;
272
273     monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
274     if (target_ptr->is_dead || check_multishadow(target_ptr))
275         return;
276
277     if (do_dec_stat(target_ptr, A_CON))
278         monap_ptr->obvious = TRUE;
279 }
280
281 /*!
282  * @brief 魅力低下ダメージを計算する (維持があれば、(1d4 + 4) / 9になる)
283  * @param target_ptr プレーヤーへの参照ポインタ
284  * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
285  * @return なし
286  */
287 static void calc_blow_lose_charisma(player_type *target_ptr, monap_type *monap_ptr)
288 {
289     if (is_sustain_chr(target_ptr))
290         monap_ptr->get_damage = monap_ptr->get_damage * (randint1(4) + 4) / 9;
291
292     monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
293     if (target_ptr->is_dead || check_multishadow(target_ptr))
294         return;
295
296     if (do_dec_stat(target_ptr, A_CHR))
297         monap_ptr->obvious = TRUE;
298 }
299
300 /*!
301  * @brief 全能力低下ダメージを計算する (維持があれば、1つに付き-3%軽減する)
302  * @param target_ptr プレーヤーへの参照ポインタ
303  * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
304  * @return なし
305  */
306 static void calc_blow_lose_all(player_type *target_ptr, monap_type *monap_ptr)
307 {
308     int damage_ratio = 100;
309     if (is_sustain_str(target_ptr))
310         damage_ratio -= 3;
311
312     if (is_sustain_int(target_ptr))
313         damage_ratio -= 3;
314
315     if (is_sustain_wis(target_ptr))
316         damage_ratio -= 3;
317
318     if (is_sustain_dex(target_ptr))
319         damage_ratio -= 3;
320
321     if (is_sustain_con(target_ptr))
322         damage_ratio -= 3;
323
324     if (is_sustain_chr(target_ptr))
325         damage_ratio -= 3;
326
327     monap_ptr->damage = monap_ptr->damage * damage_ratio / 100;
328     monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
329     if (target_ptr->is_dead || check_multishadow(target_ptr))
330         return;
331
332     process_lose_all_attack(target_ptr, monap_ptr);
333 }
334
335 void switch_monster_blow_to_player(player_type *target_ptr, monap_type *monap_ptr)
336 {
337     switch (monap_ptr->effect) {
338     case RBE_NONE:
339         monap_ptr->obvious = TRUE;
340         monap_ptr->damage = 0;
341         break;
342     case RBE_SUPERHURT: { /* AC軽減あり / Player armor reduces total damage */
343         if (((randint1(monap_ptr->rlev * 2 + 300) > (monap_ptr->ac + 200)) || one_in_(13)) && !check_multishadow(target_ptr)) {
344             int tmp_damage = monap_ptr->damage - (monap_ptr->damage * ((monap_ptr->ac < 150) ? monap_ptr->ac : 150) / 250);
345             msg_print(_("痛恨の一撃!", "It was a critical hit!"));
346             tmp_damage = MAX(monap_ptr->damage, tmp_damage * 2);
347             monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, tmp_damage, monap_ptr->ddesc, -1);
348             break;
349         }
350     }
351         /* Fall through */
352     case RBE_HURT: { /* AC軽減あり / Player armor reduces total damage */
353         monap_ptr->obvious = TRUE;
354         monap_ptr->damage -= (monap_ptr->damage * ((monap_ptr->ac < 150) ? monap_ptr->ac : 150) / 250);
355         monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
356         break;
357     }
358     case RBE_POISON:
359         calc_blow_poison(target_ptr, monap_ptr);
360         break;
361     case RBE_UN_BONUS:
362         calc_blow_disenchant(target_ptr, monap_ptr);
363         break;
364     case RBE_UN_POWER: {
365         monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
366         if (target_ptr->is_dead || check_multishadow(target_ptr))
367             break;
368
369         for (int i = 0; i < 10; i++) {
370             INVENTORY_IDX i_idx = (INVENTORY_IDX)randint0(INVEN_PACK);
371             monap_ptr->o_ptr = &target_ptr->inventory_list[i_idx];
372             if (monap_ptr->o_ptr->k_idx == 0)
373                 continue;
374
375             if (process_un_power(target_ptr, monap_ptr))
376                 break;
377         }
378
379         break;
380     }
381     case RBE_EAT_GOLD: {
382         monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
383         if (monster_confused_remaining(monap_ptr->m_ptr))
384             break;
385
386         if (target_ptr->is_dead || check_multishadow(target_ptr))
387             break;
388
389         monap_ptr->obvious = TRUE;
390         process_eat_gold(target_ptr, monap_ptr);
391         break;
392     }
393     case RBE_EAT_ITEM: {
394         monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
395         if (!check_eat_item(target_ptr, monap_ptr))
396             break;
397
398         process_eat_item(target_ptr, monap_ptr);
399         break;
400     }
401
402     case RBE_EAT_FOOD: {
403         monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
404         if (target_ptr->is_dead || check_multishadow(target_ptr))
405             break;
406
407         process_eat_food(target_ptr, monap_ptr);
408         break;
409     }
410     case RBE_EAT_LITE: {
411         monap_ptr->o_ptr = &target_ptr->inventory_list[INVEN_LITE];
412         monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
413         if (target_ptr->is_dead || check_multishadow(target_ptr))
414             break;
415
416         process_eat_lite(target_ptr, monap_ptr);
417         break;
418     }
419     case RBE_ACID: {
420         if (monap_ptr->explode)
421             break;
422
423         monap_ptr->obvious = TRUE;
424         msg_print(_("酸を浴びせられた!", "You are covered in acid!"));
425         monap_ptr->get_damage += acid_dam(target_ptr, monap_ptr->damage, monap_ptr->ddesc, -1, FALSE);
426         update_creature(target_ptr);
427         update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_ACID);
428         break;
429     }
430     case RBE_ELEC: {
431         if (monap_ptr->explode)
432             break;
433
434         monap_ptr->obvious = TRUE;
435         msg_print(_("電撃を浴びせられた!", "You are struck by electricity!"));
436         monap_ptr->get_damage += elec_dam(target_ptr, monap_ptr->damage, monap_ptr->ddesc, -1, FALSE);
437         update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_ELEC);
438         break;
439     }
440     case RBE_FIRE: {
441         if (monap_ptr->explode)
442             break;
443
444         monap_ptr->obvious = TRUE;
445         msg_print(_("全身が炎に包まれた!", "You are enveloped in flames!"));
446         monap_ptr->get_damage += fire_dam(target_ptr, monap_ptr->damage, monap_ptr->ddesc, -1, FALSE);
447         update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_FIRE);
448         break;
449     }
450     case RBE_COLD: {
451         if (monap_ptr->explode)
452             break;
453
454         monap_ptr->obvious = TRUE;
455         msg_print(_("全身が冷気で覆われた!", "You are covered with frost!"));
456         monap_ptr->get_damage += cold_dam(target_ptr, monap_ptr->damage, monap_ptr->ddesc, -1, FALSE);
457         update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_COLD);
458         break;
459     }
460     case RBE_BLIND:
461         calc_blow_blind(target_ptr, monap_ptr);
462         break;
463     case RBE_CONFUSE:
464         calc_blow_confusion(target_ptr, monap_ptr);
465         break;
466     case RBE_TERRIFY:
467         calc_blow_fear(target_ptr, monap_ptr);
468         break;
469     case RBE_PARALYZE:
470         calc_blow_paralysis(target_ptr, monap_ptr);
471         break;
472     case RBE_LOSE_STR:
473         calc_blow_lose_strength(target_ptr, monap_ptr);
474         break;
475     case RBE_LOSE_INT:
476         calc_blow_lose_intelligence(target_ptr, monap_ptr);
477         break;
478     case RBE_LOSE_WIS:
479         calc_blow_lose_wisdom(target_ptr, monap_ptr);
480         break;
481     case RBE_LOSE_DEX:
482         calc_blow_lose_dexterity(target_ptr, monap_ptr);
483         break;
484     case RBE_LOSE_CON:
485         calc_blow_lose_constitution(target_ptr, monap_ptr);
486         break;
487     case RBE_LOSE_CHR:
488         calc_blow_lose_charisma(target_ptr, monap_ptr);
489         break;
490     case RBE_LOSE_ALL:
491         calc_blow_lose_all(target_ptr, monap_ptr);
492         break;
493     case RBE_SHATTER: { /* AC軽減あり / Player armor reduces total damage */
494         monap_ptr->obvious = TRUE;
495         monap_ptr->damage -= (monap_ptr->damage * ((monap_ptr->ac < 150) ? monap_ptr->ac : 150) / 250);
496         monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
497         if (monap_ptr->damage > 23 || monap_ptr->explode)
498             earthquake(target_ptr, monap_ptr->m_ptr->fy, monap_ptr->m_ptr->fx, 8, monap_ptr->m_idx);
499
500         break;
501     }
502     case RBE_EXP_10: {
503         s32b d = damroll(10, 6) + (target_ptr->exp / 100) * MON_DRAIN_LIFE;
504         monap_ptr->obvious = TRUE;
505         monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
506         if (target_ptr->is_dead || check_multishadow(target_ptr))
507             break;
508
509         (void)drain_exp(target_ptr, d, d / 10, 95);
510         break;
511     }
512     case RBE_EXP_20: {
513         s32b d = damroll(20, 6) + (target_ptr->exp / 100) * MON_DRAIN_LIFE;
514         monap_ptr->obvious = TRUE;
515         monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
516         if (target_ptr->is_dead || check_multishadow(target_ptr))
517             break;
518
519         (void)drain_exp(target_ptr, d, d / 10, 90);
520         break;
521     }
522     case RBE_EXP_40: {
523         s32b d = damroll(40, 6) + (target_ptr->exp / 100) * MON_DRAIN_LIFE;
524         monap_ptr->obvious = TRUE;
525         monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
526         if (target_ptr->is_dead || check_multishadow(target_ptr))
527             break;
528
529         (void)drain_exp(target_ptr, d, d / 10, 75);
530         break;
531     }
532     case RBE_EXP_80: {
533         s32b d = damroll(80, 6) + (target_ptr->exp / 100) * MON_DRAIN_LIFE;
534         monap_ptr->obvious = TRUE;
535         monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
536         if (target_ptr->is_dead || check_multishadow(target_ptr))
537             break;
538
539         (void)drain_exp(target_ptr, d, d / 10, 50);
540         break;
541     }
542     case RBE_DISEASE:
543         calc_blow_didease(target_ptr, monap_ptr);
544         break;
545     case RBE_TIME: {
546         if (monap_ptr->explode)
547             break;
548
549         process_monster_attack_time(target_ptr, monap_ptr);
550         monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
551         break;
552     }
553     case RBE_DR_LIFE: {
554         s32b d = damroll(60, 6) + (target_ptr->exp / 100) * MON_DRAIN_LIFE;
555         monap_ptr->obvious = TRUE;
556         monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
557         if (target_ptr->is_dead || check_multishadow(target_ptr))
558             break;
559
560         bool resist_drain = check_drain_hp(target_ptr, d);
561         process_drain_life(target_ptr, monap_ptr, resist_drain);
562         break;
563     }
564     case RBE_DR_MANA: {
565         monap_ptr->obvious = TRUE;
566         process_drain_mana(target_ptr, monap_ptr);
567         update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_MANA);
568         break;
569     }
570     case RBE_INERTIA: {
571         monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
572         if (target_ptr->is_dead)
573             break;
574
575         if (check_multishadow(target_ptr)) {
576             /* Do nothing */
577         } else {
578             if (set_slow(target_ptr, (target_ptr->slow + 4 + randint0(monap_ptr->rlev / 10)), FALSE)) {
579                 monap_ptr->obvious = TRUE;
580             }
581         }
582
583         break;
584     }
585     case RBE_STUN: {
586         monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
587         if (target_ptr->is_dead)
588             break;
589
590         process_stun_attack(target_ptr, monap_ptr);
591         break;
592     }
593     }
594 }