OSDN Git Service

[Refactor] #40479 Separated check_reflection() from remove_bad_spells()
[hengband/hengband.git] / src / mspell / improper-mspell-remover.c
1 #include "mspell/improper-mspell-remover.h"
2 #include "game-option/birth-options.h"
3 #include "monster-race/monster-race.h"
4 #include "monster-race/race-flags-ability1.h"
5 #include "monster-race/race-flags-ability2.h"
6 #include "monster-race/race-flags2.h"
7 #include "monster-race/race-flags4.h"
8 #include "monster/smart-learn-types.h"
9 #include "player/player-race.h"
10 #include "status/element-resistance.h"
11 #include "system/floor-type-definition.h"
12 #include "system/monster-type-definition.h"
13
14 // Monster Spell Remover.
15 typedef struct msr_type {
16     monster_race *r_ptr;
17     u32b f4;
18     u32b f5;
19     u32b f6;
20     u32b smart;
21 } msr_type;
22
23 static msr_type *initialize_msr_type(player_type *target_ptr, msr_type *msr_ptr, MONSTER_IDX m_idx, const u32b f4p, const u32b f5p, const u32b f6p)
24 {
25     monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
26     msr_ptr->r_ptr = &r_info[m_ptr->r_idx];
27     msr_ptr->f4 = f4p;
28     msr_ptr->f5 = f5p;
29     msr_ptr->f6 = f6p;
30     msr_ptr->smart = 0L;
31     return msr_ptr;
32 }
33
34 /*!
35  * @brief モンスターがプレイヤーの弱点をついた選択を取るかどうかの判定 /
36  * Internal probability routine
37  * @param r_ptr モンスター種族の構造体参照ポインタ
38  * @param prob 基本確率(%)
39  * @return 適した選択を取るならばTRUEを返す。
40  */
41 static bool int_outof(monster_race *r_ptr, PERCENTAGE prob)
42 {
43     if (!(r_ptr->flags2 & RF2_SMART))
44         prob = prob / 2;
45
46     return (randint0(100) < prob);
47 }
48
49 static void add_cheat_remove_flags_element(player_type *target_ptr, msr_type *msr_ptr)
50 {
51     if (target_ptr->resist_acid)
52         msr_ptr->smart |= SM_RES_ACID;
53
54     if (is_oppose_acid(target_ptr))
55         msr_ptr->smart |= SM_OPP_ACID;
56
57     if (target_ptr->immune_acid)
58         msr_ptr->smart |= SM_IMM_ACID;
59
60     if (target_ptr->resist_elec)
61         msr_ptr->smart |= SM_RES_ELEC;
62
63     if (is_oppose_elec(target_ptr))
64         msr_ptr->smart |= SM_OPP_ELEC;
65
66     if (target_ptr->immune_elec)
67         msr_ptr->smart |= SM_IMM_ELEC;
68
69     if (target_ptr->resist_fire)
70         msr_ptr->smart |= SM_RES_FIRE;
71
72     if (is_oppose_fire(target_ptr))
73         msr_ptr->smart |= SM_OPP_FIRE;
74
75     if (target_ptr->immune_fire)
76         msr_ptr->smart |= SM_IMM_FIRE;
77
78     if (target_ptr->resist_cold)
79         msr_ptr->smart |= SM_RES_COLD;
80
81     if (is_oppose_cold(target_ptr))
82         msr_ptr->smart |= SM_OPP_COLD;
83
84     if (target_ptr->immune_cold)
85         msr_ptr->smart |= SM_IMM_COLD;
86
87     if (target_ptr->resist_pois)
88         msr_ptr->smart |= SM_RES_POIS;
89
90     if (is_oppose_pois(target_ptr))
91         msr_ptr->smart |= SM_OPP_POIS;
92 }
93
94 static void add_cheat_remove_flags_others(player_type *target_ptr, msr_type *msr_ptr)
95 {
96     if (target_ptr->resist_neth)
97         msr_ptr->smart |= SM_RES_NETH;
98
99     if (target_ptr->resist_lite)
100         msr_ptr->smart |= SM_RES_LITE;
101
102     if (target_ptr->resist_dark)
103         msr_ptr->smart |= SM_RES_DARK;
104
105     if (target_ptr->resist_fear)
106         msr_ptr->smart |= SM_RES_FEAR;
107
108     if (target_ptr->resist_conf)
109         msr_ptr->smart |= SM_RES_CONF;
110
111     if (target_ptr->resist_chaos)
112         msr_ptr->smart |= SM_RES_CHAOS;
113
114     if (target_ptr->resist_disen)
115         msr_ptr->smart |= SM_RES_DISEN;
116
117     if (target_ptr->resist_blind)
118         msr_ptr->smart |= SM_RES_BLIND;
119
120     if (target_ptr->resist_nexus)
121         msr_ptr->smart |= SM_RES_NEXUS;
122
123     if (target_ptr->resist_sound)
124         msr_ptr->smart |= SM_RES_SOUND;
125
126     if (target_ptr->resist_shard)
127         msr_ptr->smart |= SM_RES_SHARD;
128
129     if (target_ptr->reflect)
130         msr_ptr->smart |= SM_IMM_REFLECT;
131
132     if (target_ptr->free_act)
133         msr_ptr->smart |= SM_IMM_FREE;
134
135     if (!target_ptr->msp)
136         msr_ptr->smart |= SM_IMM_MANA;
137 }
138
139 static void add_cheat_remove_flags(player_type *target_ptr, msr_type *msr_ptr)
140 {
141     if (!smart_cheat)
142         return;
143
144     add_cheat_remove_flags_element(target_ptr, msr_ptr);
145     add_cheat_remove_flags_others(target_ptr, msr_ptr);
146 }
147
148 static void check_acid_resistance(msr_type *msr_ptr)
149 {
150     if (msr_ptr->smart & SM_IMM_ACID) {
151         msr_ptr->f4 &= ~(RF4_BR_ACID);
152         msr_ptr->f5 &= ~(RF5_BA_ACID);
153         msr_ptr->f5 &= ~(RF5_BO_ACID);
154         return;
155     }
156     
157     if ((msr_ptr->smart & SM_OPP_ACID) && (msr_ptr->smart & SM_RES_ACID)) {
158         if (int_outof(msr_ptr->r_ptr, 80))
159             msr_ptr->f4 &= ~(RF4_BR_ACID);
160
161         if (int_outof(msr_ptr->r_ptr, 80))
162             msr_ptr->f5 &= ~(RF5_BA_ACID);
163
164         if (int_outof(msr_ptr->r_ptr, 80))
165             msr_ptr->f5 &= ~(RF5_BO_ACID);
166         
167         return;
168     }
169     
170     if ((msr_ptr->smart & SM_OPP_ACID) || (msr_ptr->smart & SM_RES_ACID)) {
171         if (int_outof(msr_ptr->r_ptr, 30))
172             msr_ptr->f4 &= ~(RF4_BR_ACID);
173
174         if (int_outof(msr_ptr->r_ptr, 30))
175             msr_ptr->f5 &= ~(RF5_BA_ACID);
176
177         if (int_outof(msr_ptr->r_ptr, 30))
178             msr_ptr->f5 &= ~(RF5_BO_ACID);
179     }
180 }
181
182 static void check_elec_resistance(msr_type *msr_ptr)
183 {
184     if (msr_ptr->smart & SM_IMM_ELEC) {
185         msr_ptr->f4 &= ~(RF4_BR_ELEC);
186         msr_ptr->f5 &= ~(RF5_BA_ELEC);
187         msr_ptr->f5 &= ~(RF5_BO_ELEC);
188         return;
189     }
190     
191     if ((msr_ptr->smart & SM_OPP_ELEC) && (msr_ptr->smart & SM_RES_ELEC)) {
192         if (int_outof(msr_ptr->r_ptr, 80))
193             msr_ptr->f4 &= ~(RF4_BR_ELEC);
194
195         if (int_outof(msr_ptr->r_ptr, 80))
196             msr_ptr->f5 &= ~(RF5_BA_ELEC);
197
198         if (int_outof(msr_ptr->r_ptr, 80))
199             msr_ptr->f5 &= ~(RF5_BO_ELEC);
200
201         return;
202     }
203     
204     if ((msr_ptr->smart & SM_OPP_ELEC) || (msr_ptr->smart & SM_RES_ELEC)) {
205         if (int_outof(msr_ptr->r_ptr, 30))
206             msr_ptr->f4 &= ~(RF4_BR_ELEC);
207
208         if (int_outof(msr_ptr->r_ptr, 30))
209             msr_ptr->f5 &= ~(RF5_BA_ELEC);
210
211         if (int_outof(msr_ptr->r_ptr, 30))
212             msr_ptr->f5 &= ~(RF5_BO_ELEC);
213     }
214 }
215
216 static void check_fire_resistance(msr_type *msr_ptr)
217 {
218     if (msr_ptr->smart & SM_IMM_FIRE) {
219         msr_ptr->f4 &= ~(RF4_BR_FIRE);
220         msr_ptr->f5 &= ~(RF5_BA_FIRE);
221         msr_ptr->f5 &= ~(RF5_BO_FIRE);
222         return;
223     }
224     
225     if ((msr_ptr->smart & SM_OPP_FIRE) && (msr_ptr->smart & SM_RES_FIRE)) {
226         if (int_outof(msr_ptr->r_ptr, 80))
227             msr_ptr->f4 &= ~(RF4_BR_FIRE);
228
229         if (int_outof(msr_ptr->r_ptr, 80))
230             msr_ptr->f5 &= ~(RF5_BA_FIRE);
231
232         if (int_outof(msr_ptr->r_ptr, 80))
233             msr_ptr->f5 &= ~(RF5_BO_FIRE);
234
235         return;
236     }
237     
238     if ((msr_ptr->smart & SM_OPP_FIRE) || (msr_ptr->smart & SM_RES_FIRE)) {
239         if (int_outof(msr_ptr->r_ptr, 30))
240             msr_ptr->f4 &= ~(RF4_BR_FIRE);
241
242         if (int_outof(msr_ptr->r_ptr, 30))
243             msr_ptr->f5 &= ~(RF5_BA_FIRE);
244
245         if (int_outof(msr_ptr->r_ptr, 30))
246             msr_ptr->f5 &= ~(RF5_BO_FIRE);
247     }
248 }
249
250 static void check_cold_resistance(msr_type *msr_ptr)
251 {
252     if (msr_ptr->smart & (SM_IMM_COLD)) {
253         msr_ptr->f4 &= ~(RF4_BR_COLD);
254         msr_ptr->f5 &= ~(RF5_BA_COLD);
255         msr_ptr->f5 &= ~(RF5_BO_COLD);
256         msr_ptr->f5 &= ~(RF5_BO_ICEE);
257         return;
258     }
259     
260     if ((msr_ptr->smart & SM_OPP_COLD) && (msr_ptr->smart & SM_RES_COLD)) {
261         if (int_outof(msr_ptr->r_ptr, 80))
262             msr_ptr->f4 &= ~(RF4_BR_COLD);
263
264         if (int_outof(msr_ptr->r_ptr, 80))
265             msr_ptr->f5 &= ~(RF5_BA_COLD);
266
267         if (int_outof(msr_ptr->r_ptr, 80))
268             msr_ptr->f5 &= ~(RF5_BO_COLD);
269
270         if (int_outof(msr_ptr->r_ptr, 80))
271             msr_ptr->f5 &= ~(RF5_BO_ICEE);
272
273         return;
274     }
275     
276     if ((msr_ptr->smart & SM_OPP_COLD) || (msr_ptr->smart & SM_RES_COLD)) {
277         if (int_outof(msr_ptr->r_ptr, 30))
278             msr_ptr->f4 &= ~(RF4_BR_COLD);
279
280         if (int_outof(msr_ptr->r_ptr, 30))
281             msr_ptr->f5 &= ~(RF5_BA_COLD);
282
283         if (int_outof(msr_ptr->r_ptr, 30))
284             msr_ptr->f5 &= ~(RF5_BO_COLD);
285
286         if (int_outof(msr_ptr->r_ptr, 20))
287             msr_ptr->f5 &= ~(RF5_BO_ICEE);
288     }
289 }
290
291 static void check_pois_resistance(msr_type *msr_ptr)
292 {
293     if ((msr_ptr->smart & SM_OPP_POIS) && (msr_ptr->smart & SM_RES_POIS)) {
294         if (int_outof(msr_ptr->r_ptr, 80))
295             msr_ptr->f4 &= ~(RF4_BR_POIS);
296
297         if (int_outof(msr_ptr->r_ptr, 80))
298             msr_ptr->f5 &= ~(RF5_BA_POIS);
299
300         if (int_outof(msr_ptr->r_ptr, 60))
301             msr_ptr->f4 &= ~(RF4_BA_NUKE);
302
303         if (int_outof(msr_ptr->r_ptr, 60))
304             msr_ptr->f4 &= ~(RF4_BR_NUKE);
305
306         return;
307     }
308     
309     if ((msr_ptr->smart & SM_OPP_POIS) || (msr_ptr->smart & SM_RES_POIS)) {
310         if (int_outof(msr_ptr->r_ptr, 30))
311             msr_ptr->f4 &= ~(RF4_BR_POIS);
312
313         if (int_outof(msr_ptr->r_ptr, 30))
314             msr_ptr->f5 &= ~(RF5_BA_POIS);
315     }
316 }
317
318 void check_element_resistance(msr_type *msr_ptr)
319 {
320     check_acid_resistance(msr_ptr);
321     check_elec_resistance(msr_ptr);
322     check_fire_resistance(msr_ptr);
323     check_cold_resistance(msr_ptr);
324     check_pois_resistance(msr_ptr);
325 }
326
327 static void check_nether_resistance(player_type *target_ptr, msr_type *msr_ptr)
328 {
329     if ((msr_ptr->smart & SM_RES_NETH) == 0)
330         return;
331
332     if (is_specific_player_race(target_ptr, RACE_SPECTRE)) {
333         msr_ptr->f4 &= ~(RF4_BR_NETH);
334         msr_ptr->f5 &= ~(RF5_BA_NETH);
335         msr_ptr->f5 &= ~(RF5_BO_NETH);
336         return;
337     }
338
339     if (int_outof(msr_ptr->r_ptr, 20))
340         msr_ptr->f4 &= ~(RF4_BR_NETH);
341
342     if (int_outof(msr_ptr->r_ptr, 50))
343         msr_ptr->f5 &= ~(RF5_BA_NETH);
344
345     if (int_outof(msr_ptr->r_ptr, 50))
346         msr_ptr->f5 &= ~(RF5_BO_NETH);
347 }
348
349 static void check_lite_resistance(msr_type *msr_ptr)
350 {
351     if ((msr_ptr->smart & SM_RES_LITE) == 0)
352         return;
353
354     if (int_outof(msr_ptr->r_ptr, 50))
355         msr_ptr->f4 &= ~(RF4_BR_LITE);
356
357     if (int_outof(msr_ptr->r_ptr, 50))
358         msr_ptr->f5 &= ~(RF5_BA_LITE);
359 }
360
361 static void check_dark_resistance(player_type *target_ptr, msr_type *msr_ptr)
362 {
363     if ((msr_ptr->smart & SM_RES_DARK) == 0)
364         return;
365
366     if (is_specific_player_race(target_ptr, RACE_VAMPIRE)) {
367         msr_ptr->f4 &= ~(RF4_BR_DARK);
368         msr_ptr->f5 &= ~(RF5_BA_DARK);
369         return;
370     }
371
372     if (int_outof(msr_ptr->r_ptr, 50))
373         msr_ptr->f4 &= ~(RF4_BR_DARK);
374
375     if (int_outof(msr_ptr->r_ptr, 50))
376         msr_ptr->f5 &= ~(RF5_BA_DARK);
377 }
378
379 static void check_conf_resistance(msr_type *msr_ptr)
380 {
381     if ((msr_ptr->smart & SM_RES_CONF) == 0)
382         return;
383
384     msr_ptr->f5 &= ~(RF5_CONF);
385     if (int_outof(msr_ptr->r_ptr, 50))
386         msr_ptr->f4 &= ~(RF4_BR_CONF);
387 }
388
389 static void check_chaos_resistance(msr_type *msr_ptr)
390 {
391     if ((msr_ptr->smart & SM_RES_CHAOS) == 0)
392         return;
393
394     if (int_outof(msr_ptr->r_ptr, 20))
395         msr_ptr->f4 &= ~(RF4_BR_CHAO);
396
397     if (int_outof(msr_ptr->r_ptr, 50))
398         msr_ptr->f4 &= ~(RF4_BA_CHAO);
399 }
400
401 static void check_nexus_resistance(msr_type *msr_ptr)
402 {
403     if ((msr_ptr->smart & SM_RES_NEXUS) == 0)
404         return;
405
406     if (int_outof(msr_ptr->r_ptr, 50))
407         msr_ptr->f4 &= ~(RF4_BR_NEXU);
408
409     msr_ptr->f6 &= ~(RF6_TELE_LEVEL);
410 }
411
412 static void check_reflection(msr_type *msr_ptr)
413 {
414     if ((msr_ptr->smart & SM_IMM_REFLECT) == 0)
415         return;
416
417     if (int_outof(msr_ptr->r_ptr, 150))
418         msr_ptr->f5 &= ~(RF5_BO_COLD);
419
420     if (int_outof(msr_ptr->r_ptr, 150))
421         msr_ptr->f5 &= ~(RF5_BO_FIRE);
422
423     if (int_outof(msr_ptr->r_ptr, 150))
424         msr_ptr->f5 &= ~(RF5_BO_ACID);
425
426     if (int_outof(msr_ptr->r_ptr, 150))
427         msr_ptr->f5 &= ~(RF5_BO_ELEC);
428
429     if (int_outof(msr_ptr->r_ptr, 150))
430         msr_ptr->f5 &= ~(RF5_BO_NETH);
431
432     if (int_outof(msr_ptr->r_ptr, 150))
433         msr_ptr->f5 &= ~(RF5_BO_WATE);
434
435     if (int_outof(msr_ptr->r_ptr, 150))
436         msr_ptr->f5 &= ~(RF5_BO_MANA);
437
438     if (int_outof(msr_ptr->r_ptr, 150))
439         msr_ptr->f5 &= ~(RF5_BO_PLAS);
440
441     if (int_outof(msr_ptr->r_ptr, 150))
442         msr_ptr->f5 &= ~(RF5_BO_ICEE);
443
444     if (int_outof(msr_ptr->r_ptr, 150))
445         msr_ptr->f5 &= ~(RF5_MISSILE);
446 }
447
448 /*!
449  * @brief モンスターの魔法一覧から戦術的に適さない魔法を除外する /
450  * Remove the "bad" spells from a spell list
451  * @param m_idx モンスターの構造体参照ポインタ
452  * @param f4p モンスター魔法のフラグリスト1
453  * @param f5p モンスター魔法のフラグリスト2
454  * @param f6p モンスター魔法のフラグリスト3
455  * @return なし
456  */
457 void remove_bad_spells(MONSTER_IDX m_idx, player_type *target_ptr, u32b *f4p, u32b *f5p, u32b *f6p)
458 {
459     msr_type tmp_msr;
460     msr_type *msr_ptr = initialize_msr_type(target_ptr, &tmp_msr, m_idx, *f4p, *f5p, *f6p);
461     if (msr_ptr->r_ptr->flags2 & RF2_STUPID)
462         return;
463
464     if (!smart_cheat && !smart_learn)
465         return;
466
467     monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
468     if (smart_learn) {
469         if (m_ptr->smart && (randint0(100) < 1))
470             m_ptr->smart &= SM_FRIENDLY | SM_PET | SM_CLONED;
471
472         msr_ptr->smart = m_ptr->smart;
473     }
474
475     add_cheat_remove_flags(target_ptr, msr_ptr);
476     if (!msr_ptr->smart)
477         return;
478
479     check_element_resistance(msr_ptr);
480     check_nether_resistance(target_ptr, msr_ptr);
481     check_lite_resistance(msr_ptr);
482     check_dark_resistance(target_ptr, msr_ptr);
483     if (msr_ptr->smart & SM_RES_FEAR)
484         msr_ptr->f5 &= ~(RF5_SCARE);
485
486     check_conf_resistance(msr_ptr);
487     check_chaos_resistance(msr_ptr);
488     if (((msr_ptr->smart & SM_RES_DISEN) != 0) && int_outof(msr_ptr->r_ptr, 40))
489         msr_ptr->f4 &= ~(RF4_BR_DISE);
490
491     if (msr_ptr->smart & SM_RES_BLIND)
492         msr_ptr->f5 &= ~(RF5_BLIND);
493
494     check_nexus_resistance(msr_ptr);
495     if (((msr_ptr->smart & SM_RES_SOUND) != 0) && int_outof(msr_ptr->r_ptr, 50))
496         msr_ptr->f4 &= ~(RF4_BR_SOUN);
497
498     if (((msr_ptr->smart & SM_RES_SHARD) != 0) && int_outof(msr_ptr->r_ptr, 40))
499         msr_ptr->f4 &= ~(RF4_BR_SHAR);
500
501     check_reflection(msr_ptr);
502     if (msr_ptr->smart & SM_IMM_FREE) {
503         msr_ptr->f5 &= ~(RF5_HOLD);
504         msr_ptr->f5 &= ~(RF5_SLOW);
505     }
506
507     if (msr_ptr->smart & SM_IMM_MANA)
508         msr_ptr->f5 &= ~(RF5_DRAIN_MANA);
509
510     *f4p = msr_ptr->f4;
511     *f5p = msr_ptr->f5;
512     *f6p = msr_ptr->f6;
513 }