OSDN Git Service

[Refactor] #37353 混乱時のコマンド制限処理を cmd_limit_confused() に統合。 / Integrate command limitat...
[hengband/hengband.git] / src / cmd-spell.c
1 /*!\r
2     @file cmd-spell.c\r
3     @brief 魔法のインターフェイスと発動 / Purpose: Do everything for each spell\r
4     @date 2013/12/31\r
5     @author\r
6     2013 Deskull rearranged comment for Doxygen.\r
7  */\r
8 \r
9 #include "angband.h"\r
10 #include "selfinfo.h"\r
11 #include "spells-summon.h"\r
12 #include "realm-arcane.h"\r
13 #include "realm-chaos.h"\r
14 #include "realm-craft.h"\r
15 #include "realm-crusade.h"\r
16 #include "realm-daemon.h"\r
17 #include "realm-death.h"\r
18 #include "realm-hex.h"\r
19 #include "realm-hissatsu.h"\r
20 #include "realm-life.h"\r
21 #include "realm-nature.h"\r
22 #include "realm-song.h"\r
23 #include "realm-sorcery.h"\r
24 #include "realm-trump.h"\r
25 #include "angband.h"\r
26 #include "avatar.h"\r
27 #include "player-status.h"\r
28 #include "object-hook.h"\r
29 \r
30 /*!\r
31  * @brief\r
32  * 魔法の効果を「キャプション:ダイス+定数値」のフォーマットで出力する / Generate dice info string such as "foo 2d10"\r
33  * @param str キャプション\r
34  * @param dice ダイス数\r
35  * @param sides ダイス目\r
36  * @param base 固定値\r
37  * @return フォーマットに従い整形された文字列\r
38  */\r
39 concptr info_string_dice(concptr str, DICE_NUMBER dice, DICE_SID sides, int base)\r
40 {\r
41         /* Fix value */\r
42         if (!dice)\r
43                 return format("%s%d", str, base);\r
44 \r
45         /* Dice only */\r
46         else if (!base)\r
47                 return format("%s%dd%d", str, dice, sides);\r
48 \r
49         /* Dice plus base value */\r
50         else\r
51                 return format("%s%dd%d%+d", str, dice, sides, base);\r
52 }\r
53 \r
54 \r
55 /*!\r
56  * @brief 魔法によるダメージを出力する / Generate damage-dice info string such as "dam 2d10"\r
57  * @param dice ダイス数\r
58  * @param sides ダイス目\r
59  * @param base 固定値\r
60  * @return フォーマットに従い整形された文字列\r
61  */\r
62 concptr info_damage(DICE_NUMBER dice, DICE_SID sides, int base)\r
63 {\r
64         return info_string_dice(_("損傷:", "dam "), dice, sides, base);\r
65 }\r
66 \r
67 /*!\r
68  * @brief 魔法の効果時間を出力する / Generate duration info string such as "dur 20+1d20"\r
69  * @param base 固定値\r
70  * @param sides ダイス目\r
71  * @return フォーマットに従い整形された文字列\r
72  */\r
73 concptr info_duration(int base, DICE_SID sides)\r
74 {\r
75         return format(_("期間:%d+1d%d", "dur %d+1d%d"), base, sides);\r
76 }\r
77 \r
78 /*!\r
79  * @brief 魔法の効果範囲を出力する / Generate range info string such as "range 5"\r
80  * @param range 効果範囲\r
81  * @return フォーマットに従い整形された文字列\r
82  */\r
83 concptr info_range(POSITION range)\r
84 {\r
85         return format(_("範囲:%d", "range %d"), range);\r
86 }\r
87 \r
88 /*!\r
89  * @brief 魔法による回復量を出力する / Generate heal info string such as "heal 2d8"\r
90  * @param dice ダイス数\r
91  * @param sides ダイス目\r
92  * @param base 固定値\r
93  * @return フォーマットに従い整形された文字列\r
94  */\r
95 concptr info_heal(DICE_NUMBER dice, DICE_SID sides, int base)\r
96 {\r
97         return info_string_dice(_("回復:", "heal "), dice, sides, base);\r
98 }\r
99 \r
100 /*!\r
101  * @brief 魔法効果発動までの遅延ターンを出力する / Generate delay info string such as "delay 15+1d15"\r
102  * @param base 固定値\r
103  * @param sides ダイス目\r
104  * @return フォーマットに従い整形された文字列\r
105  */\r
106 concptr info_delay(int base, DICE_SID sides)\r
107 {\r
108         return format(_("遅延:%d+1d%d", "delay %d+1d%d"), base, sides);\r
109 }\r
110 \r
111 \r
112 /*!\r
113  * @brief 魔法によるダメージを出力する(固定値&複数回処理) / Generate multiple-damage info string such as "dam 25 each"\r
114  * @param dam 固定値\r
115  * @return フォーマットに従い整形された文字列\r
116  */\r
117 concptr info_multi_damage(HIT_POINT dam)\r
118 {\r
119         return format(_("損傷:各%d", "dam %d each"), dam);\r
120 }\r
121 \r
122 \r
123 /*!\r
124  * @brief 魔法によるダメージを出力する(ダイスのみ&複数回処理) / Generate multiple-damage-dice info string such as "dam 5d2 each"\r
125  * @param dice ダイス数\r
126  * @param sides ダイス目\r
127  * @return フォーマットに従い整形された文字列\r
128  */\r
129 concptr info_multi_damage_dice(DICE_NUMBER dice, DICE_SID sides)\r
130 {\r
131         return format(_("損傷:各%dd%d", "dam %dd%d each"), dice, sides);\r
132 }\r
133 \r
134 /*!\r
135  * @brief 魔法による一般的な効力値を出力する(固定値) / Generate power info string such as "power 100"\r
136  * @param power 固定値\r
137  * @return フォーマットに従い整形された文字列\r
138  */\r
139 concptr info_power(int power)\r
140 {\r
141         return format(_("効力:%d", "power %d"), power);\r
142 }\r
143 \r
144 \r
145 /*!\r
146  * @brief 魔法による一般的な効力値を出力する(ダイス値) / Generate power info string such as "power 100"\r
147  * @param dice ダイス数\r
148  * @param sides ダイス目\r
149  * @return フォーマットに従い整形された文字列\r
150  */\r
151 /*\r
152  * Generate power info string such as "power 1d100"\r
153  */\r
154 concptr info_power_dice(DICE_NUMBER dice, DICE_SID sides)\r
155 {\r
156         return format(_("効力:%dd%d", "power %dd%d"), dice, sides);\r
157 }\r
158 \r
159 \r
160 /*!\r
161  * @brief 魔法の効果半径を出力する / Generate radius info string such as "rad 100"\r
162  * @param rad 効果半径\r
163  * @return フォーマットに従い整形された文字列\r
164  */\r
165 concptr info_radius(POSITION rad)\r
166 {\r
167         return format(_("半径:%d", "rad %d"), rad);\r
168 }\r
169 \r
170 \r
171 /*!\r
172  * @brief 魔法効果の限界重量を出力する / Generate weight info string such as "max wgt 15"\r
173  * @param weight 最大重量\r
174  * @return フォーマットに従い整形された文字列\r
175  */\r
176 concptr info_weight(WEIGHT weight)\r
177 {\r
178 #ifdef JP\r
179         return format("最大重量:%d.%dkg", lbtokg1(weight), lbtokg2(weight));\r
180 #else\r
181         return format("max wgt %d", weight/10);\r
182 #endif\r
183 }\r
184 \r
185 /*!\r
186  * @brief 魔法処理のメインルーチン\r
187  * @param realm 魔法領域のID\r
188  * @param spell 各領域の魔法ID\r
189  * @param mode 求める処理\r
190  * @return 各領域魔法に各種テキストを求めた場合は文字列参照ポインタ、そうでない場合はNULLポインタを返す。\r
191  */\r
192 concptr do_spell(REALM_IDX realm, SPELL_IDX spell, BIT_FLAGS mode)\r
193 {\r
194         switch (realm)\r
195         {\r
196         case REALM_LIFE:     return do_life_spell(spell, mode);\r
197         case REALM_SORCERY:  return do_sorcery_spell(spell, mode);\r
198         case REALM_NATURE:   return do_nature_spell(spell, mode);\r
199         case REALM_CHAOS:    return do_chaos_spell(spell, mode);\r
200         case REALM_DEATH:    return do_death_spell(spell, mode);\r
201         case REALM_TRUMP:    return do_trump_spell(spell, mode);\r
202         case REALM_ARCANE:   return do_arcane_spell(spell, mode);\r
203         case REALM_CRAFT:    return do_craft_spell(spell, mode);\r
204         case REALM_DAEMON:   return do_daemon_spell(spell, mode);\r
205         case REALM_CRUSADE:  return do_crusade_spell(spell, mode);\r
206         case REALM_MUSIC:    return do_music_spell(spell, mode);\r
207         case REALM_HISSATSU: return do_hissatsu_spell(spell, mode);\r
208         case REALM_HEX:      return do_hex_spell(spell, mode);\r
209         }\r
210 \r
211         return NULL;\r
212 }\r
213 \r
214 \r
215 /*!\r
216  * @brief 領域魔法の閲覧、学習、使用選択するインターフェイス処理\r
217  * Allow user to choose a spell/prayer from the given book.\r
218  * @param sn 選択した魔法IDを返す参照ポインタ\r
219  * @param prompt 魔法を利用する際の動詞表記\r
220  * @param sval 魔道書のsval\r
221  * @param learned 閲覧/使用選択ならばTRUE、学習処理ならFALSE\r
222  * @param use_realm 魔法領域ID\r
223  * @return\r
224  * <pre>\r
225  * If a valid spell is chosen, saves it in '*sn' and returns TRUE\r
226  * If the user hits escape, returns FALSE, and set '*sn' to -1\r
227  * If there are no legal choices, returns FALSE, and sets '*sn' to -2\r
228  * The "prompt" should be "cast", "recite", or "study"\r
229  * The "known" should be TRUE for cast/pray, FALSE for study\r
230  * </pre>\r
231  */\r
232 static int get_spell(SPELL_IDX *sn, concptr prompt, OBJECT_SUBTYPE_VALUE sval, bool learned, REALM_IDX use_realm)\r
233 {\r
234         int i;\r
235         SPELL_IDX spell = -1;\r
236         int num = 0;\r
237         int ask = TRUE;\r
238         MANA_POINT need_mana;\r
239         SPELL_IDX spells[64];\r
240         bool flag, redraw, okay;\r
241         char choice;\r
242         const magic_type  *s_ptr;\r
243         char out_val[160];\r
244         concptr p;\r
245         COMMAND_CODE code;\r
246 #ifdef JP\r
247         char jverb_buf[128];\r
248 #endif\r
249         int menu_line = (use_menu ? 1 : 0);\r
250 \r
251         /* Get the spell, if available */\r
252         if (repeat_pull(&code))\r
253         {\r
254                 *sn = (SPELL_IDX)code;\r
255                 /* Verify the spell */\r
256                 if (spell_okay(*sn, learned, FALSE, use_realm))\r
257                 {\r
258                         /* Success */\r
259                         return (TRUE);\r
260                 }\r
261         }\r
262 \r
263         p = spell_category_name(mp_ptr->spell_book);\r
264 \r
265         /* Extract spells */\r
266         for (spell = 0; spell < 32; spell++)\r
267         {\r
268                 /* Check for this spell */\r
269                 if ((fake_spell_flags[sval] & (1L << spell)))\r
270                 {\r
271                         /* Collect this spell */\r
272                         spells[num++] = spell;\r
273                 }\r
274         }\r
275 \r
276         /* Assume no usable spells */\r
277         okay = FALSE;\r
278 \r
279         /* Assume no spells available */\r
280         (*sn) = -2;\r
281 \r
282         /* Check for "okay" spells */\r
283         for (i = 0; i < num; i++)\r
284         {\r
285                 /* Look for "okay" spells */\r
286                 if (spell_okay(spells[i], learned, FALSE, use_realm)) okay = TRUE;\r
287         }\r
288 \r
289         /* No "okay" spells */\r
290         if (!okay) return (FALSE);\r
291         if (((use_realm) != p_ptr->realm1) && ((use_realm) != p_ptr->realm2) && (p_ptr->pclass != CLASS_SORCERER) && (p_ptr->pclass != CLASS_RED_MAGE)) return FALSE;\r
292         if (((p_ptr->pclass == CLASS_SORCERER) || (p_ptr->pclass == CLASS_RED_MAGE)) && !is_magic(use_realm)) return FALSE;\r
293         if ((p_ptr->pclass == CLASS_RED_MAGE) && ((use_realm) != REALM_ARCANE) && (sval > 1)) return FALSE;\r
294 \r
295         /* Assume cancelled */\r
296         *sn = (-1);\r
297 \r
298         /* Nothing chosen yet */\r
299         flag = FALSE;\r
300 \r
301         /* No redraw yet */\r
302         redraw = FALSE;\r
303 \r
304         p_ptr->window |= (PW_SPELL);\r
305         handle_stuff();\r
306 \r
307         /* Build a prompt (accept all spells) */\r
308 #ifdef JP\r
309         jverb(prompt, jverb_buf, JVERB_AND);\r
310         (void)strnfmt(out_val, 78, "(%^s:%c-%c, '*'で一覧, ESCで中断) どの%sを%^sますか? ",\r
311                 p, I2A(0), I2A(num - 1), p, jverb_buf);\r
312 #else\r
313         (void)strnfmt(out_val, 78, "(%^ss %c-%c, *=List, ESC=exit) %^s which %s? ",\r
314                 p, I2A(0), I2A(num - 1), prompt, p);\r
315 #endif\r
316 \r
317         /* Get a spell from the user */\r
318 \r
319         choice = (always_show_list || use_menu) ? ESCAPE : 1;\r
320         while (!flag)\r
321         {\r
322                 if (choice == ESCAPE) choice = ' ';\r
323                 else if (!get_com(out_val, &choice, TRUE))break;\r
324 \r
325                 if (use_menu && choice != ' ')\r
326                 {\r
327                         switch (choice)\r
328                         {\r
329                         case '0':\r
330                         {\r
331                                 screen_load();\r
332                                 return FALSE;\r
333                         }\r
334 \r
335                         case '8':\r
336                         case 'k':\r
337                         case 'K':\r
338                         {\r
339                                 menu_line += (num - 1);\r
340                                 break;\r
341                         }\r
342 \r
343                         case '2':\r
344                         case 'j':\r
345                         case 'J':\r
346                         {\r
347                                 menu_line++;\r
348                                 break;\r
349                         }\r
350 \r
351                         case 'x':\r
352                         case 'X':\r
353                         case '\r':\r
354                         case '\n':\r
355                         {\r
356                                 i = menu_line - 1;\r
357                                 ask = FALSE;\r
358                                 break;\r
359                         }\r
360                         }\r
361                         if (menu_line > num) menu_line -= num;\r
362                         /* Display a list of spells */\r
363                         print_spells(menu_line, spells, num, 1, 15, use_realm);\r
364                         if (ask) continue;\r
365                 }\r
366                 else\r
367                 {\r
368                         /* Request redraw */\r
369                         if ((choice == ' ') || (choice == '*') || (choice == '?'))\r
370                         {\r
371                                 /* Show the list */\r
372                                 if (!redraw)\r
373                                 {\r
374                                         /* Show list */\r
375                                         redraw = TRUE;\r
376                                         screen_save();\r
377 \r
378                                         /* Display a list of spells */\r
379                                         print_spells(menu_line, spells, num, 1, 15, use_realm);\r
380                                 }\r
381 \r
382                                 /* Hide the list */\r
383                                 else\r
384                                 {\r
385                                         if (use_menu) continue;\r
386 \r
387                                         /* Hide list */\r
388                                         redraw = FALSE;\r
389                                         screen_load();\r
390                                 }\r
391 \r
392                                 /* Redo asking */\r
393                                 continue;\r
394                         }\r
395 \r
396 \r
397                         /* Note verify */\r
398                         ask = (isupper(choice));\r
399 \r
400                         /* Lowercase */\r
401                         if (ask) choice = (char)tolower(choice);\r
402 \r
403                         /* Extract request */\r
404                         i = (islower(choice) ? A2I(choice) : -1);\r
405                 }\r
406 \r
407                 /* Totally Illegal */\r
408                 if ((i < 0) || (i >= num))\r
409                 {\r
410                         bell();\r
411                         continue;\r
412                 }\r
413 \r
414                 /* Save the spell index */\r
415                 spell = spells[i];\r
416 \r
417                 /* Require "okay" spells */\r
418                 if (!spell_okay(spell, learned, FALSE, use_realm))\r
419                 {\r
420                         bell();\r
421 #ifdef JP\r
422                         msg_format("その%sを%sことはできません。", p, prompt);\r
423 #else\r
424                         msg_format("You may not %s that %s.", prompt, p);\r
425 #endif\r
426 \r
427                         continue;\r
428                 }\r
429 \r
430                 /* Verify it */\r
431                 if (ask)\r
432                 {\r
433                         char tmp_val[160];\r
434 \r
435                         /* Access the spell */\r
436                         if (!is_magic(use_realm))\r
437                         {\r
438                                 s_ptr = &technic_info[use_realm - MIN_TECHNIC][spell];\r
439                         }\r
440                         else\r
441                         {\r
442                                 s_ptr = &mp_ptr->info[use_realm - 1][spell];\r
443                         }\r
444 \r
445                         /* Extract mana consumption rate */\r
446                         if (use_realm == REALM_HISSATSU)\r
447                         {\r
448                                 need_mana = s_ptr->smana;\r
449                         }\r
450                         else\r
451                         {\r
452                                 need_mana = mod_need_mana(s_ptr->smana, spell, use_realm);\r
453                         }\r
454 \r
455                         /* Prompt */\r
456 #ifdef JP\r
457                         jverb(prompt, jverb_buf, JVERB_AND);\r
458                         /* 英日切り替え機能に対応 */\r
459                         (void)strnfmt(tmp_val, 78, "%s(MP%d, 失敗率%d%%)を%sますか? ",\r
460                                 do_spell(use_realm, spell, SPELL_NAME), need_mana,\r
461                                 spell_chance(spell, use_realm), jverb_buf);\r
462 #else\r
463                         (void)strnfmt(tmp_val, 78, "%^s %s (%d mana, %d%% fail)? ",\r
464                                 prompt, do_spell(use_realm, spell, SPELL_NAME), need_mana,\r
465                                 spell_chance(spell, use_realm));\r
466 #endif\r
467 \r
468 \r
469                         /* Belay that order */\r
470                         if (!get_check(tmp_val)) continue;\r
471                 }\r
472 \r
473                 /* Stop the loop */\r
474                 flag = TRUE;\r
475         }\r
476 \r
477         if (redraw) screen_load();\r
478 \r
479         p_ptr->window |= (PW_SPELL);\r
480         handle_stuff();\r
481 \r
482         /* Abort if needed */\r
483         if (!flag) return FALSE;\r
484 \r
485         /* Save the choice */\r
486         (*sn) = spell;\r
487 \r
488         repeat_push((COMMAND_CODE)spell);\r
489 \r
490         /* Success */\r
491         return TRUE;\r
492 }\r
493 \r
494 /*!\r
495  * @brief プレイヤーの職業が練気術師の時、領域魔法と練気術を切り換える処理のインターフェイス\r
496  * @param browse_only 魔法と技能の閲覧を行うならばTRUE\r
497  * @return 魔道書を一冊も持っていないならTRUEを返す\r
498  */\r
499 static void confirm_use_force(bool browse_only)\r
500 {\r
501         char which;\r
502         COMMAND_CODE code;\r
503 \r
504         /* Get the item index */\r
505         if (repeat_pull(&code) && (code == INVEN_FORCE))\r
506         {\r
507                 browse_only ? do_cmd_mind_browse() : do_cmd_mind();\r
508                 return;\r
509         }\r
510 \r
511         /* Show the prompt */\r
512         prt(_("('w'練気術, ESC) 'w'かESCを押してください。 ", "(w for the Force, ESC) Hit 'w' or ESC. "), 0, 0);\r
513 \r
514         while (1)\r
515         {\r
516                 /* Get a key */\r
517                 which = inkey();\r
518 \r
519                 if (which == ESCAPE) break;\r
520                 else if (which == 'w')\r
521                 {\r
522                         repeat_push(INVEN_FORCE);\r
523                         break;\r
524                 }\r
525         }\r
526 \r
527         /* Clear the prompt line */\r
528         prt("", 0, 0);\r
529 \r
530         if (which == 'w')\r
531         {\r
532                 browse_only ? do_cmd_mind_browse() : do_cmd_mind();\r
533         }\r
534 }\r
535 \r
536 \r
537 /*!\r
538  * @brief プレイヤーの魔法と技能を閲覧するコマンドのメインルーチン /\r
539  * Peruse the spells/prayers in a book\r
540  * @return なし\r
541  * @details\r
542  * <pre>\r
543  * Note that *all* spells in the book are listed\r
544  *\r
545  * Note that browsing is allowed while confused or blind,\r
546  * and in the dark, primarily to allow browsing in stores.\r
547  * </pre>\r
548  */\r
549 void do_cmd_browse(void)\r
550 {\r
551         OBJECT_IDX item;\r
552         OBJECT_SUBTYPE_VALUE sval;\r
553         REALM_IDX use_realm = 0;\r
554         int j, line;\r
555         SPELL_IDX spell = -1;\r
556         int num = 0;\r
557 \r
558         SPELL_IDX spells[64];\r
559         char temp[62 * 4];\r
560 \r
561         object_type *o_ptr;\r
562 \r
563         concptr q, s;\r
564 \r
565         /* Warriors are illiterate */\r
566         if (!(p_ptr->realm1 || p_ptr->realm2) && (p_ptr->pclass != CLASS_SORCERER) && (p_ptr->pclass != CLASS_RED_MAGE))\r
567         {\r
568                 msg_print(_("本を読むことができない!", "You cannot read books!"));\r
569                 return;\r
570         }\r
571 \r
572         if (p_ptr->special_defense & KATA_MUSOU)\r
573         {\r
574                 set_action(ACTION_NONE);\r
575         }\r
576 \r
577         if (p_ptr->pclass == CLASS_FORCETRAINER)\r
578         {\r
579                 if (player_has_no_spellbooks())\r
580                 {\r
581                         confirm_use_force(TRUE);\r
582                         return;\r
583                 }\r
584         }\r
585 \r
586         /* Restrict choices to "useful" books */\r
587         if (p_ptr->realm2 == REALM_NONE) item_tester_tval = mp_ptr->spell_book;\r
588         else item_tester_hook = item_tester_learn_spell;\r
589 \r
590         q = _("どの本を読みますか? ", "Browse which book? ");\r
591         s = _("読める本がない。", "You have no books that you can read.");\r
592 \r
593         o_ptr = choose_object(&item, q, s, (USE_INVEN | USE_FLOOR | (p_ptr->pclass == CLASS_FORCETRAINER ? USE_FORCE : 0)));\r
594         if (!o_ptr)\r
595         {\r
596                 if (item == INVEN_FORCE) /* the_force */\r
597                 {\r
598                         do_cmd_mind_browse();\r
599                         return;\r
600                 }\r
601                 return;\r
602         }\r
603 \r
604         /* Access the item's sval */\r
605         sval = o_ptr->sval;\r
606 \r
607         use_realm = tval2realm(o_ptr->tval);\r
608 \r
609         /* Track the object kind */\r
610         object_kind_track(o_ptr->k_idx);\r
611         handle_stuff();\r
612 \r
613         /* Extract spells */\r
614         for (spell = 0; spell < 32; spell++)\r
615         {\r
616                 /* Check for this spell */\r
617                 if ((fake_spell_flags[sval] & (1L << spell)))\r
618                 {\r
619                         /* Collect this spell */\r
620                         spells[num++] = spell;\r
621                 }\r
622         }\r
623 \r
624         screen_save();\r
625         prt("", 0, 0);\r
626 \r
627         /* Keep browsing spells.  Exit browsing on cancel. */\r
628         while (TRUE)\r
629         {\r
630                 /* Ask for a spell, allow cancel */\r
631                 if (!get_spell(&spell, _("読む", "browse"), o_ptr->sval, TRUE, use_realm))\r
632                 {\r
633                         /* If cancelled, leave immediately. */\r
634                         if (spell == -1) break;\r
635 \r
636                         /* Display a list of spells */\r
637                         print_spells(0, spells, num, 1, 15, use_realm);\r
638 \r
639                         /* Notify that there's nothing to see, and wait. */\r
640                         if (use_realm == REALM_HISSATSU)\r
641                                 prt(_("読める技がない。", "No techniques to browse."), 0, 0);\r
642                         else\r
643                                 prt(_("読める呪文がない。", "No spells to browse."), 0, 0);\r
644                         (void)inkey();\r
645 \r
646                         screen_load();\r
647 \r
648                         return;\r
649                 }\r
650 \r
651                 /* Clear lines, position cursor  (really should use strlen here) */\r
652                 Term_erase(14, 14, 255);\r
653                 Term_erase(14, 13, 255);\r
654                 Term_erase(14, 12, 255);\r
655                 Term_erase(14, 11, 255);\r
656 \r
657                 roff_to_buf(do_spell(use_realm, spell, SPELL_DESC), 62, temp, sizeof(temp));\r
658 \r
659                 for (j = 0, line = 11; temp[j]; j += 1 + strlen(&temp[j]))\r
660                 {\r
661                         prt(&temp[j], line, 15);\r
662                         line++;\r
663                 }\r
664         }\r
665         screen_load();\r
666 }\r
667 \r
668 /*!\r
669  * @brief プレイヤーの第二魔法領域を変更する /\r
670  * @param next_realm 変更先の魔法領域ID\r
671  * @return なし\r
672  */\r
673 static void change_realm2(CHARACTER_IDX next_realm)\r
674 {\r
675         int i, j = 0;\r
676         char tmp[80];\r
677 \r
678         for (i = 0; i < 64; i++)\r
679         {\r
680                 p_ptr->spell_order[j] = p_ptr->spell_order[i];\r
681                 if (p_ptr->spell_order[i] < 32) j++;\r
682         }\r
683         for (; j < 64; j++)\r
684                 p_ptr->spell_order[j] = 99;\r
685 \r
686         for (i = 32; i < 64; i++)\r
687         {\r
688                 p_ptr->spell_exp[i] = SPELL_EXP_UNSKILLED;\r
689         }\r
690         p_ptr->spell_learned2 = 0L;\r
691         p_ptr->spell_worked2 = 0L;\r
692         p_ptr->spell_forgotten2 = 0L;\r
693 \r
694         sprintf(tmp, _("魔法の領域を%sから%sに変更した。", "change magic realm from %s to %s."), realm_names[p_ptr->realm2], realm_names[next_realm]);\r
695         do_cmd_write_nikki(NIKKI_BUNSHOU, 0, tmp);\r
696         p_ptr->old_realm |= 1 << (p_ptr->realm2 - 1);\r
697         p_ptr->realm2 = next_realm;\r
698 \r
699         p_ptr->update |= (PU_REORDER);\r
700         p_ptr->update |= (PU_SPELLS);\r
701         handle_stuff();\r
702 \r
703         /* Load an autopick preference file */\r
704         autopick_load_pref(FALSE);\r
705 }\r
706 \r
707 \r
708 /*!\r
709  * @brief 魔法を学習するコマンドのメインルーチン /\r
710  * Study a book to gain a new spell/prayer\r
711  * @return なし\r
712  */\r
713 void do_cmd_study(void)\r
714 {\r
715         int     i;\r
716         OBJECT_IDX item;\r
717         OBJECT_SUBTYPE_VALUE sval;\r
718         int     increment = 0;\r
719         bool    learned = FALSE;\r
720 \r
721         /* Spells of realm2 will have an increment of +32 */\r
722         SPELL_IDX spell = -1;\r
723 \r
724         concptr p = spell_category_name(mp_ptr->spell_book);\r
725 \r
726         object_type *o_ptr;\r
727 \r
728         concptr q, s;\r
729 \r
730         if (!p_ptr->realm1)\r
731         {\r
732                 msg_print(_("本を読むことができない!", "You cannot read books!"));\r
733                 return;\r
734         }\r
735 \r
736         if (p_ptr->blind || no_lite())\r
737         {\r
738                 msg_print(_("目が見えない!", "You cannot see!"));\r
739                 return;\r
740         }\r
741 \r
742         if (cmd_limit_confused(p_ptr)) return;\r
743 \r
744         if (!(p_ptr->new_spells))\r
745         {\r
746                 msg_format(_("新しい%sを覚えることはできない!", "You cannot learn any new %ss!"), p);\r
747                 return;\r
748         }\r
749 \r
750         if (p_ptr->special_defense & KATA_MUSOU)\r
751         {\r
752                 set_action(ACTION_NONE);\r
753         }\r
754 \r
755 #ifdef JP\r
756         if (p_ptr->new_spells < 10) {\r
757                 msg_format("あと %d つの%sを学べる。", p_ptr->new_spells, p);\r
758         }\r
759         else {\r
760                 msg_format("あと %d 個の%sを学べる。", p_ptr->new_spells, p);\r
761         }\r
762 #else\r
763         msg_format("You can learn %d new %s%s.", p_ptr->new_spells, p,\r
764                 (p_ptr->new_spells == 1 ? "" : "s"));\r
765 #endif\r
766 \r
767         msg_print(NULL);\r
768 \r
769 \r
770         /* Restrict choices to "useful" books */\r
771         if (p_ptr->realm2 == REALM_NONE) item_tester_tval = mp_ptr->spell_book;\r
772         else item_tester_hook = item_tester_learn_spell;\r
773 \r
774         q = _("どの本から学びますか? ", "Study which book? ");\r
775         s = _("読める本がない。", "You have no books that you can read.");\r
776 \r
777         o_ptr = choose_object(&item, q, s, (USE_INVEN | USE_FLOOR));\r
778         if (!o_ptr) return;\r
779 \r
780         /* Access the item's sval */\r
781         sval = o_ptr->sval;\r
782 \r
783         if (o_ptr->tval == REALM2_BOOK) increment = 32;\r
784         else if (o_ptr->tval != REALM1_BOOK)\r
785         {\r
786                 if (!get_check(_("本当に魔法の領域を変更しますか?", "Really, change magic realm? "))) return;\r
787                 change_realm2(tval2realm(o_ptr->tval));\r
788                 increment = 32;\r
789         }\r
790 \r
791         /* Track the object kind */\r
792         object_kind_track(o_ptr->k_idx);\r
793         handle_stuff();\r
794 \r
795         /* Mage -- Learn a selected spell */\r
796         if (mp_ptr->spell_book != TV_LIFE_BOOK)\r
797         {\r
798                 /* Ask for a spell, allow cancel */\r
799                 if (!get_spell(&spell, _("学ぶ", "study"), sval, FALSE, o_ptr->tval - TV_LIFE_BOOK + 1) && (spell == -1)) return;\r
800         }\r
801 \r
802         /* Priest -- Learn a random prayer */\r
803         else\r
804         {\r
805                 int k = 0;\r
806                 int gift = -1;\r
807 \r
808                 /* Extract spells */\r
809                 for (spell = 0; spell < 32; spell++)\r
810                 {\r
811                         /* Check spells in the book */\r
812                         if ((fake_spell_flags[sval] & (1L << spell)))\r
813                         {\r
814                                 /* Skip non "okay" prayers */\r
815                                 if (!spell_okay(spell, FALSE, TRUE,\r
816                                         (increment ? p_ptr->realm2 : p_ptr->realm1))) continue;\r
817 \r
818                                 /* Hack -- Prepare the randomizer */\r
819                                 k++;\r
820 \r
821                                 /* Hack -- Apply the randomizer */\r
822                                 if (one_in_(k)) gift = spell;\r
823                         }\r
824                 }\r
825 \r
826                 /* Accept gift */\r
827                 spell = gift;\r
828         }\r
829 \r
830         /* Nothing to study */\r
831         if (spell < 0)\r
832         {\r
833                 msg_format(_("その本には学ぶべき%sがない。", "You cannot learn any %ss in that book."), p);\r
834 \r
835                 /* Abort */\r
836                 return;\r
837         }\r
838 \r
839         if (increment) spell += increment;\r
840 \r
841         /* Learn the spell */\r
842         if (spell < 32)\r
843         {\r
844                 if (p_ptr->spell_learned1 & (1L << spell)) learned = TRUE;\r
845                 else p_ptr->spell_learned1 |= (1L << spell);\r
846         }\r
847         else\r
848         {\r
849                 if (p_ptr->spell_learned2 & (1L << (spell - 32))) learned = TRUE;\r
850                 else p_ptr->spell_learned2 |= (1L << (spell - 32));\r
851         }\r
852 \r
853         if (learned)\r
854         {\r
855                 int max_exp = (spell < 32) ? SPELL_EXP_MASTER : SPELL_EXP_EXPERT;\r
856                 int old_exp = p_ptr->spell_exp[spell];\r
857                 int new_rank = EXP_LEVEL_UNSKILLED;\r
858                 concptr name = do_spell(increment ? p_ptr->realm2 : p_ptr->realm1, spell % 32, SPELL_NAME);\r
859 \r
860                 if (old_exp >= max_exp)\r
861                 {\r
862                         msg_format(_("その%sは完全に使いこなせるので学ぶ必要はない。", "You don't need to study this %s anymore."), p);\r
863                         return;\r
864                 }\r
865 #ifdef JP\r
866                 if (!get_check(format("%sの%sをさらに学びます。よろしいですか?", name, p)))\r
867 #else\r
868                 if (!get_check(format("You will study a %s of %s again. Are you sure? ", p, name)))\r
869 #endif\r
870                 {\r
871                         return;\r
872                 }\r
873                 else if (old_exp >= SPELL_EXP_EXPERT)\r
874                 {\r
875                         p_ptr->spell_exp[spell] = SPELL_EXP_MASTER;\r
876                         new_rank = EXP_LEVEL_MASTER;\r
877                 }\r
878                 else if (old_exp >= SPELL_EXP_SKILLED)\r
879                 {\r
880                         if (spell >= 32) p_ptr->spell_exp[spell] = SPELL_EXP_EXPERT;\r
881                         else p_ptr->spell_exp[spell] += SPELL_EXP_EXPERT - SPELL_EXP_SKILLED;\r
882                         new_rank = EXP_LEVEL_EXPERT;\r
883                 }\r
884                 else if (old_exp >= SPELL_EXP_BEGINNER)\r
885                 {\r
886                         p_ptr->spell_exp[spell] = SPELL_EXP_SKILLED + (old_exp - SPELL_EXP_BEGINNER) * 2 / 3;\r
887                         new_rank = EXP_LEVEL_SKILLED;\r
888                 }\r
889                 else\r
890                 {\r
891                         p_ptr->spell_exp[spell] = SPELL_EXP_BEGINNER + old_exp / 3;\r
892                         new_rank = EXP_LEVEL_BEGINNER;\r
893                 }\r
894                 msg_format(_("%sの熟練度が%sに上がった。", "Your proficiency of %s is now %s rank."), name, exp_level_str[new_rank]);\r
895         }\r
896         else\r
897         {\r
898                 /* Find the next open entry in "p_ptr->spell_order[]" */\r
899                 for (i = 0; i < 64; i++)\r
900                 {\r
901                         /* Stop at the first empty space */\r
902                         if (p_ptr->spell_order[i] == 99) break;\r
903                 }\r
904 \r
905                 /* Add the spell to the known list */\r
906                 p_ptr->spell_order[i++] = spell;\r
907 \r
908                 /* Mention the result */\r
909 #ifdef JP\r
910                 /* 英日切り替え機能に対応 */\r
911                 if (mp_ptr->spell_book == TV_MUSIC_BOOK)\r
912                 {\r
913                         msg_format("%sを学んだ。",\r
914                                 do_spell(increment ? p_ptr->realm2 : p_ptr->realm1, spell % 32, SPELL_NAME));\r
915                 }\r
916                 else\r
917                 {\r
918                         msg_format("%sの%sを学んだ。",\r
919                                 do_spell(increment ? p_ptr->realm2 : p_ptr->realm1, spell % 32, SPELL_NAME), p);\r
920                 }\r
921 #else\r
922                 msg_format("You have learned the %s of %s.",\r
923                         p, do_spell(increment ? p_ptr->realm2 : p_ptr->realm1, spell % 32, SPELL_NAME));\r
924 #endif\r
925         }\r
926 \r
927         p_ptr->energy_use = 100;\r
928 \r
929         switch (mp_ptr->spell_book)\r
930         {\r
931         case TV_LIFE_BOOK:\r
932                 chg_virtue(V_FAITH, 1);\r
933                 break;\r
934         case TV_DEATH_BOOK:\r
935                 chg_virtue(V_UNLIFE, 1);\r
936                 break;\r
937         case TV_NATURE_BOOK:\r
938                 chg_virtue(V_NATURE, 1);\r
939                 break;\r
940         default:\r
941                 chg_virtue(V_KNOWLEDGE, 1);\r
942                 break;\r
943         }\r
944 \r
945         sound(SOUND_STUDY);\r
946 \r
947         /* One less spell available */\r
948         p_ptr->learned_spells++;\r
949 \r
950         /* Update Study */\r
951         p_ptr->update |= (PU_SPELLS);\r
952         update_creature(p_ptr);\r
953 \r
954         /* Redraw object recall */\r
955         p_ptr->window |= (PW_OBJECT);\r
956 }\r
957 \r
958 \r
959 /*!\r
960  * @brief 魔法を詠唱するコマンドのメインルーチン /\r
961  * Cast a spell\r
962  * @return なし\r
963  */\r
964 void do_cmd_cast(void)\r
965 {\r
966         OBJECT_IDX item;\r
967         OBJECT_SUBTYPE_VALUE sval;\r
968         SPELL_IDX spell;\r
969         REALM_IDX realm;\r
970         int     chance;\r
971         int     increment = 0;\r
972         REALM_IDX use_realm;\r
973         MANA_POINT need_mana;\r
974 \r
975         concptr prayer;\r
976         object_type *o_ptr;\r
977         const magic_type *s_ptr;\r
978         concptr q, s;\r
979 \r
980         bool over_exerted = FALSE;\r
981 \r
982         /* Require spell ability */\r
983         if (!p_ptr->realm1 && (p_ptr->pclass != CLASS_SORCERER) && (p_ptr->pclass != CLASS_RED_MAGE))\r
984         {\r
985                 msg_print(_("呪文を唱えられない!", "You cannot cast spells!"));\r
986                 return;\r
987         }\r
988 \r
989         /* Require lite */\r
990         if (p_ptr->blind || no_lite())\r
991         {\r
992                 if (p_ptr->pclass == CLASS_FORCETRAINER) confirm_use_force(FALSE);\r
993                 else\r
994                 {\r
995                         msg_print(_("目が見えない!", "You cannot see!"));\r
996                         flush();\r
997                 }\r
998                 return;\r
999         }\r
1000 \r
1001         if (cmd_limit_confused(p_ptr)) return;\r
1002 \r
1003         /* Hex */\r
1004         if (p_ptr->realm1 == REALM_HEX)\r
1005         {\r
1006                 if (hex_spell_fully())\r
1007                 {\r
1008                         bool flag = FALSE;\r
1009                         msg_print(_("これ以上新しい呪文を詠唱することはできない。", "Can not spell new spells more."));\r
1010                         flush();\r
1011                         if (p_ptr->lev >= 35) flag = stop_hex_spell();\r
1012                         if (!flag) return;\r
1013                 }\r
1014         }\r
1015 \r
1016         if (p_ptr->pclass == CLASS_FORCETRAINER)\r
1017         {\r
1018                 if (player_has_no_spellbooks())\r
1019                 {\r
1020                         confirm_use_force(FALSE);\r
1021                         return;\r
1022                 }\r
1023         }\r
1024 \r
1025         prayer = spell_category_name(mp_ptr->spell_book);\r
1026 \r
1027         /* Restrict choices to spell books */\r
1028         item_tester_tval = mp_ptr->spell_book;\r
1029 \r
1030         q = _("どの呪文書を使いますか? ", "Use which book? ");\r
1031         s = _("呪文書がない!", "You have no spell books!");\r
1032 \r
1033         o_ptr = choose_object(&item, q, s, (USE_INVEN | USE_FLOOR | (p_ptr->pclass == CLASS_FORCETRAINER ? USE_FORCE : 0)));\r
1034         if (!o_ptr)\r
1035         {\r
1036                 if (item == INVEN_FORCE) /* the_force */\r
1037                 {\r
1038                         do_cmd_mind();\r
1039                         return;\r
1040                 }\r
1041                 return;\r
1042         }\r
1043 \r
1044         /* Access the item's sval */\r
1045         sval = o_ptr->sval;\r
1046 \r
1047         if ((p_ptr->pclass != CLASS_SORCERER) && (p_ptr->pclass != CLASS_RED_MAGE) && (o_ptr->tval == REALM2_BOOK)) increment = 32;\r
1048 \r
1049         /* Track the object kind */\r
1050         object_kind_track(o_ptr->k_idx);\r
1051         handle_stuff();\r
1052 \r
1053         if ((p_ptr->pclass == CLASS_SORCERER) || (p_ptr->pclass == CLASS_RED_MAGE))\r
1054                 realm = o_ptr->tval - TV_LIFE_BOOK + 1;\r
1055         else if (increment) realm = p_ptr->realm2;\r
1056         else realm = p_ptr->realm1;\r
1057 \r
1058         /* Ask for a spell */\r
1059 #ifdef JP\r
1060         if (!get_spell(&spell, ((mp_ptr->spell_book == TV_LIFE_BOOK) ? "詠唱する" : (mp_ptr->spell_book == TV_MUSIC_BOOK) ? "歌う" : "唱える"),\r
1061                 sval, TRUE, realm))\r
1062         {\r
1063                 if (spell == -2) msg_format("その本には知っている%sがない。", prayer);\r
1064                 return;\r
1065         }\r
1066 #else\r
1067         if (!get_spell(&spell, ((mp_ptr->spell_book == TV_LIFE_BOOK) ? "recite" : "cast"),\r
1068                 sval, TRUE, realm))\r
1069         {\r
1070                 if (spell == -2)\r
1071                         msg_format("You don't know any %ss in that book.", prayer);\r
1072                 return;\r
1073         }\r
1074 #endif\r
1075 \r
1076 \r
1077         use_realm = tval2realm(o_ptr->tval);\r
1078 \r
1079         /* Hex */\r
1080         if (use_realm == REALM_HEX)\r
1081         {\r
1082                 if (hex_spelling(spell))\r
1083                 {\r
1084                         msg_print(_("その呪文はすでに詠唱中だ。", "You are already casting it."));\r
1085                         return;\r
1086                 }\r
1087         }\r
1088 \r
1089         if (!is_magic(use_realm))\r
1090         {\r
1091                 s_ptr = &technic_info[use_realm - MIN_TECHNIC][spell];\r
1092         }\r
1093         else\r
1094         {\r
1095                 s_ptr = &mp_ptr->info[realm - 1][spell];\r
1096         }\r
1097 \r
1098         /* Extract mana consumption rate */\r
1099         need_mana = mod_need_mana(s_ptr->smana, spell, realm);\r
1100 \r
1101         /* Verify "dangerous" spells */\r
1102         if (need_mana > p_ptr->csp)\r
1103         {\r
1104                 if (flush_failure) flush();\r
1105 \r
1106                 /* Warning */\r
1107 #ifdef JP\r
1108                 msg_format("その%sを%sのに十分なマジックポイントがない。", prayer,\r
1109                         ((mp_ptr->spell_book == TV_LIFE_BOOK) ? "詠唱する" : (mp_ptr->spell_book == TV_LIFE_BOOK) ? "歌う" : "唱える"));\r
1110 #else\r
1111                 msg_format("You do not have enough mana to %s this %s.",\r
1112                         ((mp_ptr->spell_book == TV_LIFE_BOOK) ? "recite" : "cast"),\r
1113                         prayer);\r
1114 #endif\r
1115 \r
1116 \r
1117                 if (!over_exert) return;\r
1118 \r
1119                 /* Verify */\r
1120                 if (!get_check_strict(_("それでも挑戦しますか? ", "Attempt it anyway? "), CHECK_OKAY_CANCEL)) return;\r
1121         }\r
1122 \r
1123         /* Spell failure chance */\r
1124         chance = spell_chance(spell, use_realm);\r
1125 \r
1126         /* Sufficient mana */\r
1127         if (need_mana <= p_ptr->csp)\r
1128         {\r
1129                 /* Use some mana */\r
1130                 p_ptr->csp -= need_mana;\r
1131         }\r
1132         else over_exerted = TRUE;\r
1133         p_ptr->redraw |= (PR_MANA);\r
1134 \r
1135         /* Failed spell */\r
1136         if (randint0(100) < chance)\r
1137         {\r
1138                 if (flush_failure) flush();\r
1139 \r
1140                 msg_format(_("%sをうまく唱えられなかった!", "You failed to get the %s off!"), prayer);\r
1141                 sound(SOUND_FAIL);\r
1142 \r
1143                 switch (realm)\r
1144                 {\r
1145                 case REALM_LIFE:\r
1146                         if (randint1(100) < chance) chg_virtue(V_VITALITY, -1);\r
1147                         break;\r
1148                 case REALM_DEATH:\r
1149                         if (randint1(100) < chance) chg_virtue(V_UNLIFE, -1);\r
1150                         break;\r
1151                 case REALM_NATURE:\r
1152                         if (randint1(100) < chance) chg_virtue(V_NATURE, -1);\r
1153                         break;\r
1154                 case REALM_DAEMON:\r
1155                         if (randint1(100) < chance) chg_virtue(V_JUSTICE, 1);\r
1156                         break;\r
1157                 case REALM_CRUSADE:\r
1158                         if (randint1(100) < chance) chg_virtue(V_JUSTICE, -1);\r
1159                         break;\r
1160                 case REALM_HEX:\r
1161                         if (randint1(100) < chance) chg_virtue(V_COMPASSION, -1);\r
1162                         break;\r
1163                 default:\r
1164                         if (randint1(100) < chance) chg_virtue(V_KNOWLEDGE, -1);\r
1165                         break;\r
1166                 }\r
1167 \r
1168                 /* Failure casting may activate some side effect */\r
1169                 do_spell(realm, spell, SPELL_FAIL);\r
1170 \r
1171 \r
1172                 if ((o_ptr->tval == TV_CHAOS_BOOK) && (randint1(100) < spell))\r
1173                 {\r
1174                         msg_print(_("カオス的な効果を発生した!", "You produce a chaotic effect!"));\r
1175                         wild_magic(spell);\r
1176                 }\r
1177                 else if ((o_ptr->tval == TV_DEATH_BOOK) && (randint1(100) < spell))\r
1178                 {\r
1179                         if ((sval == 3) && one_in_(2))\r
1180                         {\r
1181                                 sanity_blast(0, TRUE);\r
1182                         }\r
1183                         else\r
1184                         {\r
1185                                 msg_print(_("痛い!", "It hurts!"));\r
1186                                 take_hit(DAMAGE_LOSELIFE, damroll(o_ptr->sval + 1, 6), _("暗黒魔法の逆流", "a miscast Death spell"), -1);\r
1187 \r
1188                                 if ((spell > 15) && one_in_(6) && !p_ptr->hold_exp)\r
1189                                         lose_exp(spell * 250);\r
1190                         }\r
1191                 }\r
1192                 else if ((o_ptr->tval == TV_MUSIC_BOOK) && (randint1(200) < spell))\r
1193                 {\r
1194                         msg_print(_("いやな音が響いた", "An infernal sound echoed."));\r
1195                         aggravate_monsters(0);\r
1196                 }\r
1197                 if (randint1(100) >= chance)\r
1198                         chg_virtue(V_CHANCE, -1);\r
1199         }\r
1200 \r
1201         /* Process spell */\r
1202         else\r
1203         {\r
1204                 /* Canceled spells cost neither a turn nor mana */\r
1205                 if (!do_spell(realm, spell, SPELL_CAST)) return;\r
1206 \r
1207                 if (randint1(100) < chance)\r
1208                         chg_virtue(V_CHANCE, 1);\r
1209 \r
1210                 /* A spell was cast */\r
1211                 if (!(increment ?\r
1212                         (p_ptr->spell_worked2 & (1L << spell)) :\r
1213                         (p_ptr->spell_worked1 & (1L << spell)))\r
1214                         && (p_ptr->pclass != CLASS_SORCERER)\r
1215                         && (p_ptr->pclass != CLASS_RED_MAGE))\r
1216                 {\r
1217                         int e = s_ptr->sexp;\r
1218 \r
1219                         /* The spell worked */\r
1220                         if (realm == p_ptr->realm1)\r
1221                         {\r
1222                                 p_ptr->spell_worked1 |= (1L << spell);\r
1223                         }\r
1224                         else\r
1225                         {\r
1226                                 p_ptr->spell_worked2 |= (1L << spell);\r
1227                         }\r
1228 \r
1229                         /* Gain experience */\r
1230                         gain_exp(e * s_ptr->slevel);\r
1231 \r
1232                         /* Redraw object recall */\r
1233                         p_ptr->window |= (PW_OBJECT);\r
1234 \r
1235                         switch (realm)\r
1236                         {\r
1237                         case REALM_LIFE:\r
1238                                 chg_virtue(V_TEMPERANCE, 1);\r
1239                                 chg_virtue(V_COMPASSION, 1);\r
1240                                 chg_virtue(V_VITALITY, 1);\r
1241                                 chg_virtue(V_DILIGENCE, 1);\r
1242                                 break;\r
1243                         case REALM_DEATH:\r
1244                                 chg_virtue(V_UNLIFE, 1);\r
1245                                 chg_virtue(V_JUSTICE, -1);\r
1246                                 chg_virtue(V_FAITH, -1);\r
1247                                 chg_virtue(V_VITALITY, -1);\r
1248                                 break;\r
1249                         case REALM_DAEMON:\r
1250                                 chg_virtue(V_JUSTICE, -1);\r
1251                                 chg_virtue(V_FAITH, -1);\r
1252                                 chg_virtue(V_HONOUR, -1);\r
1253                                 chg_virtue(V_TEMPERANCE, -1);\r
1254                                 break;\r
1255                         case REALM_CRUSADE:\r
1256                                 chg_virtue(V_FAITH, 1);\r
1257                                 chg_virtue(V_JUSTICE, 1);\r
1258                                 chg_virtue(V_SACRIFICE, 1);\r
1259                                 chg_virtue(V_HONOUR, 1);\r
1260                                 break;\r
1261                         case REALM_NATURE:\r
1262                                 chg_virtue(V_NATURE, 1);\r
1263                                 chg_virtue(V_HARMONY, 1);\r
1264                                 break;\r
1265                         case REALM_HEX:\r
1266                                 chg_virtue(V_JUSTICE, -1);\r
1267                                 chg_virtue(V_FAITH, -1);\r
1268                                 chg_virtue(V_HONOUR, -1);\r
1269                                 chg_virtue(V_COMPASSION, -1);\r
1270                                 break;\r
1271                         default:\r
1272                                 chg_virtue(V_KNOWLEDGE, 1);\r
1273                                 break;\r
1274                         }\r
1275                 }\r
1276                 switch (realm)\r
1277                 {\r
1278                 case REALM_LIFE:\r
1279                         if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_TEMPERANCE, 1);\r
1280                         if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_COMPASSION, 1);\r
1281                         if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_VITALITY, 1);\r
1282                         if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_DILIGENCE, 1);\r
1283                         break;\r
1284                 case REALM_DEATH:\r
1285                         if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_UNLIFE, 1);\r
1286                         if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_JUSTICE, -1);\r
1287                         if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_FAITH, -1);\r
1288                         if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_VITALITY, -1);\r
1289                         break;\r
1290                 case REALM_DAEMON:\r
1291                         if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_JUSTICE, -1);\r
1292                         if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_FAITH, -1);\r
1293                         if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_HONOUR, -1);\r
1294                         if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_TEMPERANCE, -1);\r
1295                         break;\r
1296                 case REALM_CRUSADE:\r
1297                         if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_FAITH, 1);\r
1298                         if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_JUSTICE, 1);\r
1299                         if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_SACRIFICE, 1);\r
1300                         if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_HONOUR, 1);\r
1301                         break;\r
1302                 case REALM_NATURE:\r
1303                         if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_NATURE, 1);\r
1304                         if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_HARMONY, 1);\r
1305                         break;\r
1306                 case REALM_HEX:\r
1307                         if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_JUSTICE, -1);\r
1308                         if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_FAITH, -1);\r
1309                         if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_HONOUR, -1);\r
1310                         if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_COMPASSION, -1);\r
1311                         break;\r
1312                 }\r
1313                 if (mp_ptr->spell_xtra & MAGIC_GAIN_EXP)\r
1314                 {\r
1315                         s16b cur_exp = p_ptr->spell_exp[(increment ? 32 : 0) + spell];\r
1316                         s16b exp_gain = 0;\r
1317 \r
1318                         if (cur_exp < SPELL_EXP_BEGINNER)\r
1319                                 exp_gain += 60;\r
1320                         else if (cur_exp < SPELL_EXP_SKILLED)\r
1321                         {\r
1322                                 if ((dun_level > 4) && ((dun_level + 10) > p_ptr->lev))\r
1323                                         exp_gain = 8;\r
1324                         }\r
1325                         else if (cur_exp < SPELL_EXP_EXPERT)\r
1326                         {\r
1327                                 if (((dun_level + 5) > p_ptr->lev) && ((dun_level + 5) > s_ptr->slevel))\r
1328                                         exp_gain = 2;\r
1329                         }\r
1330                         else if ((cur_exp < SPELL_EXP_MASTER) && !increment)\r
1331                         {\r
1332                                 if (((dun_level + 5) > p_ptr->lev) && (dun_level > s_ptr->slevel))\r
1333                                         exp_gain = 1;\r
1334                         }\r
1335                         p_ptr->spell_exp[(increment ? 32 : 0) + spell] += exp_gain;\r
1336                 }\r
1337         }\r
1338 \r
1339         p_ptr->energy_use = 100;\r
1340 \r
1341 \r
1342         /* Over-exert the player */\r
1343         if (over_exerted)\r
1344         {\r
1345                 int oops = need_mana;\r
1346 \r
1347                 /* No mana left */\r
1348                 p_ptr->csp = 0;\r
1349                 p_ptr->csp_frac = 0;\r
1350 \r
1351                 msg_print(_("精神を集中しすぎて気を失ってしまった!", "You faint from the effort!"));\r
1352 \r
1353                 /* Hack -- Bypass free action */\r
1354                 (void)set_paralyzed(p_ptr->paralyzed + randint1(5 * oops + 1));\r
1355 \r
1356                 switch (realm)\r
1357                 {\r
1358                 case REALM_LIFE:\r
1359                         chg_virtue(V_VITALITY, -10);\r
1360                         break;\r
1361                 case REALM_DEATH:\r
1362                         chg_virtue(V_UNLIFE, -10);\r
1363                         break;\r
1364                 case REALM_DAEMON:\r
1365                         chg_virtue(V_JUSTICE, 10);\r
1366                         break;\r
1367                 case REALM_NATURE:\r
1368                         chg_virtue(V_NATURE, -10);\r
1369                         break;\r
1370                 case REALM_CRUSADE:\r
1371                         chg_virtue(V_JUSTICE, -10);\r
1372                         break;\r
1373                 case REALM_HEX:\r
1374                         chg_virtue(V_COMPASSION, 10);\r
1375                         break;\r
1376                 default:\r
1377                         chg_virtue(V_KNOWLEDGE, -10);\r
1378                         break;\r
1379                 }\r
1380 \r
1381                 /* Damage CON (possibly permanently) */\r
1382                 if (randint0(100) < 50)\r
1383                 {\r
1384                         bool perm = (randint0(100) < 25);\r
1385 \r
1386                         msg_print(_("体を悪くしてしまった!", "You have damaged your health!"));\r
1387 \r
1388                         /* Reduce constitution */\r
1389                         (void)dec_stat(A_CON, 15 + randint1(10), perm);\r
1390                 }\r
1391         }\r
1392 \r
1393         p_ptr->window |= (PW_PLAYER);\r
1394         p_ptr->window |= (PW_SPELL);\r
1395 }\r