OSDN Git Service

#37287 #37353 (2.2.0.89) FEAT_POWER 型を定義し、型の置換を継続中。 / Define FEAT_POWER, ongoing...
[hengband/hengband.git] / src / hex.c
1 /*!
2  * @file hex.c
3  * @brief 呪術の処理実装 / Hex code
4  * @date 2014/01/14
5  * @author
6  * 2014 Deskull rearranged comment for Doxygen.\n
7  * @details
8  * p_ptr-magic_num1\n
9  * 0: Flag bits of spelling spells\n
10  * 1: Flag bits of despelled spells\n
11  * 2: Revange damage\n
12  * p_ptr->magic_num2\n
13  * 0: Number of spelling spells\n
14  * 1: Type of revenge\n
15  * 2: Turn count for revenge\n
16  */
17
18 #include "angband.h"
19
20 #define MAX_KEEP 4 /*!<呪術の最大詠唱数 */
21
22 /*!
23  * @brief プレイヤーが詠唱中の全呪術を停止する
24  * @return なし
25  */
26 bool stop_hex_spell_all(void)
27 {
28         int i;
29
30         for (i = 0; i < 32; i++)
31         {
32                 u32b spell = 1L << i;
33                 if (hex_spelling(spell)) do_spell(REALM_HEX, spell, SPELL_STOP);
34         }
35
36         p_ptr->magic_num1[0] = 0;
37         p_ptr->magic_num2[0] = 0;
38
39         /* Print message */
40         if (p_ptr->action == ACTION_SPELL) set_action(ACTION_NONE);
41
42         /* Redraw status */
43         p_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SPELLS);
44         p_ptr->redraw |= (PR_EXTRA | PR_HP | PR_MANA);
45
46         return TRUE;
47 }
48
49 /*!
50  * @brief プレイヤーが詠唱中の呪術から一つを選んで停止する
51  * @return なし
52  */
53 bool stop_hex_spell(void)
54 {
55         int spell;
56         char choice;
57         char out_val[160];
58         bool flag = FALSE;
59         int y = 1;
60         int x = 20;
61         int sp[MAX_KEEP];
62
63         if (!hex_spelling_any())
64         {
65 #ifdef JP
66                 msg_print("呪文を詠唱していません。");
67 #else
68                 msg_print("You are casting no spell.");
69 #endif
70                 return FALSE;
71         }
72
73         /* Stop all spells */
74         else if ((p_ptr->magic_num2[0] == 1) || (p_ptr->lev < 35))
75         {
76                 return stop_hex_spell_all();
77         }
78         else
79         {
80 #ifdef JP
81                 strnfmt(out_val, 78, "どの呪文の詠唱を中断しますか?(呪文 %c-%c, 'l'全て, ESC)",
82                         I2A(0), I2A(p_ptr->magic_num2[0] - 1));
83 #else
84                 strnfmt(out_val, 78, "Which spell do you stop casting? (Spell %c-%c, 'l' to all, ESC)",
85                         I2A(0), I2A(p_ptr->magic_num2[0] - 1));
86 #endif
87
88                 screen_save();
89
90                 while (!flag)
91                 {
92                         int n = 0;
93                         Term_erase(x, y, 255);
94                         prt("     名前", y, x + 5);
95                         for (spell = 0; spell < 32; spell++)
96                         {
97                                 if (hex_spelling(spell))
98                                 {
99                                         Term_erase(x, y + n + 1, 255);
100                                         put_str(format("%c)  %s", I2A(n), do_spell(REALM_HEX, spell, SPELL_NAME)), y + n + 1, x + 2);
101                                         sp[n++] = spell;
102                                 }
103                         }
104
105                         if (!get_com(out_val, &choice, TRUE)) break;
106                         if (isupper(choice)) choice = (char)tolower(choice);
107
108                         if (choice == 'l')      /* All */
109                         {
110                                 screen_load();
111                                 return stop_hex_spell_all();
112                         }
113                         if ((choice < I2A(0)) || (choice > I2A(p_ptr->magic_num2[0] - 1))) continue;
114                         flag = TRUE;
115                 }
116         }
117
118         screen_load();
119
120         if (flag)
121         {
122                 int n = sp[A2I(choice)];
123
124                 do_spell(REALM_HEX, n, SPELL_STOP);
125                 p_ptr->magic_num1[0] &= ~(1L << n);
126                 p_ptr->magic_num2[0]--;
127         }
128
129         /* Redraw status */
130         p_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SPELLS);
131         p_ptr->redraw |= (PR_EXTRA | PR_HP | PR_MANA);
132
133         return flag;
134 }
135
136
137 /*!
138  * @brief 一定時間毎に呪術で消費するMPを処理する /
139  * Upkeeping hex spells Called from dungeon.c
140  * @return なし
141  */
142 void check_hex(void)
143 {
144         int spell;
145         s32b need_mana;
146         u32b need_mana_frac;
147         bool res = FALSE;
148
149         /* Spells spelled by player */
150         if (p_ptr->realm1 != REALM_HEX) return;
151         if (!p_ptr->magic_num1[0] && !p_ptr->magic_num1[1]) return;
152
153         if (p_ptr->magic_num1[1])
154         {
155                 p_ptr->magic_num1[0] = p_ptr->magic_num1[1];
156                 p_ptr->magic_num1[1] = 0;
157                 res = TRUE;
158         }
159
160         /* Stop all spells when anti-magic ability is given */
161         if (p_ptr->anti_magic)
162         {
163                 stop_hex_spell_all();
164                 return;
165         }
166
167         need_mana = 0;
168         for (spell = 0; spell < 32; spell++)
169         {
170                 if (hex_spelling(spell))
171                 {
172                         const magic_type *s_ptr;
173                         s_ptr = &technic_info[REALM_HEX - MIN_TECHNIC][spell];
174                         need_mana += mod_need_mana(s_ptr->smana, spell, REALM_HEX);
175                 }
176         }
177
178
179         /* Culcurates final mana cost */
180         need_mana_frac = 0;
181         s64b_div(&need_mana, &need_mana_frac, 0, 3); /* Divide by 3 */
182         need_mana += (p_ptr->magic_num2[0] - 1);
183
184
185         /* Not enough mana */
186         if (s64b_cmp(p_ptr->csp, p_ptr->csp_frac, need_mana, need_mana_frac) < 0)
187         {
188                 stop_hex_spell_all();
189                 return;
190         }
191
192         /* Enough mana */
193         else
194         {
195                 s64b_sub(&(p_ptr->csp), &(p_ptr->csp_frac), need_mana, need_mana_frac);
196
197                 p_ptr->redraw |= PR_MANA;
198                 if (res)
199                 {
200 #ifdef JP
201                         msg_print("詠唱を再開した。");
202 #else
203                         msg_print("You restart spelling.");
204 #endif
205                         p_ptr->action = ACTION_SPELL;
206
207                         /* Recalculate bonuses */
208                         p_ptr->update |= (PU_BONUS | PU_HP);
209
210                         /* Redraw map and status bar */
211                         p_ptr->redraw |= (PR_MAP | PR_STATUS | PR_STATE);
212
213                         /* Update monsters */
214                         p_ptr->update |= (PU_MONSTERS);
215
216                         /* Window stuff */
217                         p_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
218                 }
219         }
220
221         /* Gain experiences of spelling spells */
222         for (spell = 0; spell < 32; spell++)
223         {
224                 const magic_type *s_ptr;
225
226                 if (!hex_spelling(spell)) continue;
227
228                 s_ptr = &technic_info[REALM_HEX - MIN_TECHNIC][spell];
229
230                 if (p_ptr->spell_exp[spell] < SPELL_EXP_BEGINNER)
231                         p_ptr->spell_exp[spell] += 5;
232                 else if(p_ptr->spell_exp[spell] < SPELL_EXP_SKILLED)
233                 { if (one_in_(2) && (dun_level > 4) && ((dun_level + 10) > p_ptr->lev)) p_ptr->spell_exp[spell] += 1; }
234                 else if(p_ptr->spell_exp[spell] < SPELL_EXP_EXPERT)
235                 { if (one_in_(5) && ((dun_level + 5) > p_ptr->lev) && ((dun_level + 5) > s_ptr->slevel)) p_ptr->spell_exp[spell] += 1; }
236                 else if(p_ptr->spell_exp[spell] < SPELL_EXP_MASTER)
237                 { if (one_in_(5) && ((dun_level + 5) > p_ptr->lev) && (dun_level > s_ptr->slevel)) p_ptr->spell_exp[spell] += 1; }
238         }
239
240         /* Do any effects of continual spells */
241         for (spell = 0; spell < 32; spell++)
242         {
243                 if (hex_spelling(spell))
244                 {
245                         do_spell(REALM_HEX, spell, SPELL_CONT);
246                 }
247         }
248 }
249
250 /*!
251  * @brief プレイヤーの呪術詠唱枠がすでに最大かどうかを返す
252  * @return すでに全枠を利用しているならTRUEを返す
253  */
254 bool hex_spell_fully(void)
255 {
256         int k_max = 0;
257
258         k_max = (p_ptr->lev / 15) + 1;
259
260         /* Paranoia */
261         k_max = MIN(k_max, MAX_KEEP);
262
263         if (p_ptr->magic_num2[0] < k_max) return FALSE;
264
265         return TRUE;
266 }
267
268 /*!
269  * @brief 一定ゲームターン毎に復讐処理の残り期間の判定を行う
270  * @return なし
271  */
272 void revenge_spell(void)
273 {
274         if (p_ptr->realm1 != REALM_HEX) return;
275         if (p_ptr->magic_num2[2] <= 0) return;
276
277         switch(p_ptr->magic_num2[1])
278         {
279         case 1: do_spell(REALM_HEX, HEX_PATIENCE, SPELL_CONT); break;
280         case 2: do_spell(REALM_HEX, HEX_REVENGE, SPELL_CONT); break;
281         }
282 }
283
284 /*!
285  * @brief 復讐ダメージの追加を行う
286  * @param dam 蓄積されるダメージ量
287  * @return なし
288  */
289 void revenge_store(int dam)
290 {
291         if (p_ptr->realm1 != REALM_HEX) return;
292         if (p_ptr->magic_num2[2] <= 0) return;
293
294         p_ptr->magic_num1[2] += dam;
295 }
296
297 /*!
298  * @brief 反テレポート結界の判定
299  * @param m_idx 判定の対象となるモンスターID
300  * @return 反テレポートの効果が適用されるならTRUEを返す
301  */
302 bool teleport_barrier(MONSTER_IDX m_idx)
303 {
304         monster_type *m_ptr = &m_list[m_idx];
305         monster_race *r_ptr = &r_info[m_ptr->r_idx];
306
307         if (!hex_spelling(HEX_ANTI_TELE)) return FALSE;
308         if ((p_ptr->lev * 3 / 2) < randint1(r_ptr->level)) return FALSE;
309
310         return TRUE;
311 }
312
313 /*!
314  * @brief 反魔法結界の判定
315  * @param m_idx 判定の対象となるモンスターID
316  * @return 反魔法の効果が適用されるならTRUEを返す
317  */
318 bool magic_barrier(MONSTER_IDX m_idx)
319 {
320         monster_type *m_ptr = &m_list[m_idx];
321         monster_race *r_ptr = &r_info[m_ptr->r_idx];
322
323         if (!hex_spelling(HEX_ANTI_MAGIC)) return FALSE;
324         if ((p_ptr->lev * 3 / 2) < randint1(r_ptr->level)) return FALSE;
325
326         return TRUE;
327 }
328
329 /*!
330  * @brief 反増殖結界の判定
331  * @param m_idx 判定の対象となるモンスターID
332  * @return 反増殖の効果が適用されるならTRUEを返す
333  */
334 bool multiply_barrier(MONSTER_IDX m_idx)
335 {
336         monster_type *m_ptr = &m_list[m_idx];
337         monster_race *r_ptr = &r_info[m_ptr->r_idx];
338
339         if (!hex_spelling(HEX_ANTI_MULTI)) return FALSE;
340         if ((p_ptr->lev * 3 / 2) < randint1(r_ptr->level)) return FALSE;
341
342         return TRUE;
343 }