OSDN Git Service

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