OSDN Git Service

cf642b51252bef436da0f1552666ea4911a52f2d
[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 (p_ptr->confused)\r
743         {\r
744                 msg_print(_("混乱していて読めない!", "You are too confused!"));\r
745                 return;\r
746         }\r
747 \r
748         if (!(p_ptr->new_spells))\r
749         {\r
750                 msg_format(_("新しい%sを覚えることはできない!", "You cannot learn any new %ss!"), p);\r
751                 return;\r
752         }\r
753 \r
754         if (p_ptr->special_defense & KATA_MUSOU)\r
755         {\r
756                 set_action(ACTION_NONE);\r
757         }\r
758 \r
759 #ifdef JP\r
760         if (p_ptr->new_spells < 10) {\r
761                 msg_format("あと %d つの%sを学べる。", p_ptr->new_spells, p);\r
762         }\r
763         else {\r
764                 msg_format("あと %d 個の%sを学べる。", p_ptr->new_spells, p);\r
765         }\r
766 #else\r
767         msg_format("You can learn %d new %s%s.", p_ptr->new_spells, p,\r
768                 (p_ptr->new_spells == 1 ? "" : "s"));\r
769 #endif\r
770 \r
771         msg_print(NULL);\r
772 \r
773 \r
774         /* Restrict choices to "useful" books */\r
775         if (p_ptr->realm2 == REALM_NONE) item_tester_tval = mp_ptr->spell_book;\r
776         else item_tester_hook = item_tester_learn_spell;\r
777 \r
778         q = _("どの本から学びますか? ", "Study which book? ");\r
779         s = _("読める本がない。", "You have no books that you can read.");\r
780 \r
781         o_ptr = choose_object(&item, q, s, (USE_INVEN | USE_FLOOR));\r
782         if (!o_ptr) return;\r
783 \r
784         /* Access the item's sval */\r
785         sval = o_ptr->sval;\r
786 \r
787         if (o_ptr->tval == REALM2_BOOK) increment = 32;\r
788         else if (o_ptr->tval != REALM1_BOOK)\r
789         {\r
790                 if (!get_check(_("本当に魔法の領域を変更しますか?", "Really, change magic realm? "))) return;\r
791                 change_realm2(tval2realm(o_ptr->tval));\r
792                 increment = 32;\r
793         }\r
794 \r
795         /* Track the object kind */\r
796         object_kind_track(o_ptr->k_idx);\r
797         handle_stuff();\r
798 \r
799         /* Mage -- Learn a selected spell */\r
800         if (mp_ptr->spell_book != TV_LIFE_BOOK)\r
801         {\r
802                 /* Ask for a spell, allow cancel */\r
803                 if (!get_spell(&spell, _("学ぶ", "study"), sval, FALSE, o_ptr->tval - TV_LIFE_BOOK + 1) && (spell == -1)) return;\r
804         }\r
805 \r
806         /* Priest -- Learn a random prayer */\r
807         else\r
808         {\r
809                 int k = 0;\r
810                 int gift = -1;\r
811 \r
812                 /* Extract spells */\r
813                 for (spell = 0; spell < 32; spell++)\r
814                 {\r
815                         /* Check spells in the book */\r
816                         if ((fake_spell_flags[sval] & (1L << spell)))\r
817                         {\r
818                                 /* Skip non "okay" prayers */\r
819                                 if (!spell_okay(spell, FALSE, TRUE,\r
820                                         (increment ? p_ptr->realm2 : p_ptr->realm1))) continue;\r
821 \r
822                                 /* Hack -- Prepare the randomizer */\r
823                                 k++;\r
824 \r
825                                 /* Hack -- Apply the randomizer */\r
826                                 if (one_in_(k)) gift = spell;\r
827                         }\r
828                 }\r
829 \r
830                 /* Accept gift */\r
831                 spell = gift;\r
832         }\r
833 \r
834         /* Nothing to study */\r
835         if (spell < 0)\r
836         {\r
837                 msg_format(_("その本には学ぶべき%sがない。", "You cannot learn any %ss in that book."), p);\r
838 \r
839                 /* Abort */\r
840                 return;\r
841         }\r
842 \r
843         if (increment) spell += increment;\r
844 \r
845         /* Learn the spell */\r
846         if (spell < 32)\r
847         {\r
848                 if (p_ptr->spell_learned1 & (1L << spell)) learned = TRUE;\r
849                 else p_ptr->spell_learned1 |= (1L << spell);\r
850         }\r
851         else\r
852         {\r
853                 if (p_ptr->spell_learned2 & (1L << (spell - 32))) learned = TRUE;\r
854                 else p_ptr->spell_learned2 |= (1L << (spell - 32));\r
855         }\r
856 \r
857         if (learned)\r
858         {\r
859                 int max_exp = (spell < 32) ? SPELL_EXP_MASTER : SPELL_EXP_EXPERT;\r
860                 int old_exp = p_ptr->spell_exp[spell];\r
861                 int new_rank = EXP_LEVEL_UNSKILLED;\r
862                 concptr name = do_spell(increment ? p_ptr->realm2 : p_ptr->realm1, spell % 32, SPELL_NAME);\r
863 \r
864                 if (old_exp >= max_exp)\r
865                 {\r
866                         msg_format(_("その%sは完全に使いこなせるので学ぶ必要はない。", "You don't need to study this %s anymore."), p);\r
867                         return;\r
868                 }\r
869 #ifdef JP\r
870                 if (!get_check(format("%sの%sをさらに学びます。よろしいですか?", name, p)))\r
871 #else\r
872                 if (!get_check(format("You will study a %s of %s again. Are you sure? ", p, name)))\r
873 #endif\r
874                 {\r
875                         return;\r
876                 }\r
877                 else if (old_exp >= SPELL_EXP_EXPERT)\r
878                 {\r
879                         p_ptr->spell_exp[spell] = SPELL_EXP_MASTER;\r
880                         new_rank = EXP_LEVEL_MASTER;\r
881                 }\r
882                 else if (old_exp >= SPELL_EXP_SKILLED)\r
883                 {\r
884                         if (spell >= 32) p_ptr->spell_exp[spell] = SPELL_EXP_EXPERT;\r
885                         else p_ptr->spell_exp[spell] += SPELL_EXP_EXPERT - SPELL_EXP_SKILLED;\r
886                         new_rank = EXP_LEVEL_EXPERT;\r
887                 }\r
888                 else if (old_exp >= SPELL_EXP_BEGINNER)\r
889                 {\r
890                         p_ptr->spell_exp[spell] = SPELL_EXP_SKILLED + (old_exp - SPELL_EXP_BEGINNER) * 2 / 3;\r
891                         new_rank = EXP_LEVEL_SKILLED;\r
892                 }\r
893                 else\r
894                 {\r
895                         p_ptr->spell_exp[spell] = SPELL_EXP_BEGINNER + old_exp / 3;\r
896                         new_rank = EXP_LEVEL_BEGINNER;\r
897                 }\r
898                 msg_format(_("%sの熟練度が%sに上がった。", "Your proficiency of %s is now %s rank."), name, exp_level_str[new_rank]);\r
899         }\r
900         else\r
901         {\r
902                 /* Find the next open entry in "p_ptr->spell_order[]" */\r
903                 for (i = 0; i < 64; i++)\r
904                 {\r
905                         /* Stop at the first empty space */\r
906                         if (p_ptr->spell_order[i] == 99) break;\r
907                 }\r
908 \r
909                 /* Add the spell to the known list */\r
910                 p_ptr->spell_order[i++] = spell;\r
911 \r
912                 /* Mention the result */\r
913 #ifdef JP\r
914                 /* 英日切り替え機能に対応 */\r
915                 if (mp_ptr->spell_book == TV_MUSIC_BOOK)\r
916                 {\r
917                         msg_format("%sを学んだ。",\r
918                                 do_spell(increment ? p_ptr->realm2 : p_ptr->realm1, spell % 32, SPELL_NAME));\r
919                 }\r
920                 else\r
921                 {\r
922                         msg_format("%sの%sを学んだ。",\r
923                                 do_spell(increment ? p_ptr->realm2 : p_ptr->realm1, spell % 32, SPELL_NAME), p);\r
924                 }\r
925 #else\r
926                 msg_format("You have learned the %s of %s.",\r
927                         p, do_spell(increment ? p_ptr->realm2 : p_ptr->realm1, spell % 32, SPELL_NAME));\r
928 #endif\r
929         }\r
930 \r
931         p_ptr->energy_use = 100;\r
932 \r
933         switch (mp_ptr->spell_book)\r
934         {\r
935         case TV_LIFE_BOOK:\r
936                 chg_virtue(V_FAITH, 1);\r
937                 break;\r
938         case TV_DEATH_BOOK:\r
939                 chg_virtue(V_UNLIFE, 1);\r
940                 break;\r
941         case TV_NATURE_BOOK:\r
942                 chg_virtue(V_NATURE, 1);\r
943                 break;\r
944         default:\r
945                 chg_virtue(V_KNOWLEDGE, 1);\r
946                 break;\r
947         }\r
948 \r
949         sound(SOUND_STUDY);\r
950 \r
951         /* One less spell available */\r
952         p_ptr->learned_spells++;\r
953 \r
954         /* Update Study */\r
955         p_ptr->update |= (PU_SPELLS);\r
956         update_creature(p_ptr);\r
957 \r
958         /* Redraw object recall */\r
959         p_ptr->window |= (PW_OBJECT);\r
960 }\r
961 \r
962 \r
963 /*!\r
964  * @brief 魔法を詠唱するコマンドのメインルーチン /\r
965  * Cast a spell\r
966  * @return なし\r
967  */\r
968 void do_cmd_cast(void)\r
969 {\r
970         OBJECT_IDX item;\r
971         OBJECT_SUBTYPE_VALUE sval;\r
972         SPELL_IDX spell;\r
973         REALM_IDX realm;\r
974         int     chance;\r
975         int     increment = 0;\r
976         REALM_IDX use_realm;\r
977         MANA_POINT need_mana;\r
978 \r
979         concptr prayer;\r
980         object_type *o_ptr;\r
981         const magic_type *s_ptr;\r
982         concptr q, s;\r
983 \r
984         bool over_exerted = FALSE;\r
985 \r
986         /* Require spell ability */\r
987         if (!p_ptr->realm1 && (p_ptr->pclass != CLASS_SORCERER) && (p_ptr->pclass != CLASS_RED_MAGE))\r
988         {\r
989                 msg_print(_("呪文を唱えられない!", "You cannot cast spells!"));\r
990                 return;\r
991         }\r
992 \r
993         /* Require lite */\r
994         if (p_ptr->blind || no_lite())\r
995         {\r
996                 if (p_ptr->pclass == CLASS_FORCETRAINER) confirm_use_force(FALSE);\r
997                 else\r
998                 {\r
999                         msg_print(_("目が見えない!", "You cannot see!"));\r
1000                         flush();\r
1001                 }\r
1002                 return;\r
1003         }\r
1004 \r
1005         /* Not when confused */\r
1006         if (p_ptr->confused)\r
1007         {\r
1008                 msg_print(_("混乱していて唱えられない!", "You are too confused!"));\r
1009                 flush();\r
1010                 return;\r
1011         }\r
1012 \r
1013         /* Hex */\r
1014         if (p_ptr->realm1 == REALM_HEX)\r
1015         {\r
1016                 if (hex_spell_fully())\r
1017                 {\r
1018                         bool flag = FALSE;\r
1019                         msg_print(_("これ以上新しい呪文を詠唱することはできない。", "Can not spell new spells more."));\r
1020                         flush();\r
1021                         if (p_ptr->lev >= 35) flag = stop_hex_spell();\r
1022                         if (!flag) return;\r
1023                 }\r
1024         }\r
1025 \r
1026         if (p_ptr->pclass == CLASS_FORCETRAINER)\r
1027         {\r
1028                 if (player_has_no_spellbooks())\r
1029                 {\r
1030                         confirm_use_force(FALSE);\r
1031                         return;\r
1032                 }\r
1033         }\r
1034 \r
1035         prayer = spell_category_name(mp_ptr->spell_book);\r
1036 \r
1037         /* Restrict choices to spell books */\r
1038         item_tester_tval = mp_ptr->spell_book;\r
1039 \r
1040         q = _("どの呪文書を使いますか? ", "Use which book? ");\r
1041         s = _("呪文書がない!", "You have no spell books!");\r
1042 \r
1043         o_ptr = choose_object(&item, q, s, (USE_INVEN | USE_FLOOR | (p_ptr->pclass == CLASS_FORCETRAINER ? USE_FORCE : 0)));\r
1044         if (!o_ptr)\r
1045         {\r
1046                 if (item == INVEN_FORCE) /* the_force */\r
1047                 {\r
1048                         do_cmd_mind();\r
1049                         return;\r
1050                 }\r
1051                 return;\r
1052         }\r
1053 \r
1054         /* Access the item's sval */\r
1055         sval = o_ptr->sval;\r
1056 \r
1057         if ((p_ptr->pclass != CLASS_SORCERER) && (p_ptr->pclass != CLASS_RED_MAGE) && (o_ptr->tval == REALM2_BOOK)) increment = 32;\r
1058 \r
1059         /* Track the object kind */\r
1060         object_kind_track(o_ptr->k_idx);\r
1061         handle_stuff();\r
1062 \r
1063         if ((p_ptr->pclass == CLASS_SORCERER) || (p_ptr->pclass == CLASS_RED_MAGE))\r
1064                 realm = o_ptr->tval - TV_LIFE_BOOK + 1;\r
1065         else if (increment) realm = p_ptr->realm2;\r
1066         else realm = p_ptr->realm1;\r
1067 \r
1068         /* Ask for a spell */\r
1069 #ifdef JP\r
1070         if (!get_spell(&spell, ((mp_ptr->spell_book == TV_LIFE_BOOK) ? "詠唱する" : (mp_ptr->spell_book == TV_MUSIC_BOOK) ? "歌う" : "唱える"),\r
1071                 sval, TRUE, realm))\r
1072         {\r
1073                 if (spell == -2) msg_format("その本には知っている%sがない。", prayer);\r
1074                 return;\r
1075         }\r
1076 #else\r
1077         if (!get_spell(&spell, ((mp_ptr->spell_book == TV_LIFE_BOOK) ? "recite" : "cast"),\r
1078                 sval, TRUE, realm))\r
1079         {\r
1080                 if (spell == -2)\r
1081                         msg_format("You don't know any %ss in that book.", prayer);\r
1082                 return;\r
1083         }\r
1084 #endif\r
1085 \r
1086 \r
1087         use_realm = tval2realm(o_ptr->tval);\r
1088 \r
1089         /* Hex */\r
1090         if (use_realm == REALM_HEX)\r
1091         {\r
1092                 if (hex_spelling(spell))\r
1093                 {\r
1094                         msg_print(_("その呪文はすでに詠唱中だ。", "You are already casting it."));\r
1095                         return;\r
1096                 }\r
1097         }\r
1098 \r
1099         if (!is_magic(use_realm))\r
1100         {\r
1101                 s_ptr = &technic_info[use_realm - MIN_TECHNIC][spell];\r
1102         }\r
1103         else\r
1104         {\r
1105                 s_ptr = &mp_ptr->info[realm - 1][spell];\r
1106         }\r
1107 \r
1108         /* Extract mana consumption rate */\r
1109         need_mana = mod_need_mana(s_ptr->smana, spell, realm);\r
1110 \r
1111         /* Verify "dangerous" spells */\r
1112         if (need_mana > p_ptr->csp)\r
1113         {\r
1114                 if (flush_failure) flush();\r
1115 \r
1116                 /* Warning */\r
1117 #ifdef JP\r
1118                 msg_format("その%sを%sのに十分なマジックポイントがない。", prayer,\r
1119                         ((mp_ptr->spell_book == TV_LIFE_BOOK) ? "詠唱する" : (mp_ptr->spell_book == TV_LIFE_BOOK) ? "歌う" : "唱える"));\r
1120 #else\r
1121                 msg_format("You do not have enough mana to %s this %s.",\r
1122                         ((mp_ptr->spell_book == TV_LIFE_BOOK) ? "recite" : "cast"),\r
1123                         prayer);\r
1124 #endif\r
1125 \r
1126 \r
1127                 if (!over_exert) return;\r
1128 \r
1129                 /* Verify */\r
1130                 if (!get_check_strict(_("それでも挑戦しますか? ", "Attempt it anyway? "), CHECK_OKAY_CANCEL)) return;\r
1131         }\r
1132 \r
1133         /* Spell failure chance */\r
1134         chance = spell_chance(spell, use_realm);\r
1135 \r
1136         /* Sufficient mana */\r
1137         if (need_mana <= p_ptr->csp)\r
1138         {\r
1139                 /* Use some mana */\r
1140                 p_ptr->csp -= need_mana;\r
1141         }\r
1142         else over_exerted = TRUE;\r
1143         p_ptr->redraw |= (PR_MANA);\r
1144 \r
1145         /* Failed spell */\r
1146         if (randint0(100) < chance)\r
1147         {\r
1148                 if (flush_failure) flush();\r
1149 \r
1150                 msg_format(_("%sをうまく唱えられなかった!", "You failed to get the %s off!"), prayer);\r
1151                 sound(SOUND_FAIL);\r
1152 \r
1153                 switch (realm)\r
1154                 {\r
1155                 case REALM_LIFE:\r
1156                         if (randint1(100) < chance) chg_virtue(V_VITALITY, -1);\r
1157                         break;\r
1158                 case REALM_DEATH:\r
1159                         if (randint1(100) < chance) chg_virtue(V_UNLIFE, -1);\r
1160                         break;\r
1161                 case REALM_NATURE:\r
1162                         if (randint1(100) < chance) chg_virtue(V_NATURE, -1);\r
1163                         break;\r
1164                 case REALM_DAEMON:\r
1165                         if (randint1(100) < chance) chg_virtue(V_JUSTICE, 1);\r
1166                         break;\r
1167                 case REALM_CRUSADE:\r
1168                         if (randint1(100) < chance) chg_virtue(V_JUSTICE, -1);\r
1169                         break;\r
1170                 case REALM_HEX:\r
1171                         if (randint1(100) < chance) chg_virtue(V_COMPASSION, -1);\r
1172                         break;\r
1173                 default:\r
1174                         if (randint1(100) < chance) chg_virtue(V_KNOWLEDGE, -1);\r
1175                         break;\r
1176                 }\r
1177 \r
1178                 /* Failure casting may activate some side effect */\r
1179                 do_spell(realm, spell, SPELL_FAIL);\r
1180 \r
1181 \r
1182                 if ((o_ptr->tval == TV_CHAOS_BOOK) && (randint1(100) < spell))\r
1183                 {\r
1184                         msg_print(_("カオス的な効果を発生した!", "You produce a chaotic effect!"));\r
1185                         wild_magic(spell);\r
1186                 }\r
1187                 else if ((o_ptr->tval == TV_DEATH_BOOK) && (randint1(100) < spell))\r
1188                 {\r
1189                         if ((sval == 3) && one_in_(2))\r
1190                         {\r
1191                                 sanity_blast(0, TRUE);\r
1192                         }\r
1193                         else\r
1194                         {\r
1195                                 msg_print(_("痛い!", "It hurts!"));\r
1196                                 take_hit(DAMAGE_LOSELIFE, damroll(o_ptr->sval + 1, 6), _("暗黒魔法の逆流", "a miscast Death spell"), -1);\r
1197 \r
1198                                 if ((spell > 15) && one_in_(6) && !p_ptr->hold_exp)\r
1199                                         lose_exp(spell * 250);\r
1200                         }\r
1201                 }\r
1202                 else if ((o_ptr->tval == TV_MUSIC_BOOK) && (randint1(200) < spell))\r
1203                 {\r
1204                         msg_print(_("いやな音が響いた", "An infernal sound echoed."));\r
1205                         aggravate_monsters(0);\r
1206                 }\r
1207                 if (randint1(100) >= chance)\r
1208                         chg_virtue(V_CHANCE, -1);\r
1209         }\r
1210 \r
1211         /* Process spell */\r
1212         else\r
1213         {\r
1214                 /* Canceled spells cost neither a turn nor mana */\r
1215                 if (!do_spell(realm, spell, SPELL_CAST)) return;\r
1216 \r
1217                 if (randint1(100) < chance)\r
1218                         chg_virtue(V_CHANCE, 1);\r
1219 \r
1220                 /* A spell was cast */\r
1221                 if (!(increment ?\r
1222                         (p_ptr->spell_worked2 & (1L << spell)) :\r
1223                         (p_ptr->spell_worked1 & (1L << spell)))\r
1224                         && (p_ptr->pclass != CLASS_SORCERER)\r
1225                         && (p_ptr->pclass != CLASS_RED_MAGE))\r
1226                 {\r
1227                         int e = s_ptr->sexp;\r
1228 \r
1229                         /* The spell worked */\r
1230                         if (realm == p_ptr->realm1)\r
1231                         {\r
1232                                 p_ptr->spell_worked1 |= (1L << spell);\r
1233                         }\r
1234                         else\r
1235                         {\r
1236                                 p_ptr->spell_worked2 |= (1L << spell);\r
1237                         }\r
1238 \r
1239                         /* Gain experience */\r
1240                         gain_exp(e * s_ptr->slevel);\r
1241 \r
1242                         /* Redraw object recall */\r
1243                         p_ptr->window |= (PW_OBJECT);\r
1244 \r
1245                         switch (realm)\r
1246                         {\r
1247                         case REALM_LIFE:\r
1248                                 chg_virtue(V_TEMPERANCE, 1);\r
1249                                 chg_virtue(V_COMPASSION, 1);\r
1250                                 chg_virtue(V_VITALITY, 1);\r
1251                                 chg_virtue(V_DILIGENCE, 1);\r
1252                                 break;\r
1253                         case REALM_DEATH:\r
1254                                 chg_virtue(V_UNLIFE, 1);\r
1255                                 chg_virtue(V_JUSTICE, -1);\r
1256                                 chg_virtue(V_FAITH, -1);\r
1257                                 chg_virtue(V_VITALITY, -1);\r
1258                                 break;\r
1259                         case REALM_DAEMON:\r
1260                                 chg_virtue(V_JUSTICE, -1);\r
1261                                 chg_virtue(V_FAITH, -1);\r
1262                                 chg_virtue(V_HONOUR, -1);\r
1263                                 chg_virtue(V_TEMPERANCE, -1);\r
1264                                 break;\r
1265                         case REALM_CRUSADE:\r
1266                                 chg_virtue(V_FAITH, 1);\r
1267                                 chg_virtue(V_JUSTICE, 1);\r
1268                                 chg_virtue(V_SACRIFICE, 1);\r
1269                                 chg_virtue(V_HONOUR, 1);\r
1270                                 break;\r
1271                         case REALM_NATURE:\r
1272                                 chg_virtue(V_NATURE, 1);\r
1273                                 chg_virtue(V_HARMONY, 1);\r
1274                                 break;\r
1275                         case REALM_HEX:\r
1276                                 chg_virtue(V_JUSTICE, -1);\r
1277                                 chg_virtue(V_FAITH, -1);\r
1278                                 chg_virtue(V_HONOUR, -1);\r
1279                                 chg_virtue(V_COMPASSION, -1);\r
1280                                 break;\r
1281                         default:\r
1282                                 chg_virtue(V_KNOWLEDGE, 1);\r
1283                                 break;\r
1284                         }\r
1285                 }\r
1286                 switch (realm)\r
1287                 {\r
1288                 case REALM_LIFE:\r
1289                         if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_TEMPERANCE, 1);\r
1290                         if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_COMPASSION, 1);\r
1291                         if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_VITALITY, 1);\r
1292                         if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_DILIGENCE, 1);\r
1293                         break;\r
1294                 case REALM_DEATH:\r
1295                         if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_UNLIFE, 1);\r
1296                         if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_JUSTICE, -1);\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_VITALITY, -1);\r
1299                         break;\r
1300                 case REALM_DAEMON:\r
1301                         if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_JUSTICE, -1);\r
1302                         if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_FAITH, -1);\r
1303                         if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_HONOUR, -1);\r
1304                         if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_TEMPERANCE, -1);\r
1305                         break;\r
1306                 case REALM_CRUSADE:\r
1307                         if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_FAITH, 1);\r
1308                         if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_JUSTICE, 1);\r
1309                         if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_SACRIFICE, 1);\r
1310                         if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_HONOUR, 1);\r
1311                         break;\r
1312                 case REALM_NATURE:\r
1313                         if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_NATURE, 1);\r
1314                         if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_HARMONY, 1);\r
1315                         break;\r
1316                 case REALM_HEX:\r
1317                         if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_JUSTICE, -1);\r
1318                         if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_FAITH, -1);\r
1319                         if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_HONOUR, -1);\r
1320                         if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_COMPASSION, -1);\r
1321                         break;\r
1322                 }\r
1323                 if (mp_ptr->spell_xtra & MAGIC_GAIN_EXP)\r
1324                 {\r
1325                         s16b cur_exp = p_ptr->spell_exp[(increment ? 32 : 0) + spell];\r
1326                         s16b exp_gain = 0;\r
1327 \r
1328                         if (cur_exp < SPELL_EXP_BEGINNER)\r
1329                                 exp_gain += 60;\r
1330                         else if (cur_exp < SPELL_EXP_SKILLED)\r
1331                         {\r
1332                                 if ((dun_level > 4) && ((dun_level + 10) > p_ptr->lev))\r
1333                                         exp_gain = 8;\r
1334                         }\r
1335                         else if (cur_exp < SPELL_EXP_EXPERT)\r
1336                         {\r
1337                                 if (((dun_level + 5) > p_ptr->lev) && ((dun_level + 5) > s_ptr->slevel))\r
1338                                         exp_gain = 2;\r
1339                         }\r
1340                         else if ((cur_exp < SPELL_EXP_MASTER) && !increment)\r
1341                         {\r
1342                                 if (((dun_level + 5) > p_ptr->lev) && (dun_level > s_ptr->slevel))\r
1343                                         exp_gain = 1;\r
1344                         }\r
1345                         p_ptr->spell_exp[(increment ? 32 : 0) + spell] += exp_gain;\r
1346                 }\r
1347         }\r
1348 \r
1349         p_ptr->energy_use = 100;\r
1350 \r
1351 \r
1352         /* Over-exert the player */\r
1353         if (over_exerted)\r
1354         {\r
1355                 int oops = need_mana;\r
1356 \r
1357                 /* No mana left */\r
1358                 p_ptr->csp = 0;\r
1359                 p_ptr->csp_frac = 0;\r
1360 \r
1361                 msg_print(_("精神を集中しすぎて気を失ってしまった!", "You faint from the effort!"));\r
1362 \r
1363                 /* Hack -- Bypass free action */\r
1364                 (void)set_paralyzed(p_ptr->paralyzed + randint1(5 * oops + 1));\r
1365 \r
1366                 switch (realm)\r
1367                 {\r
1368                 case REALM_LIFE:\r
1369                         chg_virtue(V_VITALITY, -10);\r
1370                         break;\r
1371                 case REALM_DEATH:\r
1372                         chg_virtue(V_UNLIFE, -10);\r
1373                         break;\r
1374                 case REALM_DAEMON:\r
1375                         chg_virtue(V_JUSTICE, 10);\r
1376                         break;\r
1377                 case REALM_NATURE:\r
1378                         chg_virtue(V_NATURE, -10);\r
1379                         break;\r
1380                 case REALM_CRUSADE:\r
1381                         chg_virtue(V_JUSTICE, -10);\r
1382                         break;\r
1383                 case REALM_HEX:\r
1384                         chg_virtue(V_COMPASSION, 10);\r
1385                         break;\r
1386                 default:\r
1387                         chg_virtue(V_KNOWLEDGE, -10);\r
1388                         break;\r
1389                 }\r
1390 \r
1391                 /* Damage CON (possibly permanently) */\r
1392                 if (randint0(100) < 50)\r
1393                 {\r
1394                         bool perm = (randint0(100) < 25);\r
1395 \r
1396                         msg_print(_("体を悪くしてしまった!", "You have damaged your health!"));\r
1397 \r
1398                         /* Reduce constitution */\r
1399                         (void)dec_stat(A_CON, 15 + randint1(10), perm);\r
1400                 }\r
1401         }\r
1402 \r
1403         p_ptr->window |= (PW_PLAYER);\r
1404         p_ptr->window |= (PW_SPELL);\r
1405 }\r