OSDN Git Service

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